mirror of
https://github.com/apache/struts.git
synced 2026-09-05 05:39:39 +00:00
Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 981885fd6a | |||
| 07b88fcc35 | |||
| 2cbe47297e | |||
| 545add9365 | |||
| ebecc7d39d | |||
| 226a1d49ce | |||
| 075ef7c4e1 | |||
| 1237110652 | |||
| 3f2518afa8 | |||
| 9f9edf4705 | |||
| 7e912742ed | |||
| c98b60cd9a | |||
| 5ae9688ae8 | |||
| b72200aabf | |||
| 16e7c9b459 | |||
| bea1c6f09f | |||
| 888884cc51 | |||
| b387abae01 | |||
| 059a2a6117 | |||
| c0a3be9fd8 | |||
| 4a7cae029a | |||
| 9873a7f56b | |||
| 086b514d59 | |||
| 6024dd6fa4 | |||
| 4eb2ee8384 | |||
| 8e49362bf8 | |||
| 7541d9ab35 | |||
| c82fdb5e76 | |||
| f40f9f15e5 | |||
| 2d9cdb73a5 | |||
| d07a496d5c | |||
| bef1f67d4a | |||
| 05ca1ff087 | |||
| 199f356669 | |||
| e2718aa482 | |||
| b73fec4de0 | |||
| c2795d2e30 | |||
| a987e31a0e | |||
| 6aff5b7faa | |||
| 084c66723d | |||
| 5b40f9f48e | |||
| e9d0a5518c | |||
| 4c37011020 | |||
| fbb31ee65b | |||
| c094052969 | |||
| 84164c422e | |||
| 8b11a3873a | |||
| 115fef2af7 | |||
| 4d8108e766 |
@@ -1,3 +1,4 @@
|
||||
# Documentation https://s.apache.org/asfyaml
|
||||
notifications:
|
||||
commits: commits@struts.apache.org
|
||||
# Send all issue emails (new, closed, comments) to issues@
|
||||
@@ -8,3 +9,6 @@ notifications:
|
||||
pullrequests_comment: issues@struts.apache.org
|
||||
# Link opened PRs with JIRA
|
||||
jira_options: link label worklog
|
||||
|
||||
github:
|
||||
del_branch_on_merge: true
|
||||
|
||||
+1
-1
@@ -14,5 +14,5 @@
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# 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
|
||||
|
||||
+4
-7
@@ -14,17 +14,14 @@ global:
|
||||
matrix:
|
||||
include:
|
||||
- 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:
|
||||
- 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
|
||||
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
||||
./mvnw test -DskipAssembly -B;
|
||||
else
|
||||
./mvnw test -DskipAssembly -Dupdate-impact -B;
|
||||
fi;
|
||||
./mvnw clean package test -DskipAssembly -B;
|
||||
fi;
|
||||
|
||||
cache:
|
||||
|
||||
Vendored
+10
-10
@@ -39,12 +39,12 @@ pipeline {
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh 'mvn -B clean install -DskipTests -DskipAssembly'
|
||||
sh './mvnw -B clean install -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
steps {
|
||||
sh 'mvn -B test'
|
||||
sh './mvnw -B test'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
@@ -74,12 +74,12 @@ pipeline {
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh 'mvn -B clean install -DskipTests -DskipAssembly'
|
||||
sh './mvnw -B clean install -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
steps {
|
||||
sh 'mvn -B test'
|
||||
sh './mvnw -B test'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
@@ -94,7 +94,7 @@ pipeline {
|
||||
}
|
||||
steps {
|
||||
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 {
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh 'mvn -B clean install -DskipTests -DskipAssembly'
|
||||
sh './mvnw -B clean install -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
steps {
|
||||
sh 'mvn -B test'
|
||||
sh './mvnw -B test'
|
||||
// step([$class: 'JiraIssueUpdater', issueSelector: [$class: 'DefaultIssueSelector'], scm: scm])
|
||||
}
|
||||
post {
|
||||
@@ -142,7 +142,7 @@ pipeline {
|
||||
dir("local-snapshots-dir/") {
|
||||
deleteDir()
|
||||
}
|
||||
sh 'mvn -B source:jar javadoc:jar -DskipAssembbly'
|
||||
sh './mvnw -B source:jar javadoc:jar -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
stage('Deploy Snapshot') {
|
||||
@@ -151,7 +151,7 @@ pipeline {
|
||||
}
|
||||
steps {
|
||||
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',
|
||||
transfers: [
|
||||
sshTransfer(
|
||||
remoteDirectory: '/x1/dist/struts',
|
||||
remoteDirectory: '/struts/snapshot',
|
||||
removePrefix: 'assembly/target/assembly/out',
|
||||
sourceFiles: 'assembly/target/assembly/out/struts-*.zip'
|
||||
)
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-rest-showcase</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
<name>Struts 2 Rest Showcase Webapp</name>
|
||||
<description>Struts 2 Rest Showcase Example</description>
|
||||
|
||||
@@ -108,9 +108,9 @@
|
||||
<finalName>struts2-rest-showcase</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>8.1.16.v20140903</version>
|
||||
<version>9.4.46.v20220331</version>
|
||||
<configuration>
|
||||
<stopKey>CTRL+C</stopKey>
|
||||
<stopPort>8999</stopPort>
|
||||
|
||||
+8
-20
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-showcase</artifactId>
|
||||
@@ -101,7 +101,7 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.htmlunit</groupId>
|
||||
<artifactId>htmlunit</artifactId>
|
||||
<version>2.39.0</version>
|
||||
<version>2.61.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -155,15 +155,6 @@
|
||||
<version>6.1.2.Final</version>
|
||||
</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>
|
||||
|
||||
<build>
|
||||
@@ -171,7 +162,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>3.0.0-M4</version>
|
||||
<version>3.0.0-M6</version>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>it.org.apache.struts2.showcase.*Test</include>
|
||||
@@ -193,16 +184,16 @@
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>8.1.16.v20140903</version>
|
||||
<version>9.4.46.v20220331</version>
|
||||
<configuration>
|
||||
<stopKey>CTRL+C</stopKey>
|
||||
<stopPort>8999</stopPort>
|
||||
<systemProperties>
|
||||
<systemProperty>
|
||||
<name>log4j.configuration</name>
|
||||
<value>file:${basedir}/src/main/resources/log4j.properties</value>
|
||||
<value>file:${basedir}/src/main/resources/log4j2.xml</value>
|
||||
</systemProperty>
|
||||
<systemProperty>
|
||||
<name>slf4j</name>
|
||||
@@ -223,11 +214,8 @@
|
||||
<goals>
|
||||
<!-- stop any previous instance to free up the port -->
|
||||
<goal>stop</goal>
|
||||
<goal>run-forked</goal>
|
||||
<goal>start</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<waitForChild>false</waitForChild>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>stop-jetty</id>
|
||||
|
||||
+14
-16
@@ -27,22 +27,24 @@ import org.apache.struts2.convention.annotation.Namespace;
|
||||
import org.apache.struts2.convention.annotation.ParentPackage;
|
||||
import org.apache.struts2.convention.annotation.Result;
|
||||
import org.apache.struts2.interceptor.validation.SkipValidation;
|
||||
import org.hibernate.validator.constraints.Email;
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
import org.hibernate.validator.constraints.ScriptAssert;
|
||||
import org.hibernate.validator.constraints.URL;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: beanValidatationExample -->
|
||||
*/
|
||||
// <!-- START SNIPPET: beanValidationExample -->
|
||||
@Namespace("/bean-validation")
|
||||
@ParentPackage("bean-validation")
|
||||
@Action(results = {
|
||||
@Result(name = "input", location = "bean-validation.jsp"),
|
||||
@Result(name = "success", location = "/WEB-INF/validation/successFieldValidatorsExample.jsp")
|
||||
@Result(name = "input", location = "bean-validation.jsp"),
|
||||
@Result(name = "success", location = "/WEB-INF/validation/successFieldValidatorsExample.jsp")
|
||||
})
|
||||
@FieldMatch(first = "fieldExpressionValidatorField", second = "requiredValidatorField", message = "requiredValidatorField and fieldExpressionValidatorField are not matching")
|
||||
@ScriptAssert(lang = "javascript", script = "_this.dateValidatorField != null && _this.dateValidatorField.before(new java.util.Date())", message = "Date need to before now")
|
||||
@@ -82,10 +84,10 @@ public class BeanValidationExampleAction extends ActionSupport {
|
||||
private String fieldExpressionValidatorField = null;
|
||||
|
||||
@Action(value = "bean-validation", results = {
|
||||
@Result(name = "success", location = "bean-validation.jsp")
|
||||
@Result(name = "success", location = "bean-validation.jsp")
|
||||
})
|
||||
@SkipValidation
|
||||
public String beanValidation(){
|
||||
public String beanValidation() {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -150,7 +152,7 @@ public class BeanValidationExampleAction extends ActionSupport {
|
||||
}
|
||||
|
||||
public void setFieldExpressionValidatorField(
|
||||
String fieldExpressionValidatorField) {
|
||||
String fieldExpressionValidatorField) {
|
||||
this.fieldExpressionValidatorField = fieldExpressionValidatorField;
|
||||
}
|
||||
|
||||
@@ -163,8 +165,4 @@ public class BeanValidationExampleAction extends ActionSupport {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <!-- END SNIPPET: beanValidatationExample -->
|
||||
*/
|
||||
|
||||
|
||||
// <!-- END SNIPPET: beanValidationExample -->
|
||||
|
||||
@@ -45,66 +45,46 @@
|
||||
</bean>
|
||||
|
||||
<bean id="chatLoginAction" class="org.apache.struts2.showcase.chat.ChatLoginAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="chatLogoutAction" class="org.apache.struts2.showcase.chat.ChatLogoutAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="usersAvailableAction" class="org.apache.struts2.showcase.chat.UsersAvailableAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="roomsAvailableAction" class="org.apache.struts2.showcase.chat.RoomsAvailableAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="crudRoomAction" class="org.apache.struts2.showcase.chat.CrudRoomAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="enterRoomAction" class="org.apache.struts2.showcase.chat.EnterRoomAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messagesAvailableInRoomAction" class="org.apache.struts2.showcase.chat.MessagesAvailableInRoomAction"
|
||||
scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="sendMessageToRoomAction" class="org.apache.struts2.showcase.chat.SendMessageToRoomAction"
|
||||
scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="usersAvailableInRoomAction" class="org.apache.struts2.showcase.chat.UsersAvailableInRoomAction"
|
||||
scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="exitRoomAction" class="org.apache.struts2.showcase.chat.ExitRoomAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
|
||||
@@ -129,9 +109,7 @@
|
||||
</bean>
|
||||
|
||||
<bean id="startHangmanAction" class="org.apache.struts2.showcase.hangman.StartHangmanAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="hangmanService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="hangmanService"/>
|
||||
</bean>
|
||||
|
||||
<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()) {
|
||||
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 2 Property 1: Property Set in Action Chain 2"));
|
||||
Assert.assertTrue(pageAsText.contains("Action Chain 3 Property 1: Property set in Action Chain 3"));
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ public class ActionTagExampleTest {
|
||||
try (final WebClient webClient = new WebClient()) {
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public class AsyncTest {
|
||||
|
||||
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 HtmlPage page2 = button.click();
|
||||
final String page2Text = page2.asText();
|
||||
final String page2Text = page2.asNormalizedText();
|
||||
|
||||
Assert.assertTrue(page2Text.contains("somename1"));
|
||||
Assert.assertTrue(page2Text.contains("somedescription1"));
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ public class ComponentTagExampleTest {
|
||||
final HtmlPage page = webClient
|
||||
.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' - paramValue4"));
|
||||
Assert.assertTrue(pageAsText.contains("JSP Custom Template - parameter 'paramName' - paramValue2"));
|
||||
|
||||
@@ -46,7 +46,7 @@ public class ConversionTest {
|
||||
|
||||
final HtmlSubmitInput button = form.getInputByValue("Submit");
|
||||
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 Age: 0"));
|
||||
@@ -71,7 +71,7 @@ public class ConversionTest {
|
||||
|
||||
final HtmlSubmitInput button = form.getInputByValue("Submit");
|
||||
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("id1 -> address1"));
|
||||
@@ -92,7 +92,7 @@ public class ConversionTest {
|
||||
|
||||
final HtmlSubmitInput button = form.getInputByValue("Submit");
|
||||
final HtmlPage page2 = button.click();
|
||||
final String page2Text = page2.asText();
|
||||
final String page2Text = page2.asNormalizedText();
|
||||
|
||||
Assert.assertTrue(page2Text.contains("ADD"));
|
||||
Assert.assertTrue(page2Text.contains("MINUS"));
|
||||
|
||||
@@ -43,12 +43,12 @@ public class ExecAndWaitTest {
|
||||
final HtmlSubmitInput button = form.getInputByValue("submit");
|
||||
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
|
||||
final HtmlPage page3 = webClient
|
||||
.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 {
|
||||
try (final WebClient webClient = new WebClient()) {
|
||||
final Page page = webClient.getPage(ParameterUtils.getBaseUrl() + "/filedownload/download2.action");
|
||||
|
||||
+2
-2
@@ -36,11 +36,11 @@ public class FreeMarkerManagerTest {
|
||||
|
||||
final DomElement date = page.getElementById("todaysDate");
|
||||
Assert.assertNotNull(date);
|
||||
Assert.assertTrue(date.asText().length() > 0);
|
||||
Assert.assertTrue(date.asNormalizedText().length() > 0);
|
||||
|
||||
final DomElement time = page.getElementById("timeNow");
|
||||
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..");
|
||||
Assert.fail("Previous request should have failed");
|
||||
} catch (FailingHttpStatusCodeException e) {
|
||||
Assert.assertEquals("Not Found", e.getStatusMessage());
|
||||
Assert.assertEquals(404, e.getStatusCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidRersources2() throws Exception {
|
||||
try (final WebClient webClient = new WebClient()) {
|
||||
try {
|
||||
webClient.getPage(ParameterUtils.getBaseUrl() + "/static/..%252f");
|
||||
Assert.fail("Previous request should have failed");
|
||||
} 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 HtmlPage page2 = button.click();
|
||||
|
||||
Assert.assertEquals("name", page2.getElementById("name").asText());
|
||||
Assert.assertEquals("bio", page2.getElementById("bio").asText());
|
||||
Assert.assertEquals("Red", page2.getElementById("favouriteColor").asText());
|
||||
Assert.assertEquals("[Patrick, Jason]", page2.getElementById("friends").asText());
|
||||
Assert.assertEquals("true", page2.getElementById("legalAge").asText());
|
||||
Assert.assertEquals("name", page2.getElementById("name").asNormalizedText());
|
||||
Assert.assertEquals("bio", page2.getElementById("bio").asNormalizedText());
|
||||
Assert.assertEquals("Red", page2.getElementById("favouriteColor").asNormalizedText());
|
||||
Assert.assertEquals("[Patrick, Jason]", page2.getElementById("friends").asNormalizedText());
|
||||
Assert.assertEquals("true", page2.getElementById("legalAge").asNormalizedText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class ValidationTest {
|
||||
|
||||
final HtmlSubmitInput button = form.getInputByValue("Submit");
|
||||
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 \"integerValidatorField\""));
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-assembly</artifactId>
|
||||
|
||||
+3
-3
@@ -29,7 +29,7 @@
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-bom</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Struts 2 Bill of Materials</name>
|
||||
@@ -44,7 +44,7 @@
|
||||
</licenses>
|
||||
|
||||
<properties>
|
||||
<struts-version.version>6.0.0-RC3</struts-version.version>
|
||||
<struts-version.version>6.0.0-RC4</struts-version.version>
|
||||
<maven.site.skip>true</maven.site.skip>
|
||||
<maven.site.deploy.skip>true</maven.site.deploy.skip>
|
||||
</properties>
|
||||
@@ -175,7 +175,7 @@
|
||||
</dependencyManagement>
|
||||
|
||||
<scm>
|
||||
<tag>STRUTS_6_0_0_RC3</tag>
|
||||
<tag>STRUTS_6_0_0_RC4</tag>
|
||||
<connection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</connection>
|
||||
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</developerConnection>
|
||||
<url>https://github.com/apache/struts/</url>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-admin-bundle</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-demo-bundle</artifactId>
|
||||
|
||||
+2
-4
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
@@ -53,12 +53,10 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>2.4</version>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<reporting>
|
||||
|
||||
+12
-11
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
<artifactId>struts2-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
@@ -188,7 +188,7 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -242,6 +242,16 @@
|
||||
<artifactId>spring-web</artifactId>
|
||||
<scope>test</scope>
|
||||
</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>
|
||||
<groupId>junit</groupId>
|
||||
@@ -345,15 +355,6 @@
|
||||
<scope>test</scope>
|
||||
</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>
|
||||
<groupId>commons-validator</groupId>
|
||||
<artifactId>commons-validator</artifactId>
|
||||
|
||||
@@ -28,6 +28,10 @@ import com.opensymphony.xwork2.conversion.*;
|
||||
import com.opensymphony.xwork2.conversion.impl.*;
|
||||
import com.opensymphony.xwork2.factory.*;
|
||||
import com.opensymphony.xwork2.inject.*;
|
||||
import com.opensymphony.xwork2.ognl.BeanInfoCacheFactory;
|
||||
import com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory;
|
||||
import com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory;
|
||||
import com.opensymphony.xwork2.ognl.ExpressionCacheFactory;
|
||||
import com.opensymphony.xwork2.ognl.OgnlReflectionProvider;
|
||||
import com.opensymphony.xwork2.ognl.OgnlUtil;
|
||||
import com.opensymphony.xwork2.ognl.OgnlValueStackFactory;
|
||||
@@ -79,30 +83,37 @@ public class DefaultConfiguration implements Configuration {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PackageConfig getPackageConfig(String name) {
|
||||
return packageContexts.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UnknownHandlerConfig> getUnknownHandlerStack() {
|
||||
return unknownHandlerStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUnknownHandlerStack(List<UnknownHandlerConfig> unknownHandlerStack) {
|
||||
this.unknownHandlerStack = unknownHandlerStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getPackageConfigNames() {
|
||||
return packageContexts.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, PackageConfig> getPackageConfigs() {
|
||||
return packageContexts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getLoadedFileNames() {
|
||||
return loadedFileNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RuntimeConfiguration getRuntimeConfiguration() {
|
||||
return runtimeConfiguration;
|
||||
}
|
||||
@@ -110,10 +121,12 @@ public class DefaultConfiguration implements Configuration {
|
||||
/**
|
||||
* @return the container
|
||||
*/
|
||||
@Override
|
||||
public Container getContainer() {
|
||||
return container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPackageConfig(String name, PackageConfig packageContext) {
|
||||
PackageConfig check = packageContexts.get(name);
|
||||
if (check != null) {
|
||||
@@ -131,6 +144,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
packageContexts.put(name, packageContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PackageConfig removePackageConfig(String packageName) {
|
||||
return packageContexts.remove(packageName);
|
||||
}
|
||||
@@ -138,11 +152,13 @@ public class DefaultConfiguration implements Configuration {
|
||||
/**
|
||||
* Allows the configuration to clean up any resources used
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
packageContexts.clear();
|
||||
loadedFileNames.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rebuildRuntimeConfiguration() {
|
||||
runtimeConfiguration = buildRuntimeConfiguration();
|
||||
}
|
||||
@@ -151,10 +167,12 @@ public class DefaultConfiguration implements Configuration {
|
||||
* Calls the ConfigurationProviderFactory.getConfig() to tell it to reload the configuration and then calls
|
||||
* buildRuntimeConfiguration().
|
||||
*
|
||||
* @param providers list of ContainerProvider
|
||||
* @return list of package providers
|
||||
*
|
||||
* @throws ConfigurationException in case of any configuration errors
|
||||
*/
|
||||
@Override
|
||||
public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException {
|
||||
packageContexts.clear();
|
||||
loadedFileNames.clear();
|
||||
@@ -172,6 +190,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
props.setConstants(builder);
|
||||
|
||||
builder.factory(Configuration.class, new Factory<Configuration>() {
|
||||
@Override
|
||||
public Configuration create(Context context) throws Exception {
|
||||
return DefaultConfiguration.this;
|
||||
}
|
||||
@@ -279,6 +298,8 @@ public class DefaultConfiguration implements Configuration {
|
||||
|
||||
builder.factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON);
|
||||
builder.factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON);
|
||||
builder.factory(ExpressionCacheFactory.class, "defaultOgnlExpressionCacheFactory", DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON);
|
||||
builder.factory(BeanInfoCacheFactory.class, "defaultOgnlBeanInfoCacheFactory", DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON);
|
||||
builder.factory(OgnlUtil.class, Scope.SINGLETON);
|
||||
|
||||
builder.factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON);
|
||||
@@ -417,10 +438,10 @@ public class DefaultConfiguration implements Configuration {
|
||||
|
||||
private static class RuntimeConfigurationImpl implements RuntimeConfiguration {
|
||||
|
||||
private Map<String, Map<String, ActionConfig>> namespaceActionConfigs;
|
||||
private Map<String, ActionConfigMatcher> namespaceActionConfigMatchers;
|
||||
private NamespaceMatcher namespaceMatcher;
|
||||
private Map<String, String> namespaceConfigs;
|
||||
private final Map<String, Map<String, ActionConfig>> namespaceActionConfigs;
|
||||
private final Map<String, ActionConfigMatcher> namespaceActionConfigMatchers;
|
||||
private final NamespaceMatcher namespaceMatcher;
|
||||
private final Map<String, String> namespaceConfigs;
|
||||
|
||||
public RuntimeConfigurationImpl(Map<String, Map<String, ActionConfig>> namespaceActionConfigs,
|
||||
Map<String, String> namespaceConfigs,
|
||||
@@ -448,6 +469,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
* @param namespace the namespace for the action or null for the empty namespace, ""
|
||||
* @return the configuration information for action requested
|
||||
*/
|
||||
@Override
|
||||
public ActionConfig getActionConfig(String namespace, String name) {
|
||||
ActionConfig config = findActionConfigInNamespace(namespace, name);
|
||||
|
||||
@@ -503,6 +525,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
*
|
||||
* @return a Map of namespace - > Map of ActionConfig objects, with the key being the action name
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Map<String, ActionConfig>> getActionConfigs() {
|
||||
return namespaceActionConfigs;
|
||||
}
|
||||
|
||||
+11
-1
@@ -26,6 +26,8 @@ import com.opensymphony.xwork2.StrutsTextProviderFactory;
|
||||
import com.opensymphony.xwork2.TextProviderFactory;
|
||||
import com.opensymphony.xwork2.factory.DefaultUnknownHandlerFactory;
|
||||
import com.opensymphony.xwork2.factory.UnknownHandlerFactory;
|
||||
import com.opensymphony.xwork2.ognl.BeanInfoCacheFactory;
|
||||
import com.opensymphony.xwork2.ognl.ExpressionCacheFactory;
|
||||
import com.opensymphony.xwork2.ognl.accessor.HttpParametersPropertyAccessor;
|
||||
import com.opensymphony.xwork2.ognl.accessor.ParameterPropertyAccessor;
|
||||
import com.opensymphony.xwork2.security.AcceptedPatternsChecker;
|
||||
@@ -94,6 +96,8 @@ import com.opensymphony.xwork2.ognl.accessor.XWorkMapPropertyAccessor;
|
||||
import com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor;
|
||||
import com.opensymphony.xwork2.util.CompoundRoot;
|
||||
import com.opensymphony.xwork2.LocalizedTextProvider;
|
||||
import com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory;
|
||||
import com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory;
|
||||
import com.opensymphony.xwork2.util.StrutsLocalizedTextProvider;
|
||||
import com.opensymphony.xwork2.util.OgnlTextParser;
|
||||
import com.opensymphony.xwork2.util.PatternMatcher;
|
||||
@@ -130,19 +134,24 @@ import java.util.Set;
|
||||
|
||||
public class StrutsDefaultConfigurationProvider implements ConfigurationProvider {
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Configuration configuration) throws ConfigurationException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadPackages() throws ConfigurationException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsReload() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(ContainerBuilder builder, LocatableProperties props)
|
||||
throws ConfigurationException {
|
||||
|
||||
@@ -208,6 +217,8 @@ public class StrutsDefaultConfigurationProvider implements ConfigurationProvider
|
||||
.factory(TextProviderFactory.class, StrutsTextProviderFactory.class, Scope.SINGLETON)
|
||||
.factory(LocaleProviderFactory.class, DefaultLocaleProviderFactory.class, Scope.SINGLETON)
|
||||
|
||||
.factory(ExpressionCacheFactory.class, "defaultOgnlExpressionCacheFactory", DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON)
|
||||
.factory(BeanInfoCacheFactory.class, "defaultOgnlBeanInfoCacheFactory", DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON)
|
||||
.factory(OgnlUtil.class, Scope.SINGLETON)
|
||||
.factory(CollectionConverter.class, Scope.SINGLETON)
|
||||
.factory(ArrayConverter.class, Scope.SINGLETON)
|
||||
@@ -233,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_EVAL_EXPRESSION, 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_MATCHER_APPEND_NAMED_PARAMETERS, Boolean.TRUE.toString());
|
||||
}
|
||||
|
||||
+2
-1
@@ -38,7 +38,8 @@ import java.lang.annotation.Target;
|
||||
*
|
||||
* <p>
|
||||
* Application wide conversion:<br>
|
||||
* The conversion rules will be assembled within the <code>xwork-conversion.properties</code> file within the classpath root.
|
||||
* The conversion rules will be assembled within the <code>struts-conversion.properties</code> or
|
||||
* <code>xwork-conversion.properties</code> (deprecated) file within the classpath root.
|
||||
* Set type to: <code>type = ConversionType.APPLICATION</code>
|
||||
* </p>
|
||||
* <!-- END SNIPPET: description -->
|
||||
|
||||
@@ -18,28 +18,36 @@
|
||||
*/
|
||||
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.Member;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
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.Locale;
|
||||
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 {
|
||||
|
||||
private final static Logger LOG = LogManager.getLogger(DateConverter.class);
|
||||
|
||||
@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;
|
||||
|
||||
if (value instanceof String && ((String) value).length() > 0) {
|
||||
@@ -52,15 +60,12 @@ public class DateConverter extends DefaultTypeConverter {
|
||||
} else if (java.sql.Timestamp.class == toType) {
|
||||
Date check = null;
|
||||
SimpleDateFormat dtfmt = (SimpleDateFormat) DateFormat.getDateTimeInstance(DateFormat.SHORT,
|
||||
DateFormat.MEDIUM,
|
||||
locale);
|
||||
SimpleDateFormat fullfmt = new SimpleDateFormat(dtfmt.toPattern() + MILLISECOND_FORMAT,
|
||||
locale);
|
||||
DateFormat.MEDIUM, locale);
|
||||
SimpleDateFormat fullfmt = new SimpleDateFormat(dtfmt.toPattern() + MILLISECOND_FORMAT, locale);
|
||||
|
||||
SimpleDateFormat dfmt = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT,
|
||||
locale);
|
||||
SimpleDateFormat dfmt = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale);
|
||||
|
||||
SimpleDateFormat[] fmts = {fullfmt, dtfmt, dfmt};
|
||||
SimpleDateFormat[] fmts = { fullfmt, dtfmt, dfmt };
|
||||
for (SimpleDateFormat fmt : fmts) {
|
||||
try {
|
||||
check = fmt.parse(sa);
|
||||
@@ -85,8 +90,39 @@ public class DateConverter extends DefaultTypeConverter {
|
||||
} 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) {
|
||||
df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
|
||||
}
|
||||
@@ -95,15 +131,17 @@ public class DateConverter extends DefaultTypeConverter {
|
||||
result = df.parse(sa);
|
||||
if (!(Date.class == toType)) {
|
||||
try {
|
||||
Constructor<?> constructor = toType.getConstructor(new Class[]{long.class});
|
||||
return constructor.newInstance(new Object[]{Long.valueOf(result.getTime())});
|
||||
Constructor<?> constructor = toType.getConstructor(new Class[] { long.class });
|
||||
return constructor.newInstance(new Object[] { Long.valueOf(result.getTime()) });
|
||||
} 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) {
|
||||
throw new TypeConversionException("Could not parse date", e);
|
||||
}
|
||||
|
||||
} else if (Date.class.isAssignableFrom(value.getClass())) {
|
||||
result = (Date) value;
|
||||
}
|
||||
@@ -111,16 +149,16 @@ public class DateConverter extends DefaultTypeConverter {
|
||||
}
|
||||
|
||||
/**
|
||||
* The user defined global date format,
|
||||
* see {@link org.apache.struts2.components.Date#DATETAG_PROPERTY}
|
||||
* The user defined global date format, see
|
||||
* {@link org.apache.struts2.components.Date#DATETAG_PROPERTY}
|
||||
*
|
||||
* @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;
|
||||
SimpleDateFormat globalDateFormat = null;
|
||||
String globalDateString = null;
|
||||
|
||||
final TextProvider tp = findProviderInStack(context.getValueStack());
|
||||
|
||||
@@ -130,23 +168,28 @@ public class DateConverter extends DefaultTypeConverter {
|
||||
// is the same as input = DATETAG_PROPERTY
|
||||
if (globalFormat != null && !dateTagProperty.equals(globalFormat)) {
|
||||
LOG.debug("Found \"{}\" as \"{}\"", dateTagProperty, globalFormat);
|
||||
globalDateFormat = new SimpleDateFormat(globalFormat, locale);
|
||||
globalDateString = globalFormat;
|
||||
} else {
|
||||
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
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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 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 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");
|
||||
|
||||
final DateFormat[] dateFormats;
|
||||
|
||||
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 {
|
||||
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;
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.opensymphony.xwork2.inject.Inject;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
|
||||
import java.lang.reflect.Member;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
@@ -99,6 +100,8 @@ public class XWorkBasicConverter extends DefaultTypeConverter {
|
||||
result = doConvertToArray(context, o, member, propertyName, value, toType);
|
||||
} else if (Date.class.isAssignableFrom(toType)) {
|
||||
result = doConvertToDate(context, value, toType);
|
||||
} else if (LocalDateTime.class.isAssignableFrom(toType)) {
|
||||
result = doConvertToDate(context, value, toType);
|
||||
} else if (Calendar.class.isAssignableFrom(toType)) {
|
||||
result = doConvertToCalendar(context, value);
|
||||
} else if (Collection.class.isAssignableFrom(toType)) {
|
||||
|
||||
@@ -201,7 +201,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
ReflectionContextState.setReportingConversionErrors(context, true);
|
||||
|
||||
//keep locale from original context
|
||||
newStack.getActionContext().withLocale(stack.getActionContext().getLocale());
|
||||
newStack.getActionContext().withLocale(stack.getActionContext().getLocale()).withValueStack(stack);
|
||||
}
|
||||
|
||||
boolean memberAccessStack = newStack instanceof MemberAccessValueStack;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2022 Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.ognl;
|
||||
|
||||
/**
|
||||
* A proxy interface to be used with Struts DI mechanism
|
||||
*/
|
||||
public interface BeanInfoCacheFactory<Key, Value> extends OgnlCacheFactory <Key, Value> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2022 Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.ognl;
|
||||
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
|
||||
/**
|
||||
* Default OGNL Cache factory implementation.
|
||||
*
|
||||
* Currently used for BeanInfo cache creation.
|
||||
*
|
||||
* @param <Key> The type for the cache key entries
|
||||
* @param <Value> The type for the cache value entries
|
||||
*/
|
||||
public class DefaultOgnlBeanInfoCacheFactory<Key, Value> extends DefaultOgnlCacheFactory<Key, Value>
|
||||
implements BeanInfoCacheFactory<Key, Value> {
|
||||
|
||||
@Override
|
||||
@Inject(value = StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_MAXSIZE, required = false)
|
||||
protected void setCacheMaxSize(String maxSize) {
|
||||
super.setCacheMaxSize(maxSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Inject(value = StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_LRU_MODE, required = false)
|
||||
protected void setUseLRUCache(String useLRUMode) {
|
||||
super.setUseLRUCache(useLRUMode);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2022 Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.ognl;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
|
||||
/**
|
||||
* Default OGNL Cache factory implementation.
|
||||
*
|
||||
* Currently used for Expression cache and BeanInfo cache creation.
|
||||
*
|
||||
* @param <Key> The type for the cache key entries
|
||||
* @param <Value> The type for the cache value entries
|
||||
*/
|
||||
public class DefaultOgnlCacheFactory<Key, Value> implements OgnlCacheFactory<Key, Value> {
|
||||
|
||||
private final AtomicBoolean useLRUCache = new AtomicBoolean(false);
|
||||
private final AtomicInteger cacheMaxSize = new AtomicInteger(25000);
|
||||
|
||||
@Override
|
||||
public OgnlCache<Key, Value> buildOgnlCache() {
|
||||
return buildOgnlCache(getCacheMaxSize(), 16, 0.75f, getUseLRUCache());
|
||||
}
|
||||
|
||||
@Override
|
||||
public OgnlCache<Key, Value> buildOgnlCache(int evictionLimit, int initialCapacity, float loadFactor, boolean lruCache) {
|
||||
if (lruCache) {
|
||||
return new OgnlLRUCache<>(evictionLimit, initialCapacity, loadFactor);
|
||||
} else {
|
||||
return new OgnlDefaultCache<>(evictionLimit, initialCapacity, loadFactor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCacheMaxSize() {
|
||||
return cacheMaxSize.get();
|
||||
}
|
||||
|
||||
protected void setCacheMaxSize(String maxSize) {
|
||||
cacheMaxSize.set(Integer.parseInt(maxSize));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getUseLRUCache() {
|
||||
return useLRUCache.get();
|
||||
}
|
||||
|
||||
protected void setUseLRUCache(String useLRUMode) {
|
||||
useLRUCache.set(BooleanUtils.toBoolean(useLRUMode));
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2022 Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.ognl;
|
||||
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
|
||||
/**
|
||||
* Default OGNL Expression Cache factory implementation.
|
||||
*
|
||||
* Currently used for Expression cache creation.
|
||||
*
|
||||
* @param <Key> The type for the cache key entries
|
||||
* @param <Value> The type for the cache value entries
|
||||
*/
|
||||
public class DefaultOgnlExpressionCacheFactory<Key, Value> extends DefaultOgnlCacheFactory<Key, Value>
|
||||
implements ExpressionCacheFactory<Key, Value> {
|
||||
|
||||
@Override
|
||||
@Inject(value = StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_MAXSIZE, required = false)
|
||||
protected void setCacheMaxSize(String maxSize) {
|
||||
super.setCacheMaxSize(maxSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Inject(value = StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_LRU_MODE, required = false)
|
||||
protected void setUseLRUCache(String useLRUMode) {
|
||||
super.setUseLRUCache(useLRUMode);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2022 Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.ognl;
|
||||
|
||||
/**
|
||||
* A proxy interface to be used with Struts DI mechanism
|
||||
*/
|
||||
public interface ExpressionCacheFactory<Key, Value> extends OgnlCacheFactory <Key, Value> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2022 Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.ognl;
|
||||
|
||||
/**
|
||||
* A basic cache interface for use with OGNL processing (such as Expression, BeanInfo).
|
||||
* All OGNL caches will have an eviction limit, but setting an extremely high value can
|
||||
* simulate an "effectively unlimited" cache.
|
||||
*
|
||||
* @param <Key> The type for the cache key entries
|
||||
* @param <Value> The type for the cache value entries
|
||||
*/
|
||||
public interface OgnlCache<Key, Value> {
|
||||
|
||||
public Value get(Key key);
|
||||
|
||||
public void put(Key key, Value value);
|
||||
|
||||
public void putIfAbsent(Key key, Value value);
|
||||
|
||||
public int size();
|
||||
|
||||
public void clear();
|
||||
|
||||
public int getEvictionLimit();
|
||||
|
||||
public void setEvictionLimit(int cacheEvictionLimit);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2022 Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.ognl;
|
||||
|
||||
/**
|
||||
* Used by {@link com.opensymphony.xwork2.ognl.OgnlUtil} to create appropriate OGNL
|
||||
* caches based on configuration.
|
||||
*
|
||||
* @param <Key> The type for the cache key entries
|
||||
* @param <Value> The type for the cache value entries
|
||||
*/
|
||||
interface OgnlCacheFactory<Key, Value> {
|
||||
OgnlCache<Key, Value> buildOgnlCache();
|
||||
OgnlCache<Key, Value> buildOgnlCache(int evictionLimit, int initialCapacity, float loadFactor, boolean lruCache);
|
||||
int getCacheMaxSize();
|
||||
boolean getUseLRUCache();
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2022 Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.ognl;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Default OGNL cache implementation.
|
||||
*
|
||||
* Setting a very high eviction limit simulates an unlimited cache.
|
||||
* Setting too low an eviction limit will make the cache ineffective.
|
||||
*
|
||||
* @param <Key> The type for the cache key entries
|
||||
* @param <Value> The type for the cache value entries
|
||||
*/
|
||||
public class OgnlDefaultCache<Key, Value> implements OgnlCache<Key, Value> {
|
||||
|
||||
private final ConcurrentHashMap<Key, Value> ognlCache;
|
||||
private final AtomicInteger cacheEvictionLimit = new AtomicInteger(25000);
|
||||
|
||||
public OgnlDefaultCache(int evictionLimit, int initialCapacity, float loadFactor) {
|
||||
this.cacheEvictionLimit.set(evictionLimit);
|
||||
ognlCache = new ConcurrentHashMap<>(initialCapacity, loadFactor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value get(Key key) {
|
||||
return ognlCache.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(Key key, Value value) {
|
||||
ognlCache.put(key, value);
|
||||
this.clearIfEvictionLimitExceeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putIfAbsent(Key key, Value value) {
|
||||
ognlCache.putIfAbsent(key, value);
|
||||
this.clearIfEvictionLimitExceeded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return ognlCache.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
ognlCache.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEvictionLimit() {
|
||||
return this.cacheEvictionLimit.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEvictionLimit(int cacheEvictionLimit) {
|
||||
this.cacheEvictionLimit.set(cacheEvictionLimit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the cache if the eviction limit has been exceeded.
|
||||
*/
|
||||
private void clearIfEvictionLimitExceeded() {
|
||||
if (ognlCache.size() > cacheEvictionLimit.get()) {
|
||||
ognlCache.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2022 Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.ognl;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* A basic OGNL LRU cache implementation.
|
||||
*
|
||||
* The implementation utilizes a {@link Collections#synchronizedMap(java.util.Map)}
|
||||
* backed by a {@link LinkedHashMap}. May be replaced by a more efficient implementation in the future.
|
||||
*
|
||||
* Setting too low an eviction limit will produce more overhead than value.
|
||||
* Setting too high an eviction limit may also produce more overhead than value.
|
||||
* An appropriate eviction limit will need to be determined on an individual application basis.
|
||||
*
|
||||
* @param <Key> The type for the cache key entries
|
||||
* @param <Value> The type for the cache value entries
|
||||
*/
|
||||
public class OgnlLRUCache<Key, Value> implements OgnlCache<Key, Value> {
|
||||
|
||||
private final Map<Key, Value> ognlLRUCache;
|
||||
private final AtomicInteger cacheEvictionLimit = new AtomicInteger(2500);
|
||||
|
||||
public OgnlLRUCache(int evictionLimit, int initialCapacity, float loadFactor) {
|
||||
this.cacheEvictionLimit.set(evictionLimit);
|
||||
// Access-order mode selected (order mode true in LinkedHashMap constructor).
|
||||
ognlLRUCache = Collections.synchronizedMap (new LinkedHashMap<Key, Value>(initialCapacity, loadFactor, true) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<Key,Value> eldest) {
|
||||
return (this.size() > cacheEvictionLimit.get());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Value get(Key key) {
|
||||
return ognlLRUCache.get(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(Key key, Value value) {
|
||||
ognlLRUCache.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putIfAbsent(Key key, Value value) {
|
||||
ognlLRUCache.putIfAbsent(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return ognlLRUCache.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
ognlLRUCache.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEvictionLimit() {
|
||||
return this.cacheEvictionLimit.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEvictionLimit(int cacheEvictionLimit) {
|
||||
this.cacheEvictionLimit.set(cacheEvictionLimit);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,8 +38,6 @@ import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -57,8 +55,8 @@ public class OgnlUtil {
|
||||
// Flag used to reduce flooding logs with WARNs about using DevMode excluded packages
|
||||
private final AtomicBoolean warnReported = new AtomicBoolean(false);
|
||||
|
||||
private final ConcurrentMap<String, Object> expressions = new ConcurrentHashMap<>();
|
||||
private final ConcurrentMap<Class<?>, BeanInfo> beanInfoCache = new ConcurrentHashMap<>();
|
||||
private final OgnlCache<String, Object> expressionCache;
|
||||
private final OgnlCache<Class<?>, BeanInfo> beanInfoCache;
|
||||
private TypeConverter defaultConverter;
|
||||
|
||||
private boolean devMode;
|
||||
@@ -75,10 +73,33 @@ public class OgnlUtil {
|
||||
|
||||
private Container container;
|
||||
private boolean allowStaticFieldAccess = true;
|
||||
private boolean allowStaticMethodAccess;
|
||||
private boolean disallowProxyMemberAccess;
|
||||
|
||||
/**
|
||||
* Construct a new OgnlUtil instance for use with the framework
|
||||
*
|
||||
* @deprecated It is recommended to utilize the {@link OgnlUtil#OgnlUtil(com.opensymphony.xwork2.ognl.ExpressionCacheFactory, com.opensymphony.xwork2.ognl.BeanInfoCacheFactory) method instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public OgnlUtil() {
|
||||
this(null, null); // Instantiate default Expression and BeanInfo caches (null factories)
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new OgnlUtil instance for use with the framework, with optional
|
||||
* cache factories for OGNL Expression and BeanInfo caches.
|
||||
*
|
||||
* NOTE: Although the extension points are defined for the optional cache factories, developer-defined overrides do
|
||||
* do not appear to function at this time (it always appears to instantiate the default factories).
|
||||
* Construction injectors do not allow the optional flag, so the definitions must be defined.
|
||||
*
|
||||
* @param ognlExpressionCacheFactory factory for Expression cache instance. If null, it uses a default
|
||||
* @param ognlBeanInfoCacheFactory factory for BeanInfo cache instance. If null, it uses a default
|
||||
*/
|
||||
public OgnlUtil(
|
||||
@Inject(value = StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_FACTORY, required = false) ExpressionCacheFactory<String, Object> ognlExpressionCacheFactory,
|
||||
@Inject(value = StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_FACTORY, required = false) BeanInfoCacheFactory<Class<?>, BeanInfo> ognlBeanInfoCacheFactory
|
||||
) {
|
||||
excludedClasses = Collections.unmodifiableSet(new HashSet<>());
|
||||
excludedPackageNamePatterns = Collections.unmodifiableSet(new HashSet<>());
|
||||
excludedPackageNames = Collections.unmodifiableSet(new HashSet<>());
|
||||
@@ -86,6 +107,12 @@ public class OgnlUtil {
|
||||
devModeExcludedClasses = Collections.unmodifiableSet(new HashSet<>());
|
||||
devModeExcludedPackageNamePatterns = Collections.unmodifiableSet(new HashSet<>());
|
||||
devModeExcludedPackageNames = Collections.unmodifiableSet(new HashSet<>());
|
||||
|
||||
OgnlCacheFactory<String, Object> ognlExpressionCacheFactory1 = (ognlExpressionCacheFactory != null ? ognlExpressionCacheFactory : new DefaultOgnlExpressionCacheFactory<>());
|
||||
OgnlCacheFactory<Class<?>, BeanInfo> ognlBeanInfoCacheFactory1 = (ognlBeanInfoCacheFactory != null ? ognlBeanInfoCacheFactory : new DefaultOgnlBeanInfoCacheFactory<>());
|
||||
|
||||
this.expressionCache = ognlExpressionCacheFactory1.buildOgnlCache();
|
||||
this.beanInfoCache = ognlBeanInfoCacheFactory1.buildOgnlCache();
|
||||
}
|
||||
|
||||
@Inject
|
||||
@@ -103,6 +130,16 @@ public class OgnlUtil {
|
||||
enableExpressionCache = BooleanUtils.toBoolean(cache);
|
||||
}
|
||||
|
||||
@Inject(value = StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_MAXSIZE, required = false)
|
||||
protected void setExpressionCacheMaxSize(String maxSize) {
|
||||
expressionCache.setEvictionLimit(Integer.parseInt(maxSize));
|
||||
}
|
||||
|
||||
@Inject(value = StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_MAXSIZE, required = false)
|
||||
protected void setBeanInfoCacheMaxSize(String maxSize) {
|
||||
beanInfoCache.setEvictionLimit(Integer.parseInt(maxSize));
|
||||
}
|
||||
|
||||
@Inject(value = StrutsConstants.STRUTS_OGNL_ENABLE_EVAL_EXPRESSION, required = false)
|
||||
protected void setEnableEvalExpression(String evalExpression) {
|
||||
this.enableEvalExpression = BooleanUtils.toBoolean(evalExpression);
|
||||
@@ -212,11 +249,6 @@ public class OgnlUtil {
|
||||
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)
|
||||
protected void setDisallowProxyMemberAccess(String disallowProxyMemberAccess) {
|
||||
this.disallowProxyMemberAccess = BooleanUtils.toBoolean(disallowProxyMemberAccess);
|
||||
@@ -273,7 +305,7 @@ public class OgnlUtil {
|
||||
* @since 2.5.21
|
||||
*/
|
||||
public void clearExpressionCache() {
|
||||
expressions.clear();
|
||||
expressionCache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -284,7 +316,7 @@ public class OgnlUtil {
|
||||
* @since 2.5.21
|
||||
*/
|
||||
public int expressionCacheSize() {
|
||||
return expressions.size();
|
||||
return expressionCache.size();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -532,11 +564,11 @@ public class OgnlUtil {
|
||||
private <T> Object compileAndExecute(String expression, Map<String, Object> context, OgnlTask<T> task) throws OgnlException {
|
||||
Object tree;
|
||||
if (enableExpressionCache) {
|
||||
tree = expressions.get(expression);
|
||||
tree = expressionCache.get(expression);
|
||||
if (tree == null) {
|
||||
tree = Ognl.parseExpression(expression);
|
||||
checkEnableEvalExpression(tree, context);
|
||||
expressions.putIfAbsent(expression, tree);
|
||||
expressionCache.putIfAbsent(expression, tree);
|
||||
}
|
||||
} else {
|
||||
tree = Ognl.parseExpression(expression);
|
||||
@@ -549,11 +581,11 @@ public class OgnlUtil {
|
||||
private <T> Object compileAndExecuteMethod(String expression, Map<String, Object> context, OgnlTask<T> task) throws OgnlException {
|
||||
Object tree;
|
||||
if (enableExpressionCache) {
|
||||
tree = expressions.get(expression);
|
||||
tree = expressionCache.get(expression);
|
||||
if (tree == null) {
|
||||
tree = Ognl.parseExpression(expression);
|
||||
checkSimpleMethod(tree, context);
|
||||
expressions.putIfAbsent(expression, tree);
|
||||
expressionCache.putIfAbsent(expression, tree);
|
||||
}
|
||||
} else {
|
||||
tree = Ognl.parseExpression(expression);
|
||||
@@ -798,7 +830,7 @@ public class OgnlUtil {
|
||||
resolver = container.getInstance(CompoundRootAccessor.class);
|
||||
}
|
||||
|
||||
SecurityMemberAccess memberAccess = new SecurityMemberAccess(allowStaticMethodAccess, allowStaticFieldAccess);
|
||||
SecurityMemberAccess memberAccess = new SecurityMemberAccess(allowStaticFieldAccess);
|
||||
memberAccess.setDisallowProxyMemberAccess(disallowProxyMemberAccess);
|
||||
|
||||
if (devMode) {
|
||||
|
||||
@@ -72,13 +72,13 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
|
||||
private boolean devMode;
|
||||
private boolean logMissingProperties;
|
||||
|
||||
protected OgnlValueStack(XWorkConverter xworkConverter, CompoundRootAccessor accessor, TextProvider prov, boolean allowStaticMethodAccess, boolean allowStaticFieldAccess) {
|
||||
setRoot(xworkConverter, accessor, new CompoundRoot(), allowStaticMethodAccess, allowStaticFieldAccess);
|
||||
protected OgnlValueStack(XWorkConverter xworkConverter, CompoundRootAccessor accessor, TextProvider prov, boolean allowStaticFieldAccess) {
|
||||
setRoot(xworkConverter, accessor, new CompoundRoot(), allowStaticFieldAccess);
|
||||
push(prov);
|
||||
}
|
||||
|
||||
protected OgnlValueStack(ValueStack vs, XWorkConverter xworkConverter, CompoundRootAccessor accessor, boolean allowStaticMethodAccess, boolean allowStaticFieldAccess) {
|
||||
setRoot(xworkConverter, accessor, new CompoundRoot(vs.getRoot()), allowStaticMethodAccess, allowStaticFieldAccess);
|
||||
protected OgnlValueStack(ValueStack vs, XWorkConverter xworkConverter, CompoundRootAccessor accessor, boolean allowStaticFieldAccess) {
|
||||
setRoot(xworkConverter, accessor, new CompoundRoot(vs.getRoot()), allowStaticFieldAccess);
|
||||
}
|
||||
|
||||
@Inject
|
||||
@@ -90,10 +90,9 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
|
||||
securityMemberAccess.setDisallowProxyMemberAccess(ognlUtil.isDisallowProxyMemberAccess());
|
||||
}
|
||||
|
||||
protected void setRoot(XWorkConverter xworkConverter, CompoundRootAccessor accessor, CompoundRoot compoundRoot,
|
||||
boolean allowStaticMethodAccess, boolean allowStaticFieldAccess) {
|
||||
protected void setRoot(XWorkConverter xworkConverter, CompoundRootAccessor accessor, CompoundRoot compoundRoot, boolean allowStaticFieldAccess) {
|
||||
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));
|
||||
context.put(VALUE_STACK, this);
|
||||
((OgnlContext) context).setTraceEvaluations(false);
|
||||
@@ -219,7 +218,7 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
|
||||
if (shouldLog) {
|
||||
LOG.warn(msg, e);
|
||||
}
|
||||
|
||||
|
||||
if (throwExceptionOnFailure) {
|
||||
throw new StrutsException(msg, e);
|
||||
}
|
||||
@@ -462,11 +461,10 @@ public class OgnlValueStack implements Serializable, ValueStack, ClearableValueS
|
||||
XWorkConverter xworkConverter = cont.getInstance(XWorkConverter.class);
|
||||
CompoundRootAccessor accessor = (CompoundRootAccessor) cont.getInstance(PropertyAccessor.class, CompoundRoot.class.getName());
|
||||
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));
|
||||
OgnlValueStack aStack = new OgnlValueStack(xworkConverter, accessor, prov, allowStaticMethod, allowStaticField);
|
||||
OgnlValueStack aStack = new OgnlValueStack(xworkConverter, accessor, prov, allowStaticField);
|
||||
aStack.setOgnlUtil(cont.getInstance(OgnlUtil.class));
|
||||
aStack.setRoot(xworkConverter, accessor, this.root, allowStaticMethod, allowStaticField);
|
||||
aStack.setRoot(xworkConverter, accessor, this.root, allowStaticField);
|
||||
|
||||
return aStack;
|
||||
}
|
||||
|
||||
@@ -43,8 +43,6 @@ import java.util.Set;
|
||||
*/
|
||||
public class OgnlValueStackFactory implements ValueStackFactory {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(OgnlValueStackFactory.class);
|
||||
|
||||
protected XWorkConverter xworkConverter;
|
||||
protected CompoundRootAccessor compoundRootAccessor;
|
||||
protected TextProvider textProvider;
|
||||
@@ -61,8 +59,7 @@ public class OgnlValueStackFactory implements ValueStackFactory {
|
||||
}
|
||||
|
||||
public ValueStack createValueStack() {
|
||||
ValueStack stack = new OgnlValueStack(xworkConverter, compoundRootAccessor, textProvider,
|
||||
containerAllowsStaticMethodAccess(), containerAllowsStaticFieldAccess());
|
||||
ValueStack stack = new OgnlValueStack(xworkConverter, compoundRootAccessor, textProvider, containerAllowsStaticFieldAccess());
|
||||
container.inject(stack);
|
||||
return stack.getActionContext()
|
||||
.withContainer(container)
|
||||
@@ -71,8 +68,7 @@ public class OgnlValueStackFactory implements ValueStackFactory {
|
||||
}
|
||||
|
||||
public ValueStack createValueStack(ValueStack stack) {
|
||||
ValueStack result = new OgnlValueStack(stack, xworkConverter, compoundRootAccessor,
|
||||
containerAllowsStaticMethodAccess(), containerAllowsStaticFieldAccess());
|
||||
ValueStack result = new OgnlValueStack(stack, xworkConverter, compoundRootAccessor, containerAllowsStaticFieldAccess());
|
||||
container.inject(result);
|
||||
return result.getActionContext()
|
||||
.withContainer(container)
|
||||
@@ -84,32 +80,23 @@ public class OgnlValueStackFactory implements ValueStackFactory {
|
||||
protected void setContainer(Container container) throws ClassNotFoundException {
|
||||
Set<String> names = container.getInstanceNames(PropertyAccessor.class);
|
||||
for (String name : names) {
|
||||
Class cls = Class.forName(name);
|
||||
if (cls != null) {
|
||||
if (Map.class.isAssignableFrom(cls)) {
|
||||
PropertyAccessor acc = 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);
|
||||
}
|
||||
Class<?> cls = Class.forName(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);
|
||||
for (String name : names) {
|
||||
Class cls = Class.forName(name);
|
||||
if (cls != null) {
|
||||
OgnlRuntime.setMethodAccessor(cls, container.getInstance(MethodAccessor.class, name));
|
||||
}
|
||||
Class<?> cls = Class.forName(name);
|
||||
OgnlRuntime.setMethodAccessor(cls, container.getInstance(MethodAccessor.class, name));
|
||||
}
|
||||
|
||||
names = container.getInstanceNames(NullHandler.class);
|
||||
for (String name : names) {
|
||||
Class cls = Class.forName(name);
|
||||
if (cls != null) {
|
||||
OgnlRuntime.setNullHandler(cls, new OgnlNullHandlerWrapper(container.getInstance(NullHandler.class, name)));
|
||||
}
|
||||
Class<?> cls = Class.forName(name);
|
||||
OgnlRuntime.setNullHandler(cls, new OgnlNullHandlerWrapper(container.getInstance(NullHandler.class, name)));
|
||||
}
|
||||
if (compoundRootAccessor == null) {
|
||||
throw new IllegalStateException("Couldn't find the compound root accessor");
|
||||
@@ -117,19 +104,8 @@ public class OgnlValueStackFactory implements ValueStackFactory {
|
||||
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)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected boolean containerAllowsStaticFieldAccess() {
|
||||
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 final boolean allowStaticFieldAccess;
|
||||
private final boolean allowStaticMethodAccess;
|
||||
private Set<Pattern> excludeProperties = Collections.emptySet();
|
||||
private Set<Pattern> acceptProperties = Collections.emptySet();
|
||||
private Set<Class<?>> excludedClasses = Collections.emptySet();
|
||||
@@ -52,25 +51,15 @@ public class SecurityMemberAccess implements MemberAccess {
|
||||
|
||||
/**
|
||||
* SecurityMemberAccess
|
||||
* - access decisions based on whether member is static (or not)
|
||||
* - block or allow access to properties (configurable-after-construction)
|
||||
*
|
||||
* @param allowStaticMethodAccess
|
||||
* @param allowStaticFieldAccess
|
||||
* - access decisions based on whether member is static (or not)
|
||||
* - block or allow access to properties (configurable-after-construction)
|
||||
*
|
||||
* @param allowStaticFieldAccess if set to true static fields (constants) will be accessible
|
||||
*/
|
||||
public SecurityMemberAccess(boolean allowStaticMethodAccess, boolean allowStaticFieldAccess) {
|
||||
this.allowStaticMethodAccess = allowStaticMethodAccess;
|
||||
public SecurityMemberAccess(boolean allowStaticFieldAccess) {
|
||||
this.allowStaticFieldAccess = allowStaticFieldAccess;
|
||||
}
|
||||
|
||||
public final boolean getAllowStaticMethodAccess() {
|
||||
return allowStaticMethodAccess;
|
||||
}
|
||||
|
||||
public final boolean getAllowStaticFieldAccess() {
|
||||
return allowStaticFieldAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setup(Map context, Object target, Member member, String propertyName) {
|
||||
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) {
|
||||
if (state != null) {
|
||||
final AccessibleObject accessible = (AccessibleObject) member;
|
||||
final boolean stateboolean = ((Boolean) state).booleanValue(); // Using twice (avoid unboxing)
|
||||
if (!stateboolean) {
|
||||
accessible.setAccessible(stateboolean);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Improper restore state [" + stateboolean + "] for target [" + target +
|
||||
"], member [" + member + "], propertyName [" + propertyName + "]");
|
||||
final boolean stateBoolean = ((Boolean) state).booleanValue(); // Using twice (avoid unboxing)
|
||||
if (!stateBoolean) {
|
||||
accessible.setAccessible(stateBoolean);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Improper restore state [" + stateBoolean + "] for target [" + target +
|
||||
"], member [" + member + "], propertyName [" + propertyName + "]");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,6 +105,7 @@ public class SecurityMemberAccess implements MemberAccess {
|
||||
return false;
|
||||
}
|
||||
|
||||
// it needs to be before calling #checkStaticMethodAccess()
|
||||
if (checkEnumAccess(target, member)) {
|
||||
LOG.trace("Allowing access to enum: target [{}], member [{}]", target, member);
|
||||
return true;
|
||||
@@ -127,7 +116,7 @@ public class SecurityMemberAccess implements MemberAccess {
|
||||
return false;
|
||||
}
|
||||
|
||||
final Class memberClass = member.getDeclaringClass();
|
||||
final Class<?> memberClass = member.getDeclaringClass();
|
||||
|
||||
if (isClassExcluded(memberClass)) {
|
||||
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
|
||||
final Class targetClass = Modifier.isStatic(memberModifiers) ? memberClass : target.getClass();
|
||||
final Class<?> targetClass = Modifier.isStatic(memberModifiers) ? memberClass : target.getClass();
|
||||
|
||||
if (isPackageExcluded(targetClass.getPackage(), memberClass.getPackage())) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -158,33 +147,25 @@ public class SecurityMemberAccess implements MemberAccess {
|
||||
|
||||
/**
|
||||
* Check access for static method (via modifiers).
|
||||
*
|
||||
*
|
||||
* Note: For non-static members, the result is always true.
|
||||
*
|
||||
*
|
||||
* @param member
|
||||
* @param memberModifiers
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected boolean checkStaticMethodAccess(Member member, int memberModifiers) {
|
||||
if (Modifier.isStatic(memberModifiers) && !(member instanceof Field)) {
|
||||
if (allowStaticMethodAccess) {
|
||||
LOG.debug("Support for accessing static methods [member: {}] is deprecated!", member);
|
||||
}
|
||||
return allowStaticMethodAccess;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return !Modifier.isStatic(memberModifiers) || member instanceof Field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check access for static field (via modifiers).
|
||||
*
|
||||
* <p>
|
||||
* Note: For non-static members, the result is always true.
|
||||
*
|
||||
*
|
||||
* @param member
|
||||
* @param memberModifiers
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected boolean checkStaticFieldAccess(Member member, int memberModifiers) {
|
||||
@@ -195,13 +176,12 @@ public class SecurityMemberAccess implements MemberAccess {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Check access for public members (via modifiers)
|
||||
*
|
||||
* <p>
|
||||
* Returns true if-and-only-if the member is public.
|
||||
*
|
||||
*
|
||||
* @param memberModifiers
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected boolean checkPublicMemberAccess(int memberModifiers) {
|
||||
@@ -210,10 +190,8 @@ public class SecurityMemberAccess implements MemberAccess {
|
||||
|
||||
protected boolean checkEnumAccess(Object target, Member member) {
|
||||
if (target instanceof Class) {
|
||||
final Class clazz = (Class) target;
|
||||
if (Enum.class.isAssignableFrom(clazz) && member.getName().equals("values")) {
|
||||
return true;
|
||||
}
|
||||
final Class<?> clazz = (Class<?>) target;
|
||||
return Enum.class.isAssignableFrom(clazz) && member.getName().equals("values");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -222,7 +200,7 @@ public class SecurityMemberAccess implements MemberAccess {
|
||||
if (targetPackage == null || memberPackage == null) {
|
||||
LOG.warn("The use of the default (unnamed) package is discouraged!");
|
||||
}
|
||||
|
||||
|
||||
String targetPackageName = targetPackage == null ? "" : targetPackage.getName();
|
||||
String memberPackageName = memberPackage == null ? "" : memberPackage.getName();
|
||||
|
||||
@@ -235,7 +213,7 @@ public class SecurityMemberAccess implements MemberAccess {
|
||||
targetPackageName = targetPackageName + ".";
|
||||
memberPackageName = memberPackageName + ".";
|
||||
|
||||
for (String packageName: excludedPackageNames) {
|
||||
for (String packageName : excludedPackageNames) {
|
||||
if (targetPackageName.startsWith(packageName) || memberPackageName.startsWith(packageName)) {
|
||||
return true;
|
||||
}
|
||||
@@ -245,7 +223,7 @@ public class SecurityMemberAccess implements MemberAccess {
|
||||
}
|
||||
|
||||
protected boolean isClassExcluded(Class<?> clazz) {
|
||||
if (clazz == Object.class || (clazz == Class.class && !allowStaticMethodAccess)) {
|
||||
if (clazz == Object.class || (clazz == Class.class && !allowStaticFieldAccess)) {
|
||||
return true;
|
||||
}
|
||||
for (Class<?> excludedClass : excludedClasses) {
|
||||
|
||||
@@ -36,7 +36,7 @@ import java.util.Map;
|
||||
* @author tmjee
|
||||
*/
|
||||
public class XWorkMethodAccessor extends ObjectMethodAccessor {
|
||||
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(XWorkMethodAccessor.class);
|
||||
|
||||
@Override
|
||||
@@ -58,9 +58,9 @@ public class XWorkMethodAccessor extends ObjectMethodAccessor {
|
||||
//so that property strings are not cleared
|
||||
//i.e. OgnlUtil should be used initially, OgnlRuntime
|
||||
//thereafter
|
||||
|
||||
|
||||
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
|
||||
PropertyAccessor accessor=OgnlRuntime.getPropertyAccessor(Collection.class);
|
||||
ReflectionContextState.setGettingByKeyProperty(ogContext,true);
|
||||
@@ -83,8 +83,8 @@ public class XWorkMethodAccessor extends ObjectMethodAccessor {
|
||||
return callMethodWithDebugInfo(context, object, string, objects);
|
||||
}
|
||||
}
|
||||
Boolean exec = (Boolean) context.get(ReflectionContextState.DENY_METHOD_EXECUTION);
|
||||
boolean e = ((exec == null) ? false : exec.booleanValue());
|
||||
Boolean exec = ReflectionContextState.isDenyMethodExecution(context);
|
||||
boolean e = (exec != null && exec);
|
||||
|
||||
if (!e) {
|
||||
return callMethodWithDebugInfo(context, object, string, objects);
|
||||
@@ -110,7 +110,7 @@ public class XWorkMethodAccessor extends ObjectMethodAccessor {
|
||||
|
||||
@Override
|
||||
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());
|
||||
|
||||
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 */
|
||||
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 */
|
||||
public static final String STRUTS_ACTIONVALIDATORMANAGER = "struts.actionValidatorManager";
|
||||
|
||||
@@ -253,6 +250,47 @@ public final class StrutsConstants {
|
||||
/** Throw RuntimeException when a property is not found, or the evaluation of the expression fails */
|
||||
public static final String STRUTS_EL_THROW_EXCEPTION = "struts.el.throwExceptionOnFailure";
|
||||
|
||||
/**
|
||||
* Specifies an OGNL expression cache factory implementation. A default implementation is provided, but
|
||||
* could be replaced by a custom one if desired.
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
public static final String STRUTS_OGNL_EXPRESSION_CACHE_FACTORY = "struts.ognl.expressionCacheFactory";
|
||||
|
||||
/**
|
||||
* Specifies an OGNL BeanInfo cache factory implementation. A default implementation is provided, but
|
||||
* could be replaced by a custom one if desired.
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
public static final String STRUTS_OGNL_BEANINFO_CACHE_FACTORY = "struts.ognl.beanInfoCacheFactory";
|
||||
|
||||
/**
|
||||
* Specifies a maximum number of cached BeanInfo used by OgnlUtility. Not specified/set by default. If
|
||||
* a positive integer is specified, it will set a limit whose behaviour depends on whether the
|
||||
* normal (default) cache or optional LRU cache is in place.
|
||||
*
|
||||
* For the normal (default) cache, exceeding the maximum will cause the entire cache to flush (clear).
|
||||
* For the optional LRU cache, once the maximum is reached, the least-recently-used (LRU) entry will be
|
||||
* removed when a new entry needs to be added (cache is fully-utilized).
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
public static final String STRUTS_OGNL_BEANINFO_CACHE_MAXSIZE = "struts.ognl.beanInfoCacheMaxSize";
|
||||
|
||||
/**
|
||||
* Set the cache mode of the BeanInfo cache used by OgnlUtility. A value of true means enable
|
||||
* least-recently-used (LRU) mode, a value of false (or any non-true value) means to use the
|
||||
* default cache.
|
||||
*
|
||||
* Note: When enabling LRU cache mode you must also set a maximum size (via {@link #STRUTS_OGNL_BEANINFO_CACHE_MAXSIZE})
|
||||
* for it to be effective. Otherwise, there is no condition to evict a LRU entry (cache has no limit).
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
public static final String STRUTS_OGNL_BEANINFO_CACHE_LRU_MODE = "struts.ognl.beanInfoCacheLRUMode";
|
||||
|
||||
/**
|
||||
* Logs properties that are not found (very verbose)
|
||||
* @since 2.6
|
||||
@@ -278,6 +316,31 @@ public final class StrutsConstants {
|
||||
*/
|
||||
public static final String STRUTS_ENABLE_OGNL_EXPRESSION_CACHE = STRUTS_OGNL_ENABLE_EXPRESSION_CACHE;
|
||||
|
||||
/**
|
||||
* Specifies a maximum number of cached parsed OGNL expressions. Not specified/set by default. If
|
||||
* a positive integer is specified, it will set a limit whose behaviour depends on whether the
|
||||
* normal (default) cache or optional LRU cache is in place.
|
||||
*
|
||||
* For the normal (default) cache, exceeding the maximum will cause the entire cache to flush (clear).
|
||||
* For the optional LRU cache, once the maximum is reached, the least-recently-used (LRU) entry will be
|
||||
* removed when a new entry needs to be added (cache is fully-utilized).
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
public static final String STRUTS_OGNL_EXPRESSION_CACHE_MAXSIZE = "struts.ognl.expressionCacheMaxSize";
|
||||
|
||||
/**
|
||||
* Set the cache mode of the parsed OGNL expression cache. A value of true means enable
|
||||
* least-recently-used (LRU) mode, a value of false (or any non-true value) means to use the
|
||||
* default cache.
|
||||
*
|
||||
* Note: When enabling LRU cache mode you must also set a maximum size (via {@link #STRUTS_OGNL_EXPRESSION_CACHE_MAXSIZE})
|
||||
* for it to be effective. Otherwise, there is no condition to evict a LRU entry (cache has no limit).
|
||||
*
|
||||
* @since 2.6
|
||||
*/
|
||||
public static final String STRUTS_OGNL_EXPRESSION_CACHE_LRU_MODE = "struts.ognl.expressionCacheLRUMode";
|
||||
|
||||
/**
|
||||
* Enables evaluation of OGNL expressions
|
||||
* @since 2.6
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.RequestUtils;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.StrutsException;
|
||||
import org.apache.struts2.util.FastByteArrayOutputStream;
|
||||
import org.apache.struts2.views.annotations.StrutsTag;
|
||||
import org.apache.struts2.views.annotations.StrutsTagAttribute;
|
||||
@@ -33,6 +34,7 @@ import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.WriteListener;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
@@ -296,6 +298,19 @@ public class Include extends Component {
|
||||
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.
|
||||
|
||||
@@ -321,7 +321,7 @@ public class ServletUrlRenderer implements UrlRenderer {
|
||||
* @param parameters component 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);
|
||||
|
||||
@@ -333,7 +333,7 @@ public class ServletUrlRenderer implements UrlRenderer {
|
||||
String queryString = value.substring(value.indexOf('?') + 1);
|
||||
|
||||
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())) {
|
||||
mergedParams.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ import com.opensymphony.xwork2.LocaleProviderFactory;
|
||||
import com.opensymphony.xwork2.LocalizedTextProvider;
|
||||
import com.opensymphony.xwork2.TextProviderFactory;
|
||||
import com.opensymphony.xwork2.factory.UnknownHandlerFactory;
|
||||
import com.opensymphony.xwork2.ognl.BeanInfoCacheFactory;
|
||||
import com.opensymphony.xwork2.ognl.ExpressionCacheFactory;
|
||||
import com.opensymphony.xwork2.security.AcceptedPatternsChecker;
|
||||
import com.opensymphony.xwork2.security.ExcludedPatternsChecker;
|
||||
import com.opensymphony.xwork2.FileManager;
|
||||
@@ -366,6 +368,7 @@ import org.apache.struts2.views.util.UrlHelper;
|
||||
*/
|
||||
public class StrutsBeanSelectionProvider extends AbstractBeanSelectionProvider {
|
||||
|
||||
@Override
|
||||
public void register(ContainerBuilder builder, LocatableProperties props) {
|
||||
alias(ObjectFactory.class, StrutsConstants.STRUTS_OBJECTFACTORY, builder, props);
|
||||
alias(ActionFactory.class, StrutsConstants.STRUTS_OBJECTFACTORY_ACTIONFACTORY, builder, props);
|
||||
@@ -423,6 +426,9 @@ public class StrutsBeanSelectionProvider extends AbstractBeanSelectionProvider {
|
||||
|
||||
alias(DateFormatter.class, StrutsConstants.STRUTS_DATE_FORMATTER, builder, props, Scope.SINGLETON);
|
||||
|
||||
alias(ExpressionCacheFactory.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_FACTORY, builder, props, Scope.SINGLETON);
|
||||
alias(BeanInfoCacheFactory.class, StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_FACTORY, builder, props, Scope.SINGLETON);
|
||||
|
||||
switchDevMode(props);
|
||||
}
|
||||
|
||||
|
||||
@@ -90,7 +90,6 @@ public class ConstantConfig {
|
||||
private BeanConfig localeProviderFactory;
|
||||
private String mapperIdParameterName;
|
||||
private Boolean ognlAllowStaticFieldAccess;
|
||||
private Boolean ognlAllowStaticMethodAccess;
|
||||
private BeanConfig actionValidatorManager;
|
||||
private BeanConfig valueStackFactory;
|
||||
private BeanConfig reflectionProvider;
|
||||
@@ -144,6 +143,8 @@ public class ConstantConfig {
|
||||
private Boolean disallowProxyMemberAccess;
|
||||
private Integer ognlAutoGrowthCollectionLimit;
|
||||
private String staticContentPath;
|
||||
private BeanConfig expressionCacheFactory;
|
||||
private BeanConfig beaninfoCacheFactory;
|
||||
|
||||
protected String beanConfToString(BeanConfig beanConf) {
|
||||
return beanConf == null ? null : beanConf.getName();
|
||||
@@ -220,7 +221,6 @@ public class ConstantConfig {
|
||||
map.put(StrutsConstants.STRUTS_LOCALE_PROVIDER_FACTORY, beanConfToString(localeProviderFactory));
|
||||
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_METHOD_ACCESS, Objects.toString(ognlAllowStaticMethodAccess, null));
|
||||
map.put(StrutsConstants.STRUTS_ACTIONVALIDATORMANAGER, beanConfToString(actionValidatorManager));
|
||||
map.put(StrutsConstants.STRUTS_VALUESTACKFACTORY, beanConfToString(valueStackFactory));
|
||||
map.put(StrutsConstants.STRUTS_REFLECTIONPROVIDER, beanConfToString(reflectionProvider));
|
||||
@@ -274,6 +274,8 @@ public class ConstantConfig {
|
||||
map.put(StrutsConstants.STRUTS_DISALLOW_PROXY_MEMBER_ACCESS, Objects.toString(disallowProxyMemberAccess, null));
|
||||
map.put(StrutsConstants.STRUTS_OGNL_AUTO_GROWTH_COLLECTION_LIMIT, Objects.toString(ognlAutoGrowthCollectionLimit, null));
|
||||
map.put(StrutsConstants.STRUTS_UI_STATIC_CONTENT_PATH, Objects.toString(staticContentPath, StaticContentLoader.DEFAULT_STATIC_CONTENT_PATH));
|
||||
map.put(StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_FACTORY, beanConfToString(expressionCacheFactory));
|
||||
map.put(StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_FACTORY, beanConfToString(beaninfoCacheFactory));
|
||||
|
||||
return map;
|
||||
}
|
||||
@@ -806,14 +808,6 @@ public class ConstantConfig {
|
||||
this.ognlAllowStaticFieldAccess = ognlAllowStaticFieldAccess;
|
||||
}
|
||||
|
||||
public Boolean getOgnlAllowStaticMethodAccess() {
|
||||
return ognlAllowStaticMethodAccess;
|
||||
}
|
||||
|
||||
public void setOgnlAllowStaticMethodAccess(Boolean ognlAllowStaticMethodAccess) {
|
||||
this.ognlAllowStaticMethodAccess = ognlAllowStaticMethodAccess;
|
||||
}
|
||||
|
||||
public BeanConfig getActionValidatorManager() {
|
||||
return actionValidatorManager;
|
||||
}
|
||||
@@ -1341,4 +1335,28 @@ public class ConstantConfig {
|
||||
public void setStaticContentPath(String staticContentPath) {
|
||||
this.staticContentPath = StaticContentLoader.Validator.validateStaticContentPath(staticContentPath);
|
||||
}
|
||||
|
||||
public BeanConfig getExpressionCacheFactory() {
|
||||
return expressionCacheFactory;
|
||||
}
|
||||
|
||||
public void setExpressionCacheFactory(BeanConfig expressionCacheFactory) {
|
||||
this.expressionCacheFactory = expressionCacheFactory;
|
||||
}
|
||||
|
||||
public void setExpressionCacheFactory(Class<?> clazz) {
|
||||
this.expressionCacheFactory = new BeanConfig(clazz, clazz.getName());
|
||||
}
|
||||
|
||||
public BeanConfig getBeaninfoCacheFactory() {
|
||||
return beaninfoCacheFactory;
|
||||
}
|
||||
|
||||
public void setBeaninfoCacheFactory(BeanConfig beaninfoCacheFactory) {
|
||||
this.beaninfoCacheFactory = beaninfoCacheFactory;
|
||||
}
|
||||
|
||||
public void setBeaninfoCacheFactory(Class<?> clazz) {
|
||||
this.beaninfoCacheFactory = new BeanConfig(clazz, clazz.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.StrutsException;
|
||||
import org.apache.struts2.views.jsp.ui.OgnlTool;
|
||||
import org.apache.struts2.views.util.UrlHelper;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.WriteListener;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
@@ -278,6 +280,20 @@ public class StrutsUtil {
|
||||
public void write(int 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;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import org.apache.struts2.ServletActionContext;
|
||||
import org.apache.struts2.views.util.DefaultUrlHelper;
|
||||
import org.apache.struts2.views.util.UrlHelper;
|
||||
|
||||
@@ -58,20 +57,10 @@ public class URLBean {
|
||||
|
||||
public String getURL() {
|
||||
// all this trickier with maps is to reduce the number of objects created
|
||||
Map<String, Object> fullParams = null;
|
||||
|
||||
if (params != null) {
|
||||
fullParams = new HashMap<String, Object>();
|
||||
}
|
||||
Map<String, Object> fullParams = new HashMap<>();
|
||||
|
||||
if (page == null) {
|
||||
// No particular page requested, so go to "same page"
|
||||
// Add query params to parameters
|
||||
if (fullParams != null) {
|
||||
fullParams.putAll(request.getParameterMap());
|
||||
} else {
|
||||
fullParams = request.getParameterMap();
|
||||
}
|
||||
fullParams.putAll(request.getParameterMap());
|
||||
}
|
||||
|
||||
// added parameters override, just like in URLTag
|
||||
@@ -84,7 +73,7 @@ public class URLBean {
|
||||
|
||||
public URLBean addParameter(String name, Object value) {
|
||||
if (params == null) {
|
||||
params = new HashMap<String, String>();
|
||||
params = new HashMap<>();
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
|
||||
@@ -229,19 +229,49 @@ struts.ognl.logMissingProperties=false
|
||||
### if the application generates a lot of different expressions
|
||||
struts.ognl.enableExpressionCache=true
|
||||
|
||||
### Specify the OGNL expression cache factory and BeanInfo cache factory to use.
|
||||
### Currently, the default implementations are used, but can be replaced with custom ones if desired.
|
||||
struts.ognl.expressionCacheFactory=defaultOgnlExpressionCacheFactory
|
||||
struts.ognl.beanInfoCacheFactory=defaultOgnlBeanInfoCacheFactory
|
||||
|
||||
### Specify a limit to the number of entries in the OGNL expressionCache.
|
||||
### For the standard expressionCache mode, when the limit is exceeded the entire cache's
|
||||
### content will be cleared (can help prevent memory leaks).
|
||||
### For expressionCacheLRUMode true, the limit will ensure the cache does not exceed
|
||||
### that size, dropping the oldest (least-recently-used) expressions to add new ones.
|
||||
### NOTE: If not set, the default is 25000, which may be excessive.
|
||||
# struts.ognl.expressionCacheMaxSize=1000
|
||||
|
||||
### Indicates if the OGNL expressionCache should use LRU mode.
|
||||
### NOTE: When true, make sure to set the expressionCacheMaxSize to a reasonable value
|
||||
### for your application. Otherwise the default limit will never (practically) be reached.
|
||||
# struts.ognl.expressionCacheLRUMode=false
|
||||
|
||||
### Specify a limit to the number of entries in the OGNL beanInfoCache.
|
||||
### For the standard beanInfoCache mode, when the limit is exceeded the entire cache's
|
||||
### content will be cleared (can help prevent memory leaks).
|
||||
### For beanInfoCacheLRUMode true, the limit will ensure the cache does not exceed
|
||||
### that size, dropping the oldest (least-recently-used) expressions to add new ones.
|
||||
### NOTE: If not set, the default is 25000, which may be excessive.
|
||||
# struts.ognl.beanInfoCacheMaxSize=1000
|
||||
|
||||
### Indicates if the OGNL beanInfoCache should use LRU mode.
|
||||
### NOTE: When true, make sure to set the beanInfoCacheMaxSize to a reasonable value
|
||||
### for your application. Otherwise the default limit will never (practically) be reached.
|
||||
# struts.ognl.beanInfoCacheLRUMode=false
|
||||
|
||||
### Indicates if Dispatcher should handle unexpected exceptions by calling sendError()
|
||||
### or simply rethrow it as a ServletException to allow future processing by other frameworks like Spring Security
|
||||
struts.handle.exception=true
|
||||
|
||||
### 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
|
||||
### struts.ognl.expressionMaxLength. They must choose a value large enough to permit ALL valid OGNL expressions used within the application.
|
||||
### Values larger than the 200-400 range have diminishing 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
|
||||
### **WARNING**: If developers change this option (by configuration) they should make sure that they understand
|
||||
### the implications of setting 'struts.ognl.expressionMaxLength'. They must choose a value large enough to permit
|
||||
### ALL valid OGNL expressions used within the application. Values larger than the 200-400 range have diminishing
|
||||
### 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.
|
||||
struts.ognl.expressionMaxLength=256
|
||||
|
||||
### Defines which named instance of DateFormatter to use, there are two instances:
|
||||
### - simpleDateFormatter (based on SimpleDateFormat)
|
||||
|
||||
@@ -231,6 +231,9 @@
|
||||
<bean type="org.apache.struts2.components.date.DateFormatter" name="simpleDateFormatter" class="org.apache.struts2.components.date.SimpleDateFormatAdapter" scope="singleton"/>
|
||||
<bean type="org.apache.struts2.components.date.DateFormatter" name="dateTimeFormatter" class="org.apache.struts2.components.date.DateTimeFormatterAdapter" scope="singleton"/>
|
||||
|
||||
<bean type="com.opensymphony.xwork2.ognl.OgnlCacheFactory" name="ognlExpressionCacheFactory" class="com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory" scope="singleton"/>
|
||||
<bean type="com.opensymphony.xwork2.ognl.OgnlCacheFactory" name="ognlBeanInfoCacheFactory" class="com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory" scope="singleton"/>
|
||||
|
||||
<package name="struts-default" abstract="true">
|
||||
<result-types>
|
||||
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
|
||||
|
||||
@@ -28,6 +28,9 @@ import org.apache.struts2.conversion.TypeConversionException;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.text.DateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
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_CONVERTED = "Fri Mar 20 00:00:00";
|
||||
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_DEFAULT_CONSTRUCTOR_ERROR = "Couldn't create class null using default (long) constructor";
|
||||
|
||||
public void testSqlTimeType() {
|
||||
DateConverter converter = new DateConverter();
|
||||
|
||||
ActionContext context = ActionContext.of(new HashMap<>())
|
||||
.withLocale(mxLocale);
|
||||
ActionContext context = ActionContext.of(new HashMap<>()).withLocale(mxLocale);
|
||||
|
||||
Object value = converter.convertValue(context.getContextMap(), null, null, null, TIME_01_59_10, Time.class);
|
||||
assertEquals("01:59:10", value.toString());
|
||||
@@ -59,10 +68,10 @@ public class DateConverterTest extends StrutsInternalTestCase {
|
||||
public void testSqlTimestampType() {
|
||||
DateConverter converter = new DateConverter();
|
||||
|
||||
ActionContext context = ActionContext.of(new HashMap<>())
|
||||
.withLocale(mxLocale);
|
||||
ActionContext context = ActionContext.of(new HashMap<>()).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());
|
||||
}
|
||||
|
||||
@@ -74,9 +83,8 @@ public class DateConverterTest extends StrutsInternalTestCase {
|
||||
ValueStack stack = new StubValueStack();
|
||||
stack.push(new StubTextProvider(map));
|
||||
|
||||
ActionContext context = ActionContext.of(new HashMap<>())
|
||||
.withLocale(new Locale("es_MX", "MX"))
|
||||
.withValueStack(stack);
|
||||
ActionContext context = ActionContext.of(new HashMap<>()).withLocale(new Locale("es_MX", "MX"))
|
||||
.withValueStack(stack);
|
||||
|
||||
Object value = converter.convertValue(context.getContextMap(), null, null, null, DATE_STR, Date.class);
|
||||
assertTrue(value.toString().startsWith(DATE_CONVERTED));
|
||||
@@ -90,9 +98,8 @@ public class DateConverterTest extends StrutsInternalTestCase {
|
||||
ValueStack stack = new StubValueStack();
|
||||
stack.push(new StubTextProvider(map));
|
||||
|
||||
ActionContext context = ActionContext.of(new HashMap<>())
|
||||
.withLocale(new Locale("es_MX", "MX"))
|
||||
.withValueStack(stack);
|
||||
ActionContext context = ActionContext.of(new HashMap<>()).withLocale(new Locale("es_MX", "MX"))
|
||||
.withValueStack(stack);
|
||||
|
||||
try {
|
||||
converter.convertValue(context.getContextMap(), null, null, null, INVALID_DATE, Date.class);
|
||||
@@ -106,8 +113,7 @@ public class DateConverterTest extends StrutsInternalTestCase {
|
||||
public void testTypeConversionExceptionWhenUsingLongConstructor() {
|
||||
DateConverter converter = new DateConverter();
|
||||
|
||||
ActionContext context = ActionContext.of(new HashMap<>())
|
||||
.withLocale(mxLocale);
|
||||
ActionContext context = ActionContext.of(new HashMap<>()).withLocale(mxLocale);
|
||||
|
||||
try {
|
||||
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
|
||||
protected void setUp() throws Exception {
|
||||
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);
|
||||
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_WHEN_LONG_CONSTRUCTOR_STR = "2020-03-20";
|
||||
} else {// Format when Java 8 or lower
|
||||
|
||||
+10
-5
@@ -39,13 +39,17 @@ import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor;
|
||||
import com.opensymphony.xwork2.util.CompoundRoot;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import com.opensymphony.xwork2.util.ValueStackFactory;
|
||||
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
|
||||
import ognl.OgnlContext;
|
||||
import ognl.PropertyAccessor;
|
||||
import org.apache.struts2.config.StrutsXmlConfigurationProvider;
|
||||
import org.apache.struts2.dispatcher.HttpParameters;
|
||||
import org.junit.Assert;
|
||||
import org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -335,8 +339,8 @@ public class ParametersInterceptorTest extends XWorkTestCase {
|
||||
// given
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("blah", "This is blah");
|
||||
params.put("('\\u0023_memberAccess[\\'allowStaticMethodAccess\\']')(meh)", "true");
|
||||
params.put("('(aaa)(('\\u0023context[\\'xwork.MethodAccessor.denyMethodExecution\\']\\u003d\\u0023foo')(\\u0023foo\\u003dnew java.lang.Boolean(\"false\")))", "");
|
||||
params.put("('\\u0023_memberAccess[\\'allowStaticFieldAccess\\']')(meh)", "true");
|
||||
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");
|
||||
|
||||
HashMap<String, Object> extraContext = new HashMap<>();
|
||||
@@ -351,8 +355,9 @@ public class ParametersInterceptorTest extends XWorkTestCase {
|
||||
|
||||
//then
|
||||
assertEquals("This is blah", ((SimpleAction) proxy.getAction()).getBlah());
|
||||
boolean allowMethodAccess = ((SecurityMemberAccess) ((OgnlContext) stack.getContext()).getMemberAccess()).getAllowStaticMethodAccess();
|
||||
assertFalse(allowMethodAccess);
|
||||
Field field = ReflectionContextState.class.getField("DENY_METHOD_EXECUTION");
|
||||
boolean allowStaticFieldAccess = ((OgnlContext) stack.getContext()).getMemberAccess().isAccessible(stack.getContext(), proxy.getAction(), field, "");
|
||||
assertFalse(allowStaticFieldAccess);
|
||||
}
|
||||
|
||||
public void testParameters() throws Exception {
|
||||
@@ -806,7 +811,7 @@ public class ParametersInterceptorTest extends XWorkTestCase {
|
||||
ValueStack stack = new OgnlValueStack(
|
||||
container.getInstance(XWorkConverter.class),
|
||||
(CompoundRootAccessor) container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()),
|
||||
container.getInstance(TextProvider.class, "system"), true, true) {
|
||||
container.getInstance(TextProvider.class, "system"), true) {
|
||||
@Override
|
||||
public void setValue(String expr, Object value) {
|
||||
actual.put(expr, value);
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.opensymphony.xwork2.util.Owner;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import com.opensymphony.xwork2.util.location.LocatableProperties;
|
||||
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
|
||||
import java.beans.BeanInfo;
|
||||
import ognl.InappropriateExpressionException;
|
||||
import ognl.MethodFailedException;
|
||||
import ognl.NoSuchPropertyException;
|
||||
@@ -129,6 +130,61 @@ public class OgnlUtilTest extends XWorkTestCase {
|
||||
assertSame(expr0, expr2);
|
||||
}
|
||||
|
||||
public void testCacheEnabledMaxSize() throws OgnlException {
|
||||
ognlUtil.setEnableExpressionCache("true");
|
||||
ognlUtil.setExpressionCacheMaxSize("1");
|
||||
Object expr0 = ognlUtil.compile("test");
|
||||
Object expr2 = ognlUtil.compile("test");
|
||||
assertSame(expr0, expr2);
|
||||
assertEquals("Expression cache size should be at its limit", 1, ognlUtil.expressionCacheSize());
|
||||
// Next epxression cached should cause the cache to clear (exceeding maximum sized).
|
||||
Object expr3 = ognlUtil.compile("test1");
|
||||
assertEquals("Expression cache should be empty", 0, ognlUtil.expressionCacheSize());
|
||||
Object expr4 = ognlUtil.compile("test1");
|
||||
Object expr5 = ognlUtil.compile("test1");
|
||||
assertEquals("Expression cache size should still be at its limit", 1, ognlUtil.expressionCacheSize());
|
||||
assertNotSame("2nd test expression cache attempt will exceed size and force clear, but somehow they match ?", expr3, expr4);
|
||||
assertSame(expr4, expr5);
|
||||
// Next epxression cached should cause the cache to clear (exceeding maximum sized).
|
||||
Object expr6 = ognlUtil.compile("test");
|
||||
assertEquals("Expression cache should be empty", 0, ognlUtil.expressionCacheSize());
|
||||
Object expr7 = ognlUtil.compile("test");
|
||||
Object expr8 = ognlUtil.compile("test");
|
||||
assertNotSame("2nd test expression cache attempt will exceed size and force clear, but somehow they match ?", expr6, expr7);
|
||||
assertSame(expr7, expr8);
|
||||
assertEquals("Expression LRU cache size should still be at its limit", 1, ognlUtil.expressionCacheSize());
|
||||
assertNotSame("1st test expression identical after ejection from LRU cache ?", expr5, expr0);
|
||||
}
|
||||
|
||||
public void testLRUCacheEnabled() throws OgnlException {
|
||||
// Force usage of LRU cache factories for the OgnlUtil instance
|
||||
this.ognlUtil = generateOgnlUtilInstanceWithDefaultLRUCacheFactories();
|
||||
ognlUtil.setEnableExpressionCache("true");
|
||||
Object expr0 = ognlUtil.compile("test");
|
||||
Object expr2 = ognlUtil.compile("test");
|
||||
assertSame(expr0, expr2);
|
||||
}
|
||||
|
||||
public void testLRUCacheEnabledMaxSize() throws OgnlException {
|
||||
// Force usage of LRU cache factories for the OgnlUtil instance
|
||||
this.ognlUtil = generateOgnlUtilInstanceWithDefaultLRUCacheFactories();
|
||||
ognlUtil.setEnableExpressionCache("true");
|
||||
ognlUtil.setExpressionCacheMaxSize("1");
|
||||
Object expr0 = ognlUtil.compile("test");
|
||||
Object expr2 = ognlUtil.compile("test");
|
||||
assertSame(expr0, expr2);
|
||||
assertEquals("Expression LRU cache size should be at its limit", 1, ognlUtil.expressionCacheSize());
|
||||
Object expr3 = ognlUtil.compile("test1");
|
||||
Object expr4 = ognlUtil.compile("test1");
|
||||
assertSame(expr3, expr4);
|
||||
assertEquals("Expression LRU cache size should still be at its limit", 1, ognlUtil.expressionCacheSize());
|
||||
Object expr5 = ognlUtil.compile("test");
|
||||
Object expr6 = ognlUtil.compile("test");
|
||||
assertSame(expr5, expr6);
|
||||
assertEquals("Expression LRU cache size should still be at its limit", 1, ognlUtil.expressionCacheSize());
|
||||
assertNotSame("1st test expression identical after ejection from LRU cache ?", expr5, expr0);
|
||||
}
|
||||
|
||||
public void testExpressionIsCachedIrrespectiveOfItsExecutionStatus() throws OgnlException {
|
||||
Foo foo = new Foo();
|
||||
OgnlContext context = (OgnlContext) ognlUtil.createDefaultContext(foo);
|
||||
@@ -149,6 +205,30 @@ public class OgnlUtilTest extends XWorkTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testExpressionIsLRUCachedIrrespectiveOfItsExecutionStatus() throws OgnlException {
|
||||
// Force usage of LRU cache factories for the OgnlUtil instance
|
||||
this.ognlUtil = generateOgnlUtilInstanceWithDefaultLRUCacheFactories();
|
||||
ognlUtil.setContainer(container); // Must be explicitly set as the generated OgnlUtil instance has no container
|
||||
ognlUtil.setEnableExpressionCache("true");
|
||||
Foo foo = new Foo();
|
||||
OgnlContext context = (OgnlContext) ognlUtil.createDefaultContext(foo);
|
||||
|
||||
// Expression which executes with success
|
||||
try {
|
||||
ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_FINAL_PUBLIC_ATTRIBUTE", context, foo);
|
||||
assertEquals("Successfully executed expression must have been cached", ognlUtil.expressionCacheSize(), 1);
|
||||
} catch (Exception ex) {
|
||||
fail("Expression execution should have succeeded here. Exception: " + ex);
|
||||
}
|
||||
// Expression which executes with failure
|
||||
try {
|
||||
ognlUtil.getValue("@com.opensymphony.xwork2.ognl.OgnlUtilTest@STATIC_PRIVATE_ATTRIBUTE", context, foo);
|
||||
fail("Expression execution should have failed here");
|
||||
} catch (Exception ex) {
|
||||
assertEquals("Expression with failed execution must have been cached nevertheless", ognlUtil.expressionCacheSize(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
public void testMethodExpressionIsCachedIrrespectiveOfItsExecutionStatus() throws Exception {
|
||||
Foo foo = new Foo();
|
||||
OgnlContext context = (OgnlContext) ognlUtil.createDefaultContext(foo);
|
||||
@@ -193,6 +273,32 @@ public class OgnlUtilTest extends XWorkTestCase {
|
||||
assertTrue("Expression cache empty after usage ?", ognlUtil.expressionCacheSize() > 0);
|
||||
}
|
||||
|
||||
public void testClearExpressionLRUCache() throws OgnlException {
|
||||
// Force usage of LRU cache factories for the OgnlUtil instance
|
||||
this.ognlUtil = generateOgnlUtilInstanceWithDefaultLRUCacheFactories();
|
||||
ognlUtil.setEnableExpressionCache("true");
|
||||
// Test that the expression cache is functioning as expected.
|
||||
Object expr0 = ognlUtil.compile("test");
|
||||
Object expr1 = ognlUtil.compile("test");
|
||||
Object expr2 = ognlUtil.compile("test");
|
||||
// Cache in effect, so expr0, expr1, expr2 should be the same.
|
||||
assertSame(expr0, expr1);
|
||||
assertSame(expr0, expr2);
|
||||
assertTrue("Expression cache empty before clear ?", ognlUtil.expressionCacheSize() > 0);
|
||||
// Clear the Epxression cache and confirm subsequent requests are new.
|
||||
ognlUtil.clearExpressionCache();
|
||||
assertEquals("Expression cache not empty after clear ?", 0, ognlUtil.expressionCacheSize());
|
||||
Object expr3 = ognlUtil.compile("test");
|
||||
Object expr4 = ognlUtil.compile("test");
|
||||
Object expr5 = ognlUtil.compile("test");
|
||||
// Cache cleared, expr3 should be a new instance.
|
||||
assertNotSame(expr0, expr3);
|
||||
// Cache still in effect, so expr3, expr4, expr5 should be the same.
|
||||
assertSame(expr3, expr4);
|
||||
assertSame(expr3, expr5);
|
||||
assertTrue("Expression cache empty after usage ?", ognlUtil.expressionCacheSize() > 0);
|
||||
}
|
||||
|
||||
public void testClearBeanInfoCache() throws IntrospectionException {
|
||||
final TestBean1 testBean1 = new TestBean1();
|
||||
final TestBean2 testBean2 = new TestBean2();
|
||||
@@ -242,6 +348,79 @@ public class OgnlUtilTest extends XWorkTestCase {
|
||||
assertTrue("BeanInfo cache empty after usage ?", ognlUtil.beanInfoCacheSize() > 0);
|
||||
}
|
||||
|
||||
public void testBeanInfoCache() throws IntrospectionException {
|
||||
final TestBean1 testBean1 = new TestBean1();
|
||||
final TestBean2 testBean2 = new TestBean2();
|
||||
// Test that the BeanInfo cache is functioning as expected.
|
||||
Object beanInfo1_1 = ognlUtil.getBeanInfo(testBean1);
|
||||
Object beanInfo1_2 = ognlUtil.getBeanInfo(testBean1);
|
||||
Object beanInfo1_3 = ognlUtil.getBeanInfo(testBean1);
|
||||
// Cache in effect, so beanInfo1_1, beanInfo1_2, beanInfo1_3 should be the same.
|
||||
assertSame(beanInfo1_1, beanInfo1_2);
|
||||
assertSame(beanInfo1_1, beanInfo1_3);
|
||||
Object beanInfo2_1 = ognlUtil.getBeanInfo(testBean2);
|
||||
Object beanInfo2_2 = ognlUtil.getBeanInfo(testBean2);
|
||||
Object beanInfo2_3 = ognlUtil.getBeanInfo(testBean2);
|
||||
// Cache in effect, so beanInfo2_1, beanInfo2_2, beanInfo2_3 should be the same.
|
||||
assertSame(beanInfo2_1, beanInfo2_2);
|
||||
assertSame(beanInfo2_1, beanInfo2_3);
|
||||
// BeanInfo for TestBean1 and TestBean2 should always be different.
|
||||
assertNotSame(beanInfo1_1, beanInfo2_1);
|
||||
assertTrue("BeanInfo cache empty after usage ?", ognlUtil.beanInfoCacheSize() > 0);
|
||||
}
|
||||
|
||||
public void testBeanInfoLRUCache() throws IntrospectionException {
|
||||
// Force usage of LRU cache factories for the OgnlUtil instance
|
||||
this.ognlUtil = generateOgnlUtilInstanceWithDefaultLRUCacheFactories();
|
||||
final TestBean1 testBean1 = new TestBean1();
|
||||
final TestBean2 testBean2 = new TestBean2();
|
||||
// Test that the BeanInfo cache is functioning as expected.
|
||||
Object beanInfo1_1 = ognlUtil.getBeanInfo(testBean1);
|
||||
Object beanInfo1_2 = ognlUtil.getBeanInfo(testBean1);
|
||||
Object beanInfo1_3 = ognlUtil.getBeanInfo(testBean1);
|
||||
// Cache in effect, so beanInfo1_1, beanInfo1_2, beanInfo1_3 should be the same.
|
||||
assertSame(beanInfo1_1, beanInfo1_2);
|
||||
assertSame(beanInfo1_1, beanInfo1_3);
|
||||
Object beanInfo2_1 = ognlUtil.getBeanInfo(testBean2);
|
||||
Object beanInfo2_2 = ognlUtil.getBeanInfo(testBean2);
|
||||
Object beanInfo2_3 = ognlUtil.getBeanInfo(testBean2);
|
||||
// Cache in effect, so beanInfo2_1, beanInfo2_2, beanInfo2_3 should be the same.
|
||||
assertSame(beanInfo2_1, beanInfo2_2);
|
||||
assertSame(beanInfo2_1, beanInfo2_3);
|
||||
// BeanInfo for TestBean1 and TestBean2 should always be different.
|
||||
assertNotSame(beanInfo1_1, beanInfo2_1);
|
||||
assertTrue("BeanInfo cache empty after usage ?", ognlUtil.beanInfoCacheSize() > 0);
|
||||
}
|
||||
|
||||
public void testBeanInfoLRUCacheLimits() throws IntrospectionException {
|
||||
// Force usage of LRU cache factories for the OgnlUtil instance
|
||||
this.ognlUtil = generateOgnlUtilInstanceWithDefaultLRUCacheFactories();
|
||||
ognlUtil.setBeanInfoCacheMaxSize("1");
|
||||
final TestBean1 testBean1 = new TestBean1();
|
||||
final TestBean2 testBean2 = new TestBean2();
|
||||
// Test that the BeanInfo cache is functioning as expected.
|
||||
Object beanInfo1_1 = ognlUtil.getBeanInfo(testBean1);
|
||||
Object beanInfo1_2 = ognlUtil.getBeanInfo(testBean1);
|
||||
Object beanInfo1_3 = ognlUtil.getBeanInfo(testBean1);
|
||||
// Cache in effect, so beanInfo1_1, beanInfo1_2, beanInfo1_3 should be the same.
|
||||
assertSame(beanInfo1_1, beanInfo1_2);
|
||||
assertSame(beanInfo1_1, beanInfo1_3);
|
||||
Object beanInfo2_1 = ognlUtil.getBeanInfo(testBean2);
|
||||
Object beanInfo2_2 = ognlUtil.getBeanInfo(testBean2);
|
||||
Object beanInfo2_3 = ognlUtil.getBeanInfo(testBean2);
|
||||
// Cache in effect, so beanInfo2_1, beanInfo2_2, beanInfo2_3 should be the same.
|
||||
assertSame(beanInfo2_1, beanInfo2_2);
|
||||
assertSame(beanInfo2_1, beanInfo2_3);
|
||||
// BeanInfo for TestBean1 and TestBean2 should always be different.
|
||||
assertNotSame(beanInfo1_1, beanInfo2_1);
|
||||
assertTrue("BeanInfo cache empty after usage ?", ognlUtil.beanInfoCacheSize() > 0);
|
||||
assertEquals("BeanInfo LRU cache size should be at its limit", 1, ognlUtil.beanInfoCacheSize());
|
||||
// LRU cache should not contain TestBean1 beaninfo anymore. A new entry should exist in the cache.
|
||||
Object beanInfo1_4 = ognlUtil.getBeanInfo(testBean1);
|
||||
assertNotSame("BeanInfo dropped from LRU cache is the same as newly added ?", beanInfo1_1, beanInfo1_4);
|
||||
ognlUtil.setBeanInfoCacheMaxSize(String.valueOf(Integer.MAX_VALUE));
|
||||
}
|
||||
|
||||
public void testClearRuntimeCache() {
|
||||
// Confirm that no exceptions or failures arise when calling the convenience global clear method.
|
||||
OgnlUtil.clearRuntimeCache();
|
||||
@@ -1134,6 +1313,20 @@ public class OgnlUtilTest extends XWorkTestCase {
|
||||
internalTestOgnlUtilExclusionsImmutable(basicOgnlUtil);
|
||||
}
|
||||
|
||||
public void testDefaultOgnlUtilExclusionsAlternateConstructor() {
|
||||
OgnlUtil basicOgnlUtil = new OgnlUtil(null, null);
|
||||
|
||||
internalTestInitialEmptyOgnlUtilExclusions(basicOgnlUtil);
|
||||
internalTestOgnlUtilExclusionsImmutable(basicOgnlUtil);
|
||||
}
|
||||
|
||||
public void testDefaultOgnlUtilExclusionsAlternateConstructorPopulated() {
|
||||
OgnlUtil basicOgnlUtil = new OgnlUtil(new DefaultOgnlExpressionCacheFactory<String, Object>(), new DefaultOgnlBeanInfoCacheFactory<Class<?>, BeanInfo>());
|
||||
|
||||
internalTestInitialEmptyOgnlUtilExclusions(basicOgnlUtil);
|
||||
internalTestOgnlUtilExclusionsImmutable(basicOgnlUtil);
|
||||
}
|
||||
|
||||
public void testOgnlUtilExcludedAdditivity() {
|
||||
Set<Class<?>> excludedClasses;
|
||||
Set<Pattern> excludedPackageNamePatterns;
|
||||
@@ -1497,6 +1690,34 @@ public class OgnlUtilTest extends XWorkTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetExcludedPackageNamesAlternateConstructor() {
|
||||
// Getter should return an immutable collection
|
||||
OgnlUtil util = new OgnlUtil(null, null);
|
||||
util.setExcludedPackageNames("java.lang,java.awt");
|
||||
assertEquals(util.getExcludedPackageNames().size(), 2);
|
||||
try {
|
||||
util.getExcludedPackageNames().clear();
|
||||
} catch (Exception ex) {
|
||||
assertTrue(ex instanceof UnsupportedOperationException);
|
||||
} finally {
|
||||
assertEquals(util.getExcludedPackageNames().size(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetExcludedPackageNamesAlternateConstructorPopulated() {
|
||||
// Getter should return an immutable collection
|
||||
OgnlUtil util = new OgnlUtil(new DefaultOgnlExpressionCacheFactory<String, Object>(), new DefaultOgnlBeanInfoCacheFactory<Class<?>, BeanInfo>());
|
||||
util.setExcludedPackageNames("java.lang,java.awt");
|
||||
assertEquals(util.getExcludedPackageNames().size(), 2);
|
||||
try {
|
||||
util.getExcludedPackageNames().clear();
|
||||
} catch (Exception ex) {
|
||||
assertTrue(ex instanceof UnsupportedOperationException);
|
||||
} finally {
|
||||
assertEquals(util.getExcludedPackageNames().size(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetExcludedClasses() {
|
||||
// Getter should return an immutable collection
|
||||
OgnlUtil util = new OgnlUtil();
|
||||
@@ -1511,6 +1732,34 @@ public class OgnlUtilTest extends XWorkTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetExcludedClassesAlternateConstructor() {
|
||||
// Getter should return an immutable collection
|
||||
OgnlUtil util = new OgnlUtil(null, null);
|
||||
util.setExcludedClasses("java.lang.Runtime,java.lang.ProcessBuilder,java.net.URL");
|
||||
assertEquals(util.getExcludedClasses().size(), 3);
|
||||
try {
|
||||
util.getExcludedClasses().clear();
|
||||
} catch (Exception ex) {
|
||||
assertTrue(ex instanceof UnsupportedOperationException);
|
||||
} finally {
|
||||
assertEquals(util.getExcludedClasses().size(), 3);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetExcludedClassesAlternateConstructorPopulated() {
|
||||
// Getter should return an immutable collection
|
||||
OgnlUtil util = new OgnlUtil(new DefaultOgnlExpressionCacheFactory<String, Object>(), new DefaultOgnlBeanInfoCacheFactory<Class<?>, BeanInfo>());
|
||||
util.setExcludedClasses("java.lang.Runtime,java.lang.ProcessBuilder,java.net.URL");
|
||||
assertEquals(util.getExcludedClasses().size(), 3);
|
||||
try {
|
||||
util.getExcludedClasses().clear();
|
||||
} catch (Exception ex) {
|
||||
assertTrue(ex instanceof UnsupportedOperationException);
|
||||
} finally {
|
||||
assertEquals(util.getExcludedClasses().size(), 3);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetExcludedPackageNamePatterns() {
|
||||
// Getter should return an immutable collection
|
||||
OgnlUtil util = new OgnlUtil();
|
||||
@@ -1525,13 +1774,139 @@ public class OgnlUtilTest extends XWorkTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
private void reloadTestContainerConfiguration(boolean devMode, boolean allowStaticMethod) {
|
||||
public void testGetExcludedPackageNamePatternsAlternateConstructor() {
|
||||
// Getter should return an immutable collection
|
||||
OgnlUtil util = new OgnlUtil(null, null);
|
||||
util.setExcludedPackageNamePatterns("java.lang.");
|
||||
assertEquals(util.getExcludedPackageNamePatterns().size(), 1);
|
||||
try {
|
||||
util.getExcludedPackageNamePatterns().clear();
|
||||
} catch (Exception ex) {
|
||||
assertTrue(ex instanceof UnsupportedOperationException);
|
||||
} finally {
|
||||
assertEquals(util.getExcludedPackageNamePatterns().size(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetExcludedPackageNamePatternsAlternateConstructorPopulated() {
|
||||
// Getter should return an immutable collection
|
||||
OgnlUtil util = new OgnlUtil(new DefaultOgnlExpressionCacheFactory<String, Object>(), new DefaultOgnlBeanInfoCacheFactory<Class<?>, BeanInfo>());
|
||||
util.setExcludedPackageNamePatterns("java.lang.");
|
||||
assertEquals(util.getExcludedPackageNamePatterns().size(), 1);
|
||||
try {
|
||||
util.getExcludedPackageNamePatterns().clear();
|
||||
} catch (Exception ex) {
|
||||
assertTrue(ex instanceof UnsupportedOperationException);
|
||||
} finally {
|
||||
assertEquals(util.getExcludedPackageNamePatterns().size(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
public void testOgnlUtilDefaultCacheClass() throws OgnlException {
|
||||
OgnlDefaultCache<Integer, String> defaultCache = new OgnlDefaultCache<>(2, 16, 0.75f);
|
||||
assertEquals("Initial evictionLimit did not match initial value", 2, defaultCache.getEvictionLimit());
|
||||
defaultCache.setEvictionLimit(3);
|
||||
assertEquals("Updated evictionLimit did not match updated value", 3, defaultCache.getEvictionLimit());
|
||||
String lookupResult = defaultCache.get(Integer.valueOf(0));
|
||||
assertNull("Lookup of empty cache returned non-null value ?", lookupResult);
|
||||
defaultCache.put(Integer.valueOf(0), "Zero");
|
||||
lookupResult = defaultCache.get(Integer.valueOf(0));
|
||||
assertEquals("Retrieved value does not match put value ?", "Zero", lookupResult);
|
||||
defaultCache.put(Integer.valueOf(1), "One");
|
||||
defaultCache.put(Integer.valueOf(2), "Two");
|
||||
assertEquals("Default cache not size evictionlimit after adding three values ?", defaultCache.getEvictionLimit(), defaultCache.size());
|
||||
lookupResult = defaultCache.get(Integer.valueOf(2));
|
||||
assertEquals("Retrieved value does not match put value ?", "Two", lookupResult);
|
||||
defaultCache.put(Integer.valueOf(3), "Three");
|
||||
assertEquals("Default cache not size zero after an add that exceeded the evection limit ?", 0, defaultCache.size());
|
||||
lookupResult = defaultCache.get(Integer.valueOf(0));
|
||||
assertNull("Lookup of value 0 (should have been evicted with everything) returned non-null value ?", lookupResult);
|
||||
lookupResult = defaultCache.get(Integer.valueOf(3));
|
||||
assertNull("Lookup of value 3 (should have been evicted with everything) returned non-null value ?", lookupResult);
|
||||
defaultCache.putIfAbsent(Integer.valueOf(2), "Two");
|
||||
lookupResult = defaultCache.get(Integer.valueOf(2));
|
||||
assertEquals("Retrieved value does not match put value ?", "Two", lookupResult);
|
||||
defaultCache.clear();
|
||||
assertEquals("Default cache not empty after clear ?", 0, defaultCache.size());
|
||||
}
|
||||
|
||||
public void testOgnlUtilLRUCacheClass() throws OgnlException {
|
||||
OgnlLRUCache<Integer, String> lruCache = new OgnlLRUCache<>(2, 16, 0.75f);
|
||||
assertEquals("Initial evictionLimit did not match initial value", 2, lruCache.getEvictionLimit());
|
||||
lruCache.setEvictionLimit(3);
|
||||
assertEquals("Updated evictionLimit did not match updated value", 3, lruCache.getEvictionLimit());
|
||||
String lookupResult = lruCache.get(Integer.valueOf(0));
|
||||
assertNull("Lookup of empty cache returned non-null value ?", lookupResult);
|
||||
lruCache.put(Integer.valueOf(0), "Zero");
|
||||
lookupResult = lruCache.get(Integer.valueOf(0));
|
||||
assertEquals("Retrieved value does not match put value ?", "Zero", lookupResult);
|
||||
lruCache.put(Integer.valueOf(1), "One");
|
||||
lruCache.put(Integer.valueOf(2), "Two");
|
||||
assertEquals("LRU cache not size evictionlimit after adding three values ?", lruCache.getEvictionLimit(), lruCache.size());
|
||||
lookupResult = lruCache.get(Integer.valueOf(2));
|
||||
assertEquals("Retrieved value does not match put value ?", "Two", lookupResult);
|
||||
lruCache.put(Integer.valueOf(3), "Three");
|
||||
assertEquals("LRU cache not size evictionlimit after adding values ?", lruCache.getEvictionLimit(), lruCache.size());
|
||||
lookupResult = lruCache.get(Integer.valueOf(0));
|
||||
assertNull("Lookup of value 0 (should have dropped off LRU cache) returned non-null value ?", lookupResult);
|
||||
lruCache.putIfAbsent(Integer.valueOf(2), "Two");
|
||||
lookupResult = lruCache.get(Integer.valueOf(2));
|
||||
assertEquals("Retrieved value does not match put value ?", "Two", lookupResult);
|
||||
lruCache.clear();
|
||||
assertEquals("LRU cache not empty after clear ?", 0, lruCache.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Unit test primarily for code coverage
|
||||
*/
|
||||
public void testOgnlDefaultCacheFactoryCoverage() {
|
||||
OgnlCache<String, Object> ognlCache;
|
||||
DefaultOgnlCacheFactory defaultOgnlCacheFactory = new DefaultOgnlCacheFactory<String, Object>();
|
||||
// Normal cache
|
||||
defaultOgnlCacheFactory.setCacheMaxSize("12");
|
||||
defaultOgnlCacheFactory.setUseLRUCache("false");
|
||||
ognlCache = defaultOgnlCacheFactory.buildOgnlCache();
|
||||
assertNotNull("No param build method result null ?", ognlCache);
|
||||
assertEquals("Eviction limit for cache mismatches limit for factory ?", 12, ognlCache.getEvictionLimit() );
|
||||
ognlCache = defaultOgnlCacheFactory.buildOgnlCache(6, 6, 0.75f, false);
|
||||
assertNotNull("No param build method result null ?", ognlCache);
|
||||
assertEquals("Eviction limit for cache mismatches limit for factory ?", 6, ognlCache.getEvictionLimit() );
|
||||
// LRU cache
|
||||
defaultOgnlCacheFactory.setCacheMaxSize("30");
|
||||
defaultOgnlCacheFactory.setUseLRUCache("true");
|
||||
ognlCache = defaultOgnlCacheFactory.buildOgnlCache();
|
||||
assertNotNull("No param build method result null ?", ognlCache);
|
||||
assertEquals("Eviction limit for cache mismatches limit for factory ?", 30, ognlCache.getEvictionLimit() );
|
||||
ognlCache = defaultOgnlCacheFactory.buildOgnlCache(15, 15, 0.75f, false);
|
||||
assertNotNull("No param build method result null ?", ognlCache);
|
||||
assertEquals("Eviction limit for cache mismatches limit for factory ?", 15, ognlCache.getEvictionLimit() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new OgnlUtil instance (not configured by the {@link ContainerBuilder}) that can be used for
|
||||
* basic tests, with its Expression and BeanInfo factories set to LRU mode.
|
||||
*
|
||||
* @return OgnlUtil instance with LRU enabled Expression and BeanInfo factories
|
||||
*/
|
||||
private OgnlUtil generateOgnlUtilInstanceWithDefaultLRUCacheFactories() {
|
||||
final OgnlUtil result;
|
||||
final DefaultOgnlExpressionCacheFactory<String, Object> expressionFactory = new DefaultOgnlExpressionCacheFactory<>();
|
||||
final DefaultOgnlBeanInfoCacheFactory<Class<?>, BeanInfo> beanInfoFactory = new DefaultOgnlBeanInfoCacheFactory<>();
|
||||
expressionFactory.setUseLRUCache("true");
|
||||
expressionFactory.setCacheMaxSize("25");
|
||||
beanInfoFactory.setUseLRUCache("true");
|
||||
beanInfoFactory.setCacheMaxSize("25");
|
||||
result = new OgnlUtil(expressionFactory, beanInfoFactory);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void reloadTestContainerConfiguration(boolean devMode, boolean allowStaticFieldAccess) {
|
||||
loadConfigurationProviders(new StubConfigurationProvider() {
|
||||
@Override
|
||||
public void register(ContainerBuilder builder,
|
||||
LocatableProperties props) throws ConfigurationException {
|
||||
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);
|
||||
|
||||
@@ -18,7 +18,10 @@
|
||||
*/
|
||||
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.conversion.impl.ConversionData;
|
||||
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.test.StubConfigurationProvider;
|
||||
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.ValueStackFactory;
|
||||
import com.opensymphony.xwork2.util.location.LocatableProperties;
|
||||
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
|
||||
import ognl.OgnlException;
|
||||
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.logging.log4j.LogManager;
|
||||
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.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 {
|
||||
|
||||
// Fields for static field access test
|
||||
@@ -85,16 +91,15 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
}
|
||||
|
||||
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(
|
||||
container.getInstance(XWorkConverter.class),
|
||||
(CompoundRootAccessor) container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()),
|
||||
container.getInstance(TextProvider.class, "system"), allowStaticMethodAccess, allowStaticFieldAccess);
|
||||
container.getInstance(XWorkConverter.class),
|
||||
(CompoundRootAccessor) container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()),
|
||||
container.getInstance(TextProvider.class, "system"), allowStaticFieldAccess);
|
||||
container.inject(stack);
|
||||
ognlUtil.setAllowStaticMethodAccess(Boolean.toString(allowStaticMethodAccess));
|
||||
ognlUtil.setAllowStaticFieldAccess(Boolean.toString(allowStaticFieldAccess));
|
||||
return stack;
|
||||
}
|
||||
@@ -111,16 +116,14 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
* Intended for testing OgnlValueStack instance(s) that are minimally configured.
|
||||
* This should help ensure no underlying configuration/injection side-effects are responsible
|
||||
* for the behaviour of fundamental access control flags).
|
||||
*
|
||||
* @param allowStaticMethod new allowStaticMethod configuration
|
||||
*
|
||||
* @param allowStaticField new allowStaticField configuration
|
||||
* @return a new OgnlValueStackFactory with specified new configuration
|
||||
*/
|
||||
private OgnlValueStackFactory reloadValueStackFactory(Boolean allowStaticMethod, Boolean allowStaticField) {
|
||||
private OgnlValueStackFactory reloadValueStackFactory(Boolean allowStaticField) {
|
||||
try {
|
||||
reloadTestContainerConfiguration(allowStaticMethod, allowStaticField);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
reloadTestContainerConfiguration(allowStaticField);
|
||||
} catch (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);
|
||||
}
|
||||
|
||||
public void testSuccessFailOnErrorOnInheritedPropertiesWithMethods() {
|
||||
public void testSuccessFailOnErrorOnInheritedPropertiesWithMethods() {
|
||||
//this shuld not fail as the property is defined on a parent class
|
||||
OgnlValueStack vs = createValueStack();
|
||||
|
||||
@@ -254,6 +257,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
|
||||
/**
|
||||
* monitors the resolution of WW-4999
|
||||
*
|
||||
* @since 2.5.21
|
||||
*/
|
||||
public void testLogMissingProperties() {
|
||||
@@ -281,11 +285,11 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
if (logMissingProperties) {
|
||||
assertEquals(3, testAppender.logEvents.size());
|
||||
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]!",
|
||||
testAppender.logEvents.get(1).getMessage().getFormattedMessage());
|
||||
testAppender.logEvents.get(1).getMessage().getFormattedMessage());
|
||||
assertEquals("Could not find property [missingProp3]!",
|
||||
testAppender.logEvents.get(2).getMessage().getFormattedMessage());
|
||||
testAppender.logEvents.get(2).getMessage().getFormattedMessage());
|
||||
} else {
|
||||
assertEquals(0, testAppender.logEvents.size());
|
||||
}
|
||||
@@ -297,6 +301,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
|
||||
/**
|
||||
* tests the correctness of distinguishing between user exception and NoSuchMethodException
|
||||
*
|
||||
* @since 2.5.21
|
||||
*/
|
||||
public void testNotLogUserExceptionsAsMissingProperties() {
|
||||
@@ -364,7 +369,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
}
|
||||
});
|
||||
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();
|
||||
try {
|
||||
@@ -383,65 +388,40 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
public void testNotFailOnTooLongExpressionWithDefaultProperties() {
|
||||
loadConfigurationProviders(new DefaultPropertiesProvider());
|
||||
|
||||
Object defaultMaxLengthFromConfiguration = container.getInstance(String.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_MAX_LENGTH);
|
||||
if (defaultMaxLengthFromConfiguration != null) {
|
||||
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 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
|
||||
String defaultMaxLengthFromConfiguration = container.getInstance(String.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_MAX_LENGTH);
|
||||
assertNotNull(defaultMaxLengthFromConfiguration);
|
||||
|
||||
int defaultValue = 256;
|
||||
|
||||
OgnlValueStack vs = createValueStack();
|
||||
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) ?");
|
||||
} 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(((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() {
|
||||
try {
|
||||
loadConfigurationProviders(new DefaultPropertiesProvider());
|
||||
loadConfigurationProviders(new DefaultPropertiesProvider());
|
||||
|
||||
Object defaultMaxLengthFromConfiguration = container.getInstance(String.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_MAX_LENGTH);
|
||||
if (defaultMaxLengthFromConfiguration != null) {
|
||||
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
|
||||
Object defaultMaxLengthFromConfiguration = container.getInstance(String.class, StrutsConstants.STRUTS_OGNL_EXPRESSION_MAX_LENGTH);
|
||||
assertNotNull(defaultMaxLengthFromConfiguration);
|
||||
|
||||
// Apply a non-default value for expressionMaxLength (as it should be disabled by default)
|
||||
try {
|
||||
ognlUtil.applyExpressionMaxLength(repeat.toString());
|
||||
} catch (Exception ex) {
|
||||
fail ("applyExpressionMaxLength did not accept maxlength string " + repeat.toString() + " ?");
|
||||
}
|
||||
int defaultValue = 256;
|
||||
|
||||
OgnlValueStack vs = createValueStack();
|
||||
OgnlValueStack vs = createValueStack();
|
||||
|
||||
Dog dog = new Dog();
|
||||
vs.push(dog);
|
||||
Dog dog = new 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());
|
||||
} finally {
|
||||
// Reset expressionMaxLength value to default (disabled)
|
||||
ognlUtil.applyExpressionMaxLength(null);
|
||||
}
|
||||
assertEquals(value, dog.getName());
|
||||
}
|
||||
|
||||
public void testFailsOnMethodThatThrowsException() {
|
||||
@@ -502,7 +482,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
Dog dog = new Dog();
|
||||
dog.setDeity("fido");
|
||||
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() {
|
||||
OgnlValueStack vs = createValueStack(false, true);
|
||||
OgnlValueStack vs = createValueStack(true);
|
||||
|
||||
Dog dog = new Dog();
|
||||
dog.setDeity("fido");
|
||||
@@ -845,8 +825,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
try {
|
||||
stack.setValue("bar", "3x");
|
||||
fail("Attempt to set 'bar' int property to '3x' should result in RuntimeException");
|
||||
}
|
||||
catch (RuntimeException re) {
|
||||
} catch (RuntimeException re) {
|
||||
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
|
||||
*
|
||||
* @since 2.5.21
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @since 2.5.21
|
||||
*/
|
||||
public void testNotSkipUserReturnedNullValues() {
|
||||
@@ -1187,8 +1168,8 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
stack.push("Hello World");
|
||||
|
||||
OgnlValueStack stack2 = new OgnlValueStack(stack,
|
||||
container.getInstance(XWorkConverter.class),
|
||||
(CompoundRootAccessor) container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()), true, true);
|
||||
container.getInstance(XWorkConverter.class),
|
||||
(CompoundRootAccessor) container.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()), true);
|
||||
container.inject(stack2);
|
||||
|
||||
assertEquals(stack.getRoot(), stack2.getRoot());
|
||||
@@ -1260,7 +1241,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
assertNull(stack.findValue("address.country.name", String.class));
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Test a default OgnlValueStackFactory and OgnlValueStack generated by it
|
||||
* 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)
|
||||
// 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());
|
||||
// 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.
|
||||
@@ -1300,7 +1280,7 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
* when no static access flags are set (not present in configuration).
|
||||
*/
|
||||
public void testOgnlValueStackFromOgnlValueStackFactoryNoFlagsSet() {
|
||||
OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(null, null);
|
||||
OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(null);
|
||||
OgnlValueStack ognlValueStack = (OgnlValueStack) ognlValueStackFactory.createValueStack();
|
||||
Object accessedValue;
|
||||
|
||||
@@ -1309,7 +1289,6 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
// prevent staticMethodAccess AND prevent staticFieldAccess.
|
||||
// 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.
|
||||
assertFalse("OgnlValueStackFactory staticMethodAccess (no flag present) not false?", ognlValueStackFactory.containerAllowsStaticMethodAccess());
|
||||
assertFalse("OgnlValueStackFactory staticFieldAccess (no flag present) not false?", ognlValueStackFactory.containerAllowsStaticFieldAccess());
|
||||
// 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.
|
||||
@@ -1335,16 +1314,15 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(false, false);
|
||||
OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(false);
|
||||
OgnlValueStack ognlValueStack = (OgnlValueStack) ognlValueStackFactory.createValueStack();
|
||||
Object accessedValue;
|
||||
|
||||
// An OgnlValueStackFactory using a container config with both static access flags set false should
|
||||
// prevent staticMethodAccess AND prevent staticFieldAccess.
|
||||
assertFalse("OgnlValueStackFactory staticMethodAccess (set false) not false?", ognlValueStackFactory.containerAllowsStaticMethodAccess());
|
||||
assertFalse("OgnlValueStackFactory staticFieldAccess (set false) not false?", ognlValueStackFactory.containerAllowsStaticFieldAccess());
|
||||
// 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.
|
||||
@@ -1370,22 +1348,20 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(true, true);
|
||||
OgnlValueStackFactory ognlValueStackFactory = reloadValueStackFactory(true);
|
||||
OgnlValueStack ognlValueStack = (OgnlValueStack) ognlValueStackFactory.createValueStack();
|
||||
Object accessedValue;
|
||||
|
||||
// An OgnlValueStackFactory using a container config with both static access flags set true should
|
||||
// allow both staticMethodAccess AND staticFieldAccess.
|
||||
assertTrue("OgnlValueStackFactory staticMethodAccess (set true) not true?", 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 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());
|
||||
assertNull("able to access static method (result non-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");
|
||||
@@ -1404,93 +1380,14 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
assertNull("accessed private field (result not null) ?", accessedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
private void reloadTestContainerConfiguration(Boolean allowStaticField) throws Exception {
|
||||
loadConfigurationProviders(new StubConfigurationProvider() {
|
||||
@Override
|
||||
public void register(ContainerBuilder builder,
|
||||
LocatableProperties props) throws ConfigurationException {
|
||||
// null values simulate undefined (by removing).
|
||||
// undefined values then should be evaluated to false
|
||||
if (props.containsKey(StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_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);
|
||||
}
|
||||
props.remove(StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS);
|
||||
if (allowStaticField != null) {
|
||||
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.Member;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -45,7 +44,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testWithoutClassExclusion() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
String propertyName = "stringField";
|
||||
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 {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
String propertyName = "stringField";
|
||||
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 {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
String propertyName = "toString";
|
||||
Member member = FooBar.class.getMethod(propertyName);
|
||||
@@ -91,7 +90,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testObjectOverwrittenMethodsExclusion() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
String propertyName = "hashCode";
|
||||
Member member = FooBar.class.getMethod(propertyName);
|
||||
@@ -105,7 +104,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testInterfaceInheritanceExclusion() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
String propertyName = "barLogic";
|
||||
Member member = BarInterface.class.getMethod(propertyName);
|
||||
@@ -123,7 +122,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testMiddleOfInheritanceExclusion1() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
String propertyName = "fooLogic";
|
||||
Member member = FooBar.class.getMethod(propertyName);
|
||||
@@ -141,7 +140,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testMiddleOfInheritanceExclusion3() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
String propertyName = "barLogic";
|
||||
Member member = BarInterface.class.getMethod(propertyName);
|
||||
@@ -155,7 +154,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testMiddleOfInheritanceExclusion4() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
String propertyName = "barLogic";
|
||||
Member member = BarInterface.class.getMethod(propertyName);
|
||||
@@ -173,7 +172,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testPackageExclusion() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
Set<Pattern> excluded = new HashSet<>();
|
||||
excluded.add(Pattern.compile("^" + FooBar.class.getPackage().getName().replaceAll("\\.", "\\\\.") + ".*"));
|
||||
@@ -188,10 +187,10 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
// then
|
||||
assertFalse("stringField is accessible!", actual);
|
||||
}
|
||||
|
||||
|
||||
public void testPackageNameExclusion() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
Set<String> excluded = new HashSet<>();
|
||||
excluded.add(FooBar.class.getPackage().getName());
|
||||
@@ -209,27 +208,27 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testDefaultPackageExclusion() {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(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
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
Set<Pattern> excluded = new HashSet<>();
|
||||
excluded.add(Pattern.compile("^$"));
|
||||
sma.setExcludedPackageNamePatterns(excluded);
|
||||
|
||||
|
||||
// when
|
||||
boolean actual = sma.isPackageExcluded(null, null);
|
||||
|
||||
@@ -239,7 +238,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testAccessEnum() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
// when
|
||||
Member values = MyValues.class.getMethod("values");
|
||||
@@ -249,23 +248,23 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
assertTrue("Access to enums is blocked!", actual);
|
||||
}
|
||||
|
||||
public void testAccessStatic() throws Exception {
|
||||
public void testAccessStaticMethod() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true, true);
|
||||
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
|
||||
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
|
||||
assertTrue("Access to static is blocked!", actual);
|
||||
assertFalse("Access to static method is not blocked!", actual);
|
||||
}
|
||||
|
||||
public void testAccessStaticField() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true, true);
|
||||
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
|
||||
|
||||
// when
|
||||
Member method = StaticTester.class.getField("MAX_VALUE");
|
||||
@@ -277,8 +276,8 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testBlockedStaticFieldWhenFlagIsFalse() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
|
||||
|
||||
// when
|
||||
Member method = StaticTester.class.getField("MAX_VALUE");
|
||||
@@ -289,8 +288,8 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
// public static final test
|
||||
// given
|
||||
sma = new SecurityMemberAccess(false, true);
|
||||
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
|
||||
sma = new SecurityMemberAccess(true);
|
||||
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
|
||||
|
||||
// when
|
||||
method = StaticTester.class.getField("MIN_VALUE");
|
||||
@@ -301,8 +300,8 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
// package static test
|
||||
// given
|
||||
sma = new SecurityMemberAccess(false, true);
|
||||
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
|
||||
sma = new SecurityMemberAccess(true);
|
||||
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
|
||||
|
||||
// when
|
||||
method = StaticTester.getFieldByName("PACKAGE_STRING");
|
||||
@@ -313,8 +312,8 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
// package final static test
|
||||
// given
|
||||
sma = new SecurityMemberAccess(false, true);
|
||||
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
|
||||
sma = new SecurityMemberAccess(true);
|
||||
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
|
||||
|
||||
// when
|
||||
method = StaticTester.getFieldByName("FINAL_PACKAGE_STRING");
|
||||
@@ -325,8 +324,8 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
// protected static test
|
||||
// given
|
||||
sma = new SecurityMemberAccess(false, true);
|
||||
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
|
||||
sma = new SecurityMemberAccess(true);
|
||||
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
|
||||
|
||||
// when
|
||||
method = StaticTester.getFieldByName("PROTECTED_STRING");
|
||||
@@ -337,8 +336,8 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
// protected final static test
|
||||
// given
|
||||
sma = new SecurityMemberAccess(false, true);
|
||||
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
|
||||
sma = new SecurityMemberAccess(true);
|
||||
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
|
||||
|
||||
// when
|
||||
method = StaticTester.getFieldByName("FINAL_PROTECTED_STRING");
|
||||
@@ -349,8 +348,8 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
// private static test
|
||||
// given
|
||||
sma = new SecurityMemberAccess(false, true);
|
||||
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
|
||||
sma = new SecurityMemberAccess(true);
|
||||
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
|
||||
|
||||
// when
|
||||
method = StaticTester.getFieldByName("PRIVATE_STRING");
|
||||
@@ -361,8 +360,8 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
// private final static test
|
||||
// given
|
||||
sma = new SecurityMemberAccess(false, true);
|
||||
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
|
||||
sma = new SecurityMemberAccess(true);
|
||||
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
|
||||
|
||||
// when
|
||||
method = StaticTester.getFieldByName("FINAL_PRIVATE_STRING");
|
||||
@@ -374,7 +373,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testBlockedStaticFieldWhenClassIsExcluded() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
sma.setExcludedClasses(new HashSet<>(Arrays.asList(Class.class, StaticTester.class)));
|
||||
|
||||
// when
|
||||
@@ -385,10 +384,10 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
assertFalse("Access to static field isn't blocked!", actual);
|
||||
}
|
||||
|
||||
public void testBlockStaticAccess() throws Exception {
|
||||
public void testBlockStaticMethodAccess() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
|
||||
|
||||
// when
|
||||
Member method = StaticTester.class.getMethod("sayHello");
|
||||
@@ -400,8 +399,8 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testBlockStaticAccessIfClassIsExcluded() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(Class.class)));
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(Class.class)));
|
||||
|
||||
// when
|
||||
Member method = Class.class.getMethod("getClassLoader");
|
||||
@@ -413,8 +412,8 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testAllowStaticAccessIfClassIsNotExcluded() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true, true);
|
||||
sma.setExcludedClasses(new HashSet<Class<?>>(Collections.singletonList(ClassLoader.class)));
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
sma.setExcludedClasses(new HashSet<>(Collections.singletonList(ClassLoader.class)));
|
||||
|
||||
// when
|
||||
Member method = Class.class.getMethod("getClassLoader");
|
||||
@@ -426,7 +425,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testAccessPrimitiveInt() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("java.lang.,ognl,javax"));
|
||||
|
||||
String propertyName = "intField";
|
||||
@@ -441,7 +440,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testAccessPrimitiveDoubleWithNames() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("ognl.,javax."));
|
||||
|
||||
|
||||
@@ -493,7 +492,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testAccessPrimitiveDoubleWithPackageRegExs() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
Set<Pattern> patterns = new HashSet<>();
|
||||
patterns.add(Pattern.compile("^java\\.lang\\..*"));
|
||||
sma.setExcludedPackageNamePatterns(patterns);
|
||||
@@ -510,7 +509,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testAccessMemberAccessIsAccessible() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
Set<Class<?>> excluded = new HashSet<>();
|
||||
excluded.add(ognl.MemberAccess.class);
|
||||
sma.setExcludedClasses(excluded);
|
||||
@@ -528,7 +527,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testAccessMemberAccessIsBlocked() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
Set<Class<?>> excluded = new HashSet<>();
|
||||
excluded.add(SecurityMemberAccess.class);
|
||||
sma.setExcludedClasses(excluded);
|
||||
@@ -546,7 +545,7 @@ public class SecurityMemberAccessTest extends TestCase {
|
||||
|
||||
public void testPackageNameExclusionAsCommaDelimited() {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
|
||||
sma.setExcludedPackageNames(TextParseUtil.commaDelimitedStringToSet("java.lang."));
|
||||
|
||||
@@ -46,9 +46,9 @@ import java.util.*;
|
||||
* @author tm_jee
|
||||
*/
|
||||
public class SetPropertiesTest extends XWorkTestCase {
|
||||
|
||||
|
||||
private OgnlUtil ognlUtil;
|
||||
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
@@ -57,7 +57,7 @@ public class SetPropertiesTest extends XWorkTestCase {
|
||||
}
|
||||
public void testOgnlUtilEmptyStringAsLong() {
|
||||
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);
|
||||
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(1).getClass());
|
||||
}
|
||||
|
||||
|
||||
public void testValueStackSetValueEmptyStringAsLong() {
|
||||
Bar bar = new Bar();
|
||||
ValueStack vs = ActionContext.getContext().getValueStack();
|
||||
@@ -193,11 +193,11 @@ public class SetPropertiesTest extends XWorkTestCase {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void testAddingToMapsWithObjectsTrue() throws Exception {
|
||||
doTestAddingToMapsWithObjects(true);
|
||||
}
|
||||
|
||||
|
||||
public void testAddingToMapsWithObjectsFalse() throws Exception {
|
||||
doTestAddingToMapsWithObjects(false);
|
||||
|
||||
@@ -227,8 +227,8 @@ public class SetPropertiesTest extends XWorkTestCase {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void testAddingAndModifyingCollectionWithObjectsSet() {
|
||||
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;
|
||||
|
||||
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.ActionContext;
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
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 {
|
||||
|
||||
@@ -44,9 +45,9 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
public void testIntercepDefault() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(
|
||||
new Cookie("cookie1", "cookie1value"),
|
||||
new Cookie("cookie2", "cookie2value"),
|
||||
new Cookie("cookie3", "cookie3value")
|
||||
new Cookie("cookie1", "cookie1value"),
|
||||
new Cookie("cookie2", "cookie2value"),
|
||||
new Cookie("cookie3", "cookie3value")
|
||||
);
|
||||
ServletActionContext.setRequest(request);
|
||||
|
||||
@@ -55,7 +56,7 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
ActionContext.getContext().getValueStack().push(action);
|
||||
|
||||
ActionInvocation invocation = (ActionInvocation) createMock(ActionInvocation.class);
|
||||
|
||||
|
||||
expect(invocation.getAction()).andReturn(action);
|
||||
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("cookie2"));
|
||||
assertNull(ActionContext.getContext().getValueStack().findValue("cookie3"));
|
||||
|
||||
|
||||
verify(invocation);
|
||||
}
|
||||
|
||||
public void testInterceptAll1() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(
|
||||
new Cookie("cookie1", "cookie1value"),
|
||||
new Cookie("cookie2", "cookie2value"),
|
||||
new Cookie("cookie3", "cookie3value")
|
||||
new Cookie("cookie1", "cookie1value"),
|
||||
new Cookie("cookie2", "cookie2value"),
|
||||
new Cookie("cookie3", "cookie3value")
|
||||
);
|
||||
ServletActionContext.setRequest(request);
|
||||
|
||||
@@ -93,7 +94,7 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
ActionContext.getContext().getValueStack().push(action);
|
||||
|
||||
ActionInvocation invocation = (ActionInvocation) createMock(ActionInvocation.class);
|
||||
|
||||
|
||||
expect(invocation.getAction()).andReturn(action);
|
||||
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("cookie2"), "cookie2value");
|
||||
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), "cookie3value");
|
||||
|
||||
|
||||
verify(invocation);
|
||||
}
|
||||
|
||||
@@ -125,9 +126,9 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
public void testInterceptAll2() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(
|
||||
new Cookie("cookie1", "cookie1value"),
|
||||
new Cookie("cookie2", "cookie2value"),
|
||||
new Cookie("cookie3", "cookie3value")
|
||||
new Cookie("cookie1", "cookie1value"),
|
||||
new Cookie("cookie2", "cookie2value"),
|
||||
new Cookie("cookie3", "cookie3value")
|
||||
);
|
||||
ServletActionContext.setRequest(request);
|
||||
|
||||
@@ -159,16 +160,16 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value");
|
||||
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), "cookie2value");
|
||||
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), "cookie3value");
|
||||
|
||||
|
||||
verify(invocation);
|
||||
}
|
||||
|
||||
public void testInterceptSelectedCookiesNameOnly1() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(
|
||||
new Cookie("cookie1", "cookie1value"),
|
||||
new Cookie("cookie2", "cookie2value"),
|
||||
new Cookie("cookie3", "cookie3value")
|
||||
new Cookie("cookie1", "cookie1value"),
|
||||
new Cookie("cookie2", "cookie2value"),
|
||||
new Cookie("cookie3", "cookie3value")
|
||||
);
|
||||
ServletActionContext.setRequest(request);
|
||||
|
||||
@@ -200,16 +201,16 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value");
|
||||
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), null);
|
||||
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), "cookie3value");
|
||||
|
||||
|
||||
verify(invocation);
|
||||
}
|
||||
|
||||
public void testInterceptSelectedCookiesNameOnly2() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(
|
||||
new Cookie("cookie1", "cookie1value"),
|
||||
new Cookie("cookie2", "cookie2value"),
|
||||
new Cookie("cookie3", "cookie3value")
|
||||
new Cookie("cookie1", "cookie1value"),
|
||||
new Cookie("cookie2", "cookie2value"),
|
||||
new Cookie("cookie3", "cookie3value")
|
||||
);
|
||||
ServletActionContext.setRequest(request);
|
||||
|
||||
@@ -218,7 +219,7 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
ActionContext.getContext().getValueStack().push(action);
|
||||
|
||||
ActionInvocation invocation = (ActionInvocation) createMock(ActionInvocation.class);
|
||||
|
||||
|
||||
expect(invocation.getAction()).andReturn(action);
|
||||
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("cookie2"), null);
|
||||
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), "cookie3value");
|
||||
|
||||
|
||||
verify(invocation);
|
||||
}
|
||||
|
||||
public void testInterceptSelectedCookiesNameOnly3() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(
|
||||
new Cookie("cookie1", "cookie1value"),
|
||||
new Cookie("cookie2", "cookie2value"),
|
||||
new Cookie("cookie3", "cookie3value")
|
||||
new Cookie("cookie1", "cookie1value"),
|
||||
new Cookie("cookie2", "cookie2value"),
|
||||
new Cookie("cookie3", "cookie3value")
|
||||
);
|
||||
ServletActionContext.setRequest(request);
|
||||
|
||||
@@ -283,7 +284,7 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value");
|
||||
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), null);
|
||||
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), "cookie3value");
|
||||
|
||||
|
||||
verify(invocation);
|
||||
}
|
||||
|
||||
@@ -291,9 +292,9 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
public void testInterceptSelectedCookiesNameAndValue() throws Exception {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setCookies(
|
||||
new Cookie("cookie1", "cookie1value"),
|
||||
new Cookie("cookie2", "cookie2value"),
|
||||
new Cookie("cookie3", "cookie3value")
|
||||
new Cookie("cookie1", "cookie1value"),
|
||||
new Cookie("cookie2", "cookie2value"),
|
||||
new Cookie("cookie3", "cookie3value")
|
||||
);
|
||||
ServletActionContext.setRequest(request);
|
||||
|
||||
@@ -325,7 +326,7 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie1"), "cookie1value");
|
||||
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie2"), null);
|
||||
assertEquals(ActionContext.getContext().getValueStack().findValue("cookie3"), null);
|
||||
|
||||
|
||||
verify(invocation);
|
||||
}
|
||||
|
||||
@@ -338,20 +339,44 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
String pollution5 = "model[\"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(
|
||||
new Cookie(pollution1, "pollution1"),
|
||||
new Cookie("pollution1", pollution1),
|
||||
new Cookie(pollution2, "pollution2"),
|
||||
new Cookie("pollution2", pollution2),
|
||||
new Cookie(pollution3, "pollution3"),
|
||||
new Cookie("pollution3", pollution3),
|
||||
new Cookie(pollution4, "pollution4"),
|
||||
new Cookie("pollution4", pollution4),
|
||||
new Cookie(pollution5, "pollution5"),
|
||||
new Cookie("pollution5", pollution5),
|
||||
new Cookie(pollution6, "pollution6"),
|
||||
new Cookie("pollution6", pollution6)
|
||||
);
|
||||
new Cookie("pollution1", pollution1),
|
||||
new Cookie(pollution2, "pollution2"),
|
||||
new Cookie("pollution2", pollution2),
|
||||
new Cookie(pollution3, "pollution3"),
|
||||
new Cookie("pollution3", pollution3),
|
||||
new Cookie("pollution4", pollution4),
|
||||
new Cookie("pollution5", pollution5),
|
||||
new Cookie("pollution6", pollution6)
|
||||
);
|
||||
ServletActionContext.setRequest(request);
|
||||
|
||||
final Map<String, Boolean> excludedName = new HashMap<String, Boolean>();
|
||||
@@ -375,12 +400,12 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
|
||||
interceptor.intercept(invocation);
|
||||
|
||||
assertFalse(excludedName.get(pollution1));
|
||||
//assertFalse(excludedName.get(pollution1));
|
||||
assertFalse(excludedName.get(pollution2));
|
||||
assertFalse(excludedName.get(pollution3));
|
||||
assertFalse(excludedName.get(pollution4));
|
||||
assertFalse(excludedName.get(pollution5));
|
||||
assertFalse(excludedName.get(pollution6));
|
||||
//assertFalse(excludedName.get(pollution4));
|
||||
//assertFalse(excludedName.get(pollution5));
|
||||
// assertFalse(excludedName.get(pollution6));
|
||||
}
|
||||
|
||||
public void testCookiesWithStrutsInternalsAccess() throws Exception {
|
||||
@@ -393,13 +418,13 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
String reqCookieValue = "request.userId=1";
|
||||
|
||||
request.setCookies(
|
||||
new Cookie(sessionCookieName, "1"),
|
||||
new Cookie("1", sessionCookieValue),
|
||||
new Cookie(appCookieName, "1"),
|
||||
new Cookie("1", appCookieValue),
|
||||
new Cookie(reqCookieName, "1"),
|
||||
new Cookie("1", reqCookieValue)
|
||||
);
|
||||
new Cookie(sessionCookieName, "1"),
|
||||
new Cookie("1", sessionCookieValue),
|
||||
new Cookie(appCookieName, "1"),
|
||||
new Cookie("1", appCookieValue),
|
||||
new Cookie(reqCookieName, "1"),
|
||||
new Cookie("1", reqCookieValue)
|
||||
);
|
||||
ServletActionContext.setRequest(request);
|
||||
|
||||
final Map<String, Boolean> excludedName = new HashMap<String, Boolean>();
|
||||
@@ -436,13 +461,13 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
String reqCookieValue = "request.userId=1";
|
||||
|
||||
request.setCookies(
|
||||
new Cookie(sessionCookieName, "1"),
|
||||
new Cookie("1", sessionCookieValue),
|
||||
new Cookie(appCookieName, "1"),
|
||||
new Cookie("1", appCookieValue),
|
||||
new Cookie(reqCookieName, "1"),
|
||||
new Cookie("1", reqCookieValue)
|
||||
);
|
||||
new Cookie(sessionCookieName, "1"),
|
||||
new Cookie("1", sessionCookieValue),
|
||||
new Cookie(appCookieName, "1"),
|
||||
new Cookie("1", appCookieValue),
|
||||
new Cookie(reqCookieName, "1"),
|
||||
new Cookie("1", reqCookieValue)
|
||||
);
|
||||
ServletActionContext.setRequest(request);
|
||||
|
||||
final Map<String, Boolean> excludedName = new HashMap<>();
|
||||
@@ -486,14 +511,29 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
return this.cookies;
|
||||
}
|
||||
|
||||
public String getCookie1() { return cookie1; }
|
||||
public void setCookie1(String cookie1) { this.cookie1 = cookie1; }
|
||||
public String getCookie1() {
|
||||
return cookie1;
|
||||
}
|
||||
|
||||
public String getCookie2() { return cookie2; }
|
||||
public void setCookie2(String cookie2) { this.cookie2 = cookie2; }
|
||||
public void setCookie1(String cookie1) {
|
||||
this.cookie1 = cookie1;
|
||||
}
|
||||
|
||||
public String getCookie3() { return cookie3; }
|
||||
public void setCookie3(String cookie3) { this.cookie3 = cookie3; }
|
||||
public String getCookie2() {
|
||||
return cookie2;
|
||||
}
|
||||
|
||||
public void setCookie2(String cookie2) {
|
||||
this.cookie2 = cookie2;
|
||||
}
|
||||
|
||||
public String getCookie3() {
|
||||
return cookie3;
|
||||
}
|
||||
|
||||
public void setCookie3(String cookie3) {
|
||||
this.cookie3 = cookie3;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MockActionWithActionCookieAware extends ActionSupport implements org.apache.struts2.action.CookiesAware {
|
||||
@@ -511,14 +551,29 @@ public class CookieInterceptorTest extends StrutsInternalTestCase {
|
||||
return this.cookies;
|
||||
}
|
||||
|
||||
public String getCookie1() { return cookie1; }
|
||||
public void setCookie1(String cookie1) { this.cookie1 = cookie1; }
|
||||
public String getCookie1() {
|
||||
return cookie1;
|
||||
}
|
||||
|
||||
public String getCookie2() { return cookie2; }
|
||||
public void setCookie2(String cookie2) { this.cookie2 = cookie2; }
|
||||
public void setCookie1(String cookie1) {
|
||||
this.cookie1 = cookie1;
|
||||
}
|
||||
|
||||
public String getCookie3() { return cookie3; }
|
||||
public void setCookie3(String cookie3) { this.cookie3 = cookie3; }
|
||||
public String getCookie2() {
|
||||
return cookie2;
|
||||
}
|
||||
|
||||
public void setCookie2(String cookie2) {
|
||||
this.cookie2 = cookie2;
|
||||
}
|
||||
|
||||
public String getCookie3() {
|
||||
return cookie3;
|
||||
}
|
||||
|
||||
public void setCookie3(String cookie3) {
|
||||
this.cookie3 = cookie3;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public class PlainResultTest extends StrutsInternalTestCase {
|
||||
result.execute(invocation);
|
||||
|
||||
assertEquals("{ 'value': 'test' }", response.getContentAsString());
|
||||
assertEquals("application/json", response.getContentType());
|
||||
assertEquals("application/json;charset=UTF-8", response.getContentType());
|
||||
}
|
||||
|
||||
public void testWriteContentTypeCsvWithCookie() throws Exception {
|
||||
@@ -72,7 +72,7 @@ public class PlainResultTest extends StrutsInternalTestCase {
|
||||
result.execute(invocation);
|
||||
|
||||
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 {
|
||||
@@ -146,4 +146,4 @@ public class PlainResultTest extends StrutsInternalTestCase {
|
||||
|
||||
ActionContext.getContext().withServletResponse(response).withActionInvocation(invocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public class SecurityMemberAccessInServletsTest extends StrutsInternalTestCase {
|
||||
|
||||
public void testJavaxServletPackageAccess() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
Set<Pattern> excluded = new HashSet<Pattern>();
|
||||
excluded.add(Pattern.compile("^(?!javax\\.servlet\\..+)(javax\\..+)"));
|
||||
@@ -59,7 +59,7 @@ public class SecurityMemberAccessInServletsTest extends StrutsInternalTestCase {
|
||||
|
||||
public void testJavaxServletPackageExclusion() throws Exception {
|
||||
// given
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(false, true);
|
||||
SecurityMemberAccess sma = new SecurityMemberAccess(true);
|
||||
|
||||
Set<Pattern> excluded = new HashSet<Pattern>();
|
||||
excluded.add(Pattern.compile("^javax\\..+"));
|
||||
|
||||
@@ -23,14 +23,21 @@ import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.EventListener;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterRegistration;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletContext;
|
||||
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 servletInfo;
|
||||
String contextPath;
|
||||
Map initParams = new HashMap();
|
||||
Map attributes = new HashMap();
|
||||
Map<String, String> initParams = new HashMap<>();
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
InputStream resourceAsStream;
|
||||
|
||||
public void setInitParameter(String name, String value) {
|
||||
initParams.put(name, value);
|
||||
public boolean setInitParameter(String name, String value) {
|
||||
return initParams.put(name, value) != null;
|
||||
}
|
||||
|
||||
public void setRealPath(String value) {
|
||||
@@ -74,7 +81,7 @@ public class StrutsMockServletContext implements ServletContext {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set getResourcePaths(String s) {
|
||||
public Set<String> getResourcePaths(String s) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -105,11 +112,11 @@ public class StrutsMockServletContext implements ServletContext {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Enumeration getServlets() {
|
||||
public Enumeration<Servlet> getServlets() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Enumeration getServletNames() {
|
||||
public Enumeration<String> getServletNames() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -130,7 +137,7 @@ public class StrutsMockServletContext implements ServletContext {
|
||||
return (String) initParams.get(s);
|
||||
}
|
||||
|
||||
public Enumeration getInitParameterNames() {
|
||||
public Enumeration<String> getInitParameterNames() {
|
||||
return Collections.enumeration(initParams.keySet());
|
||||
}
|
||||
|
||||
@@ -138,7 +145,7 @@ public class StrutsMockServletContext implements ServletContext {
|
||||
return attributes.get(s);
|
||||
}
|
||||
|
||||
public Enumeration getAttributeNames() {
|
||||
public Enumeration<String> getAttributeNames() {
|
||||
return Collections.enumeration(attributes.keySet());
|
||||
}
|
||||
|
||||
@@ -157,12 +164,142 @@ public class StrutsMockServletContext implements ServletContext {
|
||||
public void setServletInfo(String servletInfo) {
|
||||
this.servletInfo = servletInfo;
|
||||
}
|
||||
|
||||
|
||||
public String getContextPath() {
|
||||
return contextPath;
|
||||
}
|
||||
}
|
||||
|
||||
public void setContextPath(String 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.ognl.allowStaticFieldAccess" value="false"/>
|
||||
</struts>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-async-plugin</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -44,11 +44,6 @@
|
||||
<version>2.0.1.Final</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
@@ -60,6 +55,17 @@
|
||||
<artifactId>javax.el</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- this library is excluded in the parent pom as it clashes with Easymock dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.objenesis</groupId>
|
||||
<artifactId>objenesis</artifactId>
|
||||
<version>3.2</version>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
The Java EE API modules listed below are all marked @Deprecated(forRemoval=true), because they are scheduled
|
||||
@@ -94,4 +100,4 @@
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
||||
+17
-4
@@ -20,17 +20,20 @@
|
||||
*/
|
||||
package org.apache.struts.beanvalidation.constraints.impl;
|
||||
|
||||
import org.apache.commons.beanutils.PropertyUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts.beanvalidation.constraints.FieldMatch;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.Introspector;
|
||||
import java.beans.PropertyDescriptor;
|
||||
|
||||
public class FieldMatchValidator implements ConstraintValidator<FieldMatch, Object> {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(FieldMatchValidator.class);
|
||||
|
||||
private String firstFieldName;
|
||||
private String secondFieldName;
|
||||
|
||||
@@ -41,13 +44,23 @@ public class FieldMatchValidator implements ConstraintValidator<FieldMatch, Obje
|
||||
|
||||
public boolean isValid(final Object value, final ConstraintValidatorContext context) {
|
||||
try {
|
||||
final Object firstObj = PropertyUtils.getProperty(value, this.firstFieldName);
|
||||
final Object secondObj = PropertyUtils.getProperty(value, this.secondFieldName);
|
||||
final Object firstObj = readPropertyValue(value, this.firstFieldName);
|
||||
final Object secondObj = readPropertyValue(value, this.secondFieldName);
|
||||
return firstObj == null && secondObj == null || firstObj != null && firstObj.equals(secondObj);
|
||||
} catch (final Exception ex) {
|
||||
LOG.info("Error while getting values from object", ex);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Object readPropertyValue(Object bean, String propertyName) throws Exception {
|
||||
BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
|
||||
for (PropertyDescriptor descriptor : beanInfo.getPropertyDescriptors()) {
|
||||
if (propertyName.equals(descriptor.getName())) {
|
||||
return descriptor.getReadMethod().invoke(bean);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.struts.beanvalidation.constraints.impl;
|
||||
|
||||
import org.apache.struts.beanvalidation.constraints.FieldMatch;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class FieldMatchValidatorTest {
|
||||
|
||||
@Test
|
||||
public void matchingFields() {
|
||||
// given
|
||||
FieldMatchValidator validator = new FieldMatchValidator();
|
||||
validator.initialize(FieldMatchTestBean.class.getAnnotation(FieldMatch.class));
|
||||
|
||||
ConstraintValidatorContext context = Mockito.mock(ConstraintValidatorContext.class);
|
||||
|
||||
// when
|
||||
FieldMatchTestBean bean = new FieldMatchTestBean("12345678", "12345678");
|
||||
|
||||
boolean valid = validator.isValid(bean, context);
|
||||
|
||||
// then
|
||||
assertTrue(valid);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notMatchingFields() {
|
||||
// given
|
||||
FieldMatchValidator validator = new FieldMatchValidator();
|
||||
validator.initialize(FieldMatchTestBean.class.getAnnotation(FieldMatch.class));
|
||||
|
||||
ConstraintValidatorContext context = Mockito.mock(ConstraintValidatorContext.class);
|
||||
|
||||
// when
|
||||
FieldMatchTestBean bean = new FieldMatchTestBean("12345678", "87654321");
|
||||
|
||||
boolean valid = validator.isValid(bean, context);
|
||||
|
||||
// then
|
||||
assertFalse(valid);
|
||||
}
|
||||
|
||||
@FieldMatch(first = "password", second = "repeatPassword")
|
||||
public static class FieldMatchTestBean {
|
||||
String password;
|
||||
String repeatPassword;
|
||||
|
||||
public FieldMatchTestBean(String password, String repeatPassword) {
|
||||
this.password = password;
|
||||
this.repeatPassword = repeatPassword;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public String getRepeatPassword() {
|
||||
return repeatPassword;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-cdi-plugin</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-config-browser-plugin</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-convention-plugin</artifactId>
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-dwr-plugin</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-embeddedjsp-plugin</artifactId>
|
||||
@@ -89,15 +89,6 @@
|
||||
<artifactId>tomcat-jasper</artifactId>
|
||||
<scope>provided</scope>
|
||||
</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>
|
||||
|
||||
<build>
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-gxp-plugin</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-jasperreports-plugin</artifactId>
|
||||
@@ -63,12 +63,6 @@
|
||||
<artifactId>jsp-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-javatemplates-plugin</artifactId>
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
</parent>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-jfreechart-plugin</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
@@ -71,18 +71,9 @@
|
||||
<artifactId>easymock</artifactId>
|
||||
<scope>test</scope>
|
||||
</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>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
</project>
|
||||
|
||||
+4
-12
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-json-plugin</artifactId>
|
||||
@@ -105,18 +105,10 @@
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</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>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
||||
+3
-11
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-junit-plugin</artifactId>
|
||||
@@ -85,17 +85,9 @@
|
||||
<artifactId>struts2-portlet-mocks-plugin</artifactId>
|
||||
<optional>true</optional>
|
||||
</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>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
</project>
|
||||
|
||||
+1
-10
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-plugin</artifactId>
|
||||
@@ -106,15 +106,6 @@
|
||||
<scope>test</scope>
|
||||
</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>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-oval-plugin</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-pell-multipart-plugin</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-plexus-plugin</artifactId>
|
||||
|
||||
+2
-2
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
@@ -76,7 +76,7 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-portlet-mocks-plugin</artifactId>
|
||||
@@ -47,17 +47,10 @@
|
||||
<artifactId>portlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</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>
|
||||
|
||||
<properties>
|
||||
<spring.platformVersion>4.3.30.RELEASE</spring.platformVersion>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
</project>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-portlet-tiles-plugin</artifactId>
|
||||
|
||||
+6
-16
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-portlet-plugin</artifactId>
|
||||
@@ -129,27 +129,17 @@
|
||||
<artifactId>spring-test</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc-portlet</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<scope>test</scope>
|
||||
</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>
|
||||
|
||||
<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>
|
||||
|
||||
</project>
|
||||
|
||||
+143
@@ -20,14 +20,22 @@ package org.apache.struts2.portlet.servlet;
|
||||
|
||||
import javax.portlet.PortletContext;
|
||||
import javax.portlet.PortletRequestDispatcher;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterRegistration;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletContext;
|
||||
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.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.EventListener;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -86,6 +94,11 @@ public class PortletServletContext implements ServletContext {
|
||||
return portletContext.getInitParameterNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setInitParameter(String name, String value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see javax.servlet.ServletContext#getMajorVersion()
|
||||
*/
|
||||
@@ -107,6 +120,16 @@ public class PortletServletContext implements ServletContext {
|
||||
return portletContext.getMinorVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEffectiveMajorVersion() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEffectiveMinorVersion() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link PortletServletRequestDispatcher} wrapping the {@link PortletRequestDispatcher}
|
||||
* as a {@link RequestDispatcher} instance.
|
||||
@@ -179,6 +202,126 @@ public class PortletServletContext implements ServletContext {
|
||||
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.
|
||||
* @see javax.servlet.ServletContext#getServletNames()
|
||||
|
||||
+18
-3
@@ -21,6 +21,7 @@ package org.apache.struts2.portlet.servlet;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.servlet.ReadListener;
|
||||
import javax.servlet.ServletInputStream;
|
||||
|
||||
/**
|
||||
@@ -31,11 +32,11 @@ import javax.servlet.ServletInputStream;
|
||||
public class PortletServletInputStream extends ServletInputStream {
|
||||
|
||||
private InputStream portletInputStream;
|
||||
|
||||
|
||||
public PortletServletInputStream(InputStream portletInputStream) {
|
||||
this.portletInputStream = portletInputStream;
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.InputStream#read()
|
||||
*/
|
||||
@@ -107,7 +108,7 @@ public class PortletServletInputStream extends ServletInputStream {
|
||||
public long skip(long n) throws IOException {
|
||||
return portletInputStream.skip(n);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the wrapped {@link InputStream} instance.
|
||||
* @return The wrapped {@link InputStream} instance.
|
||||
@@ -116,4 +117,18 @@ public class PortletServletInputStream extends ServletInputStream {
|
||||
return portletInputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadListener(ReadListener readListener) {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
+13
-2
@@ -22,6 +22,7 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.WriteListener;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
private OutputStream portletOutputStream;
|
||||
|
||||
|
||||
public PortletServletOutputStream(OutputStream portletOutputStream) {
|
||||
this.portletOutputStream = portletOutputStream;
|
||||
}
|
||||
@@ -75,7 +76,7 @@ public class PortletServletOutputStream extends ServletOutputStream {
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
portletOutputStream.write(b, off, len);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the wrapped {@link OutputStream} instance.
|
||||
* @return The wrapped {@link OutputStream} instance.
|
||||
@@ -83,4 +84,14 @@ public class PortletServletOutputStream extends ServletOutputStream {
|
||||
public OutputStream getOutputStream() {
|
||||
return portletOutputStream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWriteListener(WriteListener writeListener) {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
+139
-55
@@ -23,6 +23,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.Principal;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Locale;
|
||||
@@ -34,12 +35,20 @@ import javax.portlet.PortletContext;
|
||||
import javax.portlet.PortletRequest;
|
||||
import javax.portlet.PortletRequestDispatcher;
|
||||
import javax.portlet.PortletSession;
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import javax.servlet.http.HttpUpgradeHandler;
|
||||
import javax.servlet.http.Part;
|
||||
|
||||
import static org.apache.struts2.portlet.PortletConstants.*;
|
||||
|
||||
@@ -71,7 +80,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.http.HttpServletRequest#getAuthType()
|
||||
*/
|
||||
public String getAuthType() {
|
||||
@@ -80,7 +89,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.http.HttpServletRequest#getContextPath()
|
||||
*/
|
||||
public String getContextPath() {
|
||||
@@ -89,7 +98,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -102,7 +111,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -113,7 +122,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
/**
|
||||
* Gets a property from the {@link PortletRequest}. Note that a
|
||||
* {@link PortletRequest} is not guaranteed to map properties to headers.
|
||||
*
|
||||
*
|
||||
* @see PortletRequest#getProperty(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
|
||||
* {@link PortletRequest} is not guaranteed to map properties to headers.
|
||||
*
|
||||
*
|
||||
* @see PortletRequest#getPropertyNames()
|
||||
* @see javax.servlet.http.HttpServletRequest#getHeaderNames()
|
||||
*/
|
||||
@@ -136,7 +145,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
* Gets the values for the specified property from the
|
||||
* {@link PortletRequest}. Note that a {@link PortletRequest} is not
|
||||
* guaranteed to map properties to headers.
|
||||
*
|
||||
*
|
||||
* @see PortletRequest#getProperties(String)
|
||||
* @see HttpServletRequest#getHeaders(String)
|
||||
*/
|
||||
@@ -146,7 +155,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -156,7 +165,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.http.HttpServletRequest#getMethod()
|
||||
*/
|
||||
public String getMethod() {
|
||||
@@ -170,7 +179,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.http.HttpServletRequest#getPathInfo()
|
||||
*/
|
||||
public String getPathInfo() {
|
||||
@@ -179,7 +188,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.http.HttpServletRequest#getPathTranslated()
|
||||
*/
|
||||
public String getPathTranslated() {
|
||||
@@ -188,7 +197,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.http.HttpServletRequest#getQueryString()
|
||||
*/
|
||||
public String getQueryString() {
|
||||
@@ -197,7 +206,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.http.HttpServletRequest#getRemoteUser()
|
||||
*/
|
||||
public String getRemoteUser() {
|
||||
@@ -206,7 +215,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -216,7 +225,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -226,7 +235,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.http.HttpServletRequest#getRequestedSessionId()
|
||||
*/
|
||||
public String getRequestedSessionId() {
|
||||
@@ -237,7 +246,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
* A {@link PortletRequest} has no servlet path. But for compatibility with
|
||||
* Struts 2 components and interceptors, the action parameter on the request
|
||||
* is mapped to the servlet path.
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.http.HttpServletRequest#getServletPath()
|
||||
*/
|
||||
public String getServletPath() {
|
||||
@@ -250,16 +259,21 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Get the {@link PortletSession} as a {@link PortletHttpSession} instance.
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.http.HttpServletRequest#getSession()
|
||||
*/
|
||||
public HttpSession getSession() {
|
||||
return new PortletHttpSession(portletRequest.getPortletSession());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String changeSessionId() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link PortletSession} as a {@link PortletHttpSession} instance.
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.http.HttpServletRequest#getSession(boolean)
|
||||
*/
|
||||
public HttpSession getSession(boolean create) {
|
||||
@@ -268,7 +282,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.http.HttpServletRequest#getUserPrincipal()
|
||||
*/
|
||||
public Principal getUserPrincipal() {
|
||||
@@ -277,7 +291,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -287,7 +301,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -297,7 +311,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -305,9 +319,39 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
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)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.http.HttpServletRequest#isRequestedSessionIdValid()
|
||||
*/
|
||||
public boolean isRequestedSessionIdValid() {
|
||||
@@ -316,7 +360,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.http.HttpServletRequest#isUserInRole(java.lang.String)
|
||||
*/
|
||||
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
|
||||
* name is <tt>javax.servlet.include.servlet_path</tt>, it returns the
|
||||
* same as {@link PortletServletRequest#getServletPath()}
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletRequest#getAttribute(java.lang.String)
|
||||
*/
|
||||
public Object getAttribute(String name) {
|
||||
@@ -340,7 +384,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletRequest#getAttributeNames()
|
||||
*/
|
||||
public Enumeration getAttributeNames() {
|
||||
@@ -349,7 +393,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Can only be invoked in the event phase.
|
||||
*
|
||||
*
|
||||
* @see ServletRequest#getCharacterEncoding()
|
||||
* @throws IllegalStateException
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
* @see ServletRequest#getContentLength()
|
||||
* @throws IllegalStateException
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
* @see ServletRequest#getContentType()
|
||||
* @throws IllegalStateException
|
||||
* 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,
|
||||
* it will wrap the portlet's {@link InputStream} as a
|
||||
* {@link PortletServletInputStream}.
|
||||
*
|
||||
*
|
||||
* @see ServletRequest#getInputStream()
|
||||
* @throws IllegalStateException
|
||||
* If the portlet is not in the event phase.
|
||||
@@ -412,7 +461,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -425,7 +474,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -438,7 +487,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -449,9 +498,44 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
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)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletRequest#getLocale()
|
||||
*/
|
||||
public Locale getLocale() {
|
||||
@@ -460,7 +544,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletRequest#getLocales()
|
||||
*/
|
||||
public Enumeration getLocales() {
|
||||
@@ -469,7 +553,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletRequest#getParameter(java.lang.String)
|
||||
*/
|
||||
public String getParameter(String name) {
|
||||
@@ -485,7 +569,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletRequest#getParameterMap()
|
||||
*/
|
||||
public Map getParameterMap() {
|
||||
@@ -494,7 +578,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletRequest#getParameterNames()
|
||||
*/
|
||||
public Enumeration getParameterNames() {
|
||||
@@ -503,7 +587,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletRequest#getParameterValues(java.lang.String)
|
||||
*/
|
||||
public String[] getParameterValues(String name) {
|
||||
@@ -512,7 +596,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -525,7 +609,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Can only be invoked in the event phase.
|
||||
*
|
||||
*
|
||||
* @see ServletRequest#getReader()
|
||||
* @throws IllegalStateException
|
||||
* If the portlet is not in the event phase.
|
||||
@@ -540,7 +624,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletRequest#getRealPath(java.lang.String)
|
||||
*/
|
||||
public String getRealPath(String path) {
|
||||
@@ -549,7 +633,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -562,7 +646,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -575,7 +659,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -589,7 +673,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
/**
|
||||
* Get the {@link PortletRequestDispatcher} as a
|
||||
* {@link PortletServletRequestDispatcher} instance.
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletRequest#getRequestDispatcher(java.lang.String)
|
||||
*/
|
||||
public RequestDispatcher getRequestDispatcher(String path) {
|
||||
@@ -599,7 +683,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletRequest#getScheme()
|
||||
*/
|
||||
public String getScheme() {
|
||||
@@ -608,7 +692,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletRequest#getServerName()
|
||||
*/
|
||||
public String getServerName() {
|
||||
@@ -617,7 +701,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Not allowed in a portlet.
|
||||
*
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* Not allowed in a portlet.
|
||||
*/
|
||||
@@ -630,7 +714,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletRequest#isSecure()
|
||||
*/
|
||||
public boolean isSecure() {
|
||||
@@ -639,7 +723,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletRequest#removeAttribute(java.lang.String)
|
||||
*/
|
||||
public void removeAttribute(String name) {
|
||||
@@ -648,7 +732,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.ServletRequest#setAttribute(java.lang.String,
|
||||
* java.lang.Object)
|
||||
*/
|
||||
@@ -658,7 +742,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Can only be invoked in the event phase.
|
||||
*
|
||||
*
|
||||
* @see ServletRequest#setCharacterEncoding(String)
|
||||
* @throws IllegalStateException
|
||||
* If the portlet is not in the event phase.
|
||||
@@ -674,7 +758,7 @@ public class PortletServletRequest implements HttpServletRequest {
|
||||
|
||||
/**
|
||||
* Get the wrapped {@link PortletRequest} instance.
|
||||
*
|
||||
*
|
||||
* @return The wrapped {@link PortletRequest} instance.
|
||||
*/
|
||||
public PortletRequest getPortletRequest() {
|
||||
|
||||
+28
-2
@@ -20,6 +20,7 @@ package org.apache.struts2.portlet.servlet;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Collection;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.portlet.PortletResponse;
|
||||
@@ -31,11 +32,11 @@ import javax.servlet.http.HttpServletResponse;
|
||||
public class PortletServletResponse implements HttpServletResponse {
|
||||
|
||||
protected PortletResponse portletResponse;
|
||||
|
||||
|
||||
public PortletServletResponse(PortletResponse portletResponse) {
|
||||
this.portletResponse = portletResponse;
|
||||
}
|
||||
|
||||
|
||||
public void addCookie(Cookie cookie) {
|
||||
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");
|
||||
}
|
||||
|
||||
@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 {
|
||||
if(portletResponse instanceof RenderResponse) {
|
||||
((RenderResponse)portletResponse).flushBuffer();
|
||||
@@ -211,6 +232,11 @@ public class PortletServletResponse implements HttpServletResponse {
|
||||
throw new IllegalStateException("Not allowed in a portlet");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContentLengthLong(long len) {
|
||||
|
||||
}
|
||||
|
||||
public void setContentType(String type) {
|
||||
if(portletResponse instanceof RenderResponse) {
|
||||
((RenderResponse)portletResponse).setContentType(type);
|
||||
|
||||
+1
-11
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>6.0.0-RC3</version>
|
||||
<version>6.0.0-RC4</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-rest-plugin</artifactId>
|
||||
@@ -96,16 +96,6 @@
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</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>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -34,23 +34,22 @@ import java.io.InputStreamReader;
|
||||
*/
|
||||
public class ContentTypeInterceptor extends AbstractInterceptor {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
ContentTypeHandlerManager selector;
|
||||
|
||||
private final ContentTypeHandlerManager selector;
|
||||
|
||||
@Inject
|
||||
public void setContentTypeHandlerSelector(ContentTypeHandlerManager sel) {
|
||||
this.selector = sel;
|
||||
public ContentTypeInterceptor(ContentTypeHandlerManager selector) {
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
|
||||
public String intercept(ActionInvocation invocation) throws Exception {
|
||||
HttpServletRequest request = ServletActionContext.getRequest();
|
||||
ContentTypeHandler handler = selector.getHandlerForRequest(request);
|
||||
|
||||
|
||||
Object target = invocation.getAction();
|
||||
if (target instanceof ModelDriven) {
|
||||
target = ((ModelDriven)target).getModel();
|
||||
target = ((ModelDriven<?>)target).getModel();
|
||||
}
|
||||
|
||||
|
||||
if (request.getContentLength() > 0) {
|
||||
InputStream is = request.getInputStream();
|
||||
InputStreamReader reader = new InputStreamReader(is);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user