Compare commits

..

43 Commits

Author SHA1 Message Date
Lukasz Lenart 68fb49c10e [maven-release-plugin] prepare release STRUTS_6_0_0 2022-06-02 09:11:02 +02:00
Lukasz Lenart 77c175c7be Merge pull request #555 from hboutemy/patch-4
upgrade Felix m-bundle-p: reproducible builds
2022-05-25 10:42:55 +02:00
Hervé Boutemy 65b7e8c36f upgrade Felix m-bundle-p: reproducible builds 2022-05-25 10:00:15 +02:00
Lukasz Lenart 735bbc283e [maven-release-plugin] prepare for next development iteration 2022-05-24 13:59:32 +02:00
Lukasz Lenart 981885fd6a [maven-release-plugin] prepare release STRUTS_6_0_0_RC4 2022-05-24 13:59:22 +02:00
Lukasz Lenart 07b88fcc35 Upgrades integration tests config to match Spring and Jetty 2022-05-24 09:51:42 +02:00
Lukasz Lenart 2cbe47297e Merge pull request #554 from gregh3269/More_localdatetime_support
Add basic LocalDateTime support WW-5175
2022-05-23 07:35:43 +02:00
Lukasz Lenart 545add9365 Merge pull request #553 from apache/WW-5179-max-length
[WW-5179] Set default value of struts.ognl.expressionMaxLength to 256
2022-05-23 07:34:17 +02:00
Lukasz Lenart ebecc7d39d Merge pull request #552 from apache/WW-5165-upgrade-spring
[WW-5165] Upgrades Spring to version 5.3.20
2022-05-23 07:34:05 +02:00
Greg Huber 226a1d49ce Add basic LocalDateTime support WW-5175 2022-05-20 11:47:08 +01:00
Greg Huber 075ef7c4e1 Add basic LocalDateTime support WW-5175 2022-05-19 10:30:36 +01:00
Lukasz Lenart 1237110652 WW-5179 Adjusts test to match new default value 2022-05-17 21:17:56 +02:00
Lukasz Lenart 3f2518afa8 WW-5179 Set default value of struts.ognl.expressionMaxLength to 256 2022-05-17 20:59:51 +02:00
Lukasz Lenart 9f9edf4705 WW-5165 Upgrades Spring to version 5.3.20 2022-05-17 07:37:39 +02:00
gregh3269 7e912742ed Basic LocalDateTime support (#532)
* Basic LocalDateTime support

* Basic LocalDateTime support

* Basic LocalDateTime support

* Basic LocalDateTime support

* Basic LocalDateTime support

Co-authored-by: Greg Huber <ghuber@guestales.co.uk>
Co-authored-by: Greg Huber <ghuber@apache.org>
2022-05-17 07:31:30 +02:00
Lukasz Lenart c98b60cd9a Merge pull request #528 from JCgH4164838Gh792C124B5/localS2_26_OgnlUtilOptionalCache1
Potential expression cache enhancement for 2.6 series
2022-05-16 07:38:59 +02:00
Lukasz Lenart 5ae9688ae8 Merge pull request #551 from apache/dependabot/maven/xerces-xercesImpl-2.12.2
Bump xercesImpl from 2.12.0 to 2.12.2
2022-05-16 07:18:03 +02:00
Lukasz Lenart b72200aabf Merge branch 'master' into localS2_26_OgnlUtilOptionalCache1
# Conflicts:
#	core/src/test/java/com/opensymphony/xwork2/ognl/OgnlUtilTest.java
2022-05-16 07:16:03 +02:00
JCgH4164838Gh792C124B5 16e7c9b459 Merge pull request #1 from apache/use-extension-point
Ties cache extension points with implementation
2022-05-15 19:01:17 -04:00
Yasser Zamani bea1c6f09f Merge pull request #549 from apache/WW-5181-static-methods
[WW-5181] Blocks permanently access to static methods
2022-05-15 14:40:12 +04:30
dependabot[bot] 888884cc51 Bump xercesImpl from 2.12.0 to 2.12.2
Bumps xercesImpl from 2.12.0 to 2.12.2.

---
updated-dependencies:
- dependency-name: xerces:xercesImpl
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-15 10:02:32 +00:00
Yasser Zamani b387abae01 Merge pull request #550 from apache/servlet-3
[WW-5182] Upgrade to Servlet API 3.1
2022-05-15 14:27:47 +04:30
Lukasz Lenart 059a2a6117 WW-5182 Upgrade to Servlet API 3.1 2022-05-14 09:12:42 +02:00
Lukasz Lenart c0a3be9fd8 Uses two step build process on Travis similar to Jenkins pipeline 2022-05-10 07:41:34 +02:00
Lukasz Lenart 4a7cae029a Uses proper package to match Jetty Eclipse 2022-05-08 12:31:40 +02:00
Lukasz Lenart 9873a7f56b Tries to fix Travis build 2022-05-06 08:35:06 +02:00
Lukasz Lenart 086b514d59 Adjusts Travis build to be aligned with Jenkins pipeline 2022-05-06 07:47:12 +02:00
Lukasz Lenart 6024dd6fa4 Skips test during deploy 2022-05-06 07:29:29 +02:00
Lukasz Lenart 4eb2ee8384 Fixes typo in deploy step 2022-05-06 07:24:29 +02:00
Lukasz Lenart 8e49362bf8 Uses Maven Wrapper in Jenkins pipeline 2022-05-06 07:15:13 +02:00
Lukasz Lenart 7541d9ab35 WW-5181 Blocks permanently access to static methods 2022-05-05 12:28:09 +02:00
Lukasz Lenart c82fdb5e76 Upgrades Maven Wrapper 2022-05-05 12:27:51 +02:00
Lukasz Lenart f40f9f15e5 Merge pull request #547 from apache/dependabot/maven/junit-junit-4.13.1
Bump junit from 4.13 to 4.13.1
2022-05-04 11:18:43 +02:00
dependabot[bot] 2d9cdb73a5 Bump junit from 4.13 to 4.13.1
Bumps [junit](https://github.com/junit-team/junit4) from 4.13 to 4.13.1.
- [Release notes](https://github.com/junit-team/junit4/releases)
- [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.13.1.md)
- [Commits](https://github.com/junit-team/junit4/compare/r4.13...r4.13.1)

---
updated-dependencies:
- dependency-name: junit:junit
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-04 08:52:18 +00:00
Lukasz Lenart d07a496d5c Uses common Maven Compiler plugin to set proper source and target version 2022-05-04 10:45:02 +02:00
Lukasz Lenart bef1f67d4a Upgrades Maven Jetty Plugin to work with JDK8+ 2022-05-04 10:44:54 +02:00
Lukasz Lenart e2718aa482 Enables branch autodeleting after PR has been merged 2022-04-07 14:43:38 +02:00
Lukasz Lenart b73fec4de0 Drops unused class 2022-04-04 17:12:33 +02:00
Lukasz Lenart c2795d2e30 Uses project specific folder 2022-03-28 13:09:21 +02:00
Lukasz Lenart a987e31a0e Upgrades OWASP Dependency Check plugin to version 7.0.1 2022-03-28 07:45:51 +02:00
Lukasz Lenart 6aff5b7faa WW-5174 Upgrades Jackson-Core to version 2.13.2 and Jackson-Databind to 2.13.2.1 2022-03-28 07:26:50 +02:00
Lukasz Lenart 5b40f9f48e WW-5172 Upgrades Freemarker to 2.3.31 version 2022-03-15 14:32:02 +01:00
Lukasz Lenart e9d0a5518c Cleans up code 2022-03-15 14:27:57 +01:00
92 changed files with 2003 additions and 1015 deletions
+4
View File
@@ -1,3 +1,4 @@
# Documentation https://s.apache.org/asfyaml
notifications: notifications:
commits: commits@struts.apache.org commits: commits@struts.apache.org
# Send all issue emails (new, closed, comments) to issues@ # Send all issue emails (new, closed, comments) to issues@
@@ -8,3 +9,6 @@ notifications:
pullrequests_comment: issues@struts.apache.org pullrequests_comment: issues@struts.apache.org
# Link opened PRs with JIRA # Link opened PRs with JIRA
jira_options: link label worklog jira_options: link label worklog
github:
del_branch_on_merge: true
+1 -1
View File
@@ -14,5 +14,5 @@
# KIND, either express or implied. See the License for the # KIND, either express or implied. See the License for the
# specific language governing permissions and limitations # specific language governing permissions and limitations
# under the License. # under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.5/apache-maven-3.8.5-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
+4 -7
View File
@@ -14,17 +14,14 @@ global:
matrix: matrix:
include: include:
- jdk: oraclejdk8 - jdk: oraclejdk8
env: STRUTS_IT=true # do integration tests and coverage reports when jdk7,9 and 11 tests prospered env: STRUTS_IT=true # do integration tests and coverage reports when jdk 9 and 11 tests prospered
script: script:
- if [ "$STRUTS_IT" == "true" ]; then - if [ "$STRUTS_IT" == "true" ]; then
./mvnw clean verify org.jacoco:jacoco-maven-plugin:report org.jacoco:jacoco-maven-plugin:report-integration org.eluder.coveralls:coveralls-maven-plugin:report -Ptravis-coveralls -DskipAssembly -B; ./mvnw clean install -DskipTests -DskipAssembly -B;
./mvnw test org.jacoco:jacoco-maven-plugin:report org.jacoco:jacoco-maven-plugin:report-integration org.eluder.coveralls:coveralls-maven-plugin:report -Ptravis-coveralls -DskipAssembly -B;
else else
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then ./mvnw clean package test -DskipAssembly -B;
./mvnw test -DskipAssembly -B;
else
./mvnw test -DskipAssembly -Dupdate-impact -B;
fi;
fi; fi;
cache: cache:
Vendored
+10 -10
View File
@@ -39,12 +39,12 @@ pipeline {
stages { stages {
stage('Build') { stage('Build') {
steps { steps {
sh 'mvn -B clean install -DskipTests -DskipAssembly' sh './mvnw -B clean install -DskipTests -DskipAssembly'
} }
} }
stage('Test') { stage('Test') {
steps { steps {
sh 'mvn -B test' sh './mvnw -B test'
} }
post { post {
always { always {
@@ -74,12 +74,12 @@ pipeline {
stages { stages {
stage('Build') { stage('Build') {
steps { steps {
sh 'mvn -B clean install -DskipTests -DskipAssembly' sh './mvnw -B clean install -DskipTests -DskipAssembly'
} }
} }
stage('Test') { stage('Test') {
steps { steps {
sh 'mvn -B test' sh './mvnw -B test'
} }
post { post {
always { always {
@@ -94,7 +94,7 @@ pipeline {
} }
steps { steps {
withCredentials([string(credentialsId: 'asf-struts-sonarcloud', variable: 'SONARCLOUD_TOKEN')]) { withCredentials([string(credentialsId: 'asf-struts-sonarcloud', variable: 'SONARCLOUD_TOKEN')]) {
sh 'mvn sonar:sonar -DskipAssembly -Dsonar.login=${SONARCLOUD_TOKEN}' sh './mvnw sonar:sonar -DskipAssembly -Dsonar.login=${SONARCLOUD_TOKEN}'
} }
} }
} }
@@ -119,12 +119,12 @@ pipeline {
stages { stages {
stage('Build') { stage('Build') {
steps { steps {
sh 'mvn -B clean install -DskipTests -DskipAssembly' sh './mvnw -B clean install -DskipTests -DskipAssembly'
} }
} }
stage('Test') { stage('Test') {
steps { steps {
sh 'mvn -B test' sh './mvnw -B test'
// step([$class: 'JiraIssueUpdater', issueSelector: [$class: 'DefaultIssueSelector'], scm: scm]) // step([$class: 'JiraIssueUpdater', issueSelector: [$class: 'DefaultIssueSelector'], scm: scm])
} }
post { post {
@@ -142,7 +142,7 @@ pipeline {
dir("local-snapshots-dir/") { dir("local-snapshots-dir/") {
deleteDir() deleteDir()
} }
sh 'mvn -B source:jar javadoc:jar -DskipAssembbly' sh './mvnw -B source:jar javadoc:jar -DskipTests -DskipAssembly'
} }
} }
stage('Deploy Snapshot') { stage('Deploy Snapshot') {
@@ -151,7 +151,7 @@ pipeline {
} }
steps { steps {
withCredentials([file(credentialsId: 'lukaszlenart-repository-access-token', variable: 'CUSTOM_SETTINGS')]) { withCredentials([file(credentialsId: 'lukaszlenart-repository-access-token', variable: 'CUSTOM_SETTINGS')]) {
sh 'mvn -s \${CUSTOM_SETTINGS} deploy' sh './mvnw -s \${CUSTOM_SETTINGS} deploy -DskipTests -DskipAssembly'
} }
} }
} }
@@ -165,7 +165,7 @@ pipeline {
configName: 'Nightlies', configName: 'Nightlies',
transfers: [ transfers: [
sshTransfer( sshTransfer(
remoteDirectory: '/x1/dist/struts', remoteDirectory: '/struts/snapshot',
removePrefix: 'assembly/target/assembly/out', removePrefix: 'assembly/target/assembly/out',
sourceFiles: 'assembly/target/assembly/out/struts-*.zip' sourceFiles: 'assembly/target/assembly/out/struts-*.zip'
) )
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId> <artifactId>struts2-parent</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-apps</artifactId> <artifactId>struts2-apps</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>
+4 -4
View File
@@ -24,12 +24,12 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId> <artifactId>struts2-apps</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-rest-showcase</artifactId> <artifactId>struts2-rest-showcase</artifactId>
<packaging>war</packaging> <packaging>war</packaging>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
<name>Struts 2 Rest Showcase Webapp</name> <name>Struts 2 Rest Showcase Webapp</name>
<description>Struts 2 Rest Showcase Example</description> <description>Struts 2 Rest Showcase Example</description>
@@ -108,9 +108,9 @@
<finalName>struts2-rest-showcase</finalName> <finalName>struts2-rest-showcase</finalName>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.mortbay.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId> <artifactId>jetty-maven-plugin</artifactId>
<version>8.1.16.v20140903</version> <version>9.4.46.v20220331</version>
<configuration> <configuration>
<stopKey>CTRL+C</stopKey> <stopKey>CTRL+C</stopKey>
<stopPort>8999</stopPort> <stopPort>8999</stopPort>
+8 -20
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId> <artifactId>struts2-apps</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-showcase</artifactId> <artifactId>struts2-showcase</artifactId>
@@ -101,7 +101,7 @@
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
@@ -144,7 +144,7 @@
<dependency> <dependency>
<groupId>net.sourceforge.htmlunit</groupId> <groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId> <artifactId>htmlunit</artifactId>
<version>2.39.0</version> <version>2.61.0</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
@@ -155,15 +155,6 @@
<version>6.1.2.Final</version> <version>6.1.2.Final</version>
</dependency> </dependency>
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
This is only necessary in tests-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
@@ -171,7 +162,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId> <artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M4</version> <version>3.0.0-M6</version>
<configuration> <configuration>
<includes> <includes>
<include>it.org.apache.struts2.showcase.*Test</include> <include>it.org.apache.struts2.showcase.*Test</include>
@@ -193,16 +184,16 @@
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.mortbay.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId> <artifactId>jetty-maven-plugin</artifactId>
<version>8.1.16.v20140903</version> <version>9.4.46.v20220331</version>
<configuration> <configuration>
<stopKey>CTRL+C</stopKey> <stopKey>CTRL+C</stopKey>
<stopPort>8999</stopPort> <stopPort>8999</stopPort>
<systemProperties> <systemProperties>
<systemProperty> <systemProperty>
<name>log4j.configuration</name> <name>log4j.configuration</name>
<value>file:${basedir}/src/main/resources/log4j.properties</value> <value>file:${basedir}/src/main/resources/log4j2.xml</value>
</systemProperty> </systemProperty>
<systemProperty> <systemProperty>
<name>slf4j</name> <name>slf4j</name>
@@ -223,11 +214,8 @@
<goals> <goals>
<!-- stop any previous instance to free up the port --> <!-- stop any previous instance to free up the port -->
<goal>stop</goal> <goal>stop</goal>
<goal>run-forked</goal> <goal>start</goal>
</goals> </goals>
<configuration>
<waitForChild>false</waitForChild>
</configuration>
</execution> </execution>
<execution> <execution>
<id>stop-jetty</id> <id>stop-jetty</id>
@@ -45,66 +45,46 @@
</bean> </bean>
<bean id="chatLoginAction" class="org.apache.struts2.showcase.chat.ChatLoginAction" scope="prototype"> <bean id="chatLoginAction" class="org.apache.struts2.showcase.chat.ChatLoginAction" scope="prototype">
<constructor-arg index="0"> <constructor-arg index="0" ref="chatService"/>
<ref local="chatService"/>
</constructor-arg>
</bean> </bean>
<bean id="chatLogoutAction" class="org.apache.struts2.showcase.chat.ChatLogoutAction" scope="prototype"> <bean id="chatLogoutAction" class="org.apache.struts2.showcase.chat.ChatLogoutAction" scope="prototype">
<constructor-arg index="0"> <constructor-arg index="0" ref="chatService"/>
<ref local="chatService"/>
</constructor-arg>
</bean> </bean>
<bean id="usersAvailableAction" class="org.apache.struts2.showcase.chat.UsersAvailableAction" scope="prototype"> <bean id="usersAvailableAction" class="org.apache.struts2.showcase.chat.UsersAvailableAction" scope="prototype">
<constructor-arg index="0"> <constructor-arg index="0" ref="chatService"/>
<ref local="chatService"/>
</constructor-arg>
</bean> </bean>
<bean id="roomsAvailableAction" class="org.apache.struts2.showcase.chat.RoomsAvailableAction" scope="prototype"> <bean id="roomsAvailableAction" class="org.apache.struts2.showcase.chat.RoomsAvailableAction" scope="prototype">
<constructor-arg index="0"> <constructor-arg index="0" ref="chatService"/>
<ref local="chatService"/>
</constructor-arg>
</bean> </bean>
<bean id="crudRoomAction" class="org.apache.struts2.showcase.chat.CrudRoomAction" scope="prototype"> <bean id="crudRoomAction" class="org.apache.struts2.showcase.chat.CrudRoomAction" scope="prototype">
<constructor-arg index="0"> <constructor-arg index="0" ref="chatService"/>
<ref local="chatService"/>
</constructor-arg>
</bean> </bean>
<bean id="enterRoomAction" class="org.apache.struts2.showcase.chat.EnterRoomAction" scope="prototype"> <bean id="enterRoomAction" class="org.apache.struts2.showcase.chat.EnterRoomAction" scope="prototype">
<constructor-arg index="0"> <constructor-arg index="0" ref="chatService"/>
<ref local="chatService"/>
</constructor-arg>
</bean> </bean>
<bean id="messagesAvailableInRoomAction" class="org.apache.struts2.showcase.chat.MessagesAvailableInRoomAction" <bean id="messagesAvailableInRoomAction" class="org.apache.struts2.showcase.chat.MessagesAvailableInRoomAction"
scope="prototype"> scope="prototype">
<constructor-arg index="0"> <constructor-arg index="0" ref="chatService"/>
<ref local="chatService"/>
</constructor-arg>
</bean> </bean>
<bean id="sendMessageToRoomAction" class="org.apache.struts2.showcase.chat.SendMessageToRoomAction" <bean id="sendMessageToRoomAction" class="org.apache.struts2.showcase.chat.SendMessageToRoomAction"
scope="prototype"> scope="prototype">
<constructor-arg index="0"> <constructor-arg index="0" ref="chatService"/>
<ref local="chatService"/>
</constructor-arg>
</bean> </bean>
<bean id="usersAvailableInRoomAction" class="org.apache.struts2.showcase.chat.UsersAvailableInRoomAction" <bean id="usersAvailableInRoomAction" class="org.apache.struts2.showcase.chat.UsersAvailableInRoomAction"
scope="prototype"> scope="prototype">
<constructor-arg index="0"> <constructor-arg index="0" ref="chatService"/>
<ref local="chatService"/>
</constructor-arg>
</bean> </bean>
<bean id="exitRoomAction" class="org.apache.struts2.showcase.chat.ExitRoomAction" scope="prototype"> <bean id="exitRoomAction" class="org.apache.struts2.showcase.chat.ExitRoomAction" scope="prototype">
<constructor-arg index="0"> <constructor-arg index="0" ref="chatService"/>
<ref local="chatService"/>
</constructor-arg>
</bean> </bean>
@@ -129,9 +109,7 @@
</bean> </bean>
<bean id="startHangmanAction" class="org.apache.struts2.showcase.hangman.StartHangmanAction" scope="prototype"> <bean id="startHangmanAction" class="org.apache.struts2.showcase.hangman.StartHangmanAction" scope="prototype">
<constructor-arg index="0"> <constructor-arg index="0" ref="hangmanService"/>
<ref local="hangmanService"/>
</constructor-arg>
</bean> </bean>
<bean id="guessCharacterAction" class="org.apache.struts2.showcase.hangman.GuessCharacterAction" scope="prototype"/> <bean id="guessCharacterAction" class="org.apache.struts2.showcase.hangman.GuessCharacterAction" scope="prototype"/>
@@ -32,7 +32,7 @@ public class ActionChainingTest {
try (final WebClient webClient = new WebClient()) { try (final WebClient webClient = new WebClient()) {
final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/actionchaining/actionChain1!input"); final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/actionchaining/actionChain1!input");
final String pageAsText = page.asText(); final String pageAsText = page.asNormalizedText();
Assert.assertTrue(pageAsText.contains("Action Chain 1 Property 1: Property Set In Action Chain 1")); Assert.assertTrue(pageAsText.contains("Action Chain 1 Property 1: Property Set In Action Chain 1"));
Assert.assertTrue(pageAsText.contains("Action Chain 2 Property 1: Property Set in Action Chain 2")); Assert.assertTrue(pageAsText.contains("Action Chain 2 Property 1: Property Set in Action Chain 2"));
Assert.assertTrue(pageAsText.contains("Action Chain 3 Property 1: Property set in Action Chain 3")); Assert.assertTrue(pageAsText.contains("Action Chain 3 Property 1: Property set in Action Chain 3"));
@@ -32,7 +32,7 @@ public class ActionTagExampleTest {
try (final WebClient webClient = new WebClient()) { try (final WebClient webClient = new WebClient()) {
final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/tags/ui/actionTagExample!input.action"); final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/tags/ui/actionTagExample!input.action");
final String pageAsText = page.asText(); final String pageAsText = page.asNormalizedText();
Assert.assertTrue(pageAsText.contains("This text is from the called class")); Assert.assertTrue(pageAsText.contains("This text is from the called class"));
} }
} }
@@ -46,7 +46,7 @@ public class AsyncTest {
final DomElement msgs = page2.getElementById("msgs"); final DomElement msgs = page2.getElementById("msgs");
Assert.assertEquals("hello", msgs.asText()); Assert.assertEquals("hello", msgs.asNormalizedText());
} }
} }
} }
@@ -44,7 +44,7 @@ public class CRUDTest {
final HtmlSubmitInput button = form.getInputByValue("Save"); final HtmlSubmitInput button = form.getInputByValue("Save");
final HtmlPage page2 = button.click(); final HtmlPage page2 = button.click();
final String page2Text = page2.asText(); final String page2Text = page2.asNormalizedText();
Assert.assertTrue(page2Text.contains("somename1")); Assert.assertTrue(page2Text.contains("somename1"));
Assert.assertTrue(page2Text.contains("somedescription1")); Assert.assertTrue(page2Text.contains("somedescription1"));
@@ -33,7 +33,7 @@ public class ComponentTagExampleTest {
final HtmlPage page = webClient final HtmlPage page = webClient
.getPage(ParameterUtils.getBaseUrl() + "/tags/ui/componentTagExample.action"); .getPage(ParameterUtils.getBaseUrl() + "/tags/ui/componentTagExample.action");
final String pageAsText = page.asText(); final String pageAsText = page.asNormalizedText();
Assert.assertTrue(pageAsText.contains("Freemarker Custom Template - parameter 'paramName' - paramValue1")); Assert.assertTrue(pageAsText.contains("Freemarker Custom Template - parameter 'paramName' - paramValue1"));
Assert.assertTrue(pageAsText.contains("Freemarker Custom Template - parameter 'paramName' - paramValue4")); Assert.assertTrue(pageAsText.contains("Freemarker Custom Template - parameter 'paramName' - paramValue4"));
Assert.assertTrue(pageAsText.contains("JSP Custom Template - parameter 'paramName' - paramValue2")); Assert.assertTrue(pageAsText.contains("JSP Custom Template - parameter 'paramName' - paramValue2"));
@@ -46,7 +46,7 @@ public class ConversionTest {
final HtmlSubmitInput button = form.getInputByValue("Submit"); final HtmlSubmitInput button = form.getInputByValue("Submit");
final HtmlPage page2 = button.click(); final HtmlPage page2 = button.click();
final String page2Text = page2.asText(); final String page2Text = page2.asNormalizedText();
Assert.assertTrue(page2Text.contains("SET 0 Name: name0")); Assert.assertTrue(page2Text.contains("SET 0 Name: name0"));
Assert.assertTrue(page2Text.contains("SET 0 Age: 0")); Assert.assertTrue(page2Text.contains("SET 0 Age: 0"));
@@ -71,7 +71,7 @@ public class ConversionTest {
final HtmlSubmitInput button = form.getInputByValue("Submit"); final HtmlSubmitInput button = form.getInputByValue("Submit");
final HtmlPage page2 = button.click(); final HtmlPage page2 = button.click();
final String page2Text = page2.asText(); final String page2Text = page2.asNormalizedText();
Assert.assertTrue(page2Text.contains("id0 -> address0")); Assert.assertTrue(page2Text.contains("id0 -> address0"));
Assert.assertTrue(page2Text.contains("id1 -> address1")); Assert.assertTrue(page2Text.contains("id1 -> address1"));
@@ -92,7 +92,7 @@ public class ConversionTest {
final HtmlSubmitInput button = form.getInputByValue("Submit"); final HtmlSubmitInput button = form.getInputByValue("Submit");
final HtmlPage page2 = button.click(); final HtmlPage page2 = button.click();
final String page2Text = page2.asText(); final String page2Text = page2.asNormalizedText();
Assert.assertTrue(page2Text.contains("ADD")); Assert.assertTrue(page2Text.contains("ADD"));
Assert.assertTrue(page2Text.contains("MINUS")); Assert.assertTrue(page2Text.contains("MINUS"));
@@ -43,12 +43,12 @@ public class ExecAndWaitTest {
final HtmlSubmitInput button = form.getInputByValue("submit"); final HtmlSubmitInput button = form.getInputByValue("submit");
final HtmlPage page2 = button.click(); final HtmlPage page2 = button.click();
Assert.assertTrue(page2.asText().contains("We are processing your request. Please wait.")); Assert.assertTrue(page2.asNormalizedText().contains("We are processing your request. Please wait."));
// hit it again // hit it again
final HtmlPage page3 = webClient final HtmlPage page3 = webClient
.getPage(ParameterUtils.getBaseUrl() + "/wait/longProcess1.action?time=1000"); .getPage(ParameterUtils.getBaseUrl() + "/wait/longProcess1.action?time=1000");
Assert.assertTrue(page3.asText().contains("We are processing your request. Please wait.")); Assert.assertTrue(page3.asNormalizedText().contains("We are processing your request. Please wait."));
} }
} }
} }
@@ -43,6 +43,7 @@ public class FileDownloadTest {
} }
} }
@Test
public void testZip() throws Exception { public void testZip() throws Exception {
try (final WebClient webClient = new WebClient()) { try (final WebClient webClient = new WebClient()) {
final Page page = webClient.getPage(ParameterUtils.getBaseUrl() + "/filedownload/download2.action"); final Page page = webClient.getPage(ParameterUtils.getBaseUrl() + "/filedownload/download2.action");
@@ -36,11 +36,11 @@ public class FreeMarkerManagerTest {
final DomElement date = page.getElementById("todaysDate"); final DomElement date = page.getElementById("todaysDate");
Assert.assertNotNull(date); Assert.assertNotNull(date);
Assert.assertTrue(date.asText().length() > 0); Assert.assertTrue(date.asNormalizedText().length() > 0);
final DomElement time = page.getElementById("timeNow"); final DomElement time = page.getElementById("timeNow");
Assert.assertNotNull(time); Assert.assertNotNull(time);
Assert.assertTrue(time.asText().length() > 0); Assert.assertTrue(time.asNormalizedText().length() > 0);
} }
} }
@@ -33,26 +33,23 @@ public class StaticContentTest {
webClient.getPage(ParameterUtils.getBaseUrl() + "/struts.."); webClient.getPage(ParameterUtils.getBaseUrl() + "/struts..");
Assert.fail("Previous request should have failed"); Assert.fail("Previous request should have failed");
} catch (FailingHttpStatusCodeException e) { } catch (FailingHttpStatusCodeException e) {
Assert.assertEquals("Not Found", e.getStatusMessage());
Assert.assertEquals(404, e.getStatusCode());
} }
} }
} }
@Test
public void testInvalidRersources2() throws Exception { public void testInvalidRersources2() throws Exception {
try (final WebClient webClient = new WebClient()) { try (final WebClient webClient = new WebClient()) {
try { try {
webClient.getPage(ParameterUtils.getBaseUrl() + "/static/..%252f"); webClient.getPage(ParameterUtils.getBaseUrl() + "/static/..%252f");
Assert.fail("Previous request should have failed"); Assert.fail("Previous request should have failed");
} catch (FailingHttpStatusCodeException e) { } catch (FailingHttpStatusCodeException e) {
Assert.assertEquals("Not Found", e.getStatusMessage());
Assert.assertEquals(404, e.getStatusCode());
} }
} }
} }
/*public void testInvalidRersources3() throws IOException {
try {
beginAt("/static/..%252f..%252f..%252fWEB-INF/classes/org/apache/struts2/showcase/action/EmployeeAction.class/");
fail("Previous request should have failed");
} catch (TestingEngineResponseException ex) {
// ok
}
}*/
} }
@@ -65,11 +65,11 @@ public class UITagExampleTest {
final HtmlSubmitInput button = form.getInputByValue("Submit"); final HtmlSubmitInput button = form.getInputByValue("Submit");
final HtmlPage page2 = button.click(); final HtmlPage page2 = button.click();
Assert.assertEquals("name", page2.getElementById("name").asText()); Assert.assertEquals("name", page2.getElementById("name").asNormalizedText());
Assert.assertEquals("bio", page2.getElementById("bio").asText()); Assert.assertEquals("bio", page2.getElementById("bio").asNormalizedText());
Assert.assertEquals("Red", page2.getElementById("favouriteColor").asText()); Assert.assertEquals("Red", page2.getElementById("favouriteColor").asNormalizedText());
Assert.assertEquals("[Patrick, Jason]", page2.getElementById("friends").asText()); Assert.assertEquals("[Patrick, Jason]", page2.getElementById("friends").asNormalizedText());
Assert.assertEquals("true", page2.getElementById("legalAge").asText()); Assert.assertEquals("true", page2.getElementById("legalAge").asNormalizedText());
} }
} }
} }
@@ -47,7 +47,7 @@ public class ValidationTest {
final HtmlSubmitInput button = form.getInputByValue("Submit"); final HtmlSubmitInput button = form.getInputByValue("Submit");
final HtmlPage page2 = button.click(); final HtmlPage page2 = button.click();
final String page2Text = page2.asText(); final String page2Text = page2.asNormalizedText();
Assert.assertTrue(page2Text.contains("Invalid field value for field \"dateValidatorField\"")); Assert.assertTrue(page2Text.contains("Invalid field value for field \"dateValidatorField\""));
Assert.assertTrue(page2Text.contains("Invalid field value for field \"integerValidatorField\"")); Assert.assertTrue(page2Text.contains("Invalid field value for field \"integerValidatorField\""));
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId> <artifactId>struts2-parent</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-assembly</artifactId> <artifactId>struts2-assembly</artifactId>
+3 -3
View File
@@ -29,7 +29,7 @@
</parent> </parent>
<artifactId>struts2-bom</artifactId> <artifactId>struts2-bom</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>Struts 2 Bill of Materials</name> <name>Struts 2 Bill of Materials</name>
@@ -44,7 +44,7 @@
</licenses> </licenses>
<properties> <properties>
<struts-version.version>6.0.0-SNAPSHOT</struts-version.version> <struts-version.version>6.0.0</struts-version.version>
<maven.site.skip>true</maven.site.skip> <maven.site.skip>true</maven.site.skip>
<maven.site.deploy.skip>true</maven.site.deploy.skip> <maven.site.deploy.skip>true</maven.site.deploy.skip>
</properties> </properties>
@@ -175,7 +175,7 @@
</dependencyManagement> </dependencyManagement>
<scm> <scm>
<tag>HEAD</tag> <tag>STRUTS_6_0_0</tag>
<connection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</connection> <connection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</connection>
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</developerConnection> <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</developerConnection>
<url>https://github.com/apache/struts/</url> <url>https://github.com/apache/struts/</url>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-osgi-bundles</artifactId> <artifactId>struts2-osgi-bundles</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-osgi-admin-bundle</artifactId> <artifactId>struts2-osgi-admin-bundle</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-osgi-bundles</artifactId> <artifactId>struts2-osgi-bundles</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-osgi-demo-bundle</artifactId> <artifactId>struts2-osgi-demo-bundle</artifactId>
+2 -4
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId> <artifactId>struts2-parent</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-osgi-bundles</artifactId> <artifactId>struts2-osgi-bundles</artifactId>
@@ -53,12 +53,10 @@
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
</dependencies> </dependencies>
<reporting> <reporting>
+12 -11
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId> <artifactId>struts2-parent</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-core</artifactId> <artifactId>struts2-core</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
@@ -188,7 +188,7 @@
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
@@ -242,6 +242,16 @@
<artifactId>spring-web</artifactId> <artifactId>spring-web</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
@@ -345,15 +355,6 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
This is only necessary in tests-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>commons-validator</groupId> <groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId> <artifactId>commons-validator</artifactId>
@@ -244,7 +244,6 @@ public class StrutsDefaultConfigurationProvider implements ConfigurationProvider
props.setProperty(StrutsConstants.STRUTS_OGNL_ENABLE_EXPRESSION_CACHE, Boolean.TRUE.toString()); props.setProperty(StrutsConstants.STRUTS_OGNL_ENABLE_EXPRESSION_CACHE, Boolean.TRUE.toString());
props.setProperty(StrutsConstants.STRUTS_OGNL_ENABLE_EVAL_EXPRESSION, Boolean.FALSE.toString()); props.setProperty(StrutsConstants.STRUTS_OGNL_ENABLE_EVAL_EXPRESSION, Boolean.FALSE.toString());
props.setProperty(StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD, Boolean.FALSE.toString()); props.setProperty(StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD, Boolean.FALSE.toString());
props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS, Boolean.FALSE.toString());
props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS, Boolean.TRUE.toString()); props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS, Boolean.TRUE.toString());
props.setProperty(StrutsConstants.STRUTS_MATCHER_APPEND_NAMED_PARAMETERS, Boolean.TRUE.toString()); props.setProperty(StrutsConstants.STRUTS_MATCHER_APPEND_NAMED_PARAMETERS, Boolean.TRUE.toString());
} }
@@ -18,28 +18,36 @@
*/ */
package com.opensymphony.xwork2.conversion.impl; package com.opensymphony.xwork2.conversion.impl;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.conversion.TypeConversionException;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.util.ValueStack;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.TemporalAccessor;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.conversion.TypeConversionException;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.util.ValueStack;
public class DateConverter extends DefaultTypeConverter { public class DateConverter extends DefaultTypeConverter {
private final static Logger LOG = LogManager.getLogger(DateConverter.class); private final static Logger LOG = LogManager.getLogger(DateConverter.class);
@Override @Override
public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName, Object value, Class toType) { public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName,
Object value, Class toType) {
Date result = null; Date result = null;
if (value instanceof String && ((String) value).length() > 0) { if (value instanceof String && ((String) value).length() > 0) {
@@ -52,15 +60,12 @@ public class DateConverter extends DefaultTypeConverter {
} else if (java.sql.Timestamp.class == toType) { } else if (java.sql.Timestamp.class == toType) {
Date check = null; Date check = null;
SimpleDateFormat dtfmt = (SimpleDateFormat) DateFormat.getDateTimeInstance(DateFormat.SHORT, SimpleDateFormat dtfmt = (SimpleDateFormat) DateFormat.getDateTimeInstance(DateFormat.SHORT,
DateFormat.MEDIUM, DateFormat.MEDIUM, locale);
locale); SimpleDateFormat fullfmt = new SimpleDateFormat(dtfmt.toPattern() + MILLISECOND_FORMAT, locale);
SimpleDateFormat fullfmt = new SimpleDateFormat(dtfmt.toPattern() + MILLISECOND_FORMAT,
locale);
SimpleDateFormat dfmt = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, SimpleDateFormat dfmt = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale);
locale);
SimpleDateFormat[] fmts = {fullfmt, dtfmt, dfmt}; SimpleDateFormat[] fmts = { fullfmt, dtfmt, dfmt };
for (SimpleDateFormat fmt : fmts) { for (SimpleDateFormat fmt : fmts) {
try { try {
check = fmt.parse(sa); check = fmt.parse(sa);
@@ -85,8 +90,39 @@ public class DateConverter extends DefaultTypeConverter {
} catch (ParseException ignore) { } catch (ParseException ignore) {
} }
} }
} else if (java.time.LocalDateTime.class == toType || java.time.LocalDate.class == toType
|| java.time.LocalTime.class == toType) {
DateTimeFormatter dtf = null;
TemporalAccessor check = null;
DateTimeFormatter[] dfs = getDateTimeFormats(ActionContext.of(context), locale);
for (DateTimeFormatter df1 : dfs) {
try {
check = df1.parseBest(sa, LocalDateTime::from, LocalDate::from, LocalTime::from);
dtf = df1;
if (check != null) {
break;
}
} catch (DateTimeParseException ignore) {
}
}
try {
if (dtf != null && check instanceof LocalDateTime) {
return LocalDateTime.parse(sa, dtf);
} else if (dtf != null && check instanceof LocalDate) {
return LocalDate.parse(sa, dtf);
} else if (dtf != null && check instanceof LocalTime) {
return LocalTime.parse(sa, dtf);
} else {
throw new TypeConversionException("Could not parse date");
}
} catch (DateTimeParseException e) {
throw new TypeConversionException("Could not parse date", e);
}
} }
//final fallback for dates without time
// final fallback for dates without time
if (df == null) { if (df == null) {
df = DateFormat.getDateInstance(DateFormat.SHORT, locale); df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
} }
@@ -95,15 +131,17 @@ public class DateConverter extends DefaultTypeConverter {
result = df.parse(sa); result = df.parse(sa);
if (!(Date.class == toType)) { if (!(Date.class == toType)) {
try { try {
Constructor<?> constructor = toType.getConstructor(new Class[]{long.class}); Constructor<?> constructor = toType.getConstructor(new Class[] { long.class });
return constructor.newInstance(new Object[]{Long.valueOf(result.getTime())}); return constructor.newInstance(new Object[] { Long.valueOf(result.getTime()) });
} catch (Exception e) { } catch (Exception e) {
throw new TypeConversionException("Couldn't create class " + toType + " using default (long) constructor", e); throw new TypeConversionException(
"Couldn't create class " + toType + " using default (long) constructor", e);
} }
} }
} catch (ParseException e) { } catch (ParseException e) {
throw new TypeConversionException("Could not parse date", e); throw new TypeConversionException("Could not parse date", e);
} }
} else if (Date.class.isAssignableFrom(value.getClass())) { } else if (Date.class.isAssignableFrom(value.getClass())) {
result = (Date) value; result = (Date) value;
} }
@@ -111,16 +149,16 @@ public class DateConverter extends DefaultTypeConverter {
} }
/** /**
* The user defined global date format, * The user defined global date format, see
* see {@link org.apache.struts2.components.Date#DATETAG_PROPERTY} * {@link org.apache.struts2.components.Date#DATETAG_PROPERTY}
* *
* @param context current ActionContext * @param context current ActionContext
* @param locale current Locale to convert to *
* @return defined global format * @return defined global date string format
*/ */
protected DateFormat getGlobalDateFormat(ActionContext context, Locale locale) { protected String getGlobalDateString(ActionContext context) {
final String dateTagProperty = org.apache.struts2.components.Date.DATETAG_PROPERTY; final String dateTagProperty = org.apache.struts2.components.Date.DATETAG_PROPERTY;
SimpleDateFormat globalDateFormat = null; String globalDateString = null;
final TextProvider tp = findProviderInStack(context.getValueStack()); final TextProvider tp = findProviderInStack(context.getValueStack());
@@ -130,23 +168,28 @@ public class DateConverter extends DefaultTypeConverter {
// is the same as input = DATETAG_PROPERTY // is the same as input = DATETAG_PROPERTY
if (globalFormat != null && !dateTagProperty.equals(globalFormat)) { if (globalFormat != null && !dateTagProperty.equals(globalFormat)) {
LOG.debug("Found \"{}\" as \"{}\"", dateTagProperty, globalFormat); LOG.debug("Found \"{}\" as \"{}\"", dateTagProperty, globalFormat);
globalDateFormat = new SimpleDateFormat(globalFormat, locale); globalDateString = globalFormat;
} else { } else {
LOG.debug("\"{}\" has not been defined, ignoring it", dateTagProperty); LOG.debug("\"{}\" has not been defined, ignoring it", dateTagProperty);
} }
} }
return globalDateFormat; return globalDateString;
} }
/** /**
* Retrieves the list of date formats to be used when converting dates * Retrieves the list of date formats to be used when converting dates
*
* @param context the current ActionContext * @param context the current ActionContext
* @param locale the current locale of the action * @param locale the current locale of the action
* @return a list of DateFormat to be used for date conversion * @return a list of DateFormat to be used for date conversion
*/ */
private DateFormat[] getDateFormats(ActionContext context, Locale locale) { private DateFormat[] getDateFormats(ActionContext context, Locale locale) {
DateFormat globalDateFormat = getGlobalDateFormat(context, locale); DateFormat globalDateFormat = null;
String globalFormat = getGlobalDateString(context);
if (globalFormat != null) {
globalDateFormat = new SimpleDateFormat(globalFormat, locale);
}
DateFormat dt1 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, locale); DateFormat dt1 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, locale);
DateFormat dt2 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, locale); DateFormat dt2 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, locale);
@@ -156,15 +199,46 @@ public class DateConverter extends DefaultTypeConverter {
DateFormat d2 = DateFormat.getDateInstance(DateFormat.MEDIUM, locale); DateFormat d2 = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
DateFormat d3 = DateFormat.getDateInstance(DateFormat.LONG, locale); DateFormat d3 = DateFormat.getDateInstance(DateFormat.LONG, locale);
DateFormat rfc3339 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); DateFormat rfc3339 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
DateFormat rfc3339dateOnly = new SimpleDateFormat("yyyy-MM-dd"); DateFormat rfc3339dateOnly = new SimpleDateFormat("yyyy-MM-dd");
final DateFormat[] dateFormats; final DateFormat[] dateFormats;
if (globalDateFormat == null) { if (globalDateFormat == null) {
dateFormats = new DateFormat[]{dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly}; dateFormats = new DateFormat[] { dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly };
} else { } else {
dateFormats = new DateFormat[]{globalDateFormat, dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly}; dateFormats = new DateFormat[] { globalDateFormat, dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly };
}
return dateFormats;
}
/**
* Retrieves the list of date time formats to be used when converting dates
*
* @param context the current ActionContext
* @param locale the current locale of the action
*
* @return a list of DateTimeFormatter to be used for date conversion
*/
protected DateTimeFormatter[] getDateTimeFormats(ActionContext context, Locale locale) {
DateTimeFormatter globalDateFormat = null;
String globalFormat = getGlobalDateString(context);
if (globalFormat != null) {
globalDateFormat = DateTimeFormatter.ofPattern(globalFormat, locale);
}
DateTimeFormatter df1 = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
DateTimeFormatter df2 = DateTimeFormatter.ISO_LOCAL_DATE;
DateTimeFormatter df3 = DateTimeFormatter.ISO_LOCAL_TIME;
final DateTimeFormatter[] dateFormats;
if (globalDateFormat == null) {
dateFormats = new DateTimeFormatter[] { df1, df2, df3 };
} else {
dateFormats = new DateTimeFormatter[] { globalDateFormat, df1, df2, df3 };
} }
return dateFormats; return dateFormats;
@@ -25,6 +25,7 @@ import com.opensymphony.xwork2.inject.Inject;
import org.apache.struts2.StrutsConstants; import org.apache.struts2.StrutsConstants;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.time.LocalDateTime;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
@@ -99,6 +100,8 @@ public class XWorkBasicConverter extends DefaultTypeConverter {
result = doConvertToArray(context, o, member, propertyName, value, toType); result = doConvertToArray(context, o, member, propertyName, value, toType);
} else if (Date.class.isAssignableFrom(toType)) { } else if (Date.class.isAssignableFrom(toType)) {
result = doConvertToDate(context, value, toType); result = doConvertToDate(context, value, toType);
} else if (LocalDateTime.class.isAssignableFrom(toType)) {
result = doConvertToDate(context, value, toType);
} else if (Calendar.class.isAssignableFrom(toType)) { } else if (Calendar.class.isAssignableFrom(toType)) {
result = doConvertToCalendar(context, value); result = doConvertToCalendar(context, value);
} else if (Collection.class.isAssignableFrom(toType)) { } else if (Collection.class.isAssignableFrom(toType)) {
@@ -201,7 +201,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
ReflectionContextState.setReportingConversionErrors(context, true); ReflectionContextState.setReportingConversionErrors(context, true);
//keep locale from original context //keep locale from original context
newStack.getActionContext().withLocale(stack.getActionContext().getLocale()); newStack.getActionContext().withLocale(stack.getActionContext().getLocale()).withValueStack(stack);
} }
boolean memberAccessStack = newStack instanceof MemberAccessValueStack; boolean memberAccessStack = newStack instanceof MemberAccessValueStack;
@@ -73,7 +73,6 @@ public class OgnlUtil {
private Container container; private Container container;
private boolean allowStaticFieldAccess = true; private boolean allowStaticFieldAccess = true;
private boolean allowStaticMethodAccess;
private boolean disallowProxyMemberAccess; private boolean disallowProxyMemberAccess;
/** /**
@@ -250,11 +249,6 @@ public class OgnlUtil {
this.allowStaticFieldAccess = BooleanUtils.toBoolean(allowStaticFieldAccess); this.allowStaticFieldAccess = BooleanUtils.toBoolean(allowStaticFieldAccess);
} }
@Inject(value = StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS, required = false)
protected void setAllowStaticMethodAccess(String allowStaticMethodAccess) {
this.allowStaticMethodAccess = BooleanUtils.toBoolean(allowStaticMethodAccess);
}
@Inject(value = StrutsConstants.STRUTS_DISALLOW_PROXY_MEMBER_ACCESS, required = false) @Inject(value = StrutsConstants.STRUTS_DISALLOW_PROXY_MEMBER_ACCESS, required = false)
protected void setDisallowProxyMemberAccess(String disallowProxyMemberAccess) { protected void setDisallowProxyMemberAccess(String disallowProxyMemberAccess) {
this.disallowProxyMemberAccess = BooleanUtils.toBoolean(disallowProxyMemberAccess); this.disallowProxyMemberAccess = BooleanUtils.toBoolean(disallowProxyMemberAccess);
@@ -836,7 +830,7 @@ public class OgnlUtil {
resolver = container.getInstance(CompoundRootAccessor.class); resolver = container.getInstance(CompoundRootAccessor.class);
} }
SecurityMemberAccess memberAccess = new SecurityMemberAccess(allowStaticMethodAccess, allowStaticFieldAccess); SecurityMemberAccess memberAccess = new SecurityMemberAccess(allowStaticFieldAccess);
memberAccess.setDisallowProxyMemberAccess(disallowProxyMemberAccess); memberAccess.setDisallowProxyMemberAccess(disallowProxyMemberAccess);
if (devMode) { if (devMode) {
@@ -72,13 +72,13 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
private boolean devMode; private boolean devMode;
private boolean logMissingProperties; private boolean logMissingProperties;
protected OgnlValueStack(XWorkConverter xworkConverter, CompoundRootAccessor accessor, TextProvider prov, boolean allowStaticMethodAccess, boolean allowStaticFieldAccess) { protected OgnlValueStack(XWorkConverter xworkConverter, CompoundRootAccessor accessor, TextProvider prov, boolean allowStaticFieldAccess) {
setRoot(xworkConverter, accessor, new CompoundRoot(), allowStaticMethodAccess, allowStaticFieldAccess); setRoot(xworkConverter, accessor, new CompoundRoot(), allowStaticFieldAccess);
push(prov); push(prov);
} }
protected OgnlValueStack(ValueStack vs, XWorkConverter xworkConverter, CompoundRootAccessor accessor, boolean allowStaticMethodAccess, boolean allowStaticFieldAccess) { protected OgnlValueStack(ValueStack vs, XWorkConverter xworkConverter, CompoundRootAccessor accessor, boolean allowStaticFieldAccess) {
setRoot(xworkConverter, accessor, new CompoundRoot(vs.getRoot()), allowStaticMethodAccess, allowStaticFieldAccess); setRoot(xworkConverter, accessor, new CompoundRoot(vs.getRoot()), allowStaticFieldAccess);
} }
@Inject @Inject
@@ -90,10 +90,9 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
securityMemberAccess.setDisallowProxyMemberAccess(ognlUtil.isDisallowProxyMemberAccess()); securityMemberAccess.setDisallowProxyMemberAccess(ognlUtil.isDisallowProxyMemberAccess());
} }
protected void setRoot(XWorkConverter xworkConverter, CompoundRootAccessor accessor, CompoundRoot compoundRoot, protected void setRoot(XWorkConverter xworkConverter, CompoundRootAccessor accessor, CompoundRoot compoundRoot, boolean allowStaticFieldAccess) {
boolean allowStaticMethodAccess, boolean allowStaticFieldAccess) {
this.root = compoundRoot; this.root = compoundRoot;
this.securityMemberAccess = new SecurityMemberAccess(allowStaticMethodAccess, allowStaticFieldAccess); this.securityMemberAccess = new SecurityMemberAccess(allowStaticFieldAccess);
this.context = Ognl.createDefaultContext(this.root, securityMemberAccess, accessor, new OgnlTypeConverterWrapper(xworkConverter)); this.context = Ognl.createDefaultContext(this.root, securityMemberAccess, accessor, new OgnlTypeConverterWrapper(xworkConverter));
context.put(VALUE_STACK, this); context.put(VALUE_STACK, this);
((OgnlContext) context).setTraceEvaluations(false); ((OgnlContext) context).setTraceEvaluations(false);
@@ -219,7 +218,7 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
if (shouldLog) { if (shouldLog) {
LOG.warn(msg, e); LOG.warn(msg, e);
} }
if (throwExceptionOnFailure) { if (throwExceptionOnFailure) {
throw new StrutsException(msg, e); throw new StrutsException(msg, e);
} }
@@ -462,11 +461,10 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
XWorkConverter xworkConverter = cont.getInstance(XWorkConverter.class); XWorkConverter xworkConverter = cont.getInstance(XWorkConverter.class);
CompoundRootAccessor accessor = (CompoundRootAccessor) cont.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()); CompoundRootAccessor accessor = (CompoundRootAccessor) cont.getInstance(PropertyAccessor.class, CompoundRoot.class.getName());
TextProvider prov = cont.getInstance(TextProvider.class, "system"); TextProvider prov = cont.getInstance(TextProvider.class, "system");
final boolean allowStaticMethod = BooleanUtils.toBoolean(cont.getInstance(String.class, StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS));
final boolean allowStaticField = BooleanUtils.toBoolean(cont.getInstance(String.class, StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS)); final boolean allowStaticField = BooleanUtils.toBoolean(cont.getInstance(String.class, StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS));
OgnlValueStack aStack = new OgnlValueStack(xworkConverter, accessor, prov, allowStaticMethod, allowStaticField); OgnlValueStack aStack = new OgnlValueStack(xworkConverter, accessor, prov, allowStaticField);
aStack.setOgnlUtil(cont.getInstance(OgnlUtil.class)); aStack.setOgnlUtil(cont.getInstance(OgnlUtil.class));
aStack.setRoot(xworkConverter, accessor, this.root, allowStaticMethod, allowStaticField); aStack.setRoot(xworkConverter, accessor, this.root, allowStaticField);
return aStack; return aStack;
} }
@@ -43,8 +43,6 @@ import java.util.Set;
*/ */
public class OgnlValueStackFactory implements ValueStackFactory { public class OgnlValueStackFactory implements ValueStackFactory {
private static final Logger LOG = LogManager.getLogger(OgnlValueStackFactory.class);
protected XWorkConverter xworkConverter; protected XWorkConverter xworkConverter;
protected CompoundRootAccessor compoundRootAccessor; protected CompoundRootAccessor compoundRootAccessor;
protected TextProvider textProvider; protected TextProvider textProvider;
@@ -61,8 +59,7 @@ public class OgnlValueStackFactory implements ValueStackFactory {
} }
public ValueStack createValueStack() { public ValueStack createValueStack() {
ValueStack stack = new OgnlValueStack(xworkConverter, compoundRootAccessor, textProvider, ValueStack stack = new OgnlValueStack(xworkConverter, compoundRootAccessor, textProvider, containerAllowsStaticFieldAccess());
containerAllowsStaticMethodAccess(), containerAllowsStaticFieldAccess());
container.inject(stack); container.inject(stack);
return stack.getActionContext() return stack.getActionContext()
.withContainer(container) .withContainer(container)
@@ -71,8 +68,7 @@ public class OgnlValueStackFactory implements ValueStackFactory {
} }
public ValueStack createValueStack(ValueStack stack) { public ValueStack createValueStack(ValueStack stack) {
ValueStack result = new OgnlValueStack(stack, xworkConverter, compoundRootAccessor, ValueStack result = new OgnlValueStack(stack, xworkConverter, compoundRootAccessor, containerAllowsStaticFieldAccess());
containerAllowsStaticMethodAccess(), containerAllowsStaticFieldAccess());
container.inject(result); container.inject(result);
return result.getActionContext() return result.getActionContext()
.withContainer(container) .withContainer(container)
@@ -84,32 +80,23 @@ public class OgnlValueStackFactory implements ValueStackFactory {
protected void setContainer(Container container) throws ClassNotFoundException { protected void setContainer(Container container) throws ClassNotFoundException {
Set<String> names = container.getInstanceNames(PropertyAccessor.class); Set<String> names = container.getInstanceNames(PropertyAccessor.class);
for (String name : names) { for (String name : names) {
Class cls = Class.forName(name); Class<?> cls = Class.forName(name);
if (cls != null) { OgnlRuntime.setPropertyAccessor(cls, container.getInstance(PropertyAccessor.class, name));
if (Map.class.isAssignableFrom(cls)) { if (compoundRootAccessor == null && CompoundRoot.class.isAssignableFrom(cls)) {
PropertyAccessor acc = container.getInstance(PropertyAccessor.class, name); compoundRootAccessor = (CompoundRootAccessor) container.getInstance(PropertyAccessor.class, name);
}
OgnlRuntime.setPropertyAccessor(cls, container.getInstance(PropertyAccessor.class, name));
if (compoundRootAccessor == null && CompoundRoot.class.isAssignableFrom(cls)) {
compoundRootAccessor = (CompoundRootAccessor) container.getInstance(PropertyAccessor.class, name);
}
} }
} }
names = container.getInstanceNames(MethodAccessor.class); names = container.getInstanceNames(MethodAccessor.class);
for (String name : names) { for (String name : names) {
Class cls = Class.forName(name); Class<?> cls = Class.forName(name);
if (cls != null) { OgnlRuntime.setMethodAccessor(cls, container.getInstance(MethodAccessor.class, name));
OgnlRuntime.setMethodAccessor(cls, container.getInstance(MethodAccessor.class, name));
}
} }
names = container.getInstanceNames(NullHandler.class); names = container.getInstanceNames(NullHandler.class);
for (String name : names) { for (String name : names) {
Class cls = Class.forName(name); Class<?> cls = Class.forName(name);
if (cls != null) { OgnlRuntime.setNullHandler(cls, new OgnlNullHandlerWrapper(container.getInstance(NullHandler.class, name)));
OgnlRuntime.setNullHandler(cls, new OgnlNullHandlerWrapper(container.getInstance(NullHandler.class, name)));
}
} }
if (compoundRootAccessor == null) { if (compoundRootAccessor == null) {
throw new IllegalStateException("Couldn't find the compound root accessor"); throw new IllegalStateException("Couldn't find the compound root accessor");
@@ -117,19 +104,8 @@ public class OgnlValueStackFactory implements ValueStackFactory {
this.container = container; this.container = container;
} }
/**
* Retrieve allowsStaticMethodAccess state from the container (allows for lazy fetching)
*
* @return
*/
protected boolean containerAllowsStaticMethodAccess() {
return BooleanUtils.toBoolean(container.getInstance(String.class, StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS));
}
/** /**
* Retrieve allowStaticFieldAccess state from the container (allows for lazy fetching) * Retrieve allowStaticFieldAccess state from the container (allows for lazy fetching)
*
* @return
*/ */
protected boolean containerAllowsStaticFieldAccess() { protected boolean containerAllowsStaticFieldAccess() {
return BooleanUtils.toBoolean(container.getInstance(String.class, StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS)); return BooleanUtils.toBoolean(container.getInstance(String.class, StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS));
@@ -42,7 +42,6 @@ public class SecurityMemberAccess implements MemberAccess {
private static final Logger LOG = LogManager.getLogger(SecurityMemberAccess.class); private static final Logger LOG = LogManager.getLogger(SecurityMemberAccess.class);
private final boolean allowStaticFieldAccess; private final boolean allowStaticFieldAccess;
private final boolean allowStaticMethodAccess;
private Set<Pattern> excludeProperties = Collections.emptySet(); private Set<Pattern> excludeProperties = Collections.emptySet();
private Set<Pattern> acceptProperties = Collections.emptySet(); private Set<Pattern> acceptProperties = Collections.emptySet();
private Set<Class<?>> excludedClasses = Collections.emptySet(); private Set<Class<?>> excludedClasses = Collections.emptySet();
@@ -52,25 +51,15 @@ public class SecurityMemberAccess implements MemberAccess {
/** /**
* SecurityMemberAccess * SecurityMemberAccess
* - access decisions based on whether member is static (or not) * - access decisions based on whether member is static (or not)
* - block or allow access to properties (configurable-after-construction) * - block or allow access to properties (configurable-after-construction)
* *
* @param allowStaticMethodAccess * @param allowStaticFieldAccess if set to true static fields (constants) will be accessible
* @param allowStaticFieldAccess
*/ */
public SecurityMemberAccess(boolean allowStaticMethodAccess, boolean allowStaticFieldAccess) { public SecurityMemberAccess(boolean allowStaticFieldAccess) {
this.allowStaticMethodAccess = allowStaticMethodAccess;
this.allowStaticFieldAccess = allowStaticFieldAccess; this.allowStaticFieldAccess = allowStaticFieldAccess;
} }
public final boolean getAllowStaticMethodAccess() {
return allowStaticMethodAccess;
}
public final boolean getAllowStaticFieldAccess() {
return allowStaticFieldAccess;
}
@Override @Override
public Object setup(Map context, Object target, Member member, String propertyName) { public Object setup(Map context, Object target, Member member, String propertyName) {
Object result = null; Object result = null;
@@ -90,13 +79,12 @@ public class SecurityMemberAccess implements MemberAccess {
public void restore(Map context, Object target, Member member, String propertyName, Object state) { public void restore(Map context, Object target, Member member, String propertyName, Object state) {
if (state != null) { if (state != null) {
final AccessibleObject accessible = (AccessibleObject) member; final AccessibleObject accessible = (AccessibleObject) member;
final boolean stateboolean = ((Boolean) state).booleanValue(); // Using twice (avoid unboxing) final boolean stateBoolean = ((Boolean) state).booleanValue(); // Using twice (avoid unboxing)
if (!stateboolean) { if (!stateBoolean) {
accessible.setAccessible(stateboolean); accessible.setAccessible(stateBoolean);
} } else {
else { throw new IllegalArgumentException("Improper restore state [" + stateBoolean + "] for target [" + target +
throw new IllegalArgumentException("Improper restore state [" + stateboolean + "] for target [" + target + "], member [" + member + "], propertyName [" + propertyName + "]");
"], member [" + member + "], propertyName [" + propertyName + "]");
} }
} }
} }
@@ -117,6 +105,7 @@ public class SecurityMemberAccess implements MemberAccess {
return false; return false;
} }
// it needs to be before calling #checkStaticMethodAccess()
if (checkEnumAccess(target, member)) { if (checkEnumAccess(target, member)) {
LOG.trace("Allowing access to enum: target [{}], member [{}]", target, member); LOG.trace("Allowing access to enum: target [{}], member [{}]", target, member);
return true; return true;
@@ -127,7 +116,7 @@ public class SecurityMemberAccess implements MemberAccess {
return false; return false;
} }
final Class memberClass = member.getDeclaringClass(); final Class<?> memberClass = member.getDeclaringClass();
if (isClassExcluded(memberClass)) { if (isClassExcluded(memberClass)) {
LOG.warn("Declaring class of member type [{}] is excluded!", member); LOG.warn("Declaring class of member type [{}] is excluded!", member);
@@ -135,11 +124,11 @@ public class SecurityMemberAccess implements MemberAccess {
} }
// target can be null in case of accessing static fields, since OGNL 3.2.8 // target can be null in case of accessing static fields, since OGNL 3.2.8
final Class targetClass = Modifier.isStatic(memberModifiers) ? memberClass : target.getClass(); final Class<?> targetClass = Modifier.isStatic(memberModifiers) ? memberClass : target.getClass();
if (isPackageExcluded(targetClass.getPackage(), memberClass.getPackage())) { if (isPackageExcluded(targetClass.getPackage(), memberClass.getPackage())) {
LOG.warn("Package [{}] of target class [{}] of target [{}] or package [{}] of member [{}] are excluded!", targetClass.getPackage(), targetClass, LOG.warn("Package [{}] of target class [{}] of target [{}] or package [{}] of member [{}] are excluded!", targetClass.getPackage(), targetClass,
target, memberClass.getPackage(), member); target, memberClass.getPackage(), member);
return false; return false;
} }
@@ -158,33 +147,25 @@ public class SecurityMemberAccess implements MemberAccess {
/** /**
* Check access for static method (via modifiers). * Check access for static method (via modifiers).
* *
* Note: For non-static members, the result is always true. * Note: For non-static members, the result is always true.
* *
* @param member * @param member
* @param memberModifiers * @param memberModifiers
* *
* @return * @return
*/ */
protected boolean checkStaticMethodAccess(Member member, int memberModifiers) { protected boolean checkStaticMethodAccess(Member member, int memberModifiers) {
if (Modifier.isStatic(memberModifiers) && !(member instanceof Field)) { return !Modifier.isStatic(memberModifiers) || member instanceof Field;
if (allowStaticMethodAccess) {
LOG.debug("Support for accessing static methods [member: {}] is deprecated!", member);
}
return allowStaticMethodAccess;
} else {
return true;
}
} }
/** /**
* Check access for static field (via modifiers). * Check access for static field (via modifiers).
* * <p>
* Note: For non-static members, the result is always true. * Note: For non-static members, the result is always true.
* *
* @param member * @param member
* @param memberModifiers * @param memberModifiers
*
* @return * @return
*/ */
protected boolean checkStaticFieldAccess(Member member, int memberModifiers) { protected boolean checkStaticFieldAccess(Member member, int memberModifiers) {
@@ -195,13 +176,12 @@ public class SecurityMemberAccess implements MemberAccess {
} }
} }
/** /**
* Check access for public members (via modifiers) * Check access for public members (via modifiers)
* * <p>
* Returns true if-and-only-if the member is public. * Returns true if-and-only-if the member is public.
* *
* @param memberModifiers * @param memberModifiers
*
* @return * @return
*/ */
protected boolean checkPublicMemberAccess(int memberModifiers) { protected boolean checkPublicMemberAccess(int memberModifiers) {
@@ -210,10 +190,8 @@ public class SecurityMemberAccess implements MemberAccess {
protected boolean checkEnumAccess(Object target, Member member) { protected boolean checkEnumAccess(Object target, Member member) {
if (target instanceof Class) { if (target instanceof Class) {
final Class clazz = (Class) target; final Class<?> clazz = (Class<?>) target;
if (Enum.class.isAssignableFrom(clazz) && member.getName().equals("values")) { return Enum.class.isAssignableFrom(clazz) && member.getName().equals("values");
return true;
}
} }
return false; return false;
} }
@@ -222,7 +200,7 @@ public class SecurityMemberAccess implements MemberAccess {
if (targetPackage == null || memberPackage == null) { if (targetPackage == null || memberPackage == null) {
LOG.warn("The use of the default (unnamed) package is discouraged!"); LOG.warn("The use of the default (unnamed) package is discouraged!");
} }
String targetPackageName = targetPackage == null ? "" : targetPackage.getName(); String targetPackageName = targetPackage == null ? "" : targetPackage.getName();
String memberPackageName = memberPackage == null ? "" : memberPackage.getName(); String memberPackageName = memberPackage == null ? "" : memberPackage.getName();
@@ -235,7 +213,7 @@ public class SecurityMemberAccess implements MemberAccess {
targetPackageName = targetPackageName + "."; targetPackageName = targetPackageName + ".";
memberPackageName = memberPackageName + "."; memberPackageName = memberPackageName + ".";
for (String packageName: excludedPackageNames) { for (String packageName : excludedPackageNames) {
if (targetPackageName.startsWith(packageName) || memberPackageName.startsWith(packageName)) { if (targetPackageName.startsWith(packageName) || memberPackageName.startsWith(packageName)) {
return true; return true;
} }
@@ -245,7 +223,7 @@ public class SecurityMemberAccess implements MemberAccess {
} }
protected boolean isClassExcluded(Class<?> clazz) { protected boolean isClassExcluded(Class<?> clazz) {
if (clazz == Object.class || (clazz == Class.class && !allowStaticMethodAccess)) { if (clazz == Object.class || (clazz == Class.class && !allowStaticFieldAccess)) {
return true; return true;
} }
for (Class<?> excludedClass : excludedClasses) { for (Class<?> excludedClass : excludedClasses) {
@@ -36,7 +36,7 @@ import java.util.Map;
* @author tmjee * @author tmjee
*/ */
public class XWorkMethodAccessor extends ObjectMethodAccessor { public class XWorkMethodAccessor extends ObjectMethodAccessor {
private static final Logger LOG = LogManager.getLogger(XWorkMethodAccessor.class); private static final Logger LOG = LogManager.getLogger(XWorkMethodAccessor.class);
@Override @Override
@@ -58,9 +58,9 @@ public class XWorkMethodAccessor extends ObjectMethodAccessor {
//so that property strings are not cleared //so that property strings are not cleared
//i.e. OgnlUtil should be used initially, OgnlRuntime //i.e. OgnlUtil should be used initially, OgnlRuntime
//thereafter //thereafter
Object propVal=OgnlRuntime.getProperty(ogContext, object, string); Object propVal=OgnlRuntime.getProperty(ogContext, object, string);
//use the Collection property accessor instead of the individual property accessor, because //use the Collection property accessor instead of the individual property accessor, because
//in the case of Lists otherwise the index property could be used //in the case of Lists otherwise the index property could be used
PropertyAccessor accessor=OgnlRuntime.getPropertyAccessor(Collection.class); PropertyAccessor accessor=OgnlRuntime.getPropertyAccessor(Collection.class);
ReflectionContextState.setGettingByKeyProperty(ogContext,true); ReflectionContextState.setGettingByKeyProperty(ogContext,true);
@@ -83,8 +83,8 @@ public class XWorkMethodAccessor extends ObjectMethodAccessor {
return callMethodWithDebugInfo(context, object, string, objects); return callMethodWithDebugInfo(context, object, string, objects);
} }
} }
Boolean exec = (Boolean) context.get(ReflectionContextState.DENY_METHOD_EXECUTION); Boolean exec = ReflectionContextState.isDenyMethodExecution(context);
boolean e = ((exec == null) ? false : exec.booleanValue()); boolean e = (exec != null && exec);
if (!e) { if (!e) {
return callMethodWithDebugInfo(context, object, string, objects); return callMethodWithDebugInfo(context, object, string, objects);
@@ -110,7 +110,7 @@ public class XWorkMethodAccessor extends ObjectMethodAccessor {
@Override @Override
public Object callStaticMethod(Map context, Class aClass, String string, Object[] objects) throws MethodFailedException { public Object callStaticMethod(Map context, Class aClass, String string, Object[] objects) throws MethodFailedException {
Boolean exec = (Boolean) context.get(ReflectionContextState.DENY_METHOD_EXECUTION); Boolean exec = ReflectionContextState.isDenyMethodExecution(context);
boolean e = ((exec == null) ? false : exec.booleanValue()); boolean e = ((exec == null) ? false : exec.booleanValue());
if (!e) { if (!e) {
@@ -226,9 +226,6 @@ public final class StrutsConstants {
/** The name of the parameter to determine whether static field access will be allowed in OGNL expressions or not */ /** The name of the parameter to determine whether static field access will be allowed in OGNL expressions or not */
public static final String STRUTS_ALLOW_STATIC_FIELD_ACCESS = "struts.ognl.allowStaticFieldAccess"; public static final String STRUTS_ALLOW_STATIC_FIELD_ACCESS = "struts.ognl.allowStaticFieldAccess";
/** The name of the parameter to determine whether static method access will be allowed in OGNL expressions or not */
public static final String STRUTS_ALLOW_STATIC_METHOD_ACCESS = "struts.ognl.allowStaticMethodAccess";
/** The com.opensymphony.xwork2.validator.ActionValidatorManager implementation class */ /** The com.opensymphony.xwork2.validator.ActionValidatorManager implementation class */
public static final String STRUTS_ACTIONVALIDATORMANAGER = "struts.actionValidatorManager"; public static final String STRUTS_ACTIONVALIDATORMANAGER = "struts.actionValidatorManager";
@@ -25,6 +25,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.struts2.RequestUtils; import org.apache.struts2.RequestUtils;
import org.apache.struts2.StrutsConstants; import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsException;
import org.apache.struts2.util.FastByteArrayOutputStream; import org.apache.struts2.util.FastByteArrayOutputStream;
import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTag;
import org.apache.struts2.views.annotations.StrutsTagAttribute; import org.apache.struts2.views.annotations.StrutsTagAttribute;
@@ -33,6 +34,7 @@ import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream; import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper; import javax.servlet.http.HttpServletResponseWrapper;
@@ -296,6 +298,19 @@ public class Include extends Component {
buffer = new FastByteArrayOutputStream(); buffer = new FastByteArrayOutputStream();
} }
@Override
public boolean isReady() {
return true;
}
@Override
public void setWriteListener(WriteListener writeListener) {
try {
writeListener.onWritePossible();
} catch (IOException e) {
throw new StrutsException(e);
}
}
/** /**
* Return all data that has been written to this OutputStream. * Return all data that has been written to this OutputStream.
@@ -321,7 +321,7 @@ public class ServletUrlRenderer implements UrlRenderer {
* @param parameters component parameters * @param parameters component parameters
* @param contextParameters request parameters * @param contextParameters request parameters
*/ */
protected void mergeRequestParameters(String value, Map<String, Object> parameters, Map<String, Object> contextParameters) { protected void mergeRequestParameters(String value, Map<String, Object> parameters, Map<String, ?> contextParameters) {
Map<String, Object> mergedParams = new LinkedHashMap<>(contextParameters); Map<String, Object> mergedParams = new LinkedHashMap<>(contextParameters);
@@ -333,7 +333,7 @@ public class ServletUrlRenderer implements UrlRenderer {
String queryString = value.substring(value.indexOf('?') + 1); String queryString = value.substring(value.indexOf('?') + 1);
mergedParams = urlHelper.parseQueryString(queryString, false); mergedParams = urlHelper.parseQueryString(queryString, false);
for (Map.Entry<String, Object> entry : contextParameters.entrySet()) { for (Map.Entry<String, ?> entry : contextParameters.entrySet()) {
if (!mergedParams.containsKey(entry.getKey())) { if (!mergedParams.containsKey(entry.getKey())) {
mergedParams.put(entry.getKey(), entry.getValue()); mergedParams.put(entry.getKey(), entry.getValue());
} }
@@ -90,7 +90,6 @@ public class ConstantConfig {
private BeanConfig localeProviderFactory; private BeanConfig localeProviderFactory;
private String mapperIdParameterName; private String mapperIdParameterName;
private Boolean ognlAllowStaticFieldAccess; private Boolean ognlAllowStaticFieldAccess;
private Boolean ognlAllowStaticMethodAccess;
private BeanConfig actionValidatorManager; private BeanConfig actionValidatorManager;
private BeanConfig valueStackFactory; private BeanConfig valueStackFactory;
private BeanConfig reflectionProvider; private BeanConfig reflectionProvider;
@@ -222,7 +221,6 @@ public class ConstantConfig {
map.put(StrutsConstants.STRUTS_LOCALE_PROVIDER_FACTORY, beanConfToString(localeProviderFactory)); map.put(StrutsConstants.STRUTS_LOCALE_PROVIDER_FACTORY, beanConfToString(localeProviderFactory));
map.put(StrutsConstants.STRUTS_ID_PARAMETER_NAME, mapperIdParameterName); map.put(StrutsConstants.STRUTS_ID_PARAMETER_NAME, mapperIdParameterName);
map.put(StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS, Objects.toString(ognlAllowStaticFieldAccess, null)); map.put(StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS, Objects.toString(ognlAllowStaticFieldAccess, null));
map.put(StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS, Objects.toString(ognlAllowStaticMethodAccess, null));
map.put(StrutsConstants.STRUTS_ACTIONVALIDATORMANAGER, beanConfToString(actionValidatorManager)); map.put(StrutsConstants.STRUTS_ACTIONVALIDATORMANAGER, beanConfToString(actionValidatorManager));
map.put(StrutsConstants.STRUTS_VALUESTACKFACTORY, beanConfToString(valueStackFactory)); map.put(StrutsConstants.STRUTS_VALUESTACKFACTORY, beanConfToString(valueStackFactory));
map.put(StrutsConstants.STRUTS_REFLECTIONPROVIDER, beanConfToString(reflectionProvider)); map.put(StrutsConstants.STRUTS_REFLECTIONPROVIDER, beanConfToString(reflectionProvider));
@@ -810,14 +808,6 @@ public class ConstantConfig {
this.ognlAllowStaticFieldAccess = ognlAllowStaticFieldAccess; this.ognlAllowStaticFieldAccess = ognlAllowStaticFieldAccess;
} }
public Boolean getOgnlAllowStaticMethodAccess() {
return ognlAllowStaticMethodAccess;
}
public void setOgnlAllowStaticMethodAccess(Boolean ognlAllowStaticMethodAccess) {
this.ognlAllowStaticMethodAccess = ognlAllowStaticMethodAccess;
}
public BeanConfig getActionValidatorManager() { public BeanConfig getActionValidatorManager() {
return actionValidatorManager; return actionValidatorManager;
} }
@@ -1,91 +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.util;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* A bean that can be used to format dates
*
* FIXME: remove or use to format Dates
*/
public class DateFormatter {
Date date;
DateFormat format;
// Attributes ----------------------------------------------------
DateFormat parser;
// Public --------------------------------------------------------
public DateFormatter() {
this.parser = new SimpleDateFormat();
this.format = new SimpleDateFormat();
this.date = new Date();
}
public void setDate(String date) {
try {
this.date = parser.parse(date);
} catch (ParseException e) {
throw new IllegalArgumentException(e.getMessage());
}
}
public void setDate(Date date) {
this.date = (date == null) ? null : (Date)date.clone();
}
public void setDate(int date) {
setDate(Integer.toString(date));
}
public Date getDate() {
return this.date;
}
public void setFormat(String format) {
this.format = new SimpleDateFormat(format);
}
public void setFormat(DateFormat format) {
this.format = format;
}
public String getFormattedDate() {
return format.format(date);
}
public void setParseFormat(String format) {
this.parser = new SimpleDateFormat(format);
}
public void setParser(DateFormat parser) {
this.parser = parser;
}
public void setTime(long time) {
date.setTime(time);
}
}
@@ -24,11 +24,13 @@ import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.ValueStack; import com.opensymphony.xwork2.util.ValueStack;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.struts2.StrutsException;
import org.apache.struts2.views.jsp.ui.OgnlTool; import org.apache.struts2.views.jsp.ui.OgnlTool;
import org.apache.struts2.views.util.UrlHelper; import org.apache.struts2.views.util.UrlHelper;
import javax.servlet.RequestDispatcher; import javax.servlet.RequestDispatcher;
import javax.servlet.ServletOutputStream; import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper; import javax.servlet.http.HttpServletResponseWrapper;
@@ -278,6 +280,20 @@ public class StrutsUtil {
public void write(int aByte) { public void write(int aByte) {
writer.write(aByte); writer.write(aByte);
} }
@Override
public boolean isReady() {
return true;
}
@Override
public void setWriteListener(WriteListener writeListener) {
try {
writeListener.onWritePossible();
} catch (IOException e) {
throw new StrutsException(e);
}
}
} }
} }
@@ -19,7 +19,6 @@
package org.apache.struts2.util; package org.apache.struts2.util;
import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionContext;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.views.util.DefaultUrlHelper; import org.apache.struts2.views.util.DefaultUrlHelper;
import org.apache.struts2.views.util.UrlHelper; import org.apache.struts2.views.util.UrlHelper;
@@ -58,20 +57,10 @@ public class URLBean {
public String getURL() { public String getURL() {
// all this trickier with maps is to reduce the number of objects created // all this trickier with maps is to reduce the number of objects created
Map<String, Object> fullParams = null; Map<String, Object> fullParams = new HashMap<>();
if (params != null) {
fullParams = new HashMap<String, Object>();
}
if (page == null) { if (page == null) {
// No particular page requested, so go to "same page" fullParams.putAll(request.getParameterMap());
// Add query params to parameters
if (fullParams != null) {
fullParams.putAll(request.getParameterMap());
} else {
fullParams = request.getParameterMap();
}
} }
// added parameters override, just like in URLTag // added parameters override, just like in URLTag
@@ -84,7 +73,7 @@ public class URLBean {
public URLBean addParameter(String name, Object value) { public URLBean addParameter(String name, Object value) {
if (params == null) { if (params == null) {
params = new HashMap<String, String>(); params = new HashMap<>();
} }
if (value == null) { if (value == null) {
@@ -266,13 +266,12 @@ struts.handle.exception=true
### Applies maximum length allowed on OGNL expressions for security enhancement (optional) ### Applies maximum length allowed on OGNL expressions for security enhancement (optional)
### ###
### **WARNING**: If developers enable this option (by configuration) they should make sure that they understand the implications of setting ### **WARNING**: If developers change this option (by configuration) they should make sure that they understand
### struts.ognl.expressionMaxLength. They must choose a value large enough to permit ALL valid OGNL expressions used within the application. ### the implications of setting 'struts.ognl.expressionMaxLength'. They must choose a value large enough to permit
### Values larger than the 200-400 range have diminishing security value (at which point it is really only a "style guard" for long OGNL ### ALL valid OGNL expressions used within the application. Values larger than the 200-400 range have diminishing
### expressions in an application. Setting a value of null or "" will also disable the feature. ### security value (at which point it is really only a "style guard" for long OGNL expressions in an application.
### ### Setting a value of null or "" will also disable the feature.
### NOTE: The sample line below is *INTENTIONALLY* commented out, as this feature is disabled by default. struts.ognl.expressionMaxLength=256
# struts.ognl.expressionMaxLength=256
### Defines which named instance of DateFormatter to use, there are two instances: ### Defines which named instance of DateFormatter to use, there are two instances:
### - simpleDateFormatter (based on SimpleDateFormat) ### - simpleDateFormatter (based on SimpleDateFormat)
@@ -28,6 +28,9 @@ import org.apache.struts2.conversion.TypeConversionException;
import java.sql.Time; import java.sql.Time;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.text.DateFormat; import java.text.DateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
@@ -43,14 +46,20 @@ public class DateConverterTest extends StrutsInternalTestCase {
private final static String DATE_STR = "2020-03-20"; private final static String DATE_STR = "2020-03-20";
private final static String DATE_CONVERTED = "Fri Mar 20 00:00:00"; private final static String DATE_CONVERTED = "Fri Mar 20 00:00:00";
private final static String INVALID_DATE = "99/99/2010"; private final static String INVALID_DATE = "99/99/2010";
private final static String LOCALDATETIME_STR = "2020-03-20T00:00:00.000000";
private final static String LOCALDATETIME1_STR = "12:00 AM Fri Mar 20, 2020";
private final static String LOCALDATETIME_CONVERTED = "2020-03-20T00:00";
private final static String LOCALDATE_STR = "2020-03-20";
private final static String LOCALTIME_STR = "01:59:10";
private final static String INVALID_LOCALDATETIME = "2010-99-99T00:00";
private final static String MESSAGE_PARSE_ERROR = "Could not parse date"; private final static String MESSAGE_PARSE_ERROR = "Could not parse date";
private final static String MESSAGE_DEFAULT_CONSTRUCTOR_ERROR = "Couldn't create class null using default (long) constructor"; private final static String MESSAGE_DEFAULT_CONSTRUCTOR_ERROR = "Couldn't create class null using default (long) constructor";
public void testSqlTimeType() { public void testSqlTimeType() {
DateConverter converter = new DateConverter(); DateConverter converter = new DateConverter();
ActionContext context = ActionContext.of(new HashMap<>()) ActionContext context = ActionContext.of(new HashMap<>()).withLocale(mxLocale);
.withLocale(mxLocale);
Object value = converter.convertValue(context.getContextMap(), null, null, null, TIME_01_59_10, Time.class); Object value = converter.convertValue(context.getContextMap(), null, null, null, TIME_01_59_10, Time.class);
assertEquals("01:59:10", value.toString()); assertEquals("01:59:10", value.toString());
@@ -59,10 +68,10 @@ public class DateConverterTest extends StrutsInternalTestCase {
public void testSqlTimestampType() { public void testSqlTimestampType() {
DateConverter converter = new DateConverter(); DateConverter converter = new DateConverter();
ActionContext context = ActionContext.of(new HashMap<>()) ActionContext context = ActionContext.of(new HashMap<>()).withLocale(mxLocale);
.withLocale(mxLocale);
Object value = converter.convertValue(context.getContextMap(), null, null, null, INPUT_TIME_STAMP_STR, Timestamp.class); Object value = converter.convertValue(context.getContextMap(), null, null, null, INPUT_TIME_STAMP_STR,
Timestamp.class);
assertEquals(RES_TIME_STAMP_STR, value.toString()); assertEquals(RES_TIME_STAMP_STR, value.toString());
} }
@@ -74,9 +83,8 @@ public class DateConverterTest extends StrutsInternalTestCase {
ValueStack stack = new StubValueStack(); ValueStack stack = new StubValueStack();
stack.push(new StubTextProvider(map)); stack.push(new StubTextProvider(map));
ActionContext context = ActionContext.of(new HashMap<>()) ActionContext context = ActionContext.of(new HashMap<>()).withLocale(new Locale("es_MX", "MX"))
.withLocale(new Locale("es_MX", "MX")) .withValueStack(stack);
.withValueStack(stack);
Object value = converter.convertValue(context.getContextMap(), null, null, null, DATE_STR, Date.class); Object value = converter.convertValue(context.getContextMap(), null, null, null, DATE_STR, Date.class);
assertTrue(value.toString().startsWith(DATE_CONVERTED)); assertTrue(value.toString().startsWith(DATE_CONVERTED));
@@ -90,9 +98,8 @@ public class DateConverterTest extends StrutsInternalTestCase {
ValueStack stack = new StubValueStack(); ValueStack stack = new StubValueStack();
stack.push(new StubTextProvider(map)); stack.push(new StubTextProvider(map));
ActionContext context = ActionContext.of(new HashMap<>()) ActionContext context = ActionContext.of(new HashMap<>()).withLocale(new Locale("es_MX", "MX"))
.withLocale(new Locale("es_MX", "MX")) .withValueStack(stack);
.withValueStack(stack);
try { try {
converter.convertValue(context.getContextMap(), null, null, null, INVALID_DATE, Date.class); converter.convertValue(context.getContextMap(), null, null, null, INVALID_DATE, Date.class);
@@ -106,8 +113,7 @@ public class DateConverterTest extends StrutsInternalTestCase {
public void testTypeConversionExceptionWhenUsingLongConstructor() { public void testTypeConversionExceptionWhenUsingLongConstructor() {
DateConverter converter = new DateConverter(); DateConverter converter = new DateConverter();
ActionContext context = ActionContext.of(new HashMap<>()) ActionContext context = ActionContext.of(new HashMap<>()).withLocale(mxLocale);
.withLocale(mxLocale);
try { try {
converter.convertValue(context.getContextMap(), null, null, null, INPUT_WHEN_LONG_CONSTRUCTOR_STR, null); converter.convertValue(context.getContextMap(), null, null, null, INPUT_WHEN_LONG_CONSTRUCTOR_STR, null);
@@ -118,12 +124,73 @@ public class DateConverterTest extends StrutsInternalTestCase {
} }
} }
public void testLocalDateTimeType() {
DateConverter converter = new DateConverter();
ActionContext context = ActionContext.of(new HashMap<>());
Object value = converter.convertValue(context.getContextMap(), null, null, null, LOCALDATETIME_STR,
LocalDateTime.class);
assertTrue(value.toString().startsWith(LOCALDATETIME_CONVERTED));
}
public void testLocalDateTime1Type() {
DateConverter converter = new DateConverter();
Map<String, String> map = new HashMap<>();
map.put(org.apache.struts2.components.Date.DATETAG_PROPERTY, "hh:mm a EEE MMM dd, yyyy");
ValueStack stack = new StubValueStack();
stack.push(new StubTextProvider(map));
ActionContext context = ActionContext.of(new HashMap<>()).withLocale(mxLocale)
.withValueStack(stack);
Object value = converter.convertValue(context.getContextMap(), null, null, null, LOCALDATETIME1_STR,
LocalDateTime.class);
assertTrue(value.toString().startsWith(LOCALDATETIME_CONVERTED));
}
public void testLocalDateTimeTypeConversionExceptionWhenParseError() {
DateConverter converter = new DateConverter();
ActionContext context = ActionContext.of(new HashMap<>());
try {
converter.convertValue(context.getContextMap(), null, null, null, INVALID_LOCALDATETIME,
LocalDateTime.class);
fail("TypeConversionException expected - Conversion error occurred");
} catch (Exception ex) {
assertEquals(TypeConversionException.class, ex.getClass());
assertEquals(MESSAGE_PARSE_ERROR, ex.getMessage());
}
}
public void testLocalDateType() {
DateConverter converter = new DateConverter();
ActionContext context = ActionContext.of(new HashMap<>());
Object value = converter.convertValue(context.getContextMap(), null, null, null, LOCALDATE_STR,
LocalDate.class);
assertTrue(value.toString().startsWith(LOCALDATE_STR));
}
public void testLocalTimeType() {
DateConverter converter = new DateConverter();
ActionContext context = ActionContext.of(new HashMap<>());
Object value = converter.convertValue(context.getContextMap(), null, null, null, LOCALTIME_STR,
LocalTime.class);
assertTrue(value.toString().startsWith(LOCALTIME_STR));
}
@Override @Override
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp(); super.setUp();
//Due to JEP 252: Use CLDR Locale Data by Default // Due to JEP 252: Use CLDR Locale Data by Default
DateFormat dFormat = DateFormat.getDateInstance(DateFormat.SHORT, mxLocale); DateFormat dFormat = DateFormat.getDateInstance(DateFormat.SHORT, mxLocale);
if (dFormat.format(new Date()).contains("-")) { // Format when Java 9 or greater if (dFormat.format(new Date()).contains("-")) { // Format when Java 9 or greater
INPUT_TIME_STAMP_STR = "2020-03-20 00:00:00.000"; INPUT_TIME_STAMP_STR = "2020-03-20 00:00:00.000";
INPUT_WHEN_LONG_CONSTRUCTOR_STR = "2020-03-20"; INPUT_WHEN_LONG_CONSTRUCTOR_STR = "2020-03-20";
} else {// Format when Java 8 or lower } else {// Format when Java 8 or lower
@@ -39,13 +39,17 @@ import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor;
import com.opensymphony.xwork2.util.CompoundRoot; import com.opensymphony.xwork2.util.CompoundRoot;
import com.opensymphony.xwork2.util.ValueStack; import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory; import com.opensymphony.xwork2.util.ValueStackFactory;
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
import ognl.OgnlContext; import ognl.OgnlContext;
import ognl.PropertyAccessor; import ognl.PropertyAccessor;
import org.apache.struts2.config.StrutsXmlConfigurationProvider; import org.apache.struts2.config.StrutsXmlConfigurationProvider;
import org.apache.struts2.dispatcher.HttpParameters; import org.apache.struts2.dispatcher.HttpParameters;
import org.junit.Assert; import org.junit.Assert;
import org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean;
import java.io.File; import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@@ -335,8 +339,8 @@ public class ParametersInterceptorTest extends XWorkTestCase {
// given // given
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.put("blah", "This is blah"); params.put("blah", "This is blah");
params.put("('\\u0023_memberAccess[\\'allowStaticMethodAccess\\']')(meh)", "true"); params.put("('\\u0023_memberAccess[\\'allowStaticFieldAccess\\']')(meh)", "true");
params.put("('(aaa)(('\\u0023context[\\'xwork.MethodAccessor.denyMethodExecution\\']\\u003d\\u0023foo')(\\u0023foo\\u003dnew java.lang.Boolean(\"false\")))", ""); params.put("('(aaa)(('\\u0023context[\\'xwork.MethodAccessor.denyMethodExecution\\']\\u003d\\u0023foo')(\\u0023foo\\u003dnew java.lang.Boolean(\"true\")))", "");
params.put("(asdf)(('\\u0023rt.exit(1)')(\\u0023rt\\u003d@java.lang.Runtime@getRuntime()))", "1"); params.put("(asdf)(('\\u0023rt.exit(1)')(\\u0023rt\\u003d@java.lang.Runtime@getRuntime()))", "1");
HashMap<String, Object> extraContext = new HashMap<>(); HashMap<String, Object> extraContext = new HashMap<>();
@@ -351,8 +355,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
//then //then
assertEquals("This is blah", ((SimpleAction) proxy.getAction()).getBlah()); assertEquals("This is blah", ((SimpleAction) proxy.getAction()).getBlah());
boolean allowMethodAccess = ((SecurityMemberAccess) ((OgnlContext) stack.getContext()).getMemberAccess()).getAllowStaticMethodAccess(); Field field = ReflectionContextState.class.getField("DENY_METHOD_EXECUTION");
assertFalse(allowMethodAccess); boolean allowStaticFieldAccess = ((OgnlContext) stack.getContext()).getMemberAccess().isAccessible(stack.getContext(), proxy.getAction(), field, "");
assertFalse(allowStaticFieldAccess);
} }
public void testParameters() throws Exception { public void testParameters() throws Exception {
@@ -806,7 +811,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
ValueStack stack = new OgnlValueStack( ValueStack stack = new OgnlValueStack(
container.getInstance(XWorkConverter.class), container.getInstance(XWorkConverter.class),
(CompoundRootAccessor) container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()), (CompoundRootAccessor) container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()),
container.getInstance(TextProvider.class, "system"), true, true) { container.getInstance(TextProvider.class, "system"), true) {
@Override @Override
public void setValue(String expr, Object value) { public void setValue(String expr, Object value) {
actual.put(expr, value); actual.put(expr, value);
@@ -1900,13 +1900,13 @@ public class OgnlUtilTest extends XWorkTestCase {
return result; return result;
} }
private void reloadTestContainerConfiguration(boolean devMode, boolean allowStaticMethod) { private void reloadTestContainerConfiguration(boolean devMode, boolean allowStaticFieldAccess) {
loadConfigurationProviders(new StubConfigurationProvider() { loadConfigurationProviders(new StubConfigurationProvider() {
@Override @Override
public void register(ContainerBuilder builder, public void register(ContainerBuilder builder,
LocatableProperties props) throws ConfigurationException { LocatableProperties props) throws ConfigurationException {
props.setProperty(StrutsConstants.STRUTS_DEVMODE, "" + devMode); props.setProperty(StrutsConstants.STRUTS_DEVMODE, "" + devMode);
props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS, "" + allowStaticMethod); props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS, "" + allowStaticFieldAccess);
} }
}); });
ognlUtil = container.getInstance(OgnlUtil.class); ognlUtil = container.getInstance(OgnlUtil.class);
@@ -18,7 +18,10 @@
*/ */
package com.opensymphony.xwork2.ognl; package com.opensymphony.xwork2.ognl;
import com.opensymphony.xwork2.*; import com.opensymphony.xwork2.SimpleAction;
import com.opensymphony.xwork2.TestBean;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.XWorkTestCase;
import com.opensymphony.xwork2.config.ConfigurationException; import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.conversion.impl.ConversionData; import com.opensymphony.xwork2.conversion.impl.ConversionData;
import com.opensymphony.xwork2.conversion.impl.XWorkConverter; import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
@@ -26,22 +29,17 @@ import com.opensymphony.xwork2.inject.ContainerBuilder;
import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor; import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor;
import com.opensymphony.xwork2.test.StubConfigurationProvider; import com.opensymphony.xwork2.test.StubConfigurationProvider;
import com.opensymphony.xwork2.test.TestBean2; import com.opensymphony.xwork2.test.TestBean2;
import com.opensymphony.xwork2.util.*; import com.opensymphony.xwork2.util.Bar;
import com.opensymphony.xwork2.util.BarJunior;
import com.opensymphony.xwork2.util.Cat;
import com.opensymphony.xwork2.util.CompoundRoot;
import com.opensymphony.xwork2.util.Dog;
import com.opensymphony.xwork2.util.Foo; import com.opensymphony.xwork2.util.Foo;
import com.opensymphony.xwork2.util.ValueStackFactory;
import com.opensymphony.xwork2.util.location.LocatableProperties; import com.opensymphony.xwork2.util.location.LocatableProperties;
import com.opensymphony.xwork2.util.reflection.ReflectionContextState; import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
import ognl.OgnlException; import ognl.OgnlException;
import ognl.PropertyAccessor; import ognl.PropertyAccessor;
import java.io.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import ognl.ParseException;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.LogEvent;
@@ -51,10 +49,18 @@ import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsException; import org.apache.struts2.StrutsException;
import org.apache.struts2.config.DefaultPropertiesProvider; import org.apache.struts2.config.DefaultPropertiesProvider;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Unit test for OgnlValueStack.
*/
public class OgnlValueStackTest extends XWorkTestCase { public class OgnlValueStackTest extends XWorkTestCase {
// Fields for static field access test // Fields for static field access test
@@ -85,16 +91,15 @@ public class OgnlValueStackTest extends XWorkTestCase {
} }
private OgnlValueStack createValueStack() { private OgnlValueStack createValueStack() {
return createValueStack(true, true); return createValueStack(true);
} }
private OgnlValueStack createValueStack(boolean allowStaticMethodAccess, boolean allowStaticFieldAccess) { private OgnlValueStack createValueStack(boolean allowStaticFieldAccess) {
OgnlValueStack stack = new OgnlValueStack( OgnlValueStack stack = new OgnlValueStack(
container.getInstance(XWorkConverter.class), container.getInstance(XWorkConverter.class),
(CompoundRootAccessor) container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()), (CompoundRootAccessor) container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()),
container.getInstance(TextProvider.class, "system"), allowStaticMethodAccess, allowStaticFieldAccess); container.getInstance(TextProvider.class, "system"), allowStaticFieldAccess);
container.inject(stack); container.inject(stack);
ognlUtil.setAllowStaticMethodAccess(Boolean.toString(allowStaticMethodAccess));
ognlUtil.setAllowStaticFieldAccess(Boolean.toString(allowStaticFieldAccess)); ognlUtil.setAllowStaticFieldAccess(Boolean.toString(allowStaticFieldAccess));
return stack; return stack;
} }
@@ -111,16 +116,14 @@ public class OgnlValueStackTest extends XWorkTestCase {
* Intended for testing OgnlValueStack instance(s) that are minimally configured. * Intended for testing OgnlValueStack instance(s) that are minimally configured.
* This should help ensure no underlying configuration/injection side-effects are responsible * This should help ensure no underlying configuration/injection side-effects are responsible
* for the behaviour of fundamental access control flags). * for the behaviour of fundamental access control flags).
* *
* @param allowStaticMethod new allowStaticMethod configuration
* @param allowStaticField new allowStaticField configuration * @param allowStaticField new allowStaticField configuration
* @return a new OgnlValueStackFactory with specified new configuration * @return a new OgnlValueStackFactory with specified new configuration
*/ */
private OgnlValueStackFactory reloadValueStackFactory(Boolean allowStaticMethod, Boolean allowStaticField) { private OgnlValueStackFactory reloadValueStackFactory(Boolean allowStaticField) {
try { try {
reloadTestContainerConfiguration(allowStaticMethod, allowStaticField); reloadTestContainerConfiguration(allowStaticField);
} } catch (Exception ex) {
catch (Exception ex) {
fail("Unable to reload container configuration and configure ognlValueStackFactory - exception: " + ex); fail("Unable to reload container configuration and configure ognlValueStackFactory - exception: " + ex);
} }
@@ -210,7 +213,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
vs.findValue("barJunior.title", true); vs.findValue("barJunior.title", true);
} }
public void testSuccessFailOnErrorOnInheritedPropertiesWithMethods() { public void testSuccessFailOnErrorOnInheritedPropertiesWithMethods() {
//this shuld not fail as the property is defined on a parent class //this shuld not fail as the property is defined on a parent class
OgnlValueStack vs = createValueStack(); OgnlValueStack vs = createValueStack();
@@ -254,6 +257,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
/** /**
* monitors the resolution of WW-4999 * monitors the resolution of WW-4999
*
* @since 2.5.21 * @since 2.5.21
*/ */
public void testLogMissingProperties() { public void testLogMissingProperties() {
@@ -281,11 +285,11 @@ public class OgnlValueStackTest extends XWorkTestCase {
if (logMissingProperties) { if (logMissingProperties) {
assertEquals(3, testAppender.logEvents.size()); assertEquals(3, testAppender.logEvents.size());
assertEquals("Error setting value [missingProp1Value] with expression [missingProp1]", assertEquals("Error setting value [missingProp1Value] with expression [missingProp1]",
testAppender.logEvents.get(0).getMessage().getFormattedMessage()); testAppender.logEvents.get(0).getMessage().getFormattedMessage());
assertEquals("Could not find property [missingProp2]!", assertEquals("Could not find property [missingProp2]!",
testAppender.logEvents.get(1).getMessage().getFormattedMessage()); testAppender.logEvents.get(1).getMessage().getFormattedMessage());
assertEquals("Could not find property [missingProp3]!", assertEquals("Could not find property [missingProp3]!",
testAppender.logEvents.get(2).getMessage().getFormattedMessage()); testAppender.logEvents.get(2).getMessage().getFormattedMessage());
} else { } else {
assertEquals(0, testAppender.logEvents.size()); assertEquals(0, testAppender.logEvents.size());
} }
@@ -297,6 +301,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
/** /**
* tests the correctness of distinguishing between user exception and NoSuchMethodException * tests the correctness of distinguishing between user exception and NoSuchMethodException
*
* @since 2.5.21 * @since 2.5.21
*/ */
public void testNotLogUserExceptionsAsMissingProperties() { public void testNotLogUserExceptionsAsMissingProperties() {
@@ -364,7 +369,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
} }
}); });
Integer repeat = Integer.parseInt( Integer repeat = Integer.parseInt(
container.getInstance(String.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_MAX_LENGTH)); container.getInstance(String.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_MAX_LENGTH));
OgnlValueStack vs = createValueStack(); OgnlValueStack vs = createValueStack();
try { try {
@@ -383,65 +388,40 @@ public class OgnlValueStackTest extends XWorkTestCase {
public void testNotFailOnTooLongExpressionWithDefaultProperties() { public void testNotFailOnTooLongExpressionWithDefaultProperties() {
loadConfigurationProviders(new DefaultPropertiesProvider()); loadConfigurationProviders(new DefaultPropertiesProvider());
Object defaultMaxLengthFromConfiguration = container.getInstance(String.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_MAX_LENGTH); String defaultMaxLengthFromConfiguration = container.getInstance(String.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_MAX_LENGTH);
if (defaultMaxLengthFromConfiguration != null) { assertNotNull(defaultMaxLengthFromConfiguration);
assertTrue("non-null defaultMaxLengthFromConfiguration not a String ?", defaultMaxLengthFromConfiguration instanceof String);
assertTrue("non-null defaultMaxLengthFromConfiguration not empty string by default ?", ((String) defaultMaxLengthFromConfiguration).length() == 0); int defaultValue = 256;
} else {
assertNull("defaultMaxLengthFromConfiguration not null ?", defaultMaxLengthFromConfiguration);
}
// Original test logic was to confirm failure of exceeding the default value. Now the feature should be disabled by default,
// so this test's expectations are now changed.
Integer repeat = Integer.valueOf(256); // Since maxlength is disabled by default, just choose an arbitrary value for test
OgnlValueStack vs = createValueStack(); OgnlValueStack vs = createValueStack();
try { try {
vs.findValue(StringUtils.repeat('.', repeat + 1), true); vs.findValue(StringUtils.repeat('.', defaultValue + 1), true);
fail("findValue did not throw any exception (should either fail as invalid expression syntax or security exception) ?"); fail("findValue did not throw any exception (should either fail as invalid expression syntax or security exception) ?");
} catch (Exception ex) { } catch (Exception ex) {
// If STRUTS_OGNL_EXPRESSION_MAX_LENGTH feature is disabled (default), the parse should fail due to a reason of invalid expression syntax
// with ParseException. Previously when it was enabled the reason for the failure would have been SecurityException.
assertTrue(ex.getCause() instanceof OgnlException); assertTrue(ex.getCause() instanceof OgnlException);
assertTrue(((OgnlException) ex.getCause()).getReason() instanceof ParseException); assertTrue(((OgnlException) ex.getCause()).getReason() instanceof SecurityException);
assertTrue(((OgnlException) ex.getCause()).getReason().getMessage().startsWith("This expression exceeded maximum allowed length"));
} }
} }
public void testNotFailOnTooLongValueWithDefaultProperties() { public void testNotFailOnTooLongValueWithDefaultProperties() {
try { loadConfigurationProviders(new DefaultPropertiesProvider());
loadConfigurationProviders(new DefaultPropertiesProvider());
Object defaultMaxLengthFromConfiguration = container.getInstance(String.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_MAX_LENGTH); Object defaultMaxLengthFromConfiguration = container.getInstance(String.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_MAX_LENGTH);
if (defaultMaxLengthFromConfiguration != null) { assertNotNull(defaultMaxLengthFromConfiguration);
assertTrue("non-null defaultMaxLengthFromConfiguration not a String ?", defaultMaxLengthFromConfiguration instanceof String);
assertTrue("non-null defaultMaxLengthFromConfiguration not empty string by default ?", ((String) defaultMaxLengthFromConfiguration).length() == 0);
} else {
assertNull("defaultMaxLengthFromConfiguration not null ?", defaultMaxLengthFromConfiguration);
}
// Original test logic is unchanged (testing that values can be larger than maximum expression length), but since the feature is disabled by
// default we will now have to enable it with an arbitrary value, test, and reset it to disabled.
Integer repeat = Integer.valueOf(256); // Since maxlength is disabled by default, just choose an arbitrary value for test
// Apply a non-default value for expressionMaxLength (as it should be disabled by default) int defaultValue = 256;
try {
ognlUtil.applyExpressionMaxLength(repeat.toString());
} catch (Exception ex) {
fail ("applyExpressionMaxLength did not accept maxlength string " + repeat.toString() + " ?");
}
OgnlValueStack vs = createValueStack(); OgnlValueStack vs = createValueStack();
Dog dog = new Dog(); Dog dog = new Dog();
vs.push(dog); vs.push(dog);
String value = StringUtils.repeat('.', repeat + 1); String value = StringUtils.repeat('.', defaultValue);
vs.setValue("name", value); vs.setValue("name", value);
assertEquals(value, dog.getName()); assertEquals(value, dog.getName());
} finally {
// Reset expressionMaxLength value to default (disabled)
ognlUtil.applyExpressionMaxLength(null);
}
} }
public void testFailsOnMethodThatThrowsException() { public void testFailsOnMethodThatThrowsException() {
@@ -502,7 +482,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
Dog dog = new Dog(); Dog dog = new Dog();
dog.setDeity("fido"); dog.setDeity("fido");
vs.push(dog); vs.push(dog);
assertEquals("fido", vs.findValue("@com.opensymphony.xwork2.util.Dog@getDeity()", String.class)); assertNull(vs.findValue("@com.opensymphony.xwork2.util.Dog@getDeity()", String.class));
} }
/** /**
@@ -517,7 +497,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
} }
public void testStaticMethodDisallow() { public void testStaticMethodDisallow() {
OgnlValueStack vs = createValueStack(false, true); OgnlValueStack vs = createValueStack(true);
Dog dog = new Dog(); Dog dog = new Dog();
dog.setDeity("fido"); dog.setDeity("fido");
@@ -845,8 +825,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
try { try {
stack.setValue("bar", "3x"); stack.setValue("bar", "3x");
fail("Attempt to set 'bar' int property to '3x' should result in RuntimeException"); fail("Attempt to set 'bar' int property to '3x' should result in RuntimeException");
} } catch (RuntimeException re) {
catch (RuntimeException re) {
assertTrue(true); assertTrue(true);
} }
@@ -1082,6 +1061,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
/** /**
* Fails on 2.5.20 and earlier - tested on 2.5 (5/5/2016) and failed * Fails on 2.5.20 and earlier - tested on 2.5 (5/5/2016) and failed
*
* @since 2.5.21 * @since 2.5.21
*/ */
public void testNotThrowExceptionOnTopMissingProperty() { public void testNotThrowExceptionOnTopMissingProperty() {
@@ -1104,6 +1084,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
/** /**
* Fails on 2.5.20 and earlier - tested on 2.5 (5/5/2016) and failed * Fails on 2.5.20 and earlier - tested on 2.5 (5/5/2016) and failed
*
* @since 2.5.21 * @since 2.5.21
*/ */
public void testNotSkipUserReturnedNullValues() { public void testNotSkipUserReturnedNullValues() {
@@ -1187,8 +1168,8 @@ public class OgnlValueStackTest extends XWorkTestCase {
stack.push("Hello World"); stack.push("Hello World");
OgnlValueStack stack2 = new OgnlValueStack(stack, OgnlValueStack stack2 = new OgnlValueStack(stack,
container.getInstance(XWorkConverter.class), container.getInstance(XWorkConverter.class),
(CompoundRootAccessor) container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()), true, true); (CompoundRootAccessor) container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()), true);
container.inject(stack2); container.inject(stack2);
assertEquals(stack.getRoot(), stack2.getRoot()); assertEquals(stack.getRoot(), stack2.getRoot());
@@ -1260,7 +1241,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
assertNull(stack.findValue("address.country.name", String.class)); assertNull(stack.findValue("address.country.name", String.class));
} }
/** /**
* Test a default OgnlValueStackFactory and OgnlValueStack generated by it * Test a default OgnlValueStackFactory and OgnlValueStack generated by it
* when a default configuration is used. * when a default configuration is used.
*/ */
@@ -1271,7 +1252,6 @@ public class OgnlValueStackTest extends XWorkTestCase {
// An OgnlValueStackFactory using a container config with default (from XWorkConfigurationProvider) // An OgnlValueStackFactory using a container config with default (from XWorkConfigurationProvider)
// static access flag values present should prevent staticMethodAccess but allow staticFieldAccess. // static access flag values present should prevent staticMethodAccess but allow staticFieldAccess.
assertFalse("OgnlValueStackFactory staticMethodAccess (default flags) not false?", ognlValueStackFactory.containerAllowsStaticMethodAccess());
assertTrue("OgnlValueStackFactory staticFieldAccess (default flags) not true?", ognlValueStackFactory.containerAllowsStaticFieldAccess()); assertTrue("OgnlValueStackFactory staticFieldAccess (default flags) not true?", ognlValueStackFactory.containerAllowsStaticFieldAccess());
// An OgnlValueStack created from the above OgnlValueStackFactory should allow public field access, // An OgnlValueStack created from the above OgnlValueStackFactory should allow public field access,
// but prevent non-public field access. It should also deny static method access. // but prevent non-public field access. It should also deny static method access.
@@ -1300,7 +1280,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
* when no static access flags are set (not present in configuration). * when no static access flags are set (not present in configuration).
*/ */
public void testOgnlValueStackFromOgnlValueStackFactoryNoFlagsSet() { public void testOgnlValueStackFromOgnlValueStackFactoryNoFlagsSet() {
OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(null, null); OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(null);
OgnlValueStack ognlValueStack = (OgnlValueStack) ognlValueStackFactory.createValueStack(); OgnlValueStack ognlValueStack = (OgnlValueStack) ognlValueStackFactory.createValueStack();
Object accessedValue; Object accessedValue;
@@ -1309,7 +1289,6 @@ public class OgnlValueStackTest extends XWorkTestCase {
// prevent staticMethodAccess AND prevent staticFieldAccess. // prevent staticMethodAccess AND prevent staticFieldAccess.
// Note: Under normal circumstances, explicit static access configuration flags should be present, // Note: Under normal circumstances, explicit static access configuration flags should be present,
// but this specific check verifies what happens if those configuration flags are not present. // but this specific check verifies what happens if those configuration flags are not present.
assertFalse("OgnlValueStackFactory staticMethodAccess (no flag present) not false?", ognlValueStackFactory.containerAllowsStaticMethodAccess());
assertFalse("OgnlValueStackFactory staticFieldAccess (no flag present) not false?", ognlValueStackFactory.containerAllowsStaticFieldAccess()); assertFalse("OgnlValueStackFactory staticFieldAccess (no flag present) not false?", ognlValueStackFactory.containerAllowsStaticFieldAccess());
// An OgnlValueStack created from the above OgnlValueStackFactory should prevent public field access, // An OgnlValueStack created from the above OgnlValueStackFactory should prevent public field access,
// and prevent non-public field access. It should also deny static method access. // and prevent non-public field access. It should also deny static method access.
@@ -1335,16 +1314,15 @@ public class OgnlValueStackTest extends XWorkTestCase {
/** /**
* Test a raw OgnlValueStackFactory and OgnlValueStack generated by it * Test a raw OgnlValueStackFactory and OgnlValueStack generated by it
* when both static access flags are set to false. * when static access flag is set to false.
*/ */
public void testOgnlValueStackFromOgnlValueStackFactoryNoStaticAccess() { public void testOgnlValueStackFromOgnlValueStackFactoryNoStaticAccess() {
OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(false, false); OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(false);
OgnlValueStack ognlValueStack = (OgnlValueStack) ognlValueStackFactory.createValueStack(); OgnlValueStack ognlValueStack = (OgnlValueStack) ognlValueStackFactory.createValueStack();
Object accessedValue; Object accessedValue;
// An OgnlValueStackFactory using a container config with both static access flags set false should // An OgnlValueStackFactory using a container config with both static access flags set false should
// prevent staticMethodAccess AND prevent staticFieldAccess. // prevent staticMethodAccess AND prevent staticFieldAccess.
assertFalse("OgnlValueStackFactory staticMethodAccess (set false) not false?", ognlValueStackFactory.containerAllowsStaticMethodAccess());
assertFalse("OgnlValueStackFactory staticFieldAccess (set false) not false?", ognlValueStackFactory.containerAllowsStaticFieldAccess()); assertFalse("OgnlValueStackFactory staticFieldAccess (set false) not false?", ognlValueStackFactory.containerAllowsStaticFieldAccess());
// An OgnlValueStack created from the above OgnlValueStackFactory should prevent public field access, // An OgnlValueStack created from the above OgnlValueStackFactory should prevent public field access,
// and prevent non-public field access. It should also deny static method access. // and prevent non-public field access. It should also deny static method access.
@@ -1370,22 +1348,20 @@ public class OgnlValueStackTest extends XWorkTestCase {
/** /**
* Test a raw OgnlValueStackFactory and OgnlValueStack generated by it * Test a raw OgnlValueStackFactory and OgnlValueStack generated by it
* when both static access flags are set to true. * when static access flag is set to true.
*/ */
public void testOgnlValueStackFromOgnlValueStackFactoryAllStaticAccess() { public void testOgnlValueStackFromOgnlValueStackFactoryAllStaticAccess() {
OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(true, true); OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(true);
OgnlValueStack ognlValueStack = (OgnlValueStack) ognlValueStackFactory.createValueStack(); OgnlValueStack ognlValueStack = (OgnlValueStack) ognlValueStackFactory.createValueStack();
Object accessedValue; Object accessedValue;
// An OgnlValueStackFactory using a container config with both static access flags set true should // An OgnlValueStackFactory using a container config with both static access flags set true should
// allow both staticMethodAccess AND staticFieldAccess. // allow both staticMethodAccess AND staticFieldAccess.
assertTrue("OgnlValueStackFactory staticMethodAccess (set true) not true?", ognlValueStackFactory.containerAllowsStaticMethodAccess());
assertTrue("OgnlValueStackFactory staticFieldAccess (set true) not true?", ognlValueStackFactory.containerAllowsStaticFieldAccess()); assertTrue("OgnlValueStackFactory staticFieldAccess (set true) not true?", ognlValueStackFactory.containerAllowsStaticFieldAccess());
// An OgnlValueStack created from the above OgnlValueStackFactory should allow public field access, // An OgnlValueStack created from the above OgnlValueStackFactory should allow public field access,
// but prevent non-public field access. It should also allow static method access. // but prevent non-public field access. It should also allow static method access.
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@staticInteger100Method()"); accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@staticInteger100Method()");
assertNotNull("unable to access static method (result null) ?", accessedValue); assertNull("able to access static method (result non-null)!!!", accessedValue);
assertEquals("accessed static method result not equal to expected?", accessedValue, staticInteger100Method());
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PUBLIC_ATTRIBUTE"); accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PUBLIC_ATTRIBUTE");
assertEquals("accessed static final public field value not equal to actual?", accessedValue, STATIC_FINAL_PUBLIC_ATTRIBUTE); assertEquals("accessed static final public field value not equal to actual?", accessedValue, STATIC_FINAL_PUBLIC_ATTRIBUTE);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PUBLIC_ATTRIBUTE"); accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PUBLIC_ATTRIBUTE");
@@ -1404,93 +1380,14 @@ public class OgnlValueStackTest extends XWorkTestCase {
assertNull("accessed private field (result not null) ?", accessedValue); assertNull("accessed private field (result not null) ?", accessedValue);
} }
/** private void reloadTestContainerConfiguration(Boolean allowStaticField) throws Exception {
* Test a raw OgnlValueStackFactory and OgnlValueStack generated by it
* when static method access flag is true, static field access flag is false.
*/
public void testOgnlValueStackFromOgnlValueStackFactoryOnlyStaticMethodAccess() {
OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(true, false);
OgnlValueStack ognlValueStack = (OgnlValueStack) ognlValueStackFactory.createValueStack();
Object accessedValue;
// An OgnlValueStackFactory using a container config with static method access flag true, static field access false should
// allow staticMethodAccess but deny staticFieldAccess.
assertTrue("OgnlValueStackFactory staticMethodAccess (set true) not true?", ognlValueStackFactory.containerAllowsStaticMethodAccess());
assertFalse("OgnlValueStackFactory staticFieldAccess (set false) not false?", ognlValueStackFactory.containerAllowsStaticFieldAccess());
// An OgnlValueStack created from the above OgnlValueStackFactory should deny public field access,
// and also prevent non-public field access. It should also allow static method access.
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@staticInteger100Method()");
assertNotNull("unable to access static method (result null) ?", accessedValue);
assertEquals("accessed static method result not equal to expected?", accessedValue, staticInteger100Method());
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PUBLIC_ATTRIBUTE");
assertNull("able to access static final public field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PUBLIC_ATTRIBUTE");
assertNull("able to access static public field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PACKAGE_ATTRIBUTE");
assertNull("accessed final package field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PACKAGE_ATTRIBUTE");
assertNull("accessed package field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PROTECTED_ATTRIBUTE");
assertNull("accessed final protected field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PROTECTED_ATTRIBUTE");
assertNull("accessed protected field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PRIVATE_ATTRIBUTE");
assertNull("accessed final private field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PRIVATE_ATTRIBUTE");
assertNull("accessed private field (result not null) ?", accessedValue);
}
/**
* Test a raw OgnlValueStackFactory and OgnlValueStack generated by it
* when static method access flag is false, static field access flag is true.
*/
public void testOgnlValueStackFromOgnlValueStackFactoryOnlyStaticFieldAccess() {
OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(false, true);
OgnlValueStack ognlValueStack = (OgnlValueStack) ognlValueStackFactory.createValueStack();
Object accessedValue;
// An OgnlValueStackFactory using a container config with static method access flag false, static field access true should
// deny staticMethodAccess but allow staticFieldAccess.
assertFalse("OgnlValueStackFactory staticMethodAccess (set false) not false?", ognlValueStackFactory.containerAllowsStaticMethodAccess());
assertTrue("OgnlValueStackFactory staticFieldAccess (set true) not true?", ognlValueStackFactory.containerAllowsStaticFieldAccess());
// An OgnlValueStack created from the above OgnlValueStackFactory should allow public field access,
// but prevent non-public field access. It should also deny static method access.
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@staticInteger100Method()");
assertNull("able to access static method (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PUBLIC_ATTRIBUTE");
assertEquals("accessed static final public field value not equal to actual?", accessedValue, STATIC_FINAL_PUBLIC_ATTRIBUTE);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PUBLIC_ATTRIBUTE");
assertEquals("accessed static public field value not equal to actual?", accessedValue, STATIC_PUBLIC_ATTRIBUTE);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PACKAGE_ATTRIBUTE");
assertNull("accessed final package field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PACKAGE_ATTRIBUTE");
assertNull("accessed package field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PROTECTED_ATTRIBUTE");
assertNull("accessed final protected field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PROTECTED_ATTRIBUTE");
assertNull("accessed protected field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_FINAL_PRIVATE_ATTRIBUTE");
assertNull("accessed final private field (result not null) ?", accessedValue);
accessedValue = ognlValueStack.findValue("@com.opensymphony.xwork2.ognl.OgnlValueStackTest@STATIC_PRIVATE_ATTRIBUTE");
assertNull("accessed private field (result not null) ?", accessedValue);
}
private void reloadTestContainerConfiguration(Boolean allowStaticMethod, Boolean allowStaticField) throws Exception {
loadConfigurationProviders(new StubConfigurationProvider() { loadConfigurationProviders(new StubConfigurationProvider() {
@Override @Override
public void register(ContainerBuilder builder, public void register(ContainerBuilder builder,
LocatableProperties props) throws ConfigurationException { LocatableProperties props) throws ConfigurationException {
// null values simulate undefined (by removing). // null values simulate undefined (by removing).
// undefined values then should be evaluated to false // undefined values then should be evaluated to false
if (props.containsKey(StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS)) { props.remove(StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS);
props.remove(StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS);
}
if (props.containsKey(StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS)) {
props.remove(StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS);
}
if (allowStaticMethod != null) {
props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS, "" + allowStaticMethod);
}
if (allowStaticField != null) { if (allowStaticField != null) {
props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS, "" + allowStaticField); props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS, "" + allowStaticField);
} }
@@ -23,7 +23,6 @@ import junit.framework.TestCase;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@@ -45,7 +44,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testWithoutClassExclusion() throws Exception { public void testWithoutClassExclusion() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "stringField"; String propertyName = "stringField";
Member member = FooBar.class.getMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1)); Member member = FooBar.class.getMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1));
@@ -59,7 +58,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testClassExclusion() throws Exception { public void testClassExclusion() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "stringField"; String propertyName = "stringField";
Member member = FooBar.class.getDeclaredMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1)); Member member = FooBar.class.getDeclaredMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1));
@@ -77,7 +76,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testObjectClassExclusion() throws Exception { public void testObjectClassExclusion() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "toString"; String propertyName = "toString";
Member member = FooBar.class.getMethod(propertyName); Member member = FooBar.class.getMethod(propertyName);
@@ -91,7 +90,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testObjectOverwrittenMethodsExclusion() throws Exception { public void testObjectOverwrittenMethodsExclusion() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "hashCode"; String propertyName = "hashCode";
Member member = FooBar.class.getMethod(propertyName); Member member = FooBar.class.getMethod(propertyName);
@@ -105,7 +104,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testInterfaceInheritanceExclusion() throws Exception { public void testInterfaceInheritanceExclusion() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "barLogic"; String propertyName = "barLogic";
Member member = BarInterface.class.getMethod(propertyName); Member member = BarInterface.class.getMethod(propertyName);
@@ -123,7 +122,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testMiddleOfInheritanceExclusion1() throws Exception { public void testMiddleOfInheritanceExclusion1() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "fooLogic"; String propertyName = "fooLogic";
Member member = FooBar.class.getMethod(propertyName); Member member = FooBar.class.getMethod(propertyName);
@@ -141,7 +140,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testMiddleOfInheritanceExclusion3() throws Exception { public void testMiddleOfInheritanceExclusion3() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "barLogic"; String propertyName = "barLogic";
Member member = BarInterface.class.getMethod(propertyName); Member member = BarInterface.class.getMethod(propertyName);
@@ -155,7 +154,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testMiddleOfInheritanceExclusion4() throws Exception { public void testMiddleOfInheritanceExclusion4() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "barLogic"; String propertyName = "barLogic";
Member member = BarInterface.class.getMethod(propertyName); Member member = BarInterface.class.getMethod(propertyName);
@@ -173,7 +172,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testPackageExclusion() throws Exception { public void testPackageExclusion() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
Set<Pattern> excluded = new HashSet<>(); Set<Pattern> excluded = new HashSet<>();
excluded.add(Pattern.compile("^" + FooBar.class.getPackage().getName().replaceAll("\\.", "\\\\.") + ".*")); excluded.add(Pattern.compile("^" + FooBar.class.getPackage().getName().replaceAll("\\.", "\\\\.") + ".*"));
@@ -188,10 +187,10 @@ public class SecurityMemberAccessTest extends TestCase {
// then // then
assertFalse("stringField is accessible!", actual); assertFalse("stringField is accessible!", actual);
} }
public void testPackageNameExclusion() throws Exception { public void testPackageNameExclusion() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
Set<String> excluded = new HashSet<>(); Set<String> excluded = new HashSet<>();
excluded.add(FooBar.class.getPackage().getName()); excluded.add(FooBar.class.getPackage().getName());
@@ -209,27 +208,27 @@ public class SecurityMemberAccessTest extends TestCase {
public void testDefaultPackageExclusion() { public void testDefaultPackageExclusion() {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
Set<Pattern> excluded = new HashSet<>(); Set<Pattern> excluded = new HashSet<>();
excluded.add(Pattern.compile("^" + FooBar.class.getPackage().getName().replaceAll("\\.", "\\\\.") + ".*")); excluded.add(Pattern.compile("^" + FooBar.class.getPackage().getName().replaceAll("\\.", "\\\\.") + ".*"));
sma.setExcludedPackageNamePatterns(excluded); sma.setExcludedPackageNamePatterns(excluded);
// when // when
boolean actual = sma.isPackageExcluded(null, null); boolean actual = sma.isPackageExcluded(null, null);
// then // then
assertFalse("default package is excluded!", actual); assertFalse("default package is excluded!", actual);
} }
public void testDefaultPackageExclusion2() { public void testDefaultPackageExclusion2() {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
Set<Pattern> excluded = new HashSet<>(); Set<Pattern> excluded = new HashSet<>();
excluded.add(Pattern.compile("^$")); excluded.add(Pattern.compile("^$"));
sma.setExcludedPackageNamePatterns(excluded); sma.setExcludedPackageNamePatterns(excluded);
// when // when
boolean actual = sma.isPackageExcluded(null, null); boolean actual = sma.isPackageExcluded(null, null);
@@ -239,7 +238,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessEnum() throws Exception { public void testAccessEnum() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
// when // when
Member values = MyValues.class.getMethod("values"); Member values = MyValues.class.getMethod("values");
@@ -249,23 +248,23 @@ public class SecurityMemberAccessTest extends TestCase {
assertTrue("Access to enums is blocked!", actual); assertTrue("Access to enums is blocked!", actual);
} }
public void testAccessStatic() throws Exception { public void testAccessStaticMethod() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(true, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class))); sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when // when
Member method = StaticTester.class.getMethod("sayHello"); Member method = StaticTester.class.getMethod("sayHello");
boolean actual = sma.isAccessible(context, Class.class, method, null); boolean actual = sma.isAccessible(context, Class.class, method, null);
// then // then
assertTrue("Access to static is blocked!", actual); assertFalse("Access to static method is not blocked!", actual);
} }
public void testAccessStaticField() throws Exception { public void testAccessStaticField() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(true, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class))); sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when // when
Member method = StaticTester.class.getField("MAX_VALUE"); Member method = StaticTester.class.getField("MAX_VALUE");
@@ -277,8 +276,8 @@ public class SecurityMemberAccessTest extends TestCase {
public void testBlockedStaticFieldWhenFlagIsFalse() throws Exception { public void testBlockedStaticFieldWhenFlagIsFalse() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class))); sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when // when
Member method = StaticTester.class.getField("MAX_VALUE"); Member method = StaticTester.class.getField("MAX_VALUE");
@@ -289,8 +288,8 @@ public class SecurityMemberAccessTest extends TestCase {
// public static final test // public static final test
// given // given
sma = new SecurityMemberAccess(false, true); sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class))); sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when // when
method = StaticTester.class.getField("MIN_VALUE"); method = StaticTester.class.getField("MIN_VALUE");
@@ -301,8 +300,8 @@ public class SecurityMemberAccessTest extends TestCase {
// package static test // package static test
// given // given
sma = new SecurityMemberAccess(false, true); sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class))); sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when // when
method = StaticTester.getFieldByName("PACKAGE_STRING"); method = StaticTester.getFieldByName("PACKAGE_STRING");
@@ -313,8 +312,8 @@ public class SecurityMemberAccessTest extends TestCase {
// package final static test // package final static test
// given // given
sma = new SecurityMemberAccess(false, true); sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class))); sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when // when
method = StaticTester.getFieldByName("FINAL_PACKAGE_STRING"); method = StaticTester.getFieldByName("FINAL_PACKAGE_STRING");
@@ -325,8 +324,8 @@ public class SecurityMemberAccessTest extends TestCase {
// protected static test // protected static test
// given // given
sma = new SecurityMemberAccess(false, true); sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class))); sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when // when
method = StaticTester.getFieldByName("PROTECTED_STRING"); method = StaticTester.getFieldByName("PROTECTED_STRING");
@@ -337,8 +336,8 @@ public class SecurityMemberAccessTest extends TestCase {
// protected final static test // protected final static test
// given // given
sma = new SecurityMemberAccess(false, true); sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class))); sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when // when
method = StaticTester.getFieldByName("FINAL_PROTECTED_STRING"); method = StaticTester.getFieldByName("FINAL_PROTECTED_STRING");
@@ -349,8 +348,8 @@ public class SecurityMemberAccessTest extends TestCase {
// private static test // private static test
// given // given
sma = new SecurityMemberAccess(false, true); sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class))); sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when // when
method = StaticTester.getFieldByName("PRIVATE_STRING"); method = StaticTester.getFieldByName("PRIVATE_STRING");
@@ -361,8 +360,8 @@ public class SecurityMemberAccessTest extends TestCase {
// private final static test // private final static test
// given // given
sma = new SecurityMemberAccess(false, true); sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class))); sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when // when
method = StaticTester.getFieldByName("FINAL_PRIVATE_STRING"); method = StaticTester.getFieldByName("FINAL_PRIVATE_STRING");
@@ -374,7 +373,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testBlockedStaticFieldWhenClassIsExcluded() throws Exception { public void testBlockedStaticFieldWhenClassIsExcluded() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(true, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<>(Arrays.asList(Class.class, StaticTester.class))); sma.setExcludedClasses(new HashSet<>(Arrays.asList(Class.class, StaticTester.class)));
// when // when
@@ -385,10 +384,10 @@ public class SecurityMemberAccessTest extends TestCase {
assertFalse("Access to static field isn't blocked!", actual); assertFalse("Access to static field isn't blocked!", actual);
} }
public void testBlockStaticAccess() throws Exception { public void testBlockStaticMethodAccess() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class))); sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when // when
Member method = StaticTester.class.getMethod("sayHello"); Member method = StaticTester.class.getMethod("sayHello");
@@ -400,8 +399,8 @@ public class SecurityMemberAccessTest extends TestCase {
public void testBlockStaticAccessIfClassIsExcluded() throws Exception { public void testBlockStaticAccessIfClassIsExcluded() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class))); sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when // when
Member method = Class.class.getMethod("getClassLoader"); Member method = Class.class.getMethod("getClassLoader");
@@ -413,8 +412,8 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAllowStaticAccessIfClassIsNotExcluded() throws Exception { public void testAllowStaticAccessIfClassIsNotExcluded() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(true, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(ClassLoader.class))); sma.setExcludedClasses(new HashSet<>(Collections.singletonList(ClassLoader.class)));
// when // when
Member method = Class.class.getMethod("getClassLoader"); Member method = Class.class.getMethod("getClassLoader");
@@ -426,7 +425,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessPrimitiveInt() throws Exception { public void testAccessPrimitiveInt() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("java.lang.,ognl,javax")); sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("java.lang.,ognl,javax"));
String propertyName = "intField"; String propertyName = "intField";
@@ -441,7 +440,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessPrimitiveDoubleWithNames() throws Exception { public void testAccessPrimitiveDoubleWithNames() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("ognl.,javax.")); sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("ognl.,javax."));
@@ -493,7 +492,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessPrimitiveDoubleWithPackageRegExs() throws Exception { public void testAccessPrimitiveDoubleWithPackageRegExs() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
Set<Pattern> patterns = new HashSet<>(); Set<Pattern> patterns = new HashSet<>();
patterns.add(Pattern.compile("^java\\.lang\\..*")); patterns.add(Pattern.compile("^java\\.lang\\..*"));
sma.setExcludedPackageNamePatterns(patterns); sma.setExcludedPackageNamePatterns(patterns);
@@ -510,7 +509,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessMemberAccessIsAccessible() throws Exception { public void testAccessMemberAccessIsAccessible() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
Set<Class<?>> excluded = new HashSet<>(); Set<Class<?>> excluded = new HashSet<>();
excluded.add(ognl.MemberAccess.class); excluded.add(ognl.MemberAccess.class);
sma.setExcludedClasses(excluded); sma.setExcludedClasses(excluded);
@@ -528,7 +527,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testAccessMemberAccessIsBlocked() throws Exception { public void testAccessMemberAccessIsBlocked() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
Set<Class<?>> excluded = new HashSet<>(); Set<Class<?>> excluded = new HashSet<>();
excluded.add(SecurityMemberAccess.class); excluded.add(SecurityMemberAccess.class);
sma.setExcludedClasses(excluded); sma.setExcludedClasses(excluded);
@@ -546,7 +545,7 @@ public class SecurityMemberAccessTest extends TestCase {
public void testPackageNameExclusionAsCommaDelimited() { public void testPackageNameExclusionAsCommaDelimited() {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("java.lang.")); sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("java.lang."));
@@ -46,9 +46,9 @@ import java.util.*;
* @author tm_jee * @author tm_jee
*/ */
public class SetPropertiesTest extends XWorkTestCase { public class SetPropertiesTest extends XWorkTestCase {
private OgnlUtil ognlUtil; private OgnlUtil ognlUtil;
@Override @Override
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp(); super.setUp();
@@ -57,7 +57,7 @@ public class SetPropertiesTest extends XWorkTestCase {
} }
public void testOgnlUtilEmptyStringAsLong() { public void testOgnlUtilEmptyStringAsLong() {
Bar bar = new Bar(); Bar bar = new Bar();
Map context = Ognl.createDefaultContext(bar, new SecurityMemberAccess(false, true)); Map context = Ognl.createDefaultContext(bar, new SecurityMemberAccess(true));
context.put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE); context.put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
bar.setId(null); bar.setId(null);
@@ -110,7 +110,7 @@ public class SetPropertiesTest extends XWorkTestCase {
assertEquals(Cat.class, foo.getCats().get(0).getClass()); assertEquals(Cat.class, foo.getCats().get(0).getClass());
assertEquals(Cat.class, foo.getCats().get(1).getClass()); assertEquals(Cat.class, foo.getCats().get(1).getClass());
} }
public void testValueStackSetValueEmptyStringAsLong() { public void testValueStackSetValueEmptyStringAsLong() {
Bar bar = new Bar(); Bar bar = new Bar();
ValueStack vs = ActionContext.getContext().getValueStack(); ValueStack vs = ActionContext.getContext().getValueStack();
@@ -193,11 +193,11 @@ public class SetPropertiesTest extends XWorkTestCase {
} }
public void testAddingToMapsWithObjectsTrue() throws Exception { public void testAddingToMapsWithObjectsTrue() throws Exception {
doTestAddingToMapsWithObjects(true); doTestAddingToMapsWithObjects(true);
} }
public void testAddingToMapsWithObjectsFalse() throws Exception { public void testAddingToMapsWithObjectsFalse() throws Exception {
doTestAddingToMapsWithObjects(false); doTestAddingToMapsWithObjects(false);
@@ -227,8 +227,8 @@ public class SetPropertiesTest extends XWorkTestCase {
} }
public void testAddingAndModifyingCollectionWithObjectsSet() { public void testAddingAndModifyingCollectionWithObjectsSet() {
doTestAddingAndModifyingCollectionWithObjects(new HashSet()); doTestAddingAndModifyingCollectionWithObjects(new HashSet());
} }
@@ -0,0 +1,651 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.test;
import com.opensymphony.xwork2.ognl.SecurityMemberAccess;
import com.opensymphony.xwork2.util.TextParseUtil;
import junit.framework.TestCase;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
public class SecurityMemberAccessTest extends TestCase {
private Map context;
private FooBar target;
@Override
public void setUp() throws Exception {
context = new HashMap();
target = new FooBar();
}
public void testWithoutClassExclusion() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "stringField";
Member member = FooBar.class.getMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1));
// when
boolean accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertTrue(accessible);
}
public void testClassExclusion() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "stringField";
Member member = FooBar.class.getDeclaredMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1));
Set<Class<?>> excluded = new HashSet<>();
excluded.add(FooBar.class);
sma.setExcludedClasses(excluded);
// when
boolean accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertFalse(accessible);
}
public void testObjectClassExclusion() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "toString";
Member member = FooBar.class.getMethod(propertyName);
// when
boolean accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertFalse("toString() from Object is accessible!!!", accessible);
}
public void testObjectOverwrittenMethodsExclusion() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "hashCode";
Member member = FooBar.class.getMethod(propertyName);
// when
boolean accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertTrue("hashCode() from FooBar isn't accessible!!!", accessible);
}
public void testInterfaceInheritanceExclusion() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "barLogic";
Member member = BarInterface.class.getMethod(propertyName);
Set<Class<?>> excluded = new HashSet<>();
excluded.add(BarInterface.class);
sma.setExcludedClasses(excluded);
// when
boolean accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertFalse("barLogic() from BarInterface is accessible!!!", accessible);
}
public void testMiddleOfInheritanceExclusion1() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "fooLogic";
Member member = FooBar.class.getMethod(propertyName);
Set<Class<?>> excluded = new HashSet<>();
excluded.add(BarInterface.class);
sma.setExcludedClasses(excluded);
// when
boolean accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertTrue("fooLogic() from FooInterface isn't accessible!!!", accessible);
}
public void testMiddleOfInheritanceExclusion3() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "barLogic";
Member member = BarInterface.class.getMethod(propertyName);
// when
boolean accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertTrue("barLogic() from BarInterface isn't accessible!!!", accessible);
}
public void testMiddleOfInheritanceExclusion4() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
String propertyName = "barLogic";
Member member = BarInterface.class.getMethod(propertyName);
Set<Class<?>> excluded = new HashSet<>();
excluded.add(FooBarInterface.class);
sma.setExcludedClasses(excluded);
// when
boolean accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertFalse("barLogic() from BarInterface is accessible!!!", accessible);
}
public void testPackageExclusion() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
Set<Pattern> excluded = new HashSet<>();
excluded.add(Pattern.compile("^" + FooBar.class.getPackage().getName().replaceAll("\\.", "\\\\.") + ".*"));
sma.setExcludedPackageNamePatterns(excluded);
String propertyName = "stringField";
Member member = FooBar.class.getMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1));
// when
boolean actual = sma.isAccessible(context, target, member, propertyName);
// then
assertFalse("stringField is accessible!", actual);
}
public void testPackageNameExclusion() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
Set<String> excluded = new HashSet<>();
excluded.add(FooBar.class.getPackage().getName());
sma.setExcludedPackageNames(excluded);
String propertyName = "stringField";
Member member = FooBar.class.getMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1));
// when
boolean actual = sma.isAccessible(context, target, member, propertyName);
// then
assertFalse("stringField is accessible!", actual);
}
public void testDefaultPackageExclusion() {
// given
TestSecurityMemberAccess sma = new TestSecurityMemberAccess(true);
Set<Pattern> excluded = new HashSet<>();
excluded.add(Pattern.compile("^" + FooBar.class.getPackage().getName().replaceAll("\\.", "\\\\.") + ".*"));
sma.setExcludedPackageNamePatterns(excluded);
// when
boolean actual = sma.isPackageExcluded(null, null);
// then
assertFalse("default package is excluded!", actual);
}
public void testDefaultPackageExclusion2() {
// given
TestSecurityMemberAccess sma = new TestSecurityMemberAccess(true);
Set<Pattern> excluded = new HashSet<>();
excluded.add(Pattern.compile("^$"));
sma.setExcludedPackageNamePatterns(excluded);
// when
boolean actual = sma.isPackageExcluded(null, null);
// then
assertTrue("default package isn't excluded!", actual);
}
public void testAccessEnum() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
// when
Member values = MyValues.class.getMethod("values");
boolean actual = sma.isAccessible(context, MyValues.class, values, null);
// then
assertTrue("Access to enums is blocked!", actual);
}
public void testAccessStaticMethod() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when
Member method = StaticTester.class.getMethod("sayHello");
boolean actual = sma.isAccessible(context, Class.class, method, null);
// then
assertFalse("Access to static method is not blocked!", actual);
}
public void testAccessStaticField() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when
Member method = StaticTester.class.getField("MAX_VALUE");
boolean actual = sma.isAccessible(context, null, method, null);
// then
assertTrue("Access to static field is blocked!", actual);
}
public void testBlockedStaticFieldWhenFlagIsFalse() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when
Member method = StaticTester.class.getField("MAX_VALUE");
boolean actual = sma.isAccessible(context, null, method, null);
// then
assertTrue("Access to public static field is blocked?", actual);
// public static final test
// given
sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when
method = StaticTester.class.getField("MIN_VALUE");
actual = sma.isAccessible(context, null, method, null);
// then
assertTrue("Access to public final static field is blocked?", actual);
// package static test
// given
sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when
method = StaticTester.getFieldByName("PACKAGE_STRING");
actual = sma.isAccessible(context, null, method, null);
// then
assertFalse("Access to package static field is allowed?", actual);
// package final static test
// given
sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when
method = StaticTester.getFieldByName("FINAL_PACKAGE_STRING");
actual = sma.isAccessible(context, null, method, null);
// then
assertFalse("Access to package final static field is allowed?", actual);
// protected static test
// given
sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when
method = StaticTester.getFieldByName("PROTECTED_STRING");
actual = sma.isAccessible(context, null, method, null);
// then
assertFalse("Access to protected static field is allowed?", actual);
// protected final static test
// given
sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when
method = StaticTester.getFieldByName("FINAL_PROTECTED_STRING");
actual = sma.isAccessible(context, null, method, null);
// then
assertFalse("Access to protected final static field is allowed?", actual);
// private static test
// given
sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when
method = StaticTester.getFieldByName("PRIVATE_STRING");
actual = sma.isAccessible(context, null, method, null);
// then
assertFalse("Access to private static field is allowed?", actual);
// private final static test
// given
sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when
method = StaticTester.getFieldByName("FINAL_PRIVATE_STRING");
actual = sma.isAccessible(context, null, method, null);
// then
assertFalse("Access to private final static field is allowed?", actual);
}
public void testBlockedStaticFieldWhenClassIsExcluded() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<>(Arrays.asList(Class.class, StaticTester.class)));
// when
Member method = StaticTester.class.getField("MAX_VALUE");
boolean actual = sma.isAccessible(context, null, method, null);
// then
assertFalse("Access to static field isn't blocked!", actual);
}
public void testBlockStaticAccess() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when
Member method = StaticTester.class.getMethod("sayHello");
boolean actual = sma.isAccessible(context, Class.class, method, null);
// then
assertFalse("Access to static isn't blocked!", actual);
}
public void testBlockStaticAccessIfClassIsExcluded() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
// when
Member method = Class.class.getMethod("getClassLoader");
boolean actual = sma.isAccessible(context, Class.class, method, null);
// then
assertFalse("Access to static method of excluded class isn't blocked!", actual);
}
public void testAllowStaticAccessIfClassIsNotExcluded() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(ClassLoader.class)));
// when
Member method = Class.class.getMethod("getClassLoader");
boolean actual = sma.isAccessible(context, Class.class, method, null);
// then
assertTrue("Invalid test! Access to static method of excluded class is blocked!", actual);
}
public void testAccessPrimitiveInt() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("java.lang.,ognl,javax"));
String propertyName = "intField";
Member member = FooBar.class.getMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1));
// when
boolean accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertTrue(accessible);
}
public void testAccessPrimitiveDoubleWithNames() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("ognl.,javax."));
Set<Class<?>> excluded = new HashSet<>();
excluded.add(Object.class);
excluded.add(Runtime.class);
excluded.add(System.class);
excluded.add(Class.class);
excluded.add(ClassLoader.class);
sma.setExcludedClasses(excluded);
String propertyName = "doubleValue";
Member member = Double.class.getMethod(propertyName);
// when
boolean accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertTrue(accessible);
// given
propertyName = "exit";
member = System.class.getMethod(propertyName, int.class);
// when
accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertFalse(accessible);
// given
propertyName = "intField";
member = FooBar.class.getMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1));
// when
accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertTrue(accessible);
// given
propertyName = "doubleField";
member = FooBar.class.getMethod("get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1));
// when
accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertTrue(accessible);
}
public void testAccessPrimitiveDoubleWithPackageRegExs() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
Set<Pattern> patterns = new HashSet<>();
patterns.add(Pattern.compile("^java\\.lang\\..*"));
sma.setExcludedPackageNamePatterns(patterns);
String propertyName = "doubleValue";
Member member = Double.class.getMethod(propertyName);
// when
boolean accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertTrue(accessible);
}
public void testAccessMemberAccessIsAccessible() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
Set<Class<?>> excluded = new HashSet<>();
excluded.add(ognl.MemberAccess.class);
sma.setExcludedClasses(excluded);
String propertyName = "excludedClasses";
String setter = "setExcludedClasses";
Member member = SecurityMemberAccess.class.getMethod(setter, Set.class);
// when
boolean accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertTrue(accessible);
}
public void testAccessMemberAccessIsBlocked() throws Exception {
// given
SecurityMemberAccess sma = new SecurityMemberAccess(true);
Set<Class<?>> excluded = new HashSet<>();
excluded.add(SecurityMemberAccess.class);
sma.setExcludedClasses(excluded);
String propertyName = "excludedClasses";
String setter = "setExcludedClasses";
Member member = SecurityMemberAccess.class.getMethod(setter, Set.class);
// when
boolean accessible = sma.isAccessible(context, target, member, propertyName);
// then
assertFalse(accessible);
}
public void testPackageNameExclusionAsCommaDelimited() {
// given
TestSecurityMemberAccess sma = new TestSecurityMemberAccess(true);
sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("java.lang."));
// when
boolean actual = sma.isPackageExcluded(String.class.getPackage(), null);
actual &= sma.isPackageExcluded(null, String.class.getPackage());
// then
assertTrue("package java.lang. is accessible!", actual);
}
}
class FooBar implements FooBarInterface {
private String stringField;
private int intField;
private Double doubleField;
public String getStringField() {
return stringField;
}
public void setStringField(String stringField) {
this.stringField = stringField;
}
public String fooLogic() {
return "fooLogic";
}
public String barLogic() {
return "barLogic";
}
@Override
public int hashCode() {
return 1;
}
public int getIntField() {
return intField;
}
public void setIntField(int intField) {
this.intField = intField;
}
public Double getDoubleField() {
return doubleField;
}
public void setDoubleField(Double doubleField) {
this.doubleField = doubleField;
}
}
interface FooInterface {
String fooLogic();
}
interface BarInterface {
String barLogic();
}
interface FooBarInterface extends FooInterface, BarInterface {
}
enum MyValues {
ONE, TWO, THREE
}
class StaticTester {
public static int MAX_VALUE = 0;
public static final int MIN_VALUE = 0;
static String PACKAGE_STRING = "package_string";
static final String FINAL_PACKAGE_STRING = "final_package_string";
static String PROTECTED_STRING = "protected_string";
static final String FINAL_PROTECTED_STRING = "final_protected_string";
static String PRIVATE_STRING = "private_string";
static final String FINAL_PRIVATE_STRING = "final_private_string";
public static String sayHello() {
return "Hello";
}
protected static Field getFieldByName(String fieldName) throws NoSuchFieldException {
if (fieldName != null && fieldName.length() > 0) {
return StaticTester.class.getDeclaredField(fieldName);
} else {
throw new NoSuchFieldException("field: " + fieldName + " does not exist");
}
}
}
@@ -0,0 +1,33 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.test;
import com.opensymphony.xwork2.ognl.SecurityMemberAccess;
class TestSecurityMemberAccess extends SecurityMemberAccess {
TestSecurityMemberAccess(boolean allowStaticFieldAccess) {
super(allowStaticFieldAccess);
}
@Override
public boolean isPackageExcluded(Package targetPackage, Package memberPackage) {
return super.isPackageExcluded(targetPackage, memberPackage);
}
}
@@ -18,25 +18,26 @@
*/ */
package org.apache.struts2.interceptor; package org.apache.struts2.interceptor;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.Cookie;
import com.opensymphony.xwork2.security.DefaultAcceptedPatternsChecker;
import com.opensymphony.xwork2.security.DefaultExcludedPatternsChecker;
import com.opensymphony.xwork2.mock.MockActionInvocation;
import org.springframework.mock.web.MockHttpServletRequest;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsInternalTestCase;
import static org.easymock.EasyMock.*;
import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.mock.MockActionInvocation;
import com.opensymphony.xwork2.security.DefaultAcceptedPatternsChecker;
import com.opensymphony.xwork2.security.DefaultExcludedPatternsChecker;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsInternalTestCase;
import org.springframework.mock.web.MockHttpServletRequest;
import javax.servlet.http.Cookie;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
public class CookieInterceptorTest extends StrutsInternalTestCase { public class CookieInterceptorTest extends StrutsInternalTestCase {
@@ -44,9 +45,9 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
public void testIntercepDefault() throws Exception { public void testIntercepDefault() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
request.setCookies( request.setCookies(
new Cookie("cookie1", "cookie1value"), new Cookie("cookie1", "cookie1value"),
new Cookie("cookie2", "cookie2value"), new Cookie("cookie2", "cookie2value"),
new Cookie("cookie3", "cookie3value") new Cookie("cookie3", "cookie3value")
); );
ServletActionContext.setRequest(request); ServletActionContext.setRequest(request);
@@ -55,7 +56,7 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
ActionContext.getContext().getValueStack().push(action); ActionContext.getContext().getValueStack().push(action);
ActionInvocation invocation = (ActionInvocation) createMock(ActionInvocation.class); ActionInvocation invocation = (ActionInvocation) createMock(ActionInvocation.class);
expect(invocation.getAction()).andReturn(action); expect(invocation.getAction()).andReturn(action);
expect(invocation.invoke()).andReturn(Action.SUCCESS); expect(invocation.invoke()).andReturn(Action.SUCCESS);
@@ -75,16 +76,16 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
assertNull(ActionContext.getContext().getValueStack().findValue("cookie1")); assertNull(ActionContext.getContext().getValueStack().findValue("cookie1"));
assertNull(ActionContext.getContext().getValueStack().findValue("cookie2")); assertNull(ActionContext.getContext().getValueStack().findValue("cookie2"));
assertNull(ActionContext.getContext().getValueStack().findValue("cookie3")); assertNull(ActionContext.getContext().getValueStack().findValue("cookie3"));
verify(invocation); verify(invocation);
} }
public void testInterceptAll1() throws Exception { public void testInterceptAll1() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
request.setCookies( request.setCookies(
new Cookie("cookie1", "cookie1value"), new Cookie("cookie1", "cookie1value"),
new Cookie("cookie2", "cookie2value"), new Cookie("cookie2", "cookie2value"),
new Cookie("cookie3", "cookie3value") new Cookie("cookie3", "cookie3value")
); );
ServletActionContext.setRequest(request); ServletActionContext.setRequest(request);
@@ -93,7 +94,7 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
ActionContext.getContext().getValueStack().push(action); ActionContext.getContext().getValueStack().push(action);
ActionInvocation invocation = (ActionInvocation) createMock(ActionInvocation.class); ActionInvocation invocation = (ActionInvocation) createMock(ActionInvocation.class);
expect(invocation.getAction()).andReturn(action); expect(invocation.getAction()).andReturn(action);
expect(invocation.invoke()).andReturn(Action.SUCCESS); expect(invocation.invoke()).andReturn(Action.SUCCESS);
@@ -117,7 +118,7 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value"); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value");
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), "cookie2value"); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), "cookie2value");
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), "cookie3value"); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), "cookie3value");
verify(invocation); verify(invocation);
} }
@@ -125,9 +126,9 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
public void testInterceptAll2() throws Exception { public void testInterceptAll2() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
request.setCookies( request.setCookies(
new Cookie("cookie1", "cookie1value"), new Cookie("cookie1", "cookie1value"),
new Cookie("cookie2", "cookie2value"), new Cookie("cookie2", "cookie2value"),
new Cookie("cookie3", "cookie3value") new Cookie("cookie3", "cookie3value")
); );
ServletActionContext.setRequest(request); ServletActionContext.setRequest(request);
@@ -159,16 +160,16 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value"); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value");
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), "cookie2value"); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), "cookie2value");
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), "cookie3value"); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), "cookie3value");
verify(invocation); verify(invocation);
} }
public void testInterceptSelectedCookiesNameOnly1() throws Exception { public void testInterceptSelectedCookiesNameOnly1() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
request.setCookies( request.setCookies(
new Cookie("cookie1", "cookie1value"), new Cookie("cookie1", "cookie1value"),
new Cookie("cookie2", "cookie2value"), new Cookie("cookie2", "cookie2value"),
new Cookie("cookie3", "cookie3value") new Cookie("cookie3", "cookie3value")
); );
ServletActionContext.setRequest(request); ServletActionContext.setRequest(request);
@@ -200,16 +201,16 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value"); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value");
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), null); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), null);
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), "cookie3value"); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), "cookie3value");
verify(invocation); verify(invocation);
} }
public void testInterceptSelectedCookiesNameOnly2() throws Exception { public void testInterceptSelectedCookiesNameOnly2() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
request.setCookies( request.setCookies(
new Cookie("cookie1", "cookie1value"), new Cookie("cookie1", "cookie1value"),
new Cookie("cookie2", "cookie2value"), new Cookie("cookie2", "cookie2value"),
new Cookie("cookie3", "cookie3value") new Cookie("cookie3", "cookie3value")
); );
ServletActionContext.setRequest(request); ServletActionContext.setRequest(request);
@@ -218,7 +219,7 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
ActionContext.getContext().getValueStack().push(action); ActionContext.getContext().getValueStack().push(action);
ActionInvocation invocation = (ActionInvocation) createMock(ActionInvocation.class); ActionInvocation invocation = (ActionInvocation) createMock(ActionInvocation.class);
expect(invocation.getAction()).andReturn(action); expect(invocation.getAction()).andReturn(action);
expect(invocation.invoke()).andReturn(Action.SUCCESS); expect(invocation.invoke()).andReturn(Action.SUCCESS);
@@ -242,16 +243,16 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value"); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value");
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), null); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), null);
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), "cookie3value"); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), "cookie3value");
verify(invocation); verify(invocation);
} }
public void testInterceptSelectedCookiesNameOnly3() throws Exception { public void testInterceptSelectedCookiesNameOnly3() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
request.setCookies( request.setCookies(
new Cookie("cookie1", "cookie1value"), new Cookie("cookie1", "cookie1value"),
new Cookie("cookie2", "cookie2value"), new Cookie("cookie2", "cookie2value"),
new Cookie("cookie3", "cookie3value") new Cookie("cookie3", "cookie3value")
); );
ServletActionContext.setRequest(request); ServletActionContext.setRequest(request);
@@ -283,7 +284,7 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value"); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value");
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), null); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), null);
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), "cookie3value"); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), "cookie3value");
verify(invocation); verify(invocation);
} }
@@ -291,9 +292,9 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
public void testInterceptSelectedCookiesNameAndValue() throws Exception { public void testInterceptSelectedCookiesNameAndValue() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest(); MockHttpServletRequest request = new MockHttpServletRequest();
request.setCookies( request.setCookies(
new Cookie("cookie1", "cookie1value"), new Cookie("cookie1", "cookie1value"),
new Cookie("cookie2", "cookie2value"), new Cookie("cookie2", "cookie2value"),
new Cookie("cookie3", "cookie3value") new Cookie("cookie3", "cookie3value")
); );
ServletActionContext.setRequest(request); ServletActionContext.setRequest(request);
@@ -325,7 +326,7 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value"); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value");
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), null); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), null);
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), null); assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), null);
verify(invocation); verify(invocation);
} }
@@ -338,20 +339,44 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
String pollution5 = "model[\"class\"]['classLoader']['jarPath']"; String pollution5 = "model[\"class\"]['classLoader']['jarPath']";
String pollution6 = "class[\"classLoader\"]['jarPath']"; String pollution6 = "class[\"classLoader\"]['jarPath']";
try {
new Cookie(pollution1, "pollution1");
fail("It shouldn't be possible to create cookie: " + pollution1);
} catch (IllegalArgumentException e) {
assertEquals(e.getMessage(), "Cookie name \"" + pollution1 + "\" is a reserved token");
}
try {
new Cookie(pollution4, "pollution4");
fail("It shouldn't be possible to create cookie: " + pollution4);
} catch (IllegalArgumentException e) {
assertEquals(e.getMessage(), "Cookie name \"" + pollution4 + "\" is a reserved token");
}
try {
new Cookie(pollution5, "pollution5");
fail("It shouldn't be possible to create cookie: " + pollution5);
} catch (IllegalArgumentException e) {
assertEquals(e.getMessage(), "Cookie name \"" + pollution5 + "\" is a reserved token");
}
try {
new Cookie(pollution6, "pollution6");
fail("It shouldn't be possible to create cookie: " + pollution6);
} catch (IllegalArgumentException e) {
assertEquals(e.getMessage(), "Cookie name \"" + pollution6 + "\" is a reserved token");
}
request.setCookies( request.setCookies(
new Cookie(pollution1, "pollution1"), new Cookie("pollution1", pollution1),
new Cookie("pollution1", pollution1), new Cookie(pollution2, "pollution2"),
new Cookie(pollution2, "pollution2"), new Cookie("pollution2", pollution2),
new Cookie("pollution2", pollution2), new Cookie(pollution3, "pollution3"),
new Cookie(pollution3, "pollution3"), new Cookie("pollution3", pollution3),
new Cookie("pollution3", pollution3), new Cookie("pollution4", pollution4),
new Cookie(pollution4, "pollution4"), new Cookie("pollution5", pollution5),
new Cookie("pollution4", pollution4), new Cookie("pollution6", pollution6)
new Cookie(pollution5, "pollution5"), );
new Cookie("pollution5", pollution5),
new Cookie(pollution6, "pollution6"),
new Cookie("pollution6", pollution6)
);
ServletActionContext.setRequest(request); ServletActionContext.setRequest(request);
final Map<String, Boolean> excludedName = new HashMap<String, Boolean>(); final Map<String, Boolean> excludedName = new HashMap<String, Boolean>();
@@ -375,12 +400,12 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
interceptor.intercept(invocation); interceptor.intercept(invocation);
assertFalse(excludedName.get(pollution1)); //assertFalse(excludedName.get(pollution1));
assertFalse(excludedName.get(pollution2)); assertFalse(excludedName.get(pollution2));
assertFalse(excludedName.get(pollution3)); assertFalse(excludedName.get(pollution3));
assertFalse(excludedName.get(pollution4)); //assertFalse(excludedName.get(pollution4));
assertFalse(excludedName.get(pollution5)); //assertFalse(excludedName.get(pollution5));
assertFalse(excludedName.get(pollution6)); // assertFalse(excludedName.get(pollution6));
} }
public void testCookiesWithStrutsInternalsAccess() throws Exception { public void testCookiesWithStrutsInternalsAccess() throws Exception {
@@ -393,13 +418,13 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
String reqCookieValue = "request.userId=1"; String reqCookieValue = "request.userId=1";
request.setCookies( request.setCookies(
new Cookie(sessionCookieName, "1"), new Cookie(sessionCookieName, "1"),
new Cookie("1", sessionCookieValue), new Cookie("1", sessionCookieValue),
new Cookie(appCookieName, "1"), new Cookie(appCookieName, "1"),
new Cookie("1", appCookieValue), new Cookie("1", appCookieValue),
new Cookie(reqCookieName, "1"), new Cookie(reqCookieName, "1"),
new Cookie("1", reqCookieValue) new Cookie("1", reqCookieValue)
); );
ServletActionContext.setRequest(request); ServletActionContext.setRequest(request);
final Map<String, Boolean> excludedName = new HashMap<String, Boolean>(); final Map<String, Boolean> excludedName = new HashMap<String, Boolean>();
@@ -436,13 +461,13 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
String reqCookieValue = "request.userId=1"; String reqCookieValue = "request.userId=1";
request.setCookies( request.setCookies(
new Cookie(sessionCookieName, "1"), new Cookie(sessionCookieName, "1"),
new Cookie("1", sessionCookieValue), new Cookie("1", sessionCookieValue),
new Cookie(appCookieName, "1"), new Cookie(appCookieName, "1"),
new Cookie("1", appCookieValue), new Cookie("1", appCookieValue),
new Cookie(reqCookieName, "1"), new Cookie(reqCookieName, "1"),
new Cookie("1", reqCookieValue) new Cookie("1", reqCookieValue)
); );
ServletActionContext.setRequest(request); ServletActionContext.setRequest(request);
final Map<String, Boolean> excludedName = new HashMap<>(); final Map<String, Boolean> excludedName = new HashMap<>();
@@ -486,14 +511,29 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
return this.cookies; return this.cookies;
} }
public String getCookie1() { return cookie1; } public String getCookie1() {
public void setCookie1(String cookie1) { this.cookie1 = cookie1; } return cookie1;
}
public String getCookie2() { return cookie2; } public void setCookie1(String cookie1) {
public void setCookie2(String cookie2) { this.cookie2 = cookie2; } this.cookie1 = cookie1;
}
public String getCookie3() { return cookie3; } public String getCookie2() {
public void setCookie3(String cookie3) { this.cookie3 = cookie3; } 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 { public static class MockActionWithActionCookieAware extends ActionSupport implements org.apache.struts2.action.CookiesAware {
@@ -511,14 +551,29 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
return this.cookies; return this.cookies;
} }
public String getCookie1() { return cookie1; } public String getCookie1() {
public void setCookie1(String cookie1) { this.cookie1 = cookie1; } return cookie1;
}
public String getCookie2() { return cookie2; } public void setCookie1(String cookie1) {
public void setCookie2(String cookie2) { this.cookie2 = cookie2; } this.cookie1 = cookie1;
}
public String getCookie3() { return cookie3; } public String getCookie2() {
public void setCookie3(String cookie3) { this.cookie3 = cookie3; } return cookie2;
}
public void setCookie2(String cookie2) {
this.cookie2 = cookie2;
}
public String getCookie3() {
return cookie3;
}
public void setCookie3(String cookie3) {
this.cookie3 = cookie3;
}
} }
} }
@@ -58,7 +58,7 @@ public class PlainResultTest extends StrutsInternalTestCase {
result.execute(invocation); result.execute(invocation);
assertEquals("{ 'value': 'test' }", response.getContentAsString()); assertEquals("{ 'value': 'test' }", response.getContentAsString());
assertEquals("application/json", response.getContentType()); assertEquals("application/json;charset=UTF-8", response.getContentType());
} }
public void testWriteContentTypeCsvWithCookie() throws Exception { public void testWriteContentTypeCsvWithCookie() throws Exception {
@@ -72,7 +72,7 @@ public class PlainResultTest extends StrutsInternalTestCase {
result.execute(invocation); result.execute(invocation);
assertEquals("name;value\nline;1\nline;2", response.getContentAsString()); assertEquals("name;value\nline;1\nline;2", response.getContentAsString());
assertEquals("text/csv", response.getContentType()); assertEquals("text/csv;charset=UTF-8", response.getContentType());
} }
public void testHeaders() throws Exception { public void testHeaders() throws Exception {
@@ -146,4 +146,4 @@ public class PlainResultTest extends StrutsInternalTestCase {
ActionContext.getContext().withServletResponse(response).withActionInvocation(invocation); ActionContext.getContext().withServletResponse(response).withActionInvocation(invocation);
} }
} }
@@ -41,7 +41,7 @@ public class SecurityMemberAccessInServletsTest extends StrutsInternalTestCase {
public void testJavaxServletPackageAccess() throws Exception { public void testJavaxServletPackageAccess() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
Set<Pattern> excluded = new HashSet<Pattern>(); Set<Pattern> excluded = new HashSet<Pattern>();
excluded.add(Pattern.compile("^(?!javax\\.servlet\\..+)(javax\\..+)")); excluded.add(Pattern.compile("^(?!javax\\.servlet\\..+)(javax\\..+)"));
@@ -59,7 +59,7 @@ public class SecurityMemberAccessInServletsTest extends StrutsInternalTestCase {
public void testJavaxServletPackageExclusion() throws Exception { public void testJavaxServletPackageExclusion() throws Exception {
// given // given
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
Set<Pattern> excluded = new HashSet<Pattern>(); Set<Pattern> excluded = new HashSet<Pattern>();
excluded.add(Pattern.compile("^javax\\..+")); excluded.add(Pattern.compile("^javax\\..+"));
@@ -23,14 +23,21 @@ import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
import javax.servlet.RequestDispatcher; import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet; import javax.servlet.Servlet;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import javax.servlet.descriptor.JspConfigDescriptor;
/** /**
@@ -42,12 +49,12 @@ public class StrutsMockServletContext implements ServletContext {
String realPath; String realPath;
String servletInfo; String servletInfo;
String contextPath; String contextPath;
Map initParams = new HashMap(); Map<String, String> initParams = new HashMap<>();
Map attributes = new HashMap(); Map<String, Object> attributes = new HashMap<>();
InputStream resourceAsStream; InputStream resourceAsStream;
public void setInitParameter(String name, String value) { public boolean setInitParameter(String name, String value) {
initParams.put(name, value); return initParams.put(name, value) != null;
} }
public void setRealPath(String value) { public void setRealPath(String value) {
@@ -74,7 +81,7 @@ public class StrutsMockServletContext implements ServletContext {
return null; return null;
} }
public Set getResourcePaths(String s) { public Set<String> getResourcePaths(String s) {
return null; return null;
} }
@@ -105,11 +112,11 @@ public class StrutsMockServletContext implements ServletContext {
return null; return null;
} }
public Enumeration getServlets() { public Enumeration<Servlet> getServlets() {
return null; return null;
} }
public Enumeration getServletNames() { public Enumeration<String> getServletNames() {
return null; return null;
} }
@@ -130,7 +137,7 @@ public class StrutsMockServletContext implements ServletContext {
return (String) initParams.get(s); return (String) initParams.get(s);
} }
public Enumeration getInitParameterNames() { public Enumeration<String> getInitParameterNames() {
return Collections.enumeration(initParams.keySet()); return Collections.enumeration(initParams.keySet());
} }
@@ -138,7 +145,7 @@ public class StrutsMockServletContext implements ServletContext {
return attributes.get(s); return attributes.get(s);
} }
public Enumeration getAttributeNames() { public Enumeration<String> getAttributeNames() {
return Collections.enumeration(attributes.keySet()); return Collections.enumeration(attributes.keySet());
} }
@@ -157,12 +164,142 @@ public class StrutsMockServletContext implements ServletContext {
public void setServletInfo(String servletInfo) { public void setServletInfo(String servletInfo) {
this.servletInfo = servletInfo; this.servletInfo = servletInfo;
} }
public String getContextPath() { public String getContextPath() {
return contextPath; return contextPath;
} }
public void setContextPath(String contextPath) { public void setContextPath(String contextPath) {
this.contextPath = contextPath; this.contextPath = contextPath;
} }
@Override
public int getEffectiveMajorVersion() {
return 0;
}
@Override
public int getEffectiveMinorVersion() {
return 0;
}
@Override
public ServletRegistration.Dynamic addServlet(String servletName, String className) {
return null;
}
@Override
public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet) {
return null;
}
@Override
public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass) {
return null;
}
@Override
public <T extends Servlet> T createServlet(Class<T> clazz) throws ServletException {
return null;
}
@Override
public ServletRegistration getServletRegistration(String servletName) {
return null;
}
@Override
public Map<String, ? extends ServletRegistration> getServletRegistrations() {
return null;
}
@Override
public FilterRegistration.Dynamic addFilter(String filterName, String className) {
return null;
}
@Override
public FilterRegistration.Dynamic addFilter(String filterName, Filter filter) {
return null;
}
@Override
public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass) {
return null;
}
@Override
public <T extends Filter> T createFilter(Class<T> clazz) throws ServletException {
return null;
}
@Override
public FilterRegistration getFilterRegistration(String filterName) {
return null;
}
@Override
public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
return null;
}
@Override
public SessionCookieConfig getSessionCookieConfig() {
return null;
}
@Override
public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes) {
}
@Override
public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
return null;
}
@Override
public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
return null;
}
@Override
public void addListener(String className) {
}
@Override
public <T extends EventListener> void addListener(T t) {
}
@Override
public void addListener(Class<? extends EventListener> listenerClass) {
}
@Override
public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException {
return null;
}
@Override
public JspConfigDescriptor getJspConfigDescriptor() {
return null;
}
@Override
public ClassLoader getClassLoader() {
return null;
}
@Override
public void declareRoles(String... roleNames) {
}
@Override
public String getVirtualServerName() {
return null;
}
} }
@@ -26,4 +26,5 @@
<constant name="struts.excludedClasses" value="java.lang.Object,java.lang.Runtime,ognl.OgnlContext,ognl.MemberAccess,ognl.ClassResolver,ognl.TypeConverter,com.opensymphony.xwork2.ognl.SecurityMemberAccess" /> <constant name="struts.excludedClasses" value="java.lang.Object,java.lang.Runtime,ognl.OgnlContext,ognl.MemberAccess,ognl.ClassResolver,ognl.TypeConverter,com.opensymphony.xwork2.ognl.SecurityMemberAccess" />
<constant name="struts.ognl.allowStaticFieldAccess" value="false"/>
</struts> </struts>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-async-plugin</artifactId> <artifactId>struts2-async-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -25,7 +25,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-cdi-plugin</artifactId> <artifactId>struts2-cdi-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-config-browser-plugin</artifactId> <artifactId>struts2-config-browser-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-convention-plugin</artifactId> <artifactId>struts2-convention-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-dwr-plugin</artifactId> <artifactId>struts2-dwr-plugin</artifactId>
+1 -10
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-embeddedjsp-plugin</artifactId> <artifactId>struts2-embeddedjsp-plugin</artifactId>
@@ -89,15 +89,6 @@
<artifactId>tomcat-jasper</artifactId> <artifactId>tomcat-jasper</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
This is only necessary in tests-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-gxp-plugin</artifactId> <artifactId>struts2-gxp-plugin</artifactId>
+1 -7
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-jasperreports-plugin</artifactId> <artifactId>struts2-jasperreports-plugin</artifactId>
@@ -63,12 +63,6 @@
<artifactId>jsp-api</artifactId> <artifactId>jsp-api</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId> <artifactId>spring-web</artifactId>
+1 -1
View File
@@ -25,7 +25,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-javatemplates-plugin</artifactId> <artifactId>struts2-javatemplates-plugin</artifactId>
+4 -13
View File
@@ -24,8 +24,8 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-jfreechart-plugin</artifactId> <artifactId>struts2-jfreechart-plugin</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>
@@ -71,18 +71,9 @@
<artifactId>easymock</artifactId> <artifactId>easymock</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
This is only necessary in tests-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
</project> </project>
+4 -12
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-json-plugin</artifactId> <artifactId>struts2-json-plugin</artifactId>
@@ -105,18 +105,10 @@
<artifactId>assertj-core</artifactId> <artifactId>assertj-core</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
This is only necessary in tests-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
</project> </project>
+3 -11
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-junit-plugin</artifactId> <artifactId>struts2-junit-plugin</artifactId>
@@ -85,17 +85,9 @@
<artifactId>struts2-portlet-mocks-plugin</artifactId> <artifactId>struts2-portlet-mocks-plugin</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
This is only necessary in tests-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
</project> </project>
+1 -10
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-osgi-plugin</artifactId> <artifactId>struts2-osgi-plugin</artifactId>
@@ -106,15 +106,6 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
This is only necessary in tests-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.apache.logging.log4j</groupId> <groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId> <artifactId>log4j-core</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-oval-plugin</artifactId> <artifactId>struts2-oval-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-pell-multipart-plugin</artifactId> <artifactId>struts2-pell-multipart-plugin</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-plexus-plugin</artifactId> <artifactId>struts2-plexus-plugin</artifactId>
+2 -2
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId> <artifactId>struts2-parent</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
@@ -76,7 +76,7 @@
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
+3 -10
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-portlet-mocks-plugin</artifactId> <artifactId>struts2-portlet-mocks-plugin</artifactId>
@@ -47,17 +47,10 @@
<artifactId>portlet-api</artifactId> <artifactId>portlet-api</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
This is only necessary in tests-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<properties> <properties>
<spring.platformVersion>4.3.30.RELEASE</spring.platformVersion>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
</project> </project>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-portlet-tiles-plugin</artifactId> <artifactId>struts2-portlet-tiles-plugin</artifactId>
+6 -16
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-portlet-plugin</artifactId> <artifactId>struts2-portlet-plugin</artifactId>
@@ -129,27 +129,17 @@
<artifactId>spring-test</artifactId> <artifactId>spring-test</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc-portlet</artifactId>
<optional>true</optional>
</dependency>
<dependency> <dependency>
<groupId>commons-fileupload</groupId> <groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId> <artifactId>commons-fileupload</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
This is only necessary in tests-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <spring.platformVersion>4.3.30.RELEASE</spring.platformVersion>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
</project> </project>
@@ -20,14 +20,22 @@ package org.apache.struts2.portlet.servlet;
import javax.portlet.PortletContext; import javax.portlet.PortletContext;
import javax.portlet.PortletRequestDispatcher; import javax.portlet.PortletRequestDispatcher;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
import javax.servlet.RequestDispatcher; import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet; import javax.servlet.Servlet;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import javax.servlet.descriptor.JspConfigDescriptor;
import java.io.InputStream; import java.io.InputStream;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.EventListener;
import java.util.Map;
import java.util.Set; import java.util.Set;
/** /**
@@ -86,6 +94,11 @@ public class PortletServletContext implements ServletContext {
return portletContext.getInitParameterNames(); return portletContext.getInitParameterNames();
} }
@Override
public boolean setInitParameter(String name, String value) {
return false;
}
/* (non-Javadoc) /* (non-Javadoc)
* @see javax.servlet.ServletContext#getMajorVersion() * @see javax.servlet.ServletContext#getMajorVersion()
*/ */
@@ -107,6 +120,16 @@ public class PortletServletContext implements ServletContext {
return portletContext.getMinorVersion(); return portletContext.getMinorVersion();
} }
@Override
public int getEffectiveMajorVersion() {
return 0;
}
@Override
public int getEffectiveMinorVersion() {
return 0;
}
/** /**
* Returns a {@link PortletServletRequestDispatcher} wrapping the {@link PortletRequestDispatcher} * Returns a {@link PortletServletRequestDispatcher} wrapping the {@link PortletRequestDispatcher}
* as a {@link RequestDispatcher} instance. * as a {@link RequestDispatcher} instance.
@@ -179,6 +202,126 @@ public class PortletServletContext implements ServletContext {
return portletContext.getPortletContextName(); return portletContext.getPortletContextName();
} }
@Override
public ServletRegistration.Dynamic addServlet(String servletName, String className) {
return null;
}
@Override
public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet) {
return null;
}
@Override
public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass) {
return null;
}
@Override
public <T extends Servlet> T createServlet(Class<T> clazz) throws ServletException {
return null;
}
@Override
public ServletRegistration getServletRegistration(String servletName) {
return null;
}
@Override
public Map<String, ? extends ServletRegistration> getServletRegistrations() {
return null;
}
@Override
public FilterRegistration.Dynamic addFilter(String filterName, String className) {
return null;
}
@Override
public FilterRegistration.Dynamic addFilter(String filterName, Filter filter) {
return null;
}
@Override
public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass) {
return null;
}
@Override
public <T extends Filter> T createFilter(Class<T> clazz) throws ServletException {
return null;
}
@Override
public FilterRegistration getFilterRegistration(String filterName) {
return null;
}
@Override
public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
return null;
}
@Override
public SessionCookieConfig getSessionCookieConfig() {
return null;
}
@Override
public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes) {
}
@Override
public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
return null;
}
@Override
public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
return null;
}
@Override
public void addListener(String className) {
}
@Override
public <T extends EventListener> void addListener(T t) {
}
@Override
public void addListener(Class<? extends EventListener> listenerClass) {
}
@Override
public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException {
return null;
}
@Override
public JspConfigDescriptor getJspConfigDescriptor() {
return null;
}
@Override
public ClassLoader getClassLoader() {
return null;
}
@Override
public void declareRoles(String... roleNames) {
}
@Override
public String getVirtualServerName() {
return null;
}
/** /**
* @throws IllegalStateException Not supported in a portlet. * @throws IllegalStateException Not supported in a portlet.
* @see javax.servlet.ServletContext#getServletNames() * @see javax.servlet.ServletContext#getServletNames()
@@ -21,6 +21,7 @@ package org.apache.struts2.portlet.servlet;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream; import javax.servlet.ServletInputStream;
/** /**
@@ -31,11 +32,11 @@ import javax.servlet.ServletInputStream;
public class PortletServletInputStream extends ServletInputStream { public class PortletServletInputStream extends ServletInputStream {
private InputStream portletInputStream; private InputStream portletInputStream;
public PortletServletInputStream(InputStream portletInputStream) { public PortletServletInputStream(InputStream portletInputStream) {
this.portletInputStream = portletInputStream; this.portletInputStream = portletInputStream;
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see java.io.InputStream#read() * @see java.io.InputStream#read()
*/ */
@@ -107,7 +108,7 @@ public class PortletServletInputStream extends ServletInputStream {
public long skip(long n) throws IOException { public long skip(long n) throws IOException {
return portletInputStream.skip(n); return portletInputStream.skip(n);
} }
/** /**
* Get the wrapped {@link InputStream} instance. * Get the wrapped {@link InputStream} instance.
* @return The wrapped {@link InputStream} instance. * @return The wrapped {@link InputStream} instance.
@@ -116,4 +117,18 @@ public class PortletServletInputStream extends ServletInputStream {
return portletInputStream; return portletInputStream;
} }
@Override
public boolean isFinished() {
return true;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
// no-op
}
} }
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import javax.servlet.ServletOutputStream; import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
/** /**
* Wrapper object exposing a {@link OutputStream} from a portlet as a {@link ServletOutputStream} instance. * Wrapper object exposing a {@link OutputStream} from a portlet as a {@link ServletOutputStream} instance.
@@ -31,7 +32,7 @@ import javax.servlet.ServletOutputStream;
public class PortletServletOutputStream extends ServletOutputStream { public class PortletServletOutputStream extends ServletOutputStream {
private OutputStream portletOutputStream; private OutputStream portletOutputStream;
public PortletServletOutputStream(OutputStream portletOutputStream) { public PortletServletOutputStream(OutputStream portletOutputStream) {
this.portletOutputStream = portletOutputStream; this.portletOutputStream = portletOutputStream;
} }
@@ -75,7 +76,7 @@ public class PortletServletOutputStream extends ServletOutputStream {
public void write(byte[] b, int off, int len) throws IOException { public void write(byte[] b, int off, int len) throws IOException {
portletOutputStream.write(b, off, len); portletOutputStream.write(b, off, len);
} }
/** /**
* Get the wrapped {@link OutputStream} instance. * Get the wrapped {@link OutputStream} instance.
* @return The wrapped {@link OutputStream} instance. * @return The wrapped {@link OutputStream} instance.
@@ -83,4 +84,14 @@ public class PortletServletOutputStream extends ServletOutputStream {
public OutputStream getOutputStream() { public OutputStream getOutputStream() {
return portletOutputStream; return portletOutputStream;
} }
@Override
public boolean isReady() {
return true;
}
@Override
public void setWriteListener(WriteListener writeListener) {
// no-op
}
} }
@@ -23,6 +23,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.security.Principal; import java.security.Principal;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Locale; import java.util.Locale;
@@ -34,12 +35,20 @@ import javax.portlet.PortletContext;
import javax.portlet.PortletRequest; import javax.portlet.PortletRequest;
import javax.portlet.PortletRequestDispatcher; import javax.portlet.PortletRequestDispatcher;
import javax.portlet.PortletSession; import javax.portlet.PortletSession;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher; import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream; import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie; import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpUpgradeHandler;
import javax.servlet.http.Part;
import static org.apache.struts2.portlet.PortletConstants.*; import static org.apache.struts2.portlet.PortletConstants.*;
@@ -71,7 +80,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.http.HttpServletRequest#getAuthType() * @see javax.servlet.http.HttpServletRequest#getAuthType()
*/ */
public String getAuthType() { public String getAuthType() {
@@ -80,7 +89,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.http.HttpServletRequest#getContextPath() * @see javax.servlet.http.HttpServletRequest#getContextPath()
*/ */
public String getContextPath() { public String getContextPath() {
@@ -89,7 +98,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -102,7 +111,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -113,7 +122,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Gets a property from the {@link PortletRequest}. Note that a * Gets a property from the {@link PortletRequest}. Note that a
* {@link PortletRequest} is not guaranteed to map properties to headers. * {@link PortletRequest} is not guaranteed to map properties to headers.
* *
* @see PortletRequest#getProperty(String) * @see PortletRequest#getProperty(String)
* @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String) * @see javax.servlet.http.HttpServletRequest#getHeader(java.lang.String)
*/ */
@@ -124,7 +133,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Gets the property names from the {@link PortletRequest}. Note that a * Gets the property names from the {@link PortletRequest}. Note that a
* {@link PortletRequest} is not guaranteed to map properties to headers. * {@link PortletRequest} is not guaranteed to map properties to headers.
* *
* @see PortletRequest#getPropertyNames() * @see PortletRequest#getPropertyNames()
* @see javax.servlet.http.HttpServletRequest#getHeaderNames() * @see javax.servlet.http.HttpServletRequest#getHeaderNames()
*/ */
@@ -136,7 +145,7 @@ public class PortletServletRequest implements HttpServletRequest {
* Gets the values for the specified property from the * Gets the values for the specified property from the
* {@link PortletRequest}. Note that a {@link PortletRequest} is not * {@link PortletRequest}. Note that a {@link PortletRequest} is not
* guaranteed to map properties to headers. * guaranteed to map properties to headers.
* *
* @see PortletRequest#getProperties(String) * @see PortletRequest#getProperties(String)
* @see HttpServletRequest#getHeaders(String) * @see HttpServletRequest#getHeaders(String)
*/ */
@@ -146,7 +155,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -156,7 +165,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.http.HttpServletRequest#getMethod() * @see javax.servlet.http.HttpServletRequest#getMethod()
*/ */
public String getMethod() { public String getMethod() {
@@ -170,7 +179,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.http.HttpServletRequest#getPathInfo() * @see javax.servlet.http.HttpServletRequest#getPathInfo()
*/ */
public String getPathInfo() { public String getPathInfo() {
@@ -179,7 +188,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.http.HttpServletRequest#getPathTranslated() * @see javax.servlet.http.HttpServletRequest#getPathTranslated()
*/ */
public String getPathTranslated() { public String getPathTranslated() {
@@ -188,7 +197,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.http.HttpServletRequest#getQueryString() * @see javax.servlet.http.HttpServletRequest#getQueryString()
*/ */
public String getQueryString() { public String getQueryString() {
@@ -197,7 +206,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.http.HttpServletRequest#getRemoteUser() * @see javax.servlet.http.HttpServletRequest#getRemoteUser()
*/ */
public String getRemoteUser() { public String getRemoteUser() {
@@ -206,7 +215,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -216,7 +225,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -226,7 +235,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.http.HttpServletRequest#getRequestedSessionId() * @see javax.servlet.http.HttpServletRequest#getRequestedSessionId()
*/ */
public String getRequestedSessionId() { public String getRequestedSessionId() {
@@ -237,7 +246,7 @@ public class PortletServletRequest implements HttpServletRequest {
* A {@link PortletRequest} has no servlet path. But for compatibility with * A {@link PortletRequest} has no servlet path. But for compatibility with
* Struts 2 components and interceptors, the action parameter on the request * Struts 2 components and interceptors, the action parameter on the request
* is mapped to the servlet path. * is mapped to the servlet path.
* *
* @see javax.servlet.http.HttpServletRequest#getServletPath() * @see javax.servlet.http.HttpServletRequest#getServletPath()
*/ */
public String getServletPath() { public String getServletPath() {
@@ -250,16 +259,21 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Get the {@link PortletSession} as a {@link PortletHttpSession} instance. * Get the {@link PortletSession} as a {@link PortletHttpSession} instance.
* *
* @see javax.servlet.http.HttpServletRequest#getSession() * @see javax.servlet.http.HttpServletRequest#getSession()
*/ */
public HttpSession getSession() { public HttpSession getSession() {
return new PortletHttpSession(portletRequest.getPortletSession()); return new PortletHttpSession(portletRequest.getPortletSession());
} }
@Override
public String changeSessionId() {
return null;
}
/** /**
* Get the {@link PortletSession} as a {@link PortletHttpSession} instance. * Get the {@link PortletSession} as a {@link PortletHttpSession} instance.
* *
* @see javax.servlet.http.HttpServletRequest#getSession(boolean) * @see javax.servlet.http.HttpServletRequest#getSession(boolean)
*/ */
public HttpSession getSession(boolean create) { public HttpSession getSession(boolean create) {
@@ -268,7 +282,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.http.HttpServletRequest#getUserPrincipal() * @see javax.servlet.http.HttpServletRequest#getUserPrincipal()
*/ */
public Principal getUserPrincipal() { public Principal getUserPrincipal() {
@@ -277,7 +291,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -287,7 +301,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -297,7 +311,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -305,9 +319,39 @@ public class PortletServletRequest implements HttpServletRequest {
throw new IllegalStateException("Not allowed in a portlet"); throw new IllegalStateException("Not allowed in a portlet");
} }
@Override
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
return false;
}
@Override
public void login(String username, String password) throws ServletException {
}
@Override
public void logout() throws ServletException {
}
@Override
public Collection<Part> getParts() throws IOException, ServletException {
return null;
}
@Override
public Part getPart(String name) throws IOException, ServletException {
return null;
}
@Override
public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException {
return null;
}
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid() * @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid()
*/ */
public boolean isRequestedSessionIdValid() { public boolean isRequestedSessionIdValid() {
@@ -316,7 +360,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String) * @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String)
*/ */
public boolean isUserInRole(String role) { public boolean isUserInRole(String role) {
@@ -327,7 +371,7 @@ public class PortletServletRequest implements HttpServletRequest {
* Gets an attribute value on the {@link PortletRequest}. If the attribute * Gets an attribute value on the {@link PortletRequest}. If the attribute
* name is <tt>javax.servlet.include.servlet_path</tt>, it returns the * name is <tt>javax.servlet.include.servlet_path</tt>, it returns the
* same as {@link PortletServletRequest#getServletPath()} * same as {@link PortletServletRequest#getServletPath()}
* *
* @see javax.servlet.ServletRequest#getAttribute(java.lang.String) * @see javax.servlet.ServletRequest#getAttribute(java.lang.String)
*/ */
public Object getAttribute(String name) { public Object getAttribute(String name) {
@@ -340,7 +384,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.ServletRequest#getAttributeNames() * @see javax.servlet.ServletRequest#getAttributeNames()
*/ */
public Enumeration getAttributeNames() { public Enumeration getAttributeNames() {
@@ -349,7 +393,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Can only be invoked in the event phase. * Can only be invoked in the event phase.
* *
* @see ServletRequest#getCharacterEncoding() * @see ServletRequest#getCharacterEncoding()
* @throws IllegalStateException * @throws IllegalStateException
* If the portlet is not in the event phase. * If the portlet is not in the event phase.
@@ -364,7 +408,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Can only be invoked in the event phase. * Can only be invoked in the event phase.
* *
* @see ServletRequest#getContentLength() * @see ServletRequest#getContentLength()
* @throws IllegalStateException * @throws IllegalStateException
* If the portlet is not in the event phase. * If the portlet is not in the event phase.
@@ -377,9 +421,14 @@ public class PortletServletRequest implements HttpServletRequest {
} }
} }
@Override
public long getContentLengthLong() {
return 0;
}
/** /**
* Can only be invoked in the event phase. * Can only be invoked in the event phase.
* *
* @see ServletRequest#getContentType() * @see ServletRequest#getContentType()
* @throws IllegalStateException * @throws IllegalStateException
* If the portlet is not in the event phase. * If the portlet is not in the event phase.
@@ -396,7 +445,7 @@ public class PortletServletRequest implements HttpServletRequest {
* Can only be invoked in the event phase. When invoked in the event phase, * Can only be invoked in the event phase. When invoked in the event phase,
* it will wrap the portlet's {@link InputStream} as a * it will wrap the portlet's {@link InputStream} as a
* {@link PortletServletInputStream}. * {@link PortletServletInputStream}.
* *
* @see ServletRequest#getInputStream() * @see ServletRequest#getInputStream()
* @throws IllegalStateException * @throws IllegalStateException
* If the portlet is not in the event phase. * If the portlet is not in the event phase.
@@ -412,7 +461,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -425,7 +474,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -438,7 +487,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -449,9 +498,44 @@ public class PortletServletRequest implements HttpServletRequest {
throw new IllegalStateException("Not allowed in a portlet"); throw new IllegalStateException("Not allowed in a portlet");
} }
@Override
public ServletContext getServletContext() {
return null;
}
@Override
public AsyncContext startAsync() throws IllegalStateException {
return null;
}
@Override
public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException {
return null;
}
@Override
public boolean isAsyncStarted() {
return false;
}
@Override
public boolean isAsyncSupported() {
return false;
}
@Override
public AsyncContext getAsyncContext() {
return null;
}
@Override
public DispatcherType getDispatcherType() {
return null;
}
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.ServletRequest#getLocale() * @see javax.servlet.ServletRequest#getLocale()
*/ */
public Locale getLocale() { public Locale getLocale() {
@@ -460,7 +544,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.ServletRequest#getLocales() * @see javax.servlet.ServletRequest#getLocales()
*/ */
public Enumeration getLocales() { public Enumeration getLocales() {
@@ -469,7 +553,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.ServletRequest#getParameter(java.lang.String) * @see javax.servlet.ServletRequest#getParameter(java.lang.String)
*/ */
public String getParameter(String name) { public String getParameter(String name) {
@@ -485,7 +569,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.ServletRequest#getParameterMap() * @see javax.servlet.ServletRequest#getParameterMap()
*/ */
public Map getParameterMap() { public Map getParameterMap() {
@@ -494,7 +578,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.ServletRequest#getParameterNames() * @see javax.servlet.ServletRequest#getParameterNames()
*/ */
public Enumeration getParameterNames() { public Enumeration getParameterNames() {
@@ -503,7 +587,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.ServletRequest#getParameterValues(java.lang.String) * @see javax.servlet.ServletRequest#getParameterValues(java.lang.String)
*/ */
public String[] getParameterValues(String name) { public String[] getParameterValues(String name) {
@@ -512,7 +596,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -525,7 +609,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Can only be invoked in the event phase. * Can only be invoked in the event phase.
* *
* @see ServletRequest#getReader() * @see ServletRequest#getReader()
* @throws IllegalStateException * @throws IllegalStateException
* If the portlet is not in the event phase. * If the portlet is not in the event phase.
@@ -540,7 +624,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.ServletRequest#getRealPath(java.lang.String) * @see javax.servlet.ServletRequest#getRealPath(java.lang.String)
*/ */
public String getRealPath(String path) { public String getRealPath(String path) {
@@ -549,7 +633,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -562,7 +646,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -575,7 +659,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -589,7 +673,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Get the {@link PortletRequestDispatcher} as a * Get the {@link PortletRequestDispatcher} as a
* {@link PortletServletRequestDispatcher} instance. * {@link PortletServletRequestDispatcher} instance.
* *
* @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String) * @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String)
*/ */
public RequestDispatcher getRequestDispatcher(String path) { public RequestDispatcher getRequestDispatcher(String path) {
@@ -599,7 +683,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.ServletRequest#getScheme() * @see javax.servlet.ServletRequest#getScheme()
*/ */
public String getScheme() { public String getScheme() {
@@ -608,7 +692,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.ServletRequest#getServerName() * @see javax.servlet.ServletRequest#getServerName()
*/ */
public String getServerName() { public String getServerName() {
@@ -617,7 +701,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Not allowed in a portlet. * Not allowed in a portlet.
* *
* @throws IllegalStateException * @throws IllegalStateException
* Not allowed in a portlet. * Not allowed in a portlet.
*/ */
@@ -630,7 +714,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.ServletRequest#isSecure() * @see javax.servlet.ServletRequest#isSecure()
*/ */
public boolean isSecure() { public boolean isSecure() {
@@ -639,7 +723,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.ServletRequest#removeAttribute(java.lang.String) * @see javax.servlet.ServletRequest#removeAttribute(java.lang.String)
*/ */
public void removeAttribute(String name) { public void removeAttribute(String name) {
@@ -648,7 +732,7 @@ public class PortletServletRequest implements HttpServletRequest {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see javax.servlet.ServletRequest#setAttribute(java.lang.String, * @see javax.servlet.ServletRequest#setAttribute(java.lang.String,
* java.lang.Object) * java.lang.Object)
*/ */
@@ -658,7 +742,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Can only be invoked in the event phase. * Can only be invoked in the event phase.
* *
* @see ServletRequest#setCharacterEncoding(String) * @see ServletRequest#setCharacterEncoding(String)
* @throws IllegalStateException * @throws IllegalStateException
* If the portlet is not in the event phase. * If the portlet is not in the event phase.
@@ -674,7 +758,7 @@ public class PortletServletRequest implements HttpServletRequest {
/** /**
* Get the wrapped {@link PortletRequest} instance. * Get the wrapped {@link PortletRequest} instance.
* *
* @return The wrapped {@link PortletRequest} instance. * @return The wrapped {@link PortletRequest} instance.
*/ */
public PortletRequest getPortletRequest() { public PortletRequest getPortletRequest() {
@@ -20,6 +20,7 @@ package org.apache.struts2.portlet.servlet;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.Collection;
import java.util.Locale; import java.util.Locale;
import javax.portlet.PortletResponse; import javax.portlet.PortletResponse;
@@ -31,11 +32,11 @@ import javax.servlet.http.HttpServletResponse;
public class PortletServletResponse implements HttpServletResponse { public class PortletServletResponse implements HttpServletResponse {
protected PortletResponse portletResponse; protected PortletResponse portletResponse;
public PortletServletResponse(PortletResponse portletResponse) { public PortletServletResponse(PortletResponse portletResponse) {
this.portletResponse = portletResponse; this.portletResponse = portletResponse;
} }
public void addCookie(Cookie cookie) { public void addCookie(Cookie cookie) {
throw new IllegalStateException("Not allowed in a portlet"); throw new IllegalStateException("Not allowed in a portlet");
} }
@@ -104,6 +105,26 @@ public class PortletServletResponse implements HttpServletResponse {
throw new IllegalStateException("Not allowed in a portlet"); throw new IllegalStateException("Not allowed in a portlet");
} }
@Override
public int getStatus() {
return 0;
}
@Override
public String getHeader(String name) {
return null;
}
@Override
public Collection<String> getHeaders(String name) {
return null;
}
@Override
public Collection<String> getHeaderNames() {
return null;
}
public void flushBuffer() throws IOException { public void flushBuffer() throws IOException {
if(portletResponse instanceof RenderResponse) { if(portletResponse instanceof RenderResponse) {
((RenderResponse)portletResponse).flushBuffer(); ((RenderResponse)portletResponse).flushBuffer();
@@ -211,6 +232,11 @@ public class PortletServletResponse implements HttpServletResponse {
throw new IllegalStateException("Not allowed in a portlet"); throw new IllegalStateException("Not allowed in a portlet");
} }
@Override
public void setContentLengthLong(long len) {
}
public void setContentType(String type) { public void setContentType(String type) {
if(portletResponse instanceof RenderResponse) { if(portletResponse instanceof RenderResponse) {
((RenderResponse)portletResponse).setContentType(type); ((RenderResponse)portletResponse).setContentType(type);
+1 -11
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-rest-plugin</artifactId> <artifactId>struts2-rest-plugin</artifactId>
@@ -96,16 +96,6 @@
<artifactId>assertj-core</artifactId> <artifactId>assertj-core</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
This is only necessary in tests-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>
@@ -34,23 +34,22 @@ import java.io.InputStreamReader;
*/ */
public class ContentTypeInterceptor extends AbstractInterceptor { public class ContentTypeInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 1L; private final ContentTypeHandlerManager selector;
ContentTypeHandlerManager selector;
@Inject @Inject
public void setContentTypeHandlerSelector(ContentTypeHandlerManager sel) { public ContentTypeInterceptor(ContentTypeHandlerManager selector) {
this.selector = sel; this.selector = selector;
} }
public String intercept(ActionInvocation invocation) throws Exception { public String intercept(ActionInvocation invocation) throws Exception {
HttpServletRequest request = ServletActionContext.getRequest(); HttpServletRequest request = ServletActionContext.getRequest();
ContentTypeHandler handler = selector.getHandlerForRequest(request); ContentTypeHandler handler = selector.getHandlerForRequest(request);
Object target = invocation.getAction(); Object target = invocation.getAction();
if (target instanceof ModelDriven) { if (target instanceof ModelDriven) {
target = ((ModelDriven)target).getModel(); target = ((ModelDriven<?>)target).getModel();
} }
if (request.getContentLength() > 0) { if (request.getContentLength() > 0) {
InputStream is = request.getInputStream(); InputStream is = request.getInputStream();
InputStreamReader reader = new InputStreamReader(is); InputStreamReader reader = new InputStreamReader(is);
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-sitemesh-plugin</artifactId> <artifactId>struts2-sitemesh-plugin</artifactId>
+7 -16
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-spring-plugin</artifactId> <artifactId>struts2-spring-plugin</artifactId>
@@ -51,13 +51,13 @@
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId> <artifactId>spring-web</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId> <artifactId>spring-aspects</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId> <artifactId>spring-aop</artifactId>
@@ -80,30 +80,21 @@
<artifactId>commons-jci-fam</artifactId> <artifactId>commons-jci-fam</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId> <artifactId>spring-context-support</artifactId>
<optional>true</optional> <optional>true</optional>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.easymock</groupId> <groupId>org.easymock</groupId>
<artifactId>easymock</artifactId> <artifactId>easymock</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
</dependencies>
<!-- The Servlet API mocks in Spring Framework 4.0 support Servlet 3.0 and higher
So this is only necessary in tests-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
</project> </project>
@@ -45,7 +45,7 @@ public class SecurityMemberAccessProxyTest extends XWorkTestCase {
ActionProxy proxy = actionProxyFactory.createActionProxy(null, ActionProxy proxy = actionProxyFactory.createActionProxy(null,
"chaintoAOPedTestSubBeanAction", null, context); "chaintoAOPedTestSubBeanAction", null, context);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setDisallowProxyMemberAccess(true); sma.setDisallowProxyMemberAccess(true);
Member member = proxy.getAction().getClass().getMethod("isExposeProxy"); Member member = proxy.getAction().getClass().getMethod("isExposeProxy");
@@ -58,7 +58,7 @@ public class SecurityMemberAccessProxyTest extends XWorkTestCase {
ActionProxy proxy = actionProxyFactory.createActionProxy(null, ActionProxy proxy = actionProxyFactory.createActionProxy(null,
"chaintoAOPedTestSubBeanAction", null, context); "chaintoAOPedTestSubBeanAction", null, context);
SecurityMemberAccess sma = new SecurityMemberAccess(false, true); SecurityMemberAccess sma = new SecurityMemberAccess(true);
Member member = proxy.getAction().getClass().getMethod("isExposeProxy"); Member member = proxy.getAction().getClass().getMethod("isExposeProxy");
@@ -0,0 +1,69 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.test;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.XWorkTestCase;
import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
import com.opensymphony.xwork2.ognl.SecurityMemberAccess;
import org.apache.struts2.config.StrutsXmlConfigurationProvider;
import java.lang.reflect.Member;
import java.util.HashMap;
import java.util.Map;
public class SecurityMemberAccessProxyTest extends XWorkTestCase {
private Map<String, Object> context;
@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);
}
public void testProxyAccessIsBlocked() throws Exception {
ActionProxy proxy = actionProxyFactory.createActionProxy(null,
"chaintoAOPedTestSubBeanAction", null, context);
SecurityMemberAccess sma = new SecurityMemberAccess(true);
sma.setDisallowProxyMemberAccess(true);
Member member = proxy.getAction().getClass().getMethod("isExposeProxy");
boolean accessible = sma.isAccessible(context, proxy.getAction(), member, "");
assertFalse(accessible);
}
public void testProxyAccessIsAccessible() throws Exception {
ActionProxy proxy = actionProxyFactory.createActionProxy(null,
"chaintoAOPedTestSubBeanAction", null, context);
SecurityMemberAccess sma = new SecurityMemberAccess(true);
Member member = proxy.getAction().getClass().getMethod("isExposeProxy");
boolean accessible = sma.isAccessible(context, proxy.getAction(), member, "");
assertTrue(accessible);
}
}
+4 -12
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-testng-plugin</artifactId> <artifactId>struts2-testng-plugin</artifactId>
@@ -51,18 +51,10 @@
<artifactId>jsp-api</artifactId> <artifactId>jsp-api</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
This is only necessary in tests-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
</project> </project>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-tiles-plugin</artifactId> <artifactId>struts2-tiles-plugin</artifactId>
+2 -11
View File
@@ -24,7 +24,7 @@
<parent> <parent>
<groupId>org.apache.struts</groupId> <groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId> <artifactId>struts2-plugins</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
</parent> </parent>
<artifactId>struts2-velocity-plugin</artifactId> <artifactId>struts2-velocity-plugin</artifactId>
@@ -51,7 +51,7 @@
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
</dependency> </dependency>
<dependency> <dependency>
@@ -59,15 +59,6 @@
<artifactId>jsp-api</artifactId> <artifactId>jsp-api</artifactId>
</dependency> </dependency>
<!-- The Servlet API mocks in Spring Framework 4.0 support Servlet 3.0 and higher
So this is only necessary in tests-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>mockobjects</groupId> <groupId>mockobjects</groupId>
<artifactId>mockobjects-core</artifactId> <artifactId>mockobjects-core</artifactId>
+29 -32
View File
@@ -29,7 +29,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>struts2-parent</artifactId> <artifactId>struts2-parent</artifactId>
<version>6.0.0-SNAPSHOT</version> <version>6.0.0</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>Struts 2</name> <name>Struts 2</name>
<url>http://struts.apache.org/</url> <url>http://struts.apache.org/</url>
@@ -51,7 +51,7 @@
<connection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</connection> <connection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</connection>
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</developerConnection> <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</developerConnection>
<url>https://github.com/apache/struts/</url> <url>https://github.com/apache/struts/</url>
<tag>HEAD</tag> <tag>STRUTS_6_0_0</tag>
</scm> </scm>
<issueManagement> <issueManagement>
@@ -104,17 +104,18 @@
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.outputTimestamp>2022-02-24T06:11:22Z</project.build.outputTimestamp> <project.build.outputTimestamp>2022-06-02T07:06:42Z</project.build.outputTimestamp>
<java.version>1.8</java.version> <maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!-- dependency versions in alphanumeric order --> <!-- dependency versions in alphanumeric order -->
<asm.version>9.2</asm.version> <asm.version>9.2</asm.version>
<jackson.version>2.10.5</jackson.version> <jackson.version>2.13.2</jackson.version>
<jackson-databind.version>2.10.5.1</jackson-databind.version> <jackson-databind.version>2.13.2.1</jackson-databind.version>
<log4j2.version>2.17.2</log4j2.version> <log4j2.version>2.17.2</log4j2.version>
<ognl.version>3.3.2</ognl.version> <ognl.version>3.3.2</ognl.version>
<slf4j.version>1.7.32</slf4j.version> <slf4j.version>1.7.32</slf4j.version>
<spring.platformVersion>4.3.30.RELEASE</spring.platformVersion> <spring.platformVersion>5.3.20</spring.platformVersion>
<tiles.version>3.0.8</tiles.version> <tiles.version>3.0.8</tiles.version>
<tiles-request.version>1.0.7</tiles-request.version> <tiles-request.version>1.0.7</tiles-request.version>
<maven-surefire-plugin.version>3.0.0-M4</maven-surefire-plugin.version> <maven-surefire-plugin.version>3.0.0-M4</maven-surefire-plugin.version>
@@ -235,7 +236,7 @@
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.mortbay.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId> <artifactId>jetty-maven-plugin</artifactId>
<configuration> <configuration>
<jvmArgs>${argLine}</jvmArgs> <jvmArgs>${argLine}</jvmArgs>
@@ -247,7 +248,7 @@
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId> <artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.5</version> <version>0.8.8</version>
<executions> <executions>
<execution> <execution>
<id>prepare-agent</id> <id>prepare-agent</id>
@@ -264,9 +265,9 @@
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.eluder.coveralls</groupId> <groupId>io.jsonwebtoken.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId> <artifactId>coveralls-maven-plugin</artifactId>
<version>4.3.0</version> <version>4.4.1</version>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
@@ -316,7 +317,7 @@
<plugin> <plugin>
<groupId>org.apache.felix</groupId> <groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId> <artifactId>maven-bundle-plugin</artifactId>
<version>5.1.3</version> <version>5.1.6</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@@ -377,7 +378,7 @@
<plugin> <plugin>
<groupId>org.owasp</groupId> <groupId>org.owasp</groupId>
<artifactId>dependency-check-maven</artifactId> <artifactId>dependency-check-maven</artifactId>
<version>6.5.1</version> <version>7.0.1</version>
<configuration> <configuration>
<suppressionFiles> <suppressionFiles>
<suppressionFile>src/etc/project-suppression.xml</suppressionFile> <suppressionFile>src/etc/project-suppression.xml</suppressionFile>
@@ -405,18 +406,15 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-wrapper-plugin</artifactId>
<version>3.1.0</version>
</plugin>
</plugins> </plugins>
</pluginManagement> </pluginManagement>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId> <artifactId>maven-release-plugin</artifactId>
@@ -480,7 +478,11 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-wrapper-plugin</artifactId>
<version>3.1.0</version>
</plugin>
</plugins> </plugins>
<defaultGoal>install</defaultGoal> <defaultGoal>install</defaultGoal>
@@ -704,7 +706,7 @@
<dependency> <dependency>
<groupId>org.freemarker</groupId> <groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId> <artifactId>freemarker</artifactId>
<version>2.3.30</version> <version>2.3.31</version>
</dependency> </dependency>
<dependency> <dependency>
@@ -795,7 +797,7 @@
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<version>4.13</version> <version>4.13.1</version>
</dependency> </dependency>
<dependency> <dependency>
@@ -807,8 +809,8 @@
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
<version>2.5</version> <version>3.1.0</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
@@ -986,11 +988,6 @@
<artifactId>spring-core</artifactId> <artifactId>spring-core</artifactId>
<version>${spring.platformVersion}</version> <version>${spring.platformVersion}</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc-portlet</artifactId>
<version>${spring.platformVersion}</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId> <artifactId>spring-context</artifactId>
@@ -1218,7 +1215,7 @@
<dependency> <dependency>
<groupId>xerces</groupId> <groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId> <artifactId>xercesImpl</artifactId>
<version>2.12.0</version> <version>2.12.2</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>