mirror of
https://github.com/apache/struts.git
synced 2026-08-08 16:16:58 +00:00
Compare commits
201 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7909f43237 | |||
| 1fe822cca0 | |||
| ef90b3ba3c | |||
| d35ec15c76 | |||
| 583b174fe6 | |||
| 9b044377ac | |||
| 58f37babbf | |||
| fe3dd6ba9f | |||
| 7a77c7a82c | |||
| 5038a9209f | |||
| 2135ebf651 | |||
| c0dd8dd80c | |||
| c36eafa37a | |||
| 07603b9591 | |||
| 3227d5929a | |||
| 4a8ddbb274 | |||
| 67ba458d03 | |||
| 959b2182b2 | |||
| 6de93e77db | |||
| 59dc9301e0 | |||
| 2fc4a822a4 | |||
| 6a6270f62a | |||
| 9153228b6a | |||
| 5713a74edc | |||
| 32071c71ad | |||
| 7e4791985b | |||
| 3c1e44ca2d | |||
| 2ba8d97ad0 | |||
| cba0db0b07 | |||
| 688162cae2 | |||
| a33c162f53 | |||
| c7a6daf5ce | |||
| 370c7ce17a | |||
| 55989befce | |||
| 2e4a4b5e36 | |||
| 9d07c3b4c3 | |||
| 575e4e8c9b | |||
| 74388dfba7 | |||
| 4ee8b02262 | |||
| c8febc2050 | |||
| 3ea126388c | |||
| 09993e3476 | |||
| f5688e680b | |||
| 60a3db0a63 | |||
| 4714d27678 | |||
| 4feceee5f1 | |||
| 1f5305c249 | |||
| 1903e0ef33 | |||
| 8a2f494c12 | |||
| 6b2e5ecd9b | |||
| cb08d18b5a | |||
| 1e2517b59e | |||
| 8d6ecee849 | |||
| 570bf46a7f | |||
| be82a72403 | |||
| 6fbd9e5321 | |||
| b0a4c4f417 | |||
| b001c61f89 | |||
| 2beac8eba4 | |||
| d351843ecd | |||
| 22036174c7 | |||
| ced44650ec | |||
| 1908cbab8f | |||
| c176390926 | |||
| fe46ad9f4a | |||
| a0dc19c4be | |||
| 7cdcd84b83 | |||
| 8566c14648 | |||
| c75ddbbf3e | |||
| b15dc458cf | |||
| 3f74923099 | |||
| 5b2f63fa7e | |||
| d9d580ae3d | |||
| 67e0477993 | |||
| 89bcbecc70 | |||
| 67ee1b2d67 | |||
| 5b81ec0852 | |||
| 266cd1333c | |||
| 323267fa88 | |||
| 2432449975 | |||
| 45a1f5efc6 | |||
| b488c80aa2 | |||
| 144010c3b7 | |||
| 9b87e88bb0 | |||
| 117e84f246 | |||
| a28f22605c | |||
| deb6c09bce | |||
| f95f9a7cd3 | |||
| 9e23fbe665 | |||
| a623842bce | |||
| 2757c23572 | |||
| ebedd7391f | |||
| 7ce8f484e0 | |||
| dfd07190bd | |||
| 111bc25650 | |||
| 8ba8ee5fe6 | |||
| 14bd4b80cf | |||
| bbca2717f9 | |||
| b622e5d725 | |||
| efa447af21 | |||
| cf6cbf3816 | |||
| 48ee44bbc2 | |||
| b18fbda1f7 | |||
| 28c8f1503d | |||
| d1695f7a4d | |||
| b359da5517 | |||
| 36a890ba69 | |||
| e3fbe88355 | |||
| 272c2e7bba | |||
| 60095a6934 | |||
| ae9dc42da7 | |||
| 8da6a79926 | |||
| 7deb481298 | |||
| 9f2770b2c3 | |||
| 78451db87e | |||
| 49ddf6130a | |||
| 1bcadd4682 | |||
| b115a510a6 | |||
| fbab5d4df9 | |||
| cd7f1097e2 | |||
| 2eff2da4fd | |||
| b3629460e6 | |||
| 3528b88327 | |||
| 3e04197ba7 | |||
| 09eb286020 | |||
| d33be1d43c | |||
| c812450292 | |||
| 75cc664fda | |||
| 9d903ddf96 | |||
| 4ccde0087e | |||
| 7473b4cef9 | |||
| 0bd4266d2f | |||
| 48c4e3b6a0 | |||
| 40b4395801 | |||
| 0ce2c7b5dd | |||
| 2924208228 | |||
| 3c71b2ed8c | |||
| d7626ed7d6 | |||
| fda2c546b3 | |||
| f03d36c46b | |||
| 90f984ca85 | |||
| 0f83b83972 | |||
| c352fb59c1 | |||
| 3d155048da | |||
| 9a06e7c983 | |||
| 280c3e4f5f | |||
| 4c95983abb | |||
| 3111c4b86f | |||
| efab3fc6fa | |||
| 0c69993cd7 | |||
| b04ad6b412 | |||
| 735d1bc88d | |||
| f388f6a679 | |||
| e74d21befb | |||
| 93c9856527 | |||
| f05a4d1c83 | |||
| e4872ecf8e | |||
| f6a60fc66f | |||
| 00f0942449 | |||
| 8c7c39424f | |||
| ad7f3e3523 | |||
| 5a50bd312d | |||
| 5b68d4bd59 | |||
| 64a3d0c32f | |||
| 6f135ea4d8 | |||
| bdace9bbad | |||
| 9765edf2ea | |||
| e81adc11eb | |||
| 0d84319dbf | |||
| 9b259ae43a | |||
| 0fd85517e9 | |||
| 8d07694be6 | |||
| d42e530c89 | |||
| ea9d4774dd | |||
| 9948258fca | |||
| 8bbe215b6a | |||
| 90fca13568 | |||
| d2d222e05d | |||
| dc03a83f61 | |||
| c067e25b2c | |||
| acd6ebeb6b | |||
| 89154e0479 | |||
| 107810dce2 | |||
| 1536a7e04b | |||
| 663dd3a50c | |||
| 6caa932fff | |||
| a4464099d9 | |||
| 932eed204d | |||
| e7cce1bcd7 | |||
| 9280a478c3 | |||
| adbfab8cf1 | |||
| b8da13c235 | |||
| 0d3358b035 | |||
| 935868c756 | |||
| 479a9d86ed | |||
| eeb1d8e0ca | |||
| e3e854a67b | |||
| 7e5e49e811 | |||
| 8c10a303d0 | |||
| dbd74ae3a3 | |||
| f977f0c0e5 |
@@ -11,9 +11,19 @@ notifications:
|
||||
jira_options: link label worklog
|
||||
|
||||
github:
|
||||
description: "Apache Struts is a free, open-source, MVC framework for creating elegant, modern Java web applications"
|
||||
homepage: https://struts.apache.org/
|
||||
del_branch_on_merge: true
|
||||
protected_branches:
|
||||
master:
|
||||
main:
|
||||
# contexts are the names of checks that must pass.
|
||||
contexts:
|
||||
- build
|
||||
required_pull_request_reviews:
|
||||
# it does not work because our github teams are private/secret, see INFRA-25666
|
||||
require_code_owner_reviews: false
|
||||
required_approving_review_count: 0
|
||||
release/*:
|
||||
# contexts are the names of checks that must pass.
|
||||
contexts:
|
||||
- build
|
||||
|
||||
@@ -17,7 +17,8 @@ name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
branches:
|
||||
- 'release/*'
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
@@ -41,15 +42,21 @@ jobs:
|
||||
matrix:
|
||||
language: [ 'java' ]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Java JDK
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: 17
|
||||
cache: 'maven'
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3.28.8
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v3.28.8
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3.28.8
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # 2.3.3
|
||||
uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # 2.4.0
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
@@ -57,13 +57,13 @@ jobs:
|
||||
publish_results: true
|
||||
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@0b2256b8c012f0828dc542b3febcab082c67f72b # 4.3.4
|
||||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # 4.4.3
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@03e7845b7bfcd5e7fb63d1ae8c61b0e791134fab # 2.22.11
|
||||
uses: github/codeql-action/upload-sarif@acb9cb18eec7e3a113ef83cff0be91e75cfd9526 # 2.22.11
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
Vendored
+11
-54
@@ -69,7 +69,7 @@ pipeline {
|
||||
stages {
|
||||
stage('Test & Coverage') {
|
||||
steps {
|
||||
sh './mvnw -B verify -Pcoverage -DskipAssembly --no-transfer-progress'
|
||||
sh './mvnw -B verify -Pcoverage -DskipAssembly'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
@@ -81,58 +81,15 @@ pipeline {
|
||||
stage('Code Quality') {
|
||||
when {
|
||||
anyOf {
|
||||
branch 'master'; branch 'release/struts-7-0-x'
|
||||
branch 'release/struts-6-7-x'
|
||||
}
|
||||
}
|
||||
steps {
|
||||
withCredentials([string(credentialsId: 'asf-struts-sonarcloud', variable: 'SONARCLOUD_TOKEN')]) {
|
||||
sh './mvnw -B -Pcoverage -DskipAssembly -Dsonar.login=${SONARCLOUD_TOKEN} verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar --no-transfer-progress'
|
||||
sh './mvnw -B -Pcoverage -DskipAssembly -Dsonar.login=${SONARCLOUD_TOKEN} verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Build Source & JavaDoc') {
|
||||
when {
|
||||
branch 'release/struts-7-0-x'
|
||||
}
|
||||
steps {
|
||||
dir("local-snapshots-dir/") {
|
||||
deleteDir()
|
||||
}
|
||||
sh './mvnw -B source:jar javadoc:jar -DskipTests -DskipAssembly --no-transfer-progress'
|
||||
}
|
||||
}
|
||||
stage('Deploy Snapshot') {
|
||||
when {
|
||||
branch 'release/struts-7-0-x'
|
||||
}
|
||||
steps {
|
||||
withCredentials([file(credentialsId: 'lukaszlenart-repository-access-token', variable: 'CUSTOM_SETTINGS')]) {
|
||||
sh './mvnw -s \${CUSTOM_SETTINGS} deploy -DskipTests -DskipAssembly --no-transfer-progress'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Upload nightlies') {
|
||||
when {
|
||||
branch 'release/struts-7-0-x'
|
||||
}
|
||||
steps {
|
||||
sh './mvnw -B package -DskipTests --no-transfer-progress'
|
||||
sshPublisher(publishers: [
|
||||
sshPublisherDesc(
|
||||
configName: 'Nightlies',
|
||||
transfers: [
|
||||
sshTransfer(
|
||||
remoteDirectory: '/struts/snapshot',
|
||||
removePrefix: 'assembly/target/assembly/out',
|
||||
sourceFiles: 'assembly/target/assembly/out/struts-*.zip',
|
||||
cleanRemote: true
|
||||
)
|
||||
],
|
||||
verbose: true
|
||||
)
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
@@ -154,12 +111,12 @@ pipeline {
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh './mvnw -B clean install -DskipTests -DskipAssembly --no-transfer-progress'
|
||||
sh './mvnw -B clean install -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
steps {
|
||||
sh './mvnw -B verify --no-transfer-progress'
|
||||
sh './mvnw -B verify -DskipAssembly'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
@@ -170,31 +127,31 @@ pipeline {
|
||||
}
|
||||
stage('Build Source & JavaDoc') {
|
||||
when {
|
||||
branch 'master'
|
||||
branch 'release/struts-6-7-x'
|
||||
}
|
||||
steps {
|
||||
dir("local-snapshots-dir/") {
|
||||
deleteDir()
|
||||
}
|
||||
sh './mvnw -B source:jar javadoc:jar -DskipTests -DskipAssembly --no-transfer-progress'
|
||||
sh './mvnw -B source:jar javadoc:jar -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
stage('Deploy Snapshot') {
|
||||
when {
|
||||
branch 'master'
|
||||
branch 'release/struts-6-7-x'
|
||||
}
|
||||
steps {
|
||||
withCredentials([file(credentialsId: 'lukaszlenart-repository-access-token', variable: 'CUSTOM_SETTINGS')]) {
|
||||
sh './mvnw -s \${CUSTOM_SETTINGS} deploy -DskipTests -DskipAssembly --no-transfer-progress'
|
||||
sh './mvnw -s \${CUSTOM_SETTINGS} deploy -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Upload nightlies') {
|
||||
when {
|
||||
branch 'master'
|
||||
branch 'release/struts-6-7-x'
|
||||
}
|
||||
steps {
|
||||
sh './mvnw -B package -DskipTests --no-transfer-progress'
|
||||
sh './mvnw -B package -DskipTests'
|
||||
sshPublisher(publishers: [
|
||||
sshPublisherDesc(
|
||||
configName: 'Nightlies',
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>6.6.0</version>
|
||||
<version>6.7.3</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.6.0</version>
|
||||
<version>6.7.3</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-rest-showcase</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>6.6.0</version>
|
||||
<version>6.7.3</version>
|
||||
<name>Struts 2 Rest Showcase Webapp</name>
|
||||
<description>Struts 2 Rest Showcase Example</description>
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>6.6.0</version>
|
||||
<version>6.7.3</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-showcase</artifactId>
|
||||
@@ -163,7 +163,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.5.1</version>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>it.org.apache.struts2.showcase.*Test</include>
|
||||
|
||||
+6
@@ -37,6 +37,7 @@ public class FileUploadAction extends ActionSupport implements UploadedFilesAwar
|
||||
private String fileName;
|
||||
private String caption;
|
||||
private String originalName;
|
||||
private String inputName;
|
||||
|
||||
public String input() throws Exception {
|
||||
return SUCCESS;
|
||||
@@ -58,6 +59,10 @@ public class FileUploadAction extends ActionSupport implements UploadedFilesAwar
|
||||
return originalName;
|
||||
}
|
||||
|
||||
public String getInputName() {
|
||||
return inputName;
|
||||
}
|
||||
|
||||
public Object getUploadedFile() {
|
||||
return uploadedFile.getContent();
|
||||
}
|
||||
@@ -85,5 +90,6 @@ public class FileUploadAction extends ActionSupport implements UploadedFilesAwar
|
||||
this.fileName = uploadedFile.getName();
|
||||
this.contentType = uploadedFile.getContentType();
|
||||
this.originalName = uploadedFile.getOriginalName();
|
||||
this.inputName = uploadedFile.getInputName();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ public class ModelDrivenAction extends ActionSupport implements ModelDriven {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getModel() {
|
||||
public Gangster getModel() {
|
||||
return new Gangster();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,8 @@
|
||||
<li>FileName: <s:property value="fileName" /></li>
|
||||
<li>Original FileName: <s:property value="originalName" /></li>
|
||||
<li>File: <s:property value="uploadedFile" /></li>
|
||||
<li>Caption:<s:property value="caption" /></li>
|
||||
<li>Caption: <s:property value="caption" /></li>
|
||||
<li id="input-name">Input name: <s:property value="inputName" /></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,10 +25,14 @@ import com.gargoylesoftware.htmlunit.html.HtmlForm;
|
||||
import com.gargoylesoftware.htmlunit.html.HtmlInput;
|
||||
import com.gargoylesoftware.htmlunit.html.HtmlPage;
|
||||
import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class FileUploadTest {
|
||||
|
||||
@@ -45,9 +49,31 @@ public class FileUploadTest {
|
||||
uploadInput.setValueAttribute(tempFile.getAbsolutePath());
|
||||
final HtmlSubmitInput button = form.getInputByValue("Submit");
|
||||
final HtmlPage resultPage = button.click();
|
||||
|
||||
DomElement errorMessage = resultPage.getFirstByXPath("//span[@class='errorMessage']");
|
||||
Assert.assertNotNull(errorMessage);
|
||||
Assert.assertEquals("File cannot be empty", errorMessage.getVisibleText());
|
||||
assertNotNull(errorMessage);
|
||||
assertEquals("File cannot be empty", errorMessage.getVisibleText());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFileUpload() throws Exception {
|
||||
try (final WebClient webClient = new WebClient()) {
|
||||
final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/fileupload/doUpload.action");
|
||||
final HtmlForm form = page.getFormByName("doUpload");
|
||||
HtmlInput captionInput = form.getInputByName("caption");
|
||||
HtmlFileInput uploadInput = form.getInputByName("upload");
|
||||
captionInput.type("some caption");
|
||||
File tempFile = File.createTempFile("testEmptyFile", ".tmp");
|
||||
Files.write(Paths.get(tempFile.toURI()), "some content".getBytes());
|
||||
tempFile.deleteOnExit();
|
||||
uploadInput.setValueAttribute(tempFile.getAbsolutePath());
|
||||
final HtmlSubmitInput button = form.getInputByValue("Submit");
|
||||
final HtmlPage resultPage = button.click();
|
||||
|
||||
DomElement inputName = resultPage.getElementById("input-name");
|
||||
assertNotNull(inputName);
|
||||
assertEquals("Input name: upload", inputName.getTextContent().trim());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>6.6.0</version>
|
||||
<version>6.7.3</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-assembly</artifactId>
|
||||
|
||||
+4
-4
@@ -25,11 +25,11 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>6.6.0</version>
|
||||
<version>6.7.3</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-bom</artifactId>
|
||||
<version>6.6.0</version>
|
||||
<version>6.7.3</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Struts 2 Bill of Materials</name>
|
||||
@@ -44,7 +44,7 @@
|
||||
</licenses>
|
||||
|
||||
<properties>
|
||||
<struts-version.version>6.6.0</struts-version.version>
|
||||
<struts-version.version>6.7.3</struts-version.version>
|
||||
<maven.site.skip>true</maven.site.skip>
|
||||
<maven.site.deploy.skip>true</maven.site.deploy.skip>
|
||||
</properties>
|
||||
@@ -190,7 +190,7 @@
|
||||
</dependencyManagement>
|
||||
|
||||
<scm>
|
||||
<tag>STRUTS_6_6_0</tag>
|
||||
<tag>STRUTS_6_7_3</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.6.0</version>
|
||||
<version>6.7.3</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.6.0</version>
|
||||
<version>6.7.3</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-demo-bundle</artifactId>
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>6.6.0</version>
|
||||
<version>6.7.3</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>6.6.0</version>
|
||||
<version>6.7.3</version>
|
||||
</parent>
|
||||
<artifactId>struts2-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@@ -19,70 +19,10 @@
|
||||
package com.opensymphony.xwork2;
|
||||
|
||||
/**
|
||||
* All actions <b>may</b> implement this interface, which exposes the <code>execute()</code> method.
|
||||
* <p>
|
||||
* However, as of XWork 1.1, this is <b>not</b> required and is only here to assist users. You are free to create POJOs
|
||||
* that honor the same contract defined by this interface without actually implementing the interface.
|
||||
* </p>
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.action.Action} instead.
|
||||
*/
|
||||
public interface Action {
|
||||
|
||||
/**
|
||||
* The action execution was successful. Show result
|
||||
* view to the end user.
|
||||
*/
|
||||
public static final String SUCCESS = "success";
|
||||
|
||||
/**
|
||||
* The action execution was successful but do not
|
||||
* show a view. This is useful for actions that are
|
||||
* handling the view in another fashion like redirect.
|
||||
*/
|
||||
public static final String NONE = "none";
|
||||
|
||||
/**
|
||||
* The action execution was a failure.
|
||||
* Show an error view, possibly asking the
|
||||
* user to retry entering data.
|
||||
*/
|
||||
public static final String ERROR = "error";
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* The action execution require more input
|
||||
* in order to succeed.
|
||||
* This result is typically used if a form
|
||||
* handling action has been executed so as
|
||||
* to provide defaults for a form. The
|
||||
* form associated with the handler should be
|
||||
* shown to the end user.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This result is also used if the given input
|
||||
* params are invalid, meaning the user
|
||||
* should try providing input again.
|
||||
* </p>
|
||||
*/
|
||||
public static final String INPUT = "input";
|
||||
|
||||
/**
|
||||
* The action could not execute, since the
|
||||
* user most was not logged in. The login view
|
||||
* should be shown.
|
||||
*/
|
||||
public static final String LOGIN = "login";
|
||||
|
||||
|
||||
/**
|
||||
* Where the logic of the action is executed.
|
||||
*
|
||||
* @return a string representing the logical result of the execution.
|
||||
* See constants in this interface for a list of standard result values.
|
||||
* @throws Exception thrown if a system level exception occurs.
|
||||
* <b>Note:</b> Application level exceptions should be handled by returning
|
||||
* an error value, such as <code>Action.ERROR</code>.
|
||||
*/
|
||||
public String execute() throws Exception;
|
||||
|
||||
@Deprecated
|
||||
public interface Action extends org.apache.struts2.action.Action {
|
||||
}
|
||||
|
||||
@@ -18,263 +18,21 @@
|
||||
*/
|
||||
package com.opensymphony.xwork2;
|
||||
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.TextParseUtil;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.StrutsException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: description -->
|
||||
*
|
||||
* This result invokes an entire other action, complete with it's own interceptor stack and result.
|
||||
*
|
||||
* <!-- END SNIPPET: description -->
|
||||
*
|
||||
* <b>This result type takes the following parameters:</b>
|
||||
*
|
||||
* <!-- START SNIPPET: params -->
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li><b>actionName (default)</b> - the name of the action that will be chained to</li>
|
||||
*
|
||||
* <li><b>namespace</b> - used to determine which namespace the Action is in that we're chaining. If namespace is null,
|
||||
* this defaults to the current namespace</li>
|
||||
*
|
||||
* <li><b>method</b> - used to specify another method on target action to be invoked.
|
||||
* If null, this defaults to execute method</li>
|
||||
*
|
||||
* <li><b>skipActions</b> - (optional) the list of comma separated action names for the
|
||||
* actions that could be chained to</li>
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <!-- END SNIPPET: params -->
|
||||
*
|
||||
* <b>Example:</b>
|
||||
*
|
||||
* <pre><!-- START SNIPPET: example -->
|
||||
* <package name="public" extends="struts-default">
|
||||
* <!-- Chain creatAccount to login, using the default parameter -->
|
||||
* <action name="createAccount" class="...">
|
||||
* <result type="chain">login</result>
|
||||
* </action>
|
||||
*
|
||||
* <action name="login" class="...">
|
||||
* <!-- Chain to another namespace -->
|
||||
* <result type="chain">
|
||||
* <param name="actionName">dashboard</param>
|
||||
* <param name="namespace">/secure</param>
|
||||
* </result>
|
||||
* </action>
|
||||
* </package>
|
||||
*
|
||||
* <package name="secure" extends="struts-default" namespace="/secure">
|
||||
* <action name="dashboard" class="...">
|
||||
* <result>dashboard.jsp</result>
|
||||
* </action>
|
||||
* </package>
|
||||
* <!-- END SNIPPET: example --></pre>
|
||||
*
|
||||
* @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
|
||||
*/
|
||||
public class ActionChainResult implements Result {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(ActionChainResult.class);
|
||||
|
||||
/**
|
||||
* The result parameter name to set the name of the action to chain to.
|
||||
*/
|
||||
public static final String DEFAULT_PARAM = "actionName";
|
||||
|
||||
/**
|
||||
* The action context key to save the chain history.
|
||||
*/
|
||||
private static final String CHAIN_HISTORY = "CHAIN_HISTORY";
|
||||
|
||||
private ActionProxy proxy;
|
||||
private String actionName;
|
||||
|
||||
private String namespace;
|
||||
|
||||
private String methodName;
|
||||
|
||||
/**
|
||||
* The list of actions to skip.
|
||||
*/
|
||||
private String skipActions;
|
||||
|
||||
private ActionProxyFactory actionProxyFactory;
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.result.ActionChainResult} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ActionChainResult extends org.apache.struts2.result.ActionChainResult {
|
||||
|
||||
public ActionChainResult() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ActionChainResult(String namespace, String actionName, String methodName) {
|
||||
this.namespace = namespace;
|
||||
this.actionName = actionName;
|
||||
this.methodName = methodName;
|
||||
super(namespace, actionName, methodName);
|
||||
}
|
||||
|
||||
public ActionChainResult(String namespace, String actionName, String methodName, String skipActions) {
|
||||
this.namespace = namespace;
|
||||
this.actionName = actionName;
|
||||
this.methodName = methodName;
|
||||
this.skipActions = skipActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param actionProxyFactory the actionProxyFactory to set
|
||||
*/
|
||||
@Inject
|
||||
public void setActionProxyFactory(ActionProxyFactory actionProxyFactory) {
|
||||
this.actionProxyFactory = actionProxyFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the action name.
|
||||
*
|
||||
* @param actionName The action name.
|
||||
*/
|
||||
public void setActionName(String actionName) {
|
||||
this.actionName = actionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* sets the namespace of the Action that we're chaining to. if namespace
|
||||
* is null, this defaults to the current namespace.
|
||||
*
|
||||
* @param namespace the name of the namespace we're chaining to
|
||||
*/
|
||||
public void setNamespace(String namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the list of actions to skip.
|
||||
* To test if an action should not throe an infinite recursion,
|
||||
* only the action name is used, not the namespace.
|
||||
*
|
||||
* @param actions The list of action name separated by a white space.
|
||||
*/
|
||||
public void setSkipActions(String actions) {
|
||||
this.skipActions = actions;
|
||||
}
|
||||
|
||||
public void setMethod(String method) {
|
||||
this.methodName = method;
|
||||
}
|
||||
|
||||
public ActionProxy getProxy() {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the XWork chain history.
|
||||
* The stack is a list of <code>namespace/action!method</code> keys.
|
||||
*
|
||||
* @return the chain history as string list
|
||||
*/
|
||||
public static LinkedList<String> getChainHistory() {
|
||||
LinkedList<String> chainHistory = (LinkedList<String>) ActionContext.getContext().get(CHAIN_HISTORY);
|
||||
// Add if not exists
|
||||
if (chainHistory == null) {
|
||||
chainHistory = new LinkedList<>();
|
||||
ActionContext.getContext().put(CHAIN_HISTORY, chainHistory);
|
||||
}
|
||||
|
||||
return chainHistory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param invocation the DefaultActionInvocation calling the action call stack
|
||||
*/
|
||||
public void execute(ActionInvocation invocation) throws Exception {
|
||||
if (invocation == null) {
|
||||
throw new IllegalArgumentException("Invocation cannot be null!");
|
||||
}
|
||||
|
||||
String finalNamespace = namespace != null ? translateVariables(namespace) : invocation.getProxy()
|
||||
.getNamespace();
|
||||
String finalActionName = translateVariables(actionName);
|
||||
String finalMethodName = methodName != null ? translateVariables(methodName) : null;
|
||||
|
||||
if (isInChainHistory(finalNamespace, finalActionName, finalMethodName)) {
|
||||
addToHistory(finalNamespace, finalActionName, finalMethodName);
|
||||
throw new StrutsException("Infinite recursion detected: " + ActionChainResult.getChainHistory());
|
||||
}
|
||||
|
||||
if (ActionChainResult.getChainHistory().isEmpty() && invocation.getProxy() != null) {
|
||||
addToHistory(finalNamespace, invocation.getProxy().getActionName(), invocation.getProxy().getMethod());
|
||||
}
|
||||
addToHistory(finalNamespace, finalActionName, finalMethodName);
|
||||
|
||||
Map<String, Object> extraContext = ActionContext.of()
|
||||
.withValueStack(invocation.getInvocationContext().getValueStack())
|
||||
.withParameters(invocation.getInvocationContext().getParameters())
|
||||
.with(CHAIN_HISTORY, ActionChainResult.getChainHistory())
|
||||
.getContextMap();
|
||||
|
||||
LOG.debug("Chaining to action {}", finalActionName);
|
||||
|
||||
proxy = actionProxyFactory.createActionProxy(finalNamespace, finalActionName, finalMethodName, extraContext);
|
||||
proxy.execute();
|
||||
}
|
||||
|
||||
protected String translateVariables(String text) {
|
||||
return TextParseUtil.translateVariables(text, ActionContext.getContext().getValueStack());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
ActionChainResult that = (ActionChainResult) o;
|
||||
return Objects.equals(actionName, that.actionName) && Objects.equals(methodName,
|
||||
that.methodName) && Objects.equals(namespace, that.namespace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = (actionName != null ? actionName.hashCode() : 0);
|
||||
result = 31 * result + (namespace != null ? namespace.hashCode() : 0);
|
||||
result = 31 * result + (methodName != null ? methodName.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean isInChainHistory(String namespace, String actionName, String methodName) {
|
||||
LinkedList<? extends String> chainHistory = ActionChainResult.getChainHistory();
|
||||
Set<String> skipActionsList = new HashSet<>();
|
||||
if (skipActions != null && skipActions.length() > 0) {
|
||||
String finalSkipActions = translateVariables(skipActions);
|
||||
skipActionsList.addAll(TextParseUtil.commaDelimitedStringToSet(finalSkipActions));
|
||||
}
|
||||
if (!skipActionsList.contains(actionName)) {
|
||||
return chainHistory.contains(makeKey(namespace, actionName, methodName));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addToHistory(String namespace, String actionName, String methodName) {
|
||||
List<String> chainHistory = ActionChainResult.getChainHistory();
|
||||
chainHistory.add(makeKey(namespace, actionName, methodName));
|
||||
}
|
||||
|
||||
private String makeKey(String namespace, String actionName, String methodName) {
|
||||
return namespace + "/" + actionName + (methodName != null ? "!" + methodName : "");
|
||||
super(namespace, actionName, methodName, skipActions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ package com.opensymphony.xwork2;
|
||||
import com.opensymphony.xwork2.conversion.impl.ConversionData;
|
||||
import com.opensymphony.xwork2.inject.Container;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import org.apache.struts2.StrutsException;
|
||||
import org.apache.struts2.StrutsStatics;
|
||||
import org.apache.struts2.dispatcher.HttpParameters;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapping;
|
||||
|
||||
@@ -30,515 +28,249 @@ import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* The ActionContext is the context in which an {@link Action} is executed. Each context is basically a
|
||||
* container of objects an action needs for execution like the session, parameters, locale, etc.
|
||||
* </p>
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>
|
||||
* The ActionContext is thread local which means that values stored in the ActionContext are
|
||||
* unique per thread. See the {@link ThreadLocal} class for more information. The benefit of
|
||||
* this is you don't need to worry about a user specific action context, you just get it:
|
||||
* </p>
|
||||
*
|
||||
* <code>ActionContext context = ActionContext.getContext();</code>
|
||||
*
|
||||
* <p>
|
||||
* Finally, because of the thread local usage you don't need to worry about making your actions thread safe.
|
||||
* </p>
|
||||
*
|
||||
* @author Patrick Lightbody
|
||||
* @author Bill Lynch (docs)
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.ActionContext} instead.
|
||||
*/
|
||||
public class ActionContext implements Serializable {
|
||||
@Deprecated
|
||||
public class ActionContext extends org.apache.struts2.ActionContext {
|
||||
|
||||
private static final ThreadLocal<ActionContext> actionContext = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* Constant for the name of the action being executed.
|
||||
*/
|
||||
private static final String ACTION_NAME = "org.apache.struts2.ActionContext.name";
|
||||
|
||||
/**
|
||||
* Constant for the {@link com.opensymphony.xwork2.util.ValueStack OGNL value stack}.
|
||||
*/
|
||||
private static final String VALUE_STACK = ValueStack.VALUE_STACK;
|
||||
|
||||
/**
|
||||
* Constant for the action's session.
|
||||
*/
|
||||
private static final String SESSION = "org.apache.struts2.ActionContext.session";
|
||||
|
||||
/**
|
||||
* Constant for the action's application context.
|
||||
*/
|
||||
private static final String APPLICATION = "org.apache.struts2.ActionContext.application";
|
||||
|
||||
/**
|
||||
* Constant for the action's parameters.
|
||||
*/
|
||||
private static final String PARAMETERS = "org.apache.struts2.ActionContext.parameters";
|
||||
|
||||
/**
|
||||
* Constant for the action's locale.
|
||||
*/
|
||||
private static final String LOCALE = "org.apache.struts2.ActionContext.locale";
|
||||
|
||||
/**
|
||||
* Constant for the action's {@link com.opensymphony.xwork2.ActionInvocation invocation} context.
|
||||
*/
|
||||
private static final String ACTION_INVOCATION = "org.apache.struts2.ActionContext.actionInvocation";
|
||||
|
||||
/**
|
||||
* Constant for the map of type conversion errors.
|
||||
*/
|
||||
private static final String CONVERSION_ERRORS = "org.apache.struts2.ActionContext.conversionErrors";
|
||||
|
||||
/**
|
||||
* Constant for the container
|
||||
*/
|
||||
private static final String CONTAINER = "org.apache.struts2.ActionContext.container";
|
||||
|
||||
private final Map<String, Object> context;
|
||||
|
||||
/**
|
||||
* Creates a new ActionContext initialized with another context.
|
||||
*
|
||||
* @param context a context map.
|
||||
*/
|
||||
protected ActionContext(Map<String, Object> context) {
|
||||
this.context = context;
|
||||
private ActionContext(org.apache.struts2.ActionContext actualContext) {
|
||||
super(actualContext.getContextMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ActionContext based on passed in Map
|
||||
*
|
||||
* @param context a map with context values
|
||||
* @return new ActionContext
|
||||
*/
|
||||
public static ActionContext of(Map<String, Object> context) {
|
||||
if (context == null) {
|
||||
throw new IllegalArgumentException("Context cannot be null!");
|
||||
public static ActionContext adapt(org.apache.struts2.ActionContext actualContext) {
|
||||
if (actualContext instanceof ActionContext) {
|
||||
return (ActionContext) actualContext;
|
||||
}
|
||||
return new ActionContext(context);
|
||||
return actualContext != null ? new ActionContext(actualContext) : null;
|
||||
}
|
||||
|
||||
public static ActionContext of(Map<String, Object> context) {
|
||||
return adapt(org.apache.struts2.ActionContext.of(context));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ActionContext based on empty Map
|
||||
*
|
||||
* @return new ActionContext
|
||||
*/
|
||||
public static ActionContext of() {
|
||||
return of(new HashMap<>());
|
||||
return adapt(org.apache.struts2.ActionContext.of());
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the provided context with the current thread
|
||||
*
|
||||
* @param actionContext context to bind to the thread
|
||||
* @return context which was bound to the thread
|
||||
*/
|
||||
public static ActionContext bind(ActionContext actionContext) {
|
||||
ActionContext.setContext(actionContext);
|
||||
return ActionContext.getContext();
|
||||
return adapt(org.apache.struts2.ActionContext.bind(actionContext));
|
||||
}
|
||||
|
||||
public static boolean containsValueStack(Map<String, Object> context) {
|
||||
return context != null && context.containsKey(VALUE_STACK);
|
||||
return org.apache.struts2.ActionContext.containsValueStack(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds this context with the current thread
|
||||
*
|
||||
* @return this context which was bound to the thread
|
||||
*/
|
||||
public ActionContext bind() {
|
||||
ActionContext.setContext(this);
|
||||
return ActionContext.getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wipes out current ActionContext, use wisely!
|
||||
*/
|
||||
public static void clear() {
|
||||
actionContext.remove();
|
||||
org.apache.struts2.ActionContext.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the action context for the current thread.
|
||||
*
|
||||
* @param context the action context.
|
||||
*/
|
||||
private static void setContext(ActionContext context) {
|
||||
actionContext.set(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ActionContext specific to the current thread.
|
||||
*
|
||||
* @return the ActionContext for the current thread, is never <tt>null</tt>.
|
||||
*/
|
||||
public static ActionContext getContext() {
|
||||
return actionContext.get();
|
||||
return adapt(org.apache.struts2.ActionContext.getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionContext bind() {
|
||||
super.bind();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the action invocation (the execution state).
|
||||
*
|
||||
* @param actionInvocation the action execution state.
|
||||
*/
|
||||
public ActionContext withActionInvocation(ActionInvocation actionInvocation) {
|
||||
put(ACTION_INVOCATION, actionInvocation);
|
||||
return withActionInvocation((org.apache.struts2.ActionInvocation) actionInvocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionContext withActionInvocation(org.apache.struts2.ActionInvocation actionInvocation) {
|
||||
super.withActionInvocation(actionInvocation);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the action invocation (the execution state).
|
||||
*
|
||||
* @return the action invocation (the execution state).
|
||||
*/
|
||||
@Override
|
||||
public ActionInvocation getActionInvocation() {
|
||||
return (ActionInvocation) get(ACTION_INVOCATION);
|
||||
return ActionInvocation.adapt(super.getActionInvocation());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the action's application context.
|
||||
*
|
||||
* @param application the action's application context.
|
||||
*/
|
||||
@Override
|
||||
public ActionContext withApplication(Map<String, Object> application) {
|
||||
put(APPLICATION, application);
|
||||
super.withApplication(application);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Map of the ServletContext when in a servlet environment or a generic application level Map otherwise.
|
||||
*
|
||||
* @return a Map of ServletContext or generic application level Map
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map<String, Object> getApplication() {
|
||||
return (Map<String, Object>) get(APPLICATION);
|
||||
return super.getApplication();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the context map.
|
||||
*
|
||||
* @return the context map.
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> getContextMap() {
|
||||
return context;
|
||||
return super.getContextMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets conversion errors which occurred when executing the action.
|
||||
*
|
||||
* @param conversionErrors a Map of errors which occurred when executing the action.
|
||||
*/
|
||||
@Override
|
||||
public ActionContext withConversionErrors(Map<String, ConversionData> conversionErrors) {
|
||||
put(CONVERSION_ERRORS, conversionErrors);
|
||||
super.withConversionErrors(conversionErrors);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the map of conversion errors which occurred when executing the action.
|
||||
*
|
||||
* @return the map of conversion errors which occurred when executing the action or an empty map if
|
||||
* there were no errors.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map<String, ConversionData> getConversionErrors() {
|
||||
Map<String, ConversionData> errors = (Map<String, ConversionData>) get(CONVERSION_ERRORS);
|
||||
|
||||
if (errors == null) {
|
||||
errors = withConversionErrors(new HashMap<>()).getConversionErrors();
|
||||
}
|
||||
|
||||
return errors;
|
||||
return super.getConversionErrors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Locale for the current action.
|
||||
*
|
||||
* @param locale the Locale for the current action.
|
||||
*/
|
||||
@Override
|
||||
public ActionContext withLocale(Locale locale) {
|
||||
put(LOCALE, locale);
|
||||
super.withLocale(locale);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Locale of the current action. If no locale was ever specified the platform's
|
||||
* {@link java.util.Locale#getDefault() default locale} is used.
|
||||
*
|
||||
* @return the Locale of the current action.
|
||||
*/
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
Locale locale = (Locale) get(LOCALE);
|
||||
|
||||
if (locale == null) {
|
||||
locale = Locale.getDefault();
|
||||
withLocale(locale);
|
||||
}
|
||||
|
||||
return locale;
|
||||
return super.getLocale();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the current Action in the ActionContext.
|
||||
*
|
||||
* @param actionName the name of the current action.
|
||||
*/
|
||||
@Override
|
||||
public ActionContext withActionName(String actionName) {
|
||||
put(ACTION_NAME, actionName);
|
||||
super.withActionName(actionName);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the current Action.
|
||||
*
|
||||
* @return the name of the current action.
|
||||
*/
|
||||
@Override
|
||||
public String getActionName() {
|
||||
return (String) get(ACTION_NAME);
|
||||
return super.getActionName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the action parameters.
|
||||
*
|
||||
* @param parameters the parameters for the current action.
|
||||
*/
|
||||
@Override
|
||||
public ActionContext withParameters(HttpParameters parameters) {
|
||||
put(PARAMETERS, parameters);
|
||||
super.withParameters(parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Map of the HttpServletRequest parameters when in a servlet environment or a generic Map of
|
||||
* parameters otherwise.
|
||||
*
|
||||
* @return a Map of HttpServletRequest parameters or a multipart map when in a servlet environment, or a
|
||||
* generic Map of parameters otherwise.
|
||||
*/
|
||||
@Override
|
||||
public HttpParameters getParameters() {
|
||||
return (HttpParameters) get(PARAMETERS);
|
||||
return super.getParameters();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a map of action session values.
|
||||
*
|
||||
* @param session the session values.
|
||||
*/
|
||||
@Override
|
||||
public ActionContext withSession(Map<String, Object> session) {
|
||||
put(SESSION, session);
|
||||
super.withSession(session);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Map of HttpSession values when in a servlet environment or a generic session map otherwise.
|
||||
*
|
||||
* @return the Map of HttpSession values when in a servlet environment or a generic session map otherwise.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Map<String, Object> getSession() {
|
||||
return (Map<String, Object>) get(SESSION);
|
||||
return super.getSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the OGNL value stack.
|
||||
*
|
||||
* @param valueStack the OGNL value stack.
|
||||
*/
|
||||
public ActionContext withValueStack(ValueStack valueStack) {
|
||||
put(VALUE_STACK, valueStack);
|
||||
return withValueStack((org.apache.struts2.util.ValueStack) valueStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionContext withValueStack(org.apache.struts2.util.ValueStack valueStack) {
|
||||
super.withValueStack(valueStack);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the OGNL value stack.
|
||||
*
|
||||
* @return the OGNL value stack.
|
||||
*/
|
||||
@Override
|
||||
public ValueStack getValueStack() {
|
||||
return (ValueStack) get(VALUE_STACK);
|
||||
return ValueStack.adapt(super.getValueStack());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the container for this request
|
||||
*
|
||||
* @param container The container
|
||||
*/
|
||||
@Override
|
||||
public ActionContext withContainer(Container container) {
|
||||
put(CONTAINER, container);
|
||||
super.withContainer(container);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the container for this request
|
||||
*
|
||||
* @return The container
|
||||
*/
|
||||
@Override
|
||||
public Container getContainer() {
|
||||
return (Container) get(CONTAINER);
|
||||
return super.getContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getInstance(Class<T> type) {
|
||||
Container cont = getContainer();
|
||||
if (cont != null) {
|
||||
return cont.getInstance(type);
|
||||
} else {
|
||||
throw new StrutsException("Cannot find an initialized container for this request.");
|
||||
}
|
||||
return super.getInstance(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value that is stored in the current ActionContext by doing a lookup using the value's key.
|
||||
*
|
||||
* @param key the key used to find the value.
|
||||
* @return the value that was found using the key or <tt>null</tt> if the key was not found.
|
||||
*/
|
||||
@Override
|
||||
public Object get(String key) {
|
||||
return context.get(key);
|
||||
return super.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a value in the current ActionContext. The value can be looked up using the key.
|
||||
*
|
||||
* @param key the key of the value.
|
||||
* @param value the value to be stored.
|
||||
*/
|
||||
@Override
|
||||
public void put(String key, Object value) {
|
||||
context.put(key, value);
|
||||
super.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets ServletContext associated with current action
|
||||
*
|
||||
* @return current ServletContext
|
||||
*/
|
||||
@Override
|
||||
public ServletContext getServletContext() {
|
||||
return (ServletContext) get(StrutsStatics.SERVLET_CONTEXT);
|
||||
return super.getServletContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns ServletContext to action context
|
||||
*
|
||||
* @param servletContext associated with current request
|
||||
* @return ActionContext
|
||||
*/
|
||||
@Override
|
||||
public ActionContext withServletContext(ServletContext servletContext) {
|
||||
put(StrutsStatics.SERVLET_CONTEXT, servletContext);
|
||||
super.withServletContext(servletContext);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets ServletRequest associated with current action
|
||||
*
|
||||
* @return current ServletRequest
|
||||
*/
|
||||
@Override
|
||||
public HttpServletRequest getServletRequest() {
|
||||
return (HttpServletRequest) get(StrutsStatics.HTTP_REQUEST);
|
||||
return super.getServletRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns ServletRequest to action context
|
||||
*
|
||||
* @param request associated with current request
|
||||
* @return ActionContext
|
||||
*/
|
||||
@Override
|
||||
public ActionContext withServletRequest(HttpServletRequest request) {
|
||||
put(StrutsStatics.HTTP_REQUEST, request);
|
||||
super.withServletRequest(request);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets ServletResponse associated with current action
|
||||
*
|
||||
* @return current ServletResponse
|
||||
*/
|
||||
@Override
|
||||
public HttpServletResponse getServletResponse() {
|
||||
return (HttpServletResponse) get(StrutsStatics.HTTP_RESPONSE);
|
||||
return super.getServletResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns ServletResponse to action context
|
||||
*
|
||||
* @param response associated with current request
|
||||
* @return ActionContext
|
||||
*/
|
||||
@Override
|
||||
public ActionContext withServletResponse(HttpServletResponse response) {
|
||||
put(StrutsStatics.HTTP_RESPONSE, response);
|
||||
super.withServletResponse(response);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets PageContext associated with current action
|
||||
*
|
||||
* @return current PageContext
|
||||
*/
|
||||
@Override
|
||||
public PageContext getPageContext() {
|
||||
return (PageContext) get(StrutsStatics.PAGE_CONTEXT);
|
||||
return super.getPageContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns PageContext to action context
|
||||
*
|
||||
* @param pageContext associated with current request
|
||||
* @return ActionContext
|
||||
*/
|
||||
@Override
|
||||
public ActionContext withPageContext(PageContext pageContext) {
|
||||
put(StrutsStatics.PAGE_CONTEXT, pageContext);
|
||||
super.withPageContext(pageContext);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets ActionMapping associated with current action
|
||||
*
|
||||
* @return current ActionMapping
|
||||
*/
|
||||
@Override
|
||||
public ActionMapping getActionMapping() {
|
||||
return (ActionMapping) get(StrutsStatics.ACTION_MAPPING);
|
||||
return super.getActionMapping();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns ActionMapping to action context
|
||||
*
|
||||
* @param actionMapping associated with current request
|
||||
* @return ActionContext
|
||||
*/
|
||||
@Override
|
||||
public ActionContext withActionMapping(ActionMapping actionMapping) {
|
||||
put(StrutsStatics.ACTION_MAPPING, actionMapping);
|
||||
super.withActionMapping(actionMapping);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns an extra context map to action context
|
||||
*
|
||||
* @param extraContext to add to the current action context
|
||||
* @return ActionContext
|
||||
*/
|
||||
@Override
|
||||
public ActionContext withExtraContext(Map<String, Object> extraContext) {
|
||||
if (extraContext != null) {
|
||||
context.putAll(extraContext);
|
||||
}
|
||||
super.withExtraContext(extraContext);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds arbitrary key to action context
|
||||
*
|
||||
* @param key a string
|
||||
* @param value an object
|
||||
* @return ActionContext
|
||||
*/
|
||||
@Override
|
||||
public ActionContext with(String key, Object value) {
|
||||
put(key, value);
|
||||
super.with(key, value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,24 +21,50 @@ package com.opensymphony.xwork2;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
|
||||
/**
|
||||
* Provides hooks for handling key action events
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.ActionEventListener} instead.
|
||||
*/
|
||||
public interface ActionEventListener {
|
||||
/**
|
||||
* Called after an action has been created.
|
||||
*
|
||||
* @param action The action
|
||||
* @param stack The current value stack
|
||||
* @return The action to use
|
||||
*/
|
||||
public Object prepare(Object action, ValueStack stack);
|
||||
|
||||
/**
|
||||
* Called when an exception is thrown by the action
|
||||
*
|
||||
* @param t The exception/error that was thrown
|
||||
* @param stack The current value stack
|
||||
* @return A result code to execute, can be null
|
||||
*/
|
||||
public String handleException(Throwable t, ValueStack stack);
|
||||
@Deprecated
|
||||
public interface ActionEventListener extends org.apache.struts2.ActionEventListener {
|
||||
|
||||
@Override
|
||||
default Object prepare(Object action, org.apache.struts2.util.ValueStack stack) {
|
||||
return prepare(action, ValueStack.adapt(stack));
|
||||
}
|
||||
|
||||
@Override
|
||||
default String handleException(Throwable t, org.apache.struts2.util.ValueStack stack) {
|
||||
return handleException(t, ValueStack.adapt(stack));
|
||||
}
|
||||
|
||||
Object prepare(Object action, ValueStack stack);
|
||||
|
||||
String handleException(Throwable t, ValueStack stack);
|
||||
|
||||
static ActionEventListener adapt(org.apache.struts2.ActionEventListener actualListener) {
|
||||
if (actualListener instanceof ActionEventListener) {
|
||||
return (ActionEventListener) actualListener;
|
||||
}
|
||||
return actualListener != null ? new LegacyAdapter(actualListener) : null;
|
||||
}
|
||||
|
||||
class LegacyAdapter implements ActionEventListener {
|
||||
|
||||
private final org.apache.struts2.ActionEventListener adaptee;
|
||||
|
||||
private LegacyAdapter(org.apache.struts2.ActionEventListener adaptee) {
|
||||
this.adaptee = adaptee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object prepare(Object action, ValueStack stack) {
|
||||
return adaptee.prepare(action, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handleException(Throwable t, ValueStack stack) {
|
||||
return adaptee.handleException(t, stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,158 +22,125 @@ import com.opensymphony.xwork2.interceptor.PreResultListener;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
|
||||
/**
|
||||
* An {@link ActionInvocation} represents the execution state of an {@link Action}. It holds the Interceptors and the Action instance.
|
||||
* By repeated re-entrant execution of the <code>invoke()</code> method, initially by the {@link ActionProxy}, then by the Interceptors, the
|
||||
* Interceptors are all executed, and then the {@link Action} and the {@link Result}.
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @author Jason Carreira
|
||||
* @see com.opensymphony.xwork2.ActionProxy
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.ActionInvocation} instead.
|
||||
*/
|
||||
public interface ActionInvocation {
|
||||
@Deprecated
|
||||
public interface ActionInvocation extends org.apache.struts2.ActionInvocation {
|
||||
|
||||
/**
|
||||
* Get the Action associated with this ActionInvocation.
|
||||
*
|
||||
* @return the Action
|
||||
*/
|
||||
Object getAction();
|
||||
|
||||
/**
|
||||
* Gets whether this ActionInvocation has executed before.
|
||||
* This will be set after the Action and the Result have executed.
|
||||
*
|
||||
* @return <tt>true</tt> if this ActionInvocation has executed before.
|
||||
*/
|
||||
boolean isExecuted();
|
||||
|
||||
/**
|
||||
* Gets the ActionContext associated with this ActionInvocation. The ActionProxy is
|
||||
* responsible for setting this ActionContext onto the ThreadLocal before invoking
|
||||
* the ActionInvocation and resetting the old ActionContext afterwards.
|
||||
*
|
||||
* @return the ActionContext.
|
||||
*/
|
||||
@Override
|
||||
ActionContext getInvocationContext();
|
||||
|
||||
/**
|
||||
* Get the ActionProxy holding this ActionInvocation.
|
||||
*
|
||||
* @return the ActionProxy.
|
||||
*/
|
||||
ActionProxy getProxy();
|
||||
|
||||
/**
|
||||
* If the ActionInvocation has been executed before and the Result is an instance of {@link ActionChainResult}, this method
|
||||
* will walk down the chain of <code>ActionChainResult</code>s until it finds a non-chain result, which will be returned. If the
|
||||
* ActionInvocation's result has not been executed before, the Result instance will be created and populated with
|
||||
* the result params.
|
||||
*
|
||||
* @return the result.
|
||||
* @throws Exception can be thrown.
|
||||
*/
|
||||
@Override
|
||||
Result getResult() throws Exception;
|
||||
|
||||
/**
|
||||
* Gets the result code returned from this ActionInvocation.
|
||||
*
|
||||
* @return the result code
|
||||
*/
|
||||
String getResultCode();
|
||||
@Override
|
||||
ActionProxy getProxy();
|
||||
|
||||
/**
|
||||
* Sets the result code, possibly overriding the one returned by the
|
||||
* action.
|
||||
*
|
||||
* <p>
|
||||
* The "intended" purpose of this method is to allow PreResultListeners to
|
||||
* override the result code returned by the Action.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If this method is used before the Action executes, the Action's returned
|
||||
* result code will override what was set. However the Action could (if
|
||||
* specifically coded to do so) inspect the ActionInvocation to see that
|
||||
* someone "upstream" (e.g. an Interceptor) had suggested a value as the
|
||||
* result, and it could therefore return the same value itself.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If this method is called between the Action execution and the Result
|
||||
* execution, then the value set here will override the result code the
|
||||
* action had returned. Creating an Interceptor that implements
|
||||
* {@link PreResultListener} will give you this opportunity.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If this method is called after the Result has been executed, it will
|
||||
* have the effect of raising an IllegalStateException.
|
||||
* </p>
|
||||
*
|
||||
* @param resultCode the result code.
|
||||
* @throws IllegalStateException if called after the Result has been executed.
|
||||
* @see #isExecuted()
|
||||
*/
|
||||
void setResultCode(String resultCode);
|
||||
|
||||
/**
|
||||
* Gets the ValueStack associated with this ActionInvocation.
|
||||
*
|
||||
* @return the ValueStack
|
||||
*/
|
||||
@Override
|
||||
ValueStack getStack();
|
||||
|
||||
/**
|
||||
* Register a {@link PreResultListener} to be notified after the Action is executed and
|
||||
* before the Result is executed.
|
||||
*
|
||||
* <p>
|
||||
* The ActionInvocation implementation must guarantee that listeners will be called in
|
||||
* the order in which they are registered.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Listener registration and execution does not need to be thread-safe.
|
||||
* </p>
|
||||
*
|
||||
* @param listener the listener to add.
|
||||
*/
|
||||
@Override
|
||||
default void addPreResultListener(org.apache.struts2.interceptor.PreResultListener listener) {
|
||||
addPreResultListener(PreResultListener.adapt(listener));
|
||||
}
|
||||
|
||||
void addPreResultListener(PreResultListener listener);
|
||||
|
||||
/**
|
||||
* Invokes the next step in processing this ActionInvocation.
|
||||
*
|
||||
* <p>
|
||||
* If there are more Interceptors, this will call the next one. If Interceptors choose not to short-circuit
|
||||
* ActionInvocation processing and return their own return code, they will call invoke() to allow the next Interceptor
|
||||
* to execute. If there are no more Interceptors to be applied, the Action is executed.
|
||||
* If the {@link ActionProxy#getExecuteResult()} method returns <tt>true</tt>, the Result is also executed.
|
||||
* </p>
|
||||
*
|
||||
* @throws Exception can be thrown.
|
||||
* @return the return code.
|
||||
*/
|
||||
String invoke() throws Exception;
|
||||
@Override
|
||||
default void setActionEventListener(org.apache.struts2.ActionEventListener listener) {
|
||||
setActionEventListener(ActionEventListener.adapt(listener));
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes only the Action (not Interceptors or Results).
|
||||
*
|
||||
* <p>
|
||||
* This is useful in rare situations where advanced usage with the interceptor/action/result workflow is
|
||||
* being manipulated for certain functionality.
|
||||
* </p>
|
||||
*
|
||||
* @return the return code.
|
||||
* @throws Exception can be thrown.
|
||||
*/
|
||||
String invokeActionOnly() throws Exception;
|
||||
|
||||
/**
|
||||
* Sets the action event listener to respond to key action events.
|
||||
*
|
||||
* @param listener the listener.
|
||||
*/
|
||||
void setActionEventListener(ActionEventListener listener);
|
||||
|
||||
void init(ActionProxy proxy) ;
|
||||
@Override
|
||||
default void init(org.apache.struts2.ActionProxy proxy) {
|
||||
init(ActionProxy.adapt(proxy));
|
||||
}
|
||||
|
||||
void init(ActionProxy proxy);
|
||||
|
||||
static ActionInvocation adapt(org.apache.struts2.ActionInvocation actualInvocation) {
|
||||
if (actualInvocation instanceof ActionInvocation) {
|
||||
return (ActionInvocation) actualInvocation;
|
||||
}
|
||||
return actualInvocation != null ? new LegacyAdapter(actualInvocation) : null;
|
||||
}
|
||||
|
||||
class LegacyAdapter implements ActionInvocation {
|
||||
|
||||
private final org.apache.struts2.ActionInvocation adaptee;
|
||||
|
||||
private LegacyAdapter(org.apache.struts2.ActionInvocation adaptee) {
|
||||
this.adaptee = adaptee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAction() {
|
||||
return adaptee.getAction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExecuted() {
|
||||
return adaptee.isExecuted();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionContext getInvocationContext() {
|
||||
return ActionContext.adapt(adaptee.getInvocationContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionProxy getProxy() {
|
||||
return ActionProxy.adapt(adaptee.getProxy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result getResult() throws Exception {
|
||||
return Result.adapt(adaptee.getResult());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResultCode() {
|
||||
return adaptee.getResultCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResultCode(String resultCode) {
|
||||
adaptee.setResultCode(resultCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueStack getStack() {
|
||||
return ValueStack.adapt(adaptee.getStack());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPreResultListener(PreResultListener listener) {
|
||||
adaptee.addPreResultListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String invoke() throws Exception {
|
||||
return adaptee.invoke();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String invokeActionOnly() throws Exception {
|
||||
return adaptee.invokeActionOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionEventListener(ActionEventListener listener) {
|
||||
adaptee.setActionEventListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(ActionProxy proxy) {
|
||||
adaptee.init(proxy);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,88 +20,75 @@ package com.opensymphony.xwork2;
|
||||
|
||||
import com.opensymphony.xwork2.config.entities.ActionConfig;
|
||||
|
||||
/**
|
||||
* ActionProxy is an extra layer between XWork and the action so that different proxies are possible.
|
||||
*
|
||||
* <p>
|
||||
* An example of this would be a remote proxy, where the layer between XWork and the action might be RMI or SOAP.
|
||||
* </p>
|
||||
*
|
||||
* @author Jason Carreira
|
||||
*/
|
||||
public interface ActionProxy {
|
||||
@Deprecated
|
||||
public interface ActionProxy extends org.apache.struts2.ActionProxy {
|
||||
|
||||
/**
|
||||
* Gets the Action instance for this Proxy.
|
||||
*
|
||||
* @return the Action instance
|
||||
*/
|
||||
Object getAction();
|
||||
|
||||
/**
|
||||
* Gets the alias name this ActionProxy is mapped to.
|
||||
*
|
||||
* @return the alias name
|
||||
*/
|
||||
String getActionName();
|
||||
|
||||
/**
|
||||
* Gets the ActionConfig this ActionProxy is built from.
|
||||
*
|
||||
* @return the ActionConfig
|
||||
*/
|
||||
ActionConfig getConfig();
|
||||
|
||||
/**
|
||||
* Sets whether this ActionProxy should also execute the Result after executing the Action.
|
||||
*
|
||||
* @param executeResult <tt>true</tt> to also execute the Result.
|
||||
*/
|
||||
void setExecuteResult(boolean executeResult);
|
||||
|
||||
/**
|
||||
* Gets the status of whether the ActionProxy is set to execute the Result after the Action is executed.
|
||||
*
|
||||
* @return the status
|
||||
*/
|
||||
boolean getExecuteResult();
|
||||
|
||||
/**
|
||||
* Gets the ActionInvocation associated with this ActionProxy.
|
||||
*
|
||||
* @return the ActionInvocation
|
||||
*/
|
||||
@Override
|
||||
ActionInvocation getInvocation();
|
||||
|
||||
/**
|
||||
* Gets the namespace the ActionConfig for this ActionProxy is mapped to.
|
||||
*
|
||||
* @return the namespace
|
||||
*/
|
||||
String getNamespace();
|
||||
static ActionProxy adapt(org.apache.struts2.ActionProxy actualProxy) {
|
||||
if (actualProxy instanceof ActionProxy) {
|
||||
return (ActionProxy) actualProxy;
|
||||
}
|
||||
return actualProxy != null ? new LegacyAdapter(actualProxy) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute this ActionProxy. This will set the ActionContext from the ActionInvocation into the ActionContext
|
||||
* ThreadLocal before invoking the ActionInvocation, then set the old ActionContext back into the ThreadLocal.
|
||||
*
|
||||
* @return the result code returned from executing the ActionInvocation
|
||||
* @throws Exception can be thrown.
|
||||
* @see ActionInvocation
|
||||
*/
|
||||
String execute() throws Exception;
|
||||
class LegacyAdapter implements ActionProxy {
|
||||
|
||||
/**
|
||||
* Gets the method name to execute, or <tt>null</tt> if no method has been specified (meaning <code>execute</code> will be invoked).
|
||||
*
|
||||
* @return the method to execute
|
||||
*/
|
||||
String getMethod();
|
||||
private final org.apache.struts2.ActionProxy adaptee;
|
||||
|
||||
/**
|
||||
* Gets status of the method value's initialization.
|
||||
*
|
||||
* @return true if the method returned by getMethod() is not a default initializer value.
|
||||
*/
|
||||
boolean isMethodSpecified();
|
||||
|
||||
private LegacyAdapter(org.apache.struts2.ActionProxy adaptee) {
|
||||
this.adaptee = adaptee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAction() {
|
||||
return adaptee.getAction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActionName() {
|
||||
return adaptee.getActionName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionConfig getConfig() {
|
||||
return adaptee.getConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExecuteResult(boolean executeResult) {
|
||||
adaptee.setExecuteResult(executeResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getExecuteResult() {
|
||||
return adaptee.getExecuteResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionInvocation getInvocation() {
|
||||
return ActionInvocation.adapt(adaptee.getInvocation());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return adaptee.getNamespace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute() throws Exception {
|
||||
return adaptee.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return adaptee.getMethod();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMethodSpecified() {
|
||||
return adaptee.isMethodSpecified();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,342 +18,11 @@
|
||||
*/
|
||||
package com.opensymphony.xwork2;
|
||||
|
||||
import com.opensymphony.xwork2.conversion.impl.ConversionData;
|
||||
import com.opensymphony.xwork2.inject.Container;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.interceptor.ValidationAware;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Provides a default implementation for the most common actions.
|
||||
* See the documentation for all the interfaces this class implements for more detailed information.
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.ActionSupport} instead.
|
||||
*/
|
||||
public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(ActionSupport.class);
|
||||
|
||||
private final ValidationAwareSupport validationAware = new ValidationAwareSupport();
|
||||
|
||||
private transient TextProvider textProvider;
|
||||
private transient LocaleProvider localeProvider;
|
||||
|
||||
protected Container container;
|
||||
|
||||
@Override
|
||||
public void setActionErrors(Collection<String> errorMessages) {
|
||||
validationAware.setActionErrors(errorMessages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getActionErrors() {
|
||||
return validationAware.getActionErrors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionMessages(Collection<String> messages) {
|
||||
validationAware.setActionMessages(messages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getActionMessages() {
|
||||
return validationAware.getActionMessages();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFieldErrors(Map<String, List<String>> errorMap) {
|
||||
validationAware.setFieldErrors(errorMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getFieldErrors() {
|
||||
return validationAware.getFieldErrors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return getLocaleProvider().getLocale();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidLocaleString(String localeStr) {
|
||||
return getLocaleProvider().isValidLocaleString(localeStr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidLocale(Locale locale) {
|
||||
return getLocaleProvider().isValidLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale toLocale(String localeStr) {
|
||||
return getLocaleProvider().toLocale(localeStr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasKey(String key) {
|
||||
return getTextProvider().hasKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String aTextName) {
|
||||
return getTextProvider().getText(aTextName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String aTextName, String defaultValue) {
|
||||
return getTextProvider().getText(aTextName, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String aTextName, String defaultValue, String obj) {
|
||||
return getTextProvider().getText(aTextName, defaultValue, obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String aTextName, List<?> args) {
|
||||
return getTextProvider().getText(aTextName, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String key, String[] args) {
|
||||
return getTextProvider().getText(key, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String aTextName, String defaultValue, List<?> args) {
|
||||
return getTextProvider().getText(aTextName, defaultValue, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String key, String defaultValue, String[] args) {
|
||||
return getTextProvider().getText(key, defaultValue, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String key, String defaultValue, List<?> args, ValueStack stack) {
|
||||
return getTextProvider().getText(key, defaultValue, args, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String key, String defaultValue, String[] args, ValueStack stack) {
|
||||
return getTextProvider().getText(key, defaultValue, args, stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dedicated method to support I10N and conversion errors
|
||||
*
|
||||
* @param key message which contains formatting string
|
||||
* @param expr that should be formatted
|
||||
* @return formatted expr with format specified by key
|
||||
*/
|
||||
public String getFormatted(String key, String expr) {
|
||||
Map<String, ConversionData> conversionErrors = ActionContext.getContext().getConversionErrors();
|
||||
if (conversionErrors.containsKey(expr)) {
|
||||
String[] vals = (String[]) conversionErrors.get(expr).getValue();
|
||||
return vals[0];
|
||||
} else {
|
||||
final ValueStack valueStack = ActionContext.getContext().getValueStack();
|
||||
final Object val = valueStack.findValue(expr);
|
||||
return getText(key, Arrays.asList(val));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceBundle getTexts() {
|
||||
return getTextProvider().getTexts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceBundle getTexts(String aBundleName) {
|
||||
return getTextProvider().getTexts(aBundleName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addActionError(String anErrorMessage) {
|
||||
validationAware.addActionError(anErrorMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addActionMessage(String aMessage) {
|
||||
validationAware.addActionMessage(aMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFieldError(String fieldName, String errorMessage) {
|
||||
validationAware.addFieldError(fieldName, errorMessage);
|
||||
}
|
||||
|
||||
public String input() throws Exception {
|
||||
return INPUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* A default implementation that does nothing an returns "success".
|
||||
*
|
||||
* <p>
|
||||
* Subclasses should override this method to provide their business logic.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* See also {@link com.opensymphony.xwork2.Action#execute()}.
|
||||
* </p>
|
||||
*
|
||||
* @return returns {@link #SUCCESS}
|
||||
* @throws Exception can be thrown by subclasses.
|
||||
*/
|
||||
@Override
|
||||
public String execute() throws Exception {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasActionErrors() {
|
||||
return validationAware.hasActionErrors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasActionMessages() {
|
||||
return validationAware.hasActionMessages();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasErrors() {
|
||||
return validationAware.hasErrors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFieldErrors() {
|
||||
return validationAware.hasFieldErrors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears field errors. Useful for Continuations and other situations
|
||||
* where you might want to clear parts of the state on the same action.
|
||||
*/
|
||||
public void clearFieldErrors() {
|
||||
validationAware.clearFieldErrors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears action errors. Useful for Continuations and other situations
|
||||
* where you might want to clear parts of the state on the same action.
|
||||
*/
|
||||
public void clearActionErrors() {
|
||||
validationAware.clearActionErrors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears messages. Useful for Continuations and other situations
|
||||
* where you might want to clear parts of the state on the same action.
|
||||
*/
|
||||
public void clearMessages() {
|
||||
validationAware.clearMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all errors. Useful for Continuations and other situations
|
||||
* where you might want to clear parts of the state on the same action.
|
||||
*/
|
||||
public void clearErrors() {
|
||||
validationAware.clearErrors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all errors and messages. Useful for Continuations and other situations
|
||||
* where you might want to clear parts of the state on the same action.
|
||||
*/
|
||||
public void clearErrorsAndMessages() {
|
||||
validationAware.clearErrorsAndMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
* A default implementation that validates nothing.
|
||||
* Subclasses should override this method to provide validations.
|
||||
*/
|
||||
@Override
|
||||
public void validate() {
|
||||
// A default implementation that validates nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
return super.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: pause-method -->
|
||||
* Stops the action invocation immediately (by throwing a PauseException) and causes the action invocation to return
|
||||
* the specified result, such as {@link #SUCCESS}, {@link #INPUT}, etc.
|
||||
*
|
||||
* <p>
|
||||
* The next time this action is invoked (and using the same continuation ID), the method will resume immediately
|
||||
* after where this method was called, with the entire call stack in the execute method restored.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Note: this method can <b>only</b> be called within the {@link #execute()} method.
|
||||
* </p>
|
||||
*
|
||||
* <!-- END SNIPPET: pause-method -->
|
||||
*
|
||||
* @param result the result to return - the same type of return value in the {@link #execute()} method.
|
||||
*/
|
||||
public void pause(String result) {
|
||||
}
|
||||
|
||||
/**
|
||||
* If called first time it will create {@link com.opensymphony.xwork2.TextProviderFactory},
|
||||
* inject dependency (if {@link com.opensymphony.xwork2.inject.Container} is accesible) into in,
|
||||
* then will create new {@link com.opensymphony.xwork2.TextProvider} and store it in a field
|
||||
* for future references and at the returns reference to that field
|
||||
*
|
||||
* @return reference to field with TextProvider
|
||||
*/
|
||||
protected TextProvider getTextProvider() {
|
||||
if (textProvider == null) {
|
||||
final TextProviderFactory tpf = getContainer().getInstance(TextProviderFactory.class);
|
||||
textProvider = tpf.createInstance(getClass());
|
||||
}
|
||||
return textProvider;
|
||||
}
|
||||
|
||||
protected LocaleProvider getLocaleProvider() {
|
||||
if (localeProvider == null) {
|
||||
final LocaleProviderFactory localeProviderFactory = getContainer().getInstance(LocaleProviderFactory.class);
|
||||
localeProvider = localeProviderFactory.createLocaleProvider();
|
||||
}
|
||||
return localeProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: This a temporary solution, maybe we should consider stop injecting container into beans
|
||||
*/
|
||||
protected Container getContainer() {
|
||||
if (container == null) {
|
||||
container = ActionContext.getContext().getContainer();
|
||||
if (container != null) {
|
||||
boolean devMode = Boolean.parseBoolean(container.getInstance(String.class, StrutsConstants.STRUTS_DEVMODE));
|
||||
if (devMode) {
|
||||
LOG.warn("Container is null, action was created manually? Fallback to ActionContext");
|
||||
} else {
|
||||
LOG.debug("Container is null, action was created manually? Fallback to ActionContext");
|
||||
}
|
||||
} else {
|
||||
LOG.warn("Container is null, action was created out of ActionContext scope?!?");
|
||||
}
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setContainer(Container container) {
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public class ActionSupport extends org.apache.struts2.ActionSupport implements Action, Validateable, ValidationAware {
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import ognl.NoSuchPropertyException;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.StrutsException;
|
||||
import org.apache.struts2.result.ActionChainResult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
@@ -248,12 +249,15 @@ public class DefaultActionInvocation implements ActionInvocation {
|
||||
Interceptor interceptor = interceptorMapping.getInterceptor();
|
||||
if (interceptor instanceof WithLazyParams) {
|
||||
interceptor = lazyParamInjector.injectParams(interceptor, interceptorMapping.getParams(), invocationContext);
|
||||
} else if (interceptor instanceof Interceptor.LegacyAdapter && ((Interceptor.LegacyAdapter) interceptor).getAdaptee() instanceof WithLazyParams) {
|
||||
org.apache.struts2.interceptor.Interceptor adaptee = ((Interceptor.LegacyAdapter) interceptor).getAdaptee();
|
||||
lazyParamInjector.injectParams(adaptee, interceptorMapping.getParams(), invocationContext);
|
||||
}
|
||||
if (interceptor instanceof ConditionalInterceptor) {
|
||||
resultCode = executeConditional((ConditionalInterceptor) interceptor);
|
||||
} else {
|
||||
LOG.debug("Executing normal interceptor: {}", interceptorMapping.getName());
|
||||
resultCode = interceptor.intercept(this);
|
||||
resultCode = interceptor.intercept((org.apache.struts2.ActionInvocation) this);
|
||||
}
|
||||
} else {
|
||||
resultCode = invokeActionOnly();
|
||||
@@ -294,9 +298,9 @@ public class DefaultActionInvocation implements ActionInvocation {
|
||||
}
|
||||
|
||||
protected String executeConditional(ConditionalInterceptor conditionalInterceptor) throws Exception {
|
||||
if (conditionalInterceptor.shouldIntercept(this)) {
|
||||
if (conditionalInterceptor.shouldIntercept((org.apache.struts2.ActionInvocation) this)) {
|
||||
LOG.debug("Executing conditional interceptor: {}", conditionalInterceptor.getClass().getSimpleName());
|
||||
return conditionalInterceptor.intercept(this);
|
||||
return conditionalInterceptor.intercept((org.apache.struts2.ActionInvocation) this);
|
||||
} else {
|
||||
LOG.debug("Interceptor: {} is disabled, skipping to next", conditionalInterceptor.getClass().getSimpleName());
|
||||
return this.invoke();
|
||||
@@ -374,7 +378,7 @@ public class DefaultActionInvocation implements ActionInvocation {
|
||||
result = createResult();
|
||||
|
||||
if (result != null) {
|
||||
result.execute(this);
|
||||
result.execute((org.apache.struts2.ActionInvocation) this);
|
||||
} else if (resultCode != null && !Action.NONE.equals(resultCode)) {
|
||||
throw new ConfigurationException("No result defined for action " + getAction().getClass().getName()
|
||||
+ " and result " + getResultCode(), proxy.getConfig());
|
||||
|
||||
@@ -19,18 +19,8 @@
|
||||
package com.opensymphony.xwork2;
|
||||
|
||||
/**
|
||||
* ModelDriven Actions provide a model object to be pushed onto the ValueStack
|
||||
* in addition to the Action itself, allowing a FormBean type approach like Struts.
|
||||
*
|
||||
* @author Jason Carreira
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.ModelDriven} instead.
|
||||
*/
|
||||
public interface ModelDriven<T> {
|
||||
|
||||
/**
|
||||
* Gets the model to be pushed onto the ValueStack instead of the Action itself.
|
||||
*
|
||||
* @return the model
|
||||
*/
|
||||
T getModel();
|
||||
|
||||
@Deprecated
|
||||
public interface ModelDriven<T> extends org.apache.struts2.ModelDriven<T> {
|
||||
}
|
||||
|
||||
@@ -19,19 +19,8 @@
|
||||
package com.opensymphony.xwork2;
|
||||
|
||||
/**
|
||||
* Preparable Actions will have their <code>prepare()</code> method called if the {@link com.opensymphony.xwork2.interceptor.PrepareInterceptor}
|
||||
* is applied to the ActionConfig.
|
||||
*
|
||||
* @author Jason Carreira
|
||||
* @see com.opensymphony.xwork2.interceptor.PrepareInterceptor
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.Preparable} instead.
|
||||
*/
|
||||
public interface Preparable {
|
||||
|
||||
/**
|
||||
* This method is called to allow the action to prepare itself.
|
||||
*
|
||||
* @throws Exception thrown if a system level exception occurs.
|
||||
*/
|
||||
void prepare() throws Exception;
|
||||
|
||||
@Deprecated
|
||||
public interface Preparable extends org.apache.struts2.Preparable {
|
||||
}
|
||||
|
||||
@@ -18,33 +18,39 @@
|
||||
*/
|
||||
package com.opensymphony.xwork2;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* All results (except for <code>Action.NONE</code>) of an {@link Action} are mapped to a View implementation.
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>
|
||||
* Examples of Views might be:
|
||||
* </p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>SwingPanelView - pops up a new Swing panel</li>
|
||||
* <li>ActionChainView - executes another action</li>
|
||||
* <li>SerlvetRedirectView - redirects the HTTP response to a URL</li>
|
||||
* <li>ServletDispatcherView - dispatches the HTTP response to a URL</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author plightbo
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.result.Result} instead.
|
||||
*/
|
||||
public interface Result extends Serializable {
|
||||
@Deprecated
|
||||
public interface Result extends org.apache.struts2.result.Result {
|
||||
|
||||
@Override
|
||||
default void execute(org.apache.struts2.ActionInvocation invocation) throws Exception {
|
||||
execute(ActionInvocation.adapt(invocation));
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a generic interface for all action execution results.
|
||||
* Whether that be displaying a webpage, generating an email, sending a JMS message, etc.
|
||||
*
|
||||
* @param invocation the invocation context.
|
||||
* @throws Exception can be thrown.
|
||||
*/
|
||||
void execute(ActionInvocation invocation) throws Exception;
|
||||
|
||||
static Result adapt(org.apache.struts2.result.Result actualResult) {
|
||||
if (actualResult instanceof Result) {
|
||||
return (Result) actualResult;
|
||||
}
|
||||
return actualResult != null ? new LegacyAdapter(actualResult) : null;
|
||||
}
|
||||
|
||||
class LegacyAdapter implements Result {
|
||||
|
||||
private final org.apache.struts2.result.Result adaptee;
|
||||
|
||||
private LegacyAdapter(org.apache.struts2.result.Result adaptee) {
|
||||
this.adaptee = adaptee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ActionInvocation invocation) throws Exception {
|
||||
adaptee.execute(ActionInvocation.adapt(invocation));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,9 +19,8 @@
|
||||
package com.opensymphony.xwork2;
|
||||
|
||||
/**
|
||||
* Simple marker interface to indicate an object should <b>not</b> have its properties copied during chaining.
|
||||
*
|
||||
* @see com.opensymphony.xwork2.interceptor.ChainingInterceptor
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.Unchainable} instead.
|
||||
*/
|
||||
public interface Unchainable {
|
||||
@Deprecated
|
||||
public interface Unchainable extends org.apache.struts2.Unchainable {
|
||||
}
|
||||
|
||||
@@ -19,17 +19,8 @@
|
||||
package com.opensymphony.xwork2;
|
||||
|
||||
/**
|
||||
* Provides an interface in which a call for a validation check can be done.
|
||||
*
|
||||
* @author Jason Carreira
|
||||
* @see ActionSupport
|
||||
* @see com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.Validateable} instead.
|
||||
*/
|
||||
public interface Validateable {
|
||||
|
||||
/**
|
||||
* Performs validation.
|
||||
*/
|
||||
void validate();
|
||||
|
||||
@Deprecated
|
||||
public interface Validateable extends org.apache.struts2.Validateable {
|
||||
}
|
||||
|
||||
@@ -36,8 +36,16 @@ public class InterceptorMapping implements Serializable {
|
||||
private Interceptor interceptor;
|
||||
private final Map<String, String> params;
|
||||
|
||||
public InterceptorMapping(String name, org.apache.struts2.interceptor.Interceptor interceptor) {
|
||||
this(name, Interceptor.adapt(interceptor));
|
||||
}
|
||||
|
||||
public InterceptorMapping(String name, org.apache.struts2.interceptor.Interceptor interceptor, Map<String, String> params) {
|
||||
this(name, Interceptor.adapt(interceptor), params);
|
||||
}
|
||||
|
||||
public InterceptorMapping(String name, Interceptor interceptor) {
|
||||
this(name, interceptor, new HashMap<String, String>());
|
||||
this(name, interceptor, new HashMap<>());
|
||||
}
|
||||
|
||||
public InterceptorMapping(String name, Interceptor interceptor, Map<String, String> params) {
|
||||
|
||||
@@ -38,7 +38,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class ResultConfig extends Located implements Serializable {
|
||||
|
||||
protected Map<String,String> params;
|
||||
protected Map<String, String> params;
|
||||
protected String className;
|
||||
protected String name;
|
||||
|
||||
@@ -63,7 +63,7 @@ public class ResultConfig extends Located implements Serializable {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Map<String,String> getParams() {
|
||||
public Map<String, String> getParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ public class ResultConfig extends Located implements Serializable {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addParams(Map<String,String> params) {
|
||||
public Builder addParams(Map<String, String> params) {
|
||||
target.params.putAll(params);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,6 @@ import com.opensymphony.xwork2.factory.ActionFactory;
|
||||
import com.opensymphony.xwork2.factory.ConverterFactory;
|
||||
import com.opensymphony.xwork2.factory.DefaultActionFactory;
|
||||
import com.opensymphony.xwork2.factory.DefaultInterceptorFactory;
|
||||
import com.opensymphony.xwork2.factory.DefaultResultFactory;
|
||||
import com.opensymphony.xwork2.factory.DefaultUnknownHandlerFactory;
|
||||
import com.opensymphony.xwork2.factory.DefaultValidatorFactory;
|
||||
import com.opensymphony.xwork2.factory.InterceptorFactory;
|
||||
@@ -109,6 +108,7 @@ import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.conversion.StrutsConversionPropertiesProcessor;
|
||||
import org.apache.struts2.conversion.StrutsTypeConverterCreator;
|
||||
import org.apache.struts2.conversion.StrutsTypeConverterHolder;
|
||||
import org.apache.struts2.factory.StrutsResultFactory;
|
||||
import org.apache.struts2.ognl.OgnlGuard;
|
||||
import org.apache.struts2.ognl.ProviderAllowlist;
|
||||
import org.apache.struts2.ognl.StrutsOgnlGuard;
|
||||
@@ -363,7 +363,7 @@ public class DefaultConfiguration implements Configuration {
|
||||
// TODO: SpringObjectFactoryTest fails when these are SINGLETON
|
||||
.factory(ObjectFactory.class, Scope.PROTOTYPE)
|
||||
.factory(ActionFactory.class, DefaultActionFactory.class, Scope.PROTOTYPE)
|
||||
.factory(ResultFactory.class, DefaultResultFactory.class, Scope.PROTOTYPE)
|
||||
.factory(ResultFactory.class, StrutsResultFactory.class, Scope.PROTOTYPE)
|
||||
.factory(InterceptorFactory.class, DefaultInterceptorFactory.class, Scope.PROTOTYPE)
|
||||
.factory(ValidatorFactory.class, DefaultValidatorFactory.class, Scope.PROTOTYPE)
|
||||
.factory(ConverterFactory.class, StrutsConverterFactory.class, Scope.PROTOTYPE)
|
||||
|
||||
@@ -70,13 +70,18 @@ public class DefaultInterceptorFactory implements InterceptorFactory {
|
||||
reflectionProvider.setProperties(params, o);
|
||||
}
|
||||
|
||||
Interceptor interceptor = null;
|
||||
if (o instanceof Interceptor) {
|
||||
Interceptor interceptor = (Interceptor) o;
|
||||
interceptor.init();
|
||||
return interceptor;
|
||||
interceptor = (Interceptor) o;
|
||||
} else if (o instanceof org.apache.struts2.interceptor.Interceptor) {
|
||||
interceptor = Interceptor.adapt((org.apache.struts2.interceptor.Interceptor) o);
|
||||
}
|
||||
|
||||
throw new ConfigurationException("Class [" + interceptorClassName + "] does not implement Interceptor", interceptorConfig);
|
||||
if (interceptor == null) {
|
||||
throw new ConfigurationException("Class [" + interceptorClassName + "] does not implement Interceptor", interceptorConfig);
|
||||
}
|
||||
interceptor.init();
|
||||
return interceptor;
|
||||
} catch (InstantiationException e) {
|
||||
cause = e;
|
||||
message = "Unable to instantiate an instance of Interceptor class [" + interceptorClassName + "].";
|
||||
|
||||
@@ -20,17 +20,22 @@ package com.opensymphony.xwork2.factory;
|
||||
|
||||
import com.opensymphony.xwork2.ObjectFactory;
|
||||
import com.opensymphony.xwork2.Result;
|
||||
import com.opensymphony.xwork2.config.ConfigurationException;
|
||||
import com.opensymphony.xwork2.config.entities.ResultConfig;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.reflection.ReflectionException;
|
||||
import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler;
|
||||
import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
|
||||
import org.apache.struts2.factory.StrutsResultFactory;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Default implementation
|
||||
*
|
||||
* @deprecated since 6.7.0, use {@link StrutsResultFactory} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class DefaultResultFactory implements ResultFactory {
|
||||
|
||||
private ObjectFactory objectFactory;
|
||||
@@ -51,19 +56,29 @@ public class DefaultResultFactory implements ResultFactory {
|
||||
Result result = null;
|
||||
|
||||
if (resultClassName != null) {
|
||||
result = (Result) objectFactory.buildBean(resultClassName, extraContext);
|
||||
Object o = objectFactory.buildBean(resultClassName, extraContext);
|
||||
|
||||
Map<String, String> params = resultConfig.getParams();
|
||||
if (params != null) {
|
||||
for (Map.Entry<String, String> paramEntry : params.entrySet()) {
|
||||
try {
|
||||
reflectionProvider.setProperty(paramEntry.getKey(), paramEntry.getValue(), result, extraContext, true);
|
||||
reflectionProvider.setProperty(paramEntry.getKey(), paramEntry.getValue(), o, extraContext, true);
|
||||
} catch (ReflectionException ex) {
|
||||
if (result instanceof ReflectionExceptionHandler) {
|
||||
((ReflectionExceptionHandler) result).handle(ex);
|
||||
if (o instanceof ReflectionExceptionHandler) {
|
||||
((ReflectionExceptionHandler) o).handle(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (o instanceof Result) {
|
||||
result = (Result) o;
|
||||
} else if (o instanceof org.apache.struts2.result.Result) {
|
||||
result = Result.adapt((org.apache.struts2.result.Result) o);
|
||||
}
|
||||
if (result == null) {
|
||||
throw new ConfigurationException("Class [" + resultClassName + "] does not implement Result", resultConfig);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -242,6 +242,41 @@ class ContainerImpl implements Container {
|
||||
return toArray(parameterInjectors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets parameter injectors with nulls for optional dependencies.
|
||||
*
|
||||
* @param member to which the parameters belong
|
||||
* @param annotations on the parameters
|
||||
* @param parameterTypes parameter types
|
||||
* @return injections
|
||||
*/
|
||||
<M extends AccessibleObject & Member> ParameterInjector<?>[] getParametersInjectorsWithNulls(
|
||||
M member,
|
||||
Annotation[][] annotations,
|
||||
Class<?>[] parameterTypes,
|
||||
String defaultName
|
||||
) throws MissingDependencyException {
|
||||
final List<ParameterInjector<?>> parameterInjectors = new ArrayList<>();
|
||||
|
||||
final Iterator<Annotation[]> annotationsIterator = Arrays.asList(annotations).iterator();
|
||||
for (Class<?> parameterType : parameterTypes) {
|
||||
Inject annotation = findInject(annotationsIterator.next());
|
||||
String name = annotation == null ? defaultName : annotation.value();
|
||||
Key<?> key = Key.newInstance(parameterType, name);
|
||||
try {
|
||||
parameterInjectors.add(createParameterInjector(key, member));
|
||||
} catch (MissingDependencyException e) {
|
||||
if (annotation != null && annotation.required()) {
|
||||
throw e;
|
||||
} else {
|
||||
parameterInjectors.add(createNullParameterInjector(key, member));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return toArray(parameterInjectors);
|
||||
}
|
||||
|
||||
<T> ParameterInjector<T> createParameterInjector(Key<T> key, Member member) throws MissingDependencyException {
|
||||
final InternalFactory<? extends T> factory = getFactory(key);
|
||||
if (factory == null) {
|
||||
@@ -252,6 +287,23 @@ class ContainerImpl implements Container {
|
||||
return new ParameterInjector<>(externalContext, factory);
|
||||
}
|
||||
|
||||
<T> ParameterInjector<T> createNullParameterInjector(Key<T> key, Member member) throws MissingDependencyException {
|
||||
final InternalFactory<? extends T> factory = new InternalFactory<T>() {
|
||||
@Override
|
||||
public T create(InternalContext context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> type() {
|
||||
return key.getType();
|
||||
}
|
||||
};
|
||||
|
||||
final ExternalContext<T> externalContext = ExternalContext.newInstance(member, key, this);
|
||||
return new ParameterInjector<>(externalContext, factory);
|
||||
}
|
||||
|
||||
private ParameterInjector<?>[] toArray(List<ParameterInjector<?>> parameterInjections) {
|
||||
return parameterInjections.toArray(new ParameterInjector[0]);
|
||||
}
|
||||
@@ -361,7 +413,7 @@ class ContainerImpl implements Container {
|
||||
Inject inject, ContainerImpl container, Constructor<T> constructor) throws MissingDependencyException {
|
||||
return constructor.getParameterTypes().length == 0
|
||||
? null // default constructor.
|
||||
: container.getParametersInjectors(
|
||||
: container.getParametersInjectorsWithNulls(
|
||||
constructor,
|
||||
constructor.getParameterAnnotations(),
|
||||
constructor.getParameterTypes(),
|
||||
|
||||
@@ -21,41 +21,28 @@ package com.opensymphony.xwork2.interceptor;
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
|
||||
/**
|
||||
* Provides default implementations of optional lifecycle methods
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.AbstractInterceptor} instead.
|
||||
*/
|
||||
public abstract class AbstractInterceptor implements ConditionalInterceptor {
|
||||
|
||||
private boolean disabled;
|
||||
|
||||
/**
|
||||
* Does nothing
|
||||
*/
|
||||
public void init() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Does nothing
|
||||
*/
|
||||
public void destroy() {
|
||||
}
|
||||
@Deprecated
|
||||
public abstract class AbstractInterceptor extends org.apache.struts2.interceptor.AbstractInterceptor implements ConditionalInterceptor {
|
||||
|
||||
/**
|
||||
* Override to handle interception
|
||||
*/
|
||||
public abstract String intercept(ActionInvocation invocation) throws Exception;
|
||||
|
||||
/**
|
||||
* Allows to skip executing a given interceptor, just define {@code <param name="disabled">true</param>}
|
||||
* or use other way to override interceptor's parameters, see
|
||||
* <a href="https://struts.apache.org/core-developers/interceptors#interceptor-parameter-overriding">docs</a>.
|
||||
* @param disable if set to true, execution of a given interceptor will be skipped.
|
||||
*/
|
||||
public void setDisabled(String disable) {
|
||||
this.disabled = Boolean.parseBoolean(disable);
|
||||
@Override
|
||||
public String intercept(org.apache.struts2.ActionInvocation invocation) throws Exception {
|
||||
return intercept(ActionInvocation.adapt(invocation));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIntercept(ActionInvocation invocation) {
|
||||
return !this.disabled;
|
||||
return super.shouldIntercept(invocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIntercept(org.apache.struts2.ActionInvocation invocation) {
|
||||
return shouldIntercept(ActionInvocation.adapt(invocation));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,21 +20,22 @@ package com.opensymphony.xwork2.interceptor;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.LocalizedTextProvider;
|
||||
import com.opensymphony.xwork2.config.entities.ActionConfig;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.security.AcceptedPatternsChecker;
|
||||
import com.opensymphony.xwork2.security.ExcludedPatternsChecker;
|
||||
import com.opensymphony.xwork2.util.ClearableValueStack;
|
||||
import com.opensymphony.xwork2.util.Evaluated;
|
||||
import com.opensymphony.xwork2.LocalizedTextProvider;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import com.opensymphony.xwork2.util.ValueStackFactory;
|
||||
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.dispatcher.HttpParameters;
|
||||
import org.apache.struts2.dispatcher.Parameter;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.interceptor.ValidationAware;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -90,7 +91,10 @@ import java.util.Map;
|
||||
* </pre>
|
||||
*
|
||||
* @author Matthew Payne
|
||||
*
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.AliasInterceptor} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class AliasInterceptor extends AbstractInterceptor {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(AliasInterceptor.class);
|
||||
@@ -108,7 +112,7 @@ public class AliasInterceptor extends AbstractInterceptor {
|
||||
@Inject(StrutsConstants.STRUTS_DEVMODE)
|
||||
public void setDevMode(String mode) {
|
||||
this.devMode = Boolean.parseBoolean(mode);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setValueStackFactory(ValueStackFactory valueStackFactory) {
|
||||
@@ -225,7 +229,7 @@ public class AliasInterceptor extends AbstractInterceptor {
|
||||
LOG.debug("invalid alias expression: {}", aliasesKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return invocation.invoke();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,21 +18,26 @@
|
||||
*/
|
||||
package com.opensymphony.xwork2.interceptor;
|
||||
|
||||
import com.opensymphony.xwork2.ActionChainResult;
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.Result;
|
||||
import com.opensymphony.xwork2.Unchainable;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.ProxyUtil;
|
||||
import com.opensymphony.xwork2.util.CompoundRoot;
|
||||
import com.opensymphony.xwork2.util.ProxyUtil;
|
||||
import com.opensymphony.xwork2.util.TextParseUtil;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import com.opensymphony.xwork2.util.reflection.ReflectionProvider;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.Unchainable;
|
||||
import org.apache.struts2.result.ActionChainResult;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
@@ -112,8 +117,11 @@ import java.util.*;
|
||||
*
|
||||
* @author mrdon
|
||||
* @author tm_jee ( tm_jee(at)yahoo.co.uk )
|
||||
* @see com.opensymphony.xwork2.ActionChainResult
|
||||
* @see ActionChainResult
|
||||
*
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ChainingInterceptor} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ChainingInterceptor extends AbstractInterceptor {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(ChainingInterceptor.class);
|
||||
|
||||
+31
-11
@@ -21,19 +21,39 @@ package com.opensymphony.xwork2.interceptor;
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
|
||||
/**
|
||||
* A marking interface, when implemented allows to conditionally execute a given interceptor
|
||||
* within the current action invocation.
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @since Struts 6.1.1
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.Interceptor} instead.
|
||||
*/
|
||||
public interface ConditionalInterceptor extends Interceptor {
|
||||
@Deprecated
|
||||
public interface ConditionalInterceptor extends org.apache.struts2.interceptor.ConditionalInterceptor, Interceptor {
|
||||
|
||||
@Override
|
||||
default boolean shouldIntercept(org.apache.struts2.ActionInvocation invocation) {
|
||||
return shouldIntercept(ActionInvocation.adapt(invocation));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a given interceptor should be executed in the current processing of action invocation.
|
||||
*
|
||||
* @param invocation current {@link ActionInvocation} to determine if the interceptor should be executed
|
||||
* @return true if the given interceptor should be included in the current action invocation
|
||||
* @since 6.1.1
|
||||
*/
|
||||
boolean shouldIntercept(ActionInvocation invocation);
|
||||
|
||||
static ConditionalInterceptor adapt(org.apache.struts2.interceptor.ConditionalInterceptor actualInterceptor) {
|
||||
if (actualInterceptor instanceof ConditionalInterceptor) {
|
||||
return (ConditionalInterceptor) actualInterceptor;
|
||||
}
|
||||
return actualInterceptor != null ? new LegacyAdapter(actualInterceptor) : null;
|
||||
}
|
||||
|
||||
class LegacyAdapter extends Interceptor.LegacyAdapter implements ConditionalInterceptor {
|
||||
|
||||
private final org.apache.struts2.interceptor.ConditionalInterceptor adaptee;
|
||||
|
||||
private LegacyAdapter(org.apache.struts2.interceptor.ConditionalInterceptor adaptee) {
|
||||
super(adaptee);
|
||||
this.adaptee = adaptee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldIntercept(ActionInvocation invocation) {
|
||||
return adaptee.shouldIntercept(invocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-2
@@ -24,6 +24,7 @@ import com.opensymphony.xwork2.conversion.impl.ConversionData;
|
||||
import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
import org.apache.struts2.interceptor.ValidationAware;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -41,13 +42,13 @@ import java.util.Map;
|
||||
* display the original string ("abc") again rather than the int value (likely 0, which would make very little sense to
|
||||
* the user).
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* <b>Note:</b> Since 2.5.2, this interceptor extends {@link MethodFilterInterceptor}, therefore being
|
||||
* able to deal with excludeMethods / includeMethods parameters. See [Workflow Interceptor]
|
||||
* (class {@link DefaultWorkflowInterceptor}) for documentation and examples on how to use this feature.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <!-- END SNIPPET: description -->
|
||||
*
|
||||
* <p><u>Interceptor parameters:</u></p>
|
||||
@@ -84,7 +85,10 @@ import java.util.Map;
|
||||
* </pre>
|
||||
*
|
||||
* @author Jason Carreira
|
||||
*
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ConversionErrorInterceptor} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ConversionErrorInterceptor extends MethodFilterInterceptor {
|
||||
|
||||
public static final String ORIGINAL_PROPERTY_OVERRIDE = "original.property.override";
|
||||
|
||||
+7
-1
@@ -25,11 +25,14 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.reflect.MethodUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.interceptor.ValidationAware;
|
||||
import org.apache.struts2.interceptor.ValidationErrorAware;
|
||||
import org.apache.struts2.interceptor.ValidationWorkflowAware;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: description -->
|
||||
* <p>
|
||||
* An interceptor that makes sure there are not validation, conversion or action errors before allowing the interceptor chain to continue.
|
||||
* An interceptor that makes sure there are not validation, conversion or action errors before allowing the interceptor chain to continue.
|
||||
* If a single FieldError or ActionError (including the ones replicated by the Message Store Interceptor in a redirection) is found, the INPUT result will be triggered.
|
||||
* <b>This interceptor does not perform any validation</b>.
|
||||
* </p>
|
||||
@@ -129,7 +132,10 @@ import org.apache.logging.log4j.Logger;
|
||||
* @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
|
||||
* @author Philip Luppens
|
||||
* @author tm_jee
|
||||
*
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.DefaultWorkflowInterceptor} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class DefaultWorkflowInterceptor extends MethodFilterInterceptor {
|
||||
|
||||
private static final long serialVersionUID = 7563014655616490865L;
|
||||
|
||||
+4
-1
@@ -20,8 +20,8 @@ package com.opensymphony.xwork2.interceptor;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.dispatcher.HttpParameters;
|
||||
|
||||
import java.util.List;
|
||||
@@ -153,7 +153,10 @@ import java.util.Map;
|
||||
*
|
||||
* @author Matthew E. Porter (matthew dot porter at metissian dot com)
|
||||
* @author Claus Ibsen
|
||||
*
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ExceptionMappingInterceptor} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ExceptionMappingInterceptor extends AbstractInterceptor {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(ExceptionMappingInterceptor.class);
|
||||
|
||||
@@ -20,203 +20,56 @@ package com.opensymphony.xwork2.interceptor;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: introduction -->
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>
|
||||
* An interceptor is a stateless class that follows the interceptor pattern, as
|
||||
* found in {@link javax.servlet.Filter} and in AOP languages.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Interceptors are objects that dynamically intercept Action invocations.
|
||||
* They provide the developer with the opportunity to define code that can be executed
|
||||
* before and/or after the execution of an action. They also have the ability
|
||||
* to prevent an action from executing. Interceptors provide developers a way to
|
||||
* encapsulate common functionality in a re-usable form that can be applied to
|
||||
* one or more Actions.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Interceptors <b>must</b> be stateless and not assume that a new instance will be created for each request or Action.
|
||||
* Interceptors may choose to either short-circuit the {@link ActionInvocation} execution and return a return code
|
||||
* (such as {@link com.opensymphony.xwork2.Action#SUCCESS}), or it may choose to do some processing before
|
||||
* and/or after delegating the rest of the procesing using {@link ActionInvocation#invoke()}.
|
||||
* </p>
|
||||
* <!-- END SNIPPET: introduction -->
|
||||
*
|
||||
* <!-- START SNIPPET: parameterOverriding -->
|
||||
* <p>
|
||||
* Interceptor's parameter could be overridden through the following ways :-
|
||||
* </p>
|
||||
|
||||
* <b>Method 1:</b>
|
||||
* <pre>
|
||||
* <action name="myAction" class="myActionClass">
|
||||
* <interceptor-ref name="exception"/>
|
||||
* <interceptor-ref name="alias"/>
|
||||
* <interceptor-ref name="params"/>
|
||||
* <interceptor-ref name="servletConfig"/>
|
||||
* <interceptor-ref name="prepare"/>
|
||||
* <interceptor-ref name="i18n"/>
|
||||
* <interceptor-ref name="chain"/>
|
||||
* <interceptor-ref name="modelDriven"/>
|
||||
* <interceptor-ref name="fileUpload"/>
|
||||
* <interceptor-ref name="staticParams"/>
|
||||
* <interceptor-ref name="params"/>
|
||||
* <interceptor-ref name="conversionError"/>
|
||||
* <interceptor-ref name="validation">
|
||||
* <param name="excludeMethods">myValidationExcudeMethod</param>
|
||||
* </interceptor-ref>
|
||||
* <interceptor-ref name="workflow">
|
||||
* <param name="excludeMethods">myWorkflowExcludeMethod</param>
|
||||
* </interceptor-ref>
|
||||
* </action>
|
||||
* </pre>
|
||||
*
|
||||
* <b>Method 2:</b>
|
||||
* <pre>
|
||||
* <action name="myAction" class="myActionClass">
|
||||
* <interceptor-ref name="defaultStack">
|
||||
* <param name="validation.excludeMethods">myValidationExcludeMethod</param>
|
||||
* <param name="workflow.excludeMethods">myWorkflowExcludeMethod</param>
|
||||
* </interceptor-ref>
|
||||
* </action>
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* In the first method, the whole default stack is copied and the parameter then
|
||||
* changed accordingly.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* In the second method, the 'interceptor-ref' refer to an existing
|
||||
* interceptor-stack, namely defaultStack in this example, and override the validator
|
||||
* and workflow interceptor excludeMethods typically in this case. Note that in the
|
||||
* 'param' tag, the name attribute contains a dot (.) the word before the dot(.)
|
||||
* specifies the interceptor name whose parameter is to be overridden and the word after
|
||||
* the dot (.) specifies the parameter itself. Essetially it is as follows :-
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* <interceptor-name>.<parameter-name>
|
||||
* </pre>
|
||||
* <p>
|
||||
* <b>Note</b> also that in this case the 'interceptor-ref' name attribute
|
||||
* is used to indicate an interceptor stack which makes sense as if it is referring
|
||||
* to the interceptor itself it would be just using Method 1 describe above.
|
||||
* </p>
|
||||
* <!-- END SNIPPET: parameterOverriding -->
|
||||
*
|
||||
* <p>
|
||||
* <b>Nested Interceptor param overriding</b>
|
||||
* </p>
|
||||
*
|
||||
* <!-- START SNIPPET: nestedParameterOverriding -->
|
||||
* <p>
|
||||
* Interceptor stack parameter overriding could be nested into as many level as possible, though it would
|
||||
* be advisable not to nest it too deep as to avoid confusion, For example,
|
||||
* </p>
|
||||
* <pre>
|
||||
* <interceptor name="interceptor1" class="foo.bar.Interceptor1" />
|
||||
* <interceptor name="interceptor2" class="foo.bar.Interceptor2" />
|
||||
* <interceptor name="interceptor3" class="foo.bar.Interceptor3" />
|
||||
* <interceptor name="interceptor4" class="foo.bar.Interceptor4" />
|
||||
* <interceptor-stack name="stack1">
|
||||
* <interceptor-ref name="interceptor1" />
|
||||
* </interceptor-stack>
|
||||
* <interceptor-stack name="stack2">
|
||||
* <interceptor-ref name="intercetor2" />
|
||||
* <interceptor-ref name="stack1" />
|
||||
* </interceptor-stack>
|
||||
* <interceptor-stack name="stack3">
|
||||
* <interceptor-ref name="interceptor3" />
|
||||
* <interceptor-ref name="stack2" />
|
||||
* </interceptor-stack>
|
||||
* <interceptor-stack name="stack4">
|
||||
* <interceptor-ref name="interceptor4" />
|
||||
* <interceptor-ref name="stack3" />
|
||||
* </interceptor-stack>
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* Assuming the interceptor has the following properties
|
||||
* </p>
|
||||
*
|
||||
* <table border="1" summary="">
|
||||
* <tr>
|
||||
* <td>Interceptor</td>
|
||||
* <td>property</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>Interceptor1</td>
|
||||
* <td>param1</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>Interceptor2</td>
|
||||
* <td>param2</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>Interceptor3</td>
|
||||
* <td>param3</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>Interceptor4</td>
|
||||
* <td>param4</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <p>
|
||||
* We could override them as follows :
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* <action ... >
|
||||
* <!-- to override parameters of interceptor located directly in the stack -->
|
||||
* <interceptor-ref name="stack4">
|
||||
* <param name="interceptor4.param4"> ... </param>
|
||||
* </interceptor-ref>
|
||||
* </action>
|
||||
*
|
||||
* <action ... >
|
||||
* <!-- to override parameters of interceptor located under nested stack -->
|
||||
* <interceptor-ref name="stack4">
|
||||
* <param name="stack3.interceptor3.param3"> ... </param>
|
||||
* <param name="stack3.stack2.interceptor2.param2"> ... </param>
|
||||
* <param name="stack3.stack2.stack1.interceptor1.param1"> ... </param>
|
||||
* </interceptor-ref>
|
||||
* </action>
|
||||
* </pre>
|
||||
*
|
||||
* <!-- END SNIPPET: nestedParameterOverriding -->
|
||||
*
|
||||
* @author Jason Carreira
|
||||
* @author tmjee
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.Interceptor} instead.
|
||||
*/
|
||||
public interface Interceptor extends Serializable {
|
||||
@Deprecated
|
||||
public interface Interceptor extends org.apache.struts2.interceptor.Interceptor {
|
||||
|
||||
/**
|
||||
* Called to let an interceptor clean up any resources it has allocated.
|
||||
*/
|
||||
void destroy();
|
||||
@Override
|
||||
default String intercept(org.apache.struts2.ActionInvocation invocation) throws Exception {
|
||||
return intercept(ActionInvocation.adapt(invocation));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after an interceptor is created, but before any requests are processed using
|
||||
* {@link #intercept(com.opensymphony.xwork2.ActionInvocation) intercept} , giving
|
||||
* the Interceptor a chance to initialize any needed resources.
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Allows the Interceptor to do some processing on the request before and/or after the rest of the processing of the
|
||||
* request by the {@link ActionInvocation} or to short-circuit the processing and just return a String return code.
|
||||
*
|
||||
* @param invocation the action invocation
|
||||
* @return the return code, either returned from {@link ActionInvocation#invoke()}, or from the interceptor itself.
|
||||
* @throws Exception any system-level error, as defined in {@link com.opensymphony.xwork2.Action#execute()}.
|
||||
*/
|
||||
String intercept(ActionInvocation invocation) throws Exception;
|
||||
|
||||
static Interceptor adapt(org.apache.struts2.interceptor.Interceptor actualInterceptor) {
|
||||
if (actualInterceptor instanceof org.apache.struts2.interceptor.ConditionalInterceptor) {
|
||||
return ConditionalInterceptor.adapt((org.apache.struts2.interceptor.ConditionalInterceptor) actualInterceptor);
|
||||
}
|
||||
if (actualInterceptor instanceof Interceptor) {
|
||||
return (Interceptor) actualInterceptor;
|
||||
}
|
||||
return actualInterceptor != null ? new LegacyAdapter(actualInterceptor) : null;
|
||||
}
|
||||
|
||||
class LegacyAdapter implements Interceptor {
|
||||
|
||||
private final org.apache.struts2.interceptor.Interceptor adaptee;
|
||||
|
||||
protected LegacyAdapter(org.apache.struts2.interceptor.Interceptor adaptee) {
|
||||
this.adaptee = adaptee;
|
||||
}
|
||||
|
||||
public org.apache.struts2.interceptor.Interceptor getAdaptee() {
|
||||
return adaptee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String intercept(ActionInvocation invocation) throws Exception {
|
||||
return adaptee.intercept(invocation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
adaptee.destroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
adaptee.init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,10 @@ import org.apache.logging.log4j.Logger;
|
||||
* </pre>
|
||||
*
|
||||
* @author Jason Carreira
|
||||
*
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.LoggingInterceptor} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class LoggingInterceptor extends AbstractInterceptor {
|
||||
private static final Logger LOG = LogManager.getLogger(LoggingInterceptor.class);
|
||||
private static final String FINISH_MESSAGE = "Finishing execution stack for action ";
|
||||
|
||||
+24
-21
@@ -31,56 +31,59 @@ import java.util.Set;
|
||||
*
|
||||
* <p>
|
||||
* MethodFilterInterceptor is an abstract <code>Interceptor</code> used as
|
||||
* a base class for interceptors that will filter execution based on method
|
||||
* a base class for interceptors that will filter execution based on method
|
||||
* names according to specified included/excluded method lists.
|
||||
*
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* Settable parameters are as follows:
|
||||
*
|
||||
*
|
||||
* <ul>
|
||||
* <li>excludeMethods - method names to be excluded from interceptor processing</li>
|
||||
* <li>includeMethods - method names to be included in interceptor processing</li>
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* <b>NOTE:</b> If method name are available in both includeMethods and
|
||||
* excludeMethods, it will be considered as an included method:
|
||||
*
|
||||
* <b>NOTE:</b> If method name are available in both includeMethods and
|
||||
* excludeMethods, it will be considered as an included method:
|
||||
* includeMethods takes precedence over excludeMethods.
|
||||
*
|
||||
*
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* Interceptors that extends this capability include:
|
||||
*
|
||||
*
|
||||
* <ul>
|
||||
* <li>TokenInterceptor</li>
|
||||
* <li>TokenSessionStoreInterceptor</li>
|
||||
* <li>DefaultWorkflowInterceptor</li>
|
||||
* <li>ValidationInterceptor</li>
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*
|
||||
*
|
||||
* @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
|
||||
* @author Rainer Hermanns
|
||||
*
|
||||
*
|
||||
* @see org.apache.struts2.interceptor.TokenInterceptor
|
||||
* @see org.apache.struts2.interceptor.TokenSessionStoreInterceptor
|
||||
* @see com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor
|
||||
* @see com.opensymphony.xwork2.validator.ValidationInterceptor
|
||||
*
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.MethodFilterInterceptor} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class MethodFilterInterceptor extends AbstractInterceptor {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(MethodFilterInterceptor.class);
|
||||
|
||||
|
||||
protected Set<String> excludeMethods = Collections.emptySet();
|
||||
protected Set<String> includeMethods = Collections.emptySet();
|
||||
|
||||
public void setExcludeMethods(String excludeMethods) {
|
||||
this.excludeMethods = TextParseUtil.commaDelimitedStringToSet(excludeMethods);
|
||||
}
|
||||
|
||||
|
||||
public Set<String> getExcludeMethodsSet() {
|
||||
return excludeMethods;
|
||||
}
|
||||
@@ -88,7 +91,7 @@ public abstract class MethodFilterInterceptor extends AbstractInterceptor {
|
||||
public void setIncludeMethods(String includeMethods) {
|
||||
this.includeMethods = TextParseUtil.commaDelimitedStringToSet(includeMethods);
|
||||
}
|
||||
|
||||
|
||||
public Set<String> getIncludeMethodsSet() {
|
||||
return includeMethods;
|
||||
}
|
||||
@@ -97,7 +100,7 @@ public abstract class MethodFilterInterceptor extends AbstractInterceptor {
|
||||
public String intercept(ActionInvocation invocation) throws Exception {
|
||||
if (applyInterceptor(invocation)) {
|
||||
return doIntercept(invocation);
|
||||
}
|
||||
}
|
||||
return invocation.invoke();
|
||||
}
|
||||
|
||||
@@ -110,14 +113,14 @@ public abstract class MethodFilterInterceptor extends AbstractInterceptor {
|
||||
}
|
||||
return applyMethod;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Subclasses must override to implement the interceptor logic.
|
||||
*
|
||||
*
|
||||
* @param invocation the action invocation
|
||||
* @return the result of invocation
|
||||
* @throws Exception in case of any errors
|
||||
*/
|
||||
protected abstract String doIntercept(ActionInvocation invocation) throws Exception;
|
||||
|
||||
|
||||
}
|
||||
|
||||
+3
-125
@@ -18,131 +18,9 @@
|
||||
*/
|
||||
package com.opensymphony.xwork2.interceptor;
|
||||
|
||||
import com.opensymphony.xwork2.util.TextParseUtil;
|
||||
import com.opensymphony.xwork2.util.WildcardHelper;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Utility class contains common methods used by
|
||||
* {@link com.opensymphony.xwork2.interceptor.MethodFilterInterceptor}.
|
||||
*
|
||||
* @author tm_jee
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.MethodFilterInterceptorUtil} instead.
|
||||
*/
|
||||
public class MethodFilterInterceptorUtil {
|
||||
|
||||
/**
|
||||
* Static method to decide if the specified <code>method</code> should be
|
||||
* apply (not filtered) depending on the set of <code>excludeMethods</code> and
|
||||
* <code>includeMethods</code>.
|
||||
*
|
||||
* <ul>
|
||||
* <li>
|
||||
* <code>includeMethods</code> takes precedence over <code>excludeMethods</code>
|
||||
* </li>
|
||||
* </ul>
|
||||
* <b>Note:</b> Supports wildcard listings in includeMethods/excludeMethods
|
||||
*
|
||||
* @param excludeMethods list of methods to exclude.
|
||||
* @param includeMethods list of methods to include.
|
||||
* @param method the specified method to check
|
||||
* @return <tt>true</tt> if the method should be applied.
|
||||
*/
|
||||
public static boolean applyMethod(Set<String> excludeMethods, Set<String> includeMethods, String method) {
|
||||
|
||||
// quick check to see if any actual pattern matching is needed
|
||||
boolean needsPatternMatch = false;
|
||||
for (String includeMethod : includeMethods) {
|
||||
if (!"*".equals(includeMethod) && includeMethod.contains("*")) {
|
||||
needsPatternMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (String excludeMethod : excludeMethods) {
|
||||
if (!"*".equals(excludeMethod) && excludeMethod.contains("*")) {
|
||||
needsPatternMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// this section will try to honor the original logic, while
|
||||
// still allowing for wildcards later
|
||||
if (!needsPatternMatch && (includeMethods.contains("*") || includeMethods.size() == 0) ) {
|
||||
if (excludeMethods != null
|
||||
&& excludeMethods.contains(method)
|
||||
&& !includeMethods.contains(method) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// test the methods using pattern matching
|
||||
WildcardHelper wildcard = new WildcardHelper();
|
||||
String methodCopy ;
|
||||
if (method == null ) { // no method specified
|
||||
methodCopy = "";
|
||||
}
|
||||
else {
|
||||
methodCopy = new String(method);
|
||||
}
|
||||
for (String pattern : includeMethods) {
|
||||
if (pattern.contains("*")) {
|
||||
int[] compiledPattern = wildcard.compilePattern(pattern);
|
||||
HashMap<String, String> matchedPatterns = new HashMap<>();
|
||||
boolean matches = wildcard.match(matchedPatterns, methodCopy, compiledPattern);
|
||||
if (matches) {
|
||||
return true; // run it, includeMethods takes precedence
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (pattern.equals(methodCopy)) {
|
||||
return true; // run it, includeMethods takes precedence
|
||||
}
|
||||
}
|
||||
}
|
||||
if (excludeMethods.contains("*") ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// CHECK ME: Previous implementation used include method
|
||||
for ( String pattern : excludeMethods) {
|
||||
if (pattern.contains("*")) {
|
||||
int[] compiledPattern = wildcard.compilePattern(pattern);
|
||||
HashMap<String, String> matchedPatterns = new HashMap<>();
|
||||
boolean matches = wildcard.match(matchedPatterns, methodCopy, compiledPattern);
|
||||
if (matches) {
|
||||
// if found, and wasn't included earlier, don't run it
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (pattern.equals(methodCopy)) {
|
||||
// if found, and wasn't included earlier, don't run it
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// default fall-back from before changes
|
||||
return includeMethods.size() == 0 || includeMethods.contains(method) || includeMethods.contains("*");
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #applyMethod(Set, Set, String)}, except that <code>excludeMethods</code>
|
||||
* and <code>includeMethods</code> are supplied as comma separated string.
|
||||
*
|
||||
* @param excludeMethods comma seperated string of methods to exclude.
|
||||
* @param includeMethods comma seperated string of methods to include.
|
||||
* @param method the specified method to check
|
||||
* @return <tt>true</tt> if the method should be applied.
|
||||
*/
|
||||
public static boolean applyMethod(String excludeMethods, String includeMethods, String method) {
|
||||
Set<String> includeMethodsSet = TextParseUtil.commaDelimitedStringToSet(includeMethods == null? "" : includeMethods);
|
||||
Set<String> excludeMethodsSet = TextParseUtil.commaDelimitedStringToSet(excludeMethods == null? "" : excludeMethods);
|
||||
|
||||
return applyMethod(excludeMethodsSet, includeMethodsSet, method);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public class MethodFilterInterceptorUtil extends org.apache.struts2.interceptor.MethodFilterInterceptorUtil {
|
||||
}
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
package com.opensymphony.xwork2.interceptor;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.ModelDriven;
|
||||
import com.opensymphony.xwork2.util.CompoundRoot;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import org.apache.struts2.ModelDriven;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: description -->
|
||||
@@ -71,10 +71,13 @@ import com.opensymphony.xwork2.util.ValueStack;
|
||||
* </action>
|
||||
* <!-- END SNIPPET: example -->
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author tm_jee
|
||||
* @version $Date$ $Id$
|
||||
*
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ModelDrivenInterceptor} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ModelDrivenInterceptor extends AbstractInterceptor {
|
||||
|
||||
protected boolean refreshModelBeforeResult = false;
|
||||
|
||||
+3
@@ -66,7 +66,10 @@ import java.util.Set;
|
||||
* ...
|
||||
* </action>
|
||||
* </pre>
|
||||
*
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ParameterRemoverInterceptor} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ParameterRemoverInterceptor extends AbstractInterceptor {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(ParameterRemoverInterceptor.class);
|
||||
|
||||
@@ -21,21 +21,38 @@ package com.opensymphony.xwork2.interceptor;
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
|
||||
/**
|
||||
* PreResultListeners may be registered with an {@link ActionInvocation} to get a callback after the
|
||||
* {@link com.opensymphony.xwork2.Action} has been executed but before the {@link com.opensymphony.xwork2.Result}
|
||||
* is executed.
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @author Jason Carreira
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.PreResultListener} instead.
|
||||
*/
|
||||
public interface PreResultListener {
|
||||
@Deprecated
|
||||
public interface PreResultListener extends org.apache.struts2.interceptor.PreResultListener {
|
||||
|
||||
@Override
|
||||
default void beforeResult(org.apache.struts2.ActionInvocation invocation, String resultCode) {
|
||||
beforeResult(ActionInvocation.adapt(invocation), resultCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* This callback method will be called after the {@link com.opensymphony.xwork2.Action} execution and
|
||||
* before the {@link com.opensymphony.xwork2.Result} execution.
|
||||
*
|
||||
* @param invocation the action invocation
|
||||
* @param resultCode the result code returned by the action (eg. <code>success</code>).
|
||||
*/
|
||||
void beforeResult(ActionInvocation invocation, String resultCode);
|
||||
|
||||
static PreResultListener adapt(org.apache.struts2.interceptor.PreResultListener actualListener) {
|
||||
if (actualListener instanceof PreResultListener) {
|
||||
return (PreResultListener) actualListener;
|
||||
}
|
||||
return actualListener != null ? new LegacyAdapter(actualListener) : null;
|
||||
}
|
||||
|
||||
class LegacyAdapter implements PreResultListener {
|
||||
|
||||
private final org.apache.struts2.interceptor.PreResultListener adaptee;
|
||||
|
||||
private LegacyAdapter(org.apache.struts2.interceptor.PreResultListener adaptee) {
|
||||
this.adaptee = adaptee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeResult(ActionInvocation invocation, String resultCode) {
|
||||
adaptee.beforeResult(invocation, resultCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-24
@@ -19,8 +19,8 @@
|
||||
package com.opensymphony.xwork2.interceptor;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
@@ -28,7 +28,7 @@ import java.lang.reflect.Method;
|
||||
/**
|
||||
* <p>
|
||||
* A utility class for invoking prefixed methods in action class.
|
||||
*
|
||||
*
|
||||
* Interceptors that made use of this class are:
|
||||
* </p>
|
||||
* <ul>
|
||||
@@ -37,7 +37,7 @@ import java.lang.reflect.Method;
|
||||
* </ul>
|
||||
* *
|
||||
* <!-- START SNIPPET: javadocDefaultWorkflowInterceptor -->
|
||||
*
|
||||
*
|
||||
* <b>In DefaultWorkflowInterceptor</b>
|
||||
* <p>applies only when action implements {@link com.opensymphony.xwork2.Validateable}</p>
|
||||
* <ol>
|
||||
@@ -45,12 +45,12 @@ import java.lang.reflect.Method;
|
||||
* <li>else if the action class have validateDo{MethodName}(), it will be invoked</li>
|
||||
* <li>no matter if 1] or 2] is performed, if alwaysInvokeValidate property of the interceptor is "true" (which is by default "true"), validate() will be invoked.</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* <!-- END SNIPPET: javadocDefaultWorkflowInterceptor -->
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* <!-- START SNIPPET: javadocPrepareInterceptor -->
|
||||
*
|
||||
*
|
||||
* <b>In PrepareInterceptor</b>
|
||||
* <p>Applies only when action implements Preparable</p>
|
||||
* <ol>
|
||||
@@ -58,14 +58,14 @@ import java.lang.reflect.Method;
|
||||
* <li>else if the action class have prepareDo(MethodName()}(), it will be invoked</li>
|
||||
* <li>no matter if 1] or 2] is performed, if alwaysinvokePrepare property of the interceptor is "true" (which is by default "true"), prepare() will be invoked.</li>
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* <!-- END SNIPPET: javadocPrepareInterceptor -->
|
||||
*
|
||||
*
|
||||
* @author Philip Luppens
|
||||
* @author tm_jee
|
||||
*/
|
||||
public class PrefixMethodInvocationUtil {
|
||||
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(PrefixMethodInvocationUtil.class);
|
||||
|
||||
private static final String DEFAULT_INVOCATION_METHODNAME = "execute";
|
||||
@@ -76,7 +76,7 @@ public class PrefixMethodInvocationUtil {
|
||||
* <p>
|
||||
* This method will prefix <code>actionInvocation</code>'s <code>ActionProxy</code>'s
|
||||
* <code>method</code> with <code>prefixes</code> before invoking the prefixed method.
|
||||
* Order of the <code>prefixes</code> is important, as this method will return once
|
||||
* Order of the <code>prefixes</code> is important, as this method will return once
|
||||
* a prefixed method is found in the action class.
|
||||
* </p>
|
||||
*
|
||||
@@ -89,7 +89,7 @@ public class PrefixMethodInvocationUtil {
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* Assuming <code>actionInvocation.getProxy(),getMethod()</code> returns "submit",
|
||||
* Assuming <code>actionInvocation.getProxy(),getMethod()</code> returns "submit",
|
||||
* the order of invocation would be as follows:-
|
||||
* </p>
|
||||
*
|
||||
@@ -99,12 +99,12 @@ public class PrefixMethodInvocationUtil {
|
||||
* </ol>
|
||||
*
|
||||
* <p>
|
||||
* If <code>prepareSubmit()</code> exists, it will be invoked and this method
|
||||
* will return, <code>prepareDoSubmit()</code> will NOT be invoked.
|
||||
* If <code>prepareSubmit()</code> exists, it will be invoked and this method
|
||||
* will return, <code>prepareDoSubmit()</code> will NOT be invoked.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* On the other hand, if <code>prepareDoSubmit()</code> does not exists, and
|
||||
* On the other hand, if <code>prepareDoSubmit()</code> does not exists, and
|
||||
* <code>prepareDoSubmit()</code> exists, it will be invoked.
|
||||
* </p>
|
||||
*
|
||||
@@ -119,29 +119,32 @@ public class PrefixMethodInvocationUtil {
|
||||
*/
|
||||
public static void invokePrefixMethod(ActionInvocation actionInvocation, String[] prefixes) throws InvocationTargetException, IllegalAccessException {
|
||||
Object action = actionInvocation.getAction();
|
||||
|
||||
|
||||
String methodName = actionInvocation.getProxy().getMethod();
|
||||
|
||||
|
||||
if (methodName == null) {
|
||||
// if null returns (possible according to the docs), use the default execute
|
||||
// if null returns (possible according to the docs), use the default execute
|
||||
methodName = DEFAULT_INVOCATION_METHODNAME;
|
||||
}
|
||||
|
||||
|
||||
Method method = getPrefixedMethod(prefixes, methodName, action);
|
||||
if (method != null) {
|
||||
method.invoke(action, new Object[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void invokePrefixMethod(org.apache.struts2.ActionInvocation actionInvocation, String[] prefixes) throws InvocationTargetException, IllegalAccessException {
|
||||
invokePrefixMethod(ActionInvocation.adapt(actionInvocation), prefixes);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a {@link Method} in <code>action</code>. The method
|
||||
* This method returns a {@link Method} in <code>action</code>. The method
|
||||
* returned is found by searching for method in <code>action</code> whose method name
|
||||
* is equals to the result of appending each <code>prefixes</code>
|
||||
* to <code>methodName</code>. Only the first method found will be returned, hence
|
||||
* the order of <code>prefixes</code> is important. If none is found this method
|
||||
* will return null.
|
||||
*
|
||||
*
|
||||
* @param prefixes the prefixes to prefix the <code>methodName</code>
|
||||
* @param methodName the method name to be prefixed with <code>prefixes</code>
|
||||
* @param action the action class of which the prefixed method is to be search for.
|
||||
@@ -162,7 +165,7 @@ public class PrefixMethodInvocationUtil {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This method capitalized the first character of <code>methodName</code>.
|
||||
|
||||
@@ -19,9 +19,7 @@
|
||||
package com.opensymphony.xwork2.interceptor;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.Preparable;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.struts2.Preparable;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
@@ -98,7 +96,10 @@ import java.lang.reflect.InvocationTargetException;
|
||||
* @author Philip Luppens
|
||||
* @author tm_jee
|
||||
* @see com.opensymphony.xwork2.Preparable
|
||||
*
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.PrepareInterceptor} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class PrepareInterceptor extends MethodFilterInterceptor {
|
||||
|
||||
private static final long serialVersionUID = -5216969014510719786L;
|
||||
|
||||
@@ -21,23 +21,8 @@ package com.opensymphony.xwork2.interceptor;
|
||||
import com.opensymphony.xwork2.ModelDriven;
|
||||
|
||||
/**
|
||||
* Adds the ability to set a model, probably retrieved from a given state.
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ScopedModelDriven} instead.
|
||||
*/
|
||||
public interface ScopedModelDriven<T> extends ModelDriven<T> {
|
||||
|
||||
/**
|
||||
* @param model sets the model
|
||||
*/
|
||||
void setModel(T model);
|
||||
|
||||
/**
|
||||
* Sets the key under which the model is stored
|
||||
* @param key The model key
|
||||
*/
|
||||
void setScopeKey(String key);
|
||||
|
||||
/**
|
||||
* @return the key under which the model is stored
|
||||
*/
|
||||
String getScopeKey();
|
||||
@Deprecated
|
||||
public interface ScopedModelDriven<T> extends org.apache.struts2.interceptor.ScopedModelDriven<T>, ModelDriven<T> {
|
||||
}
|
||||
|
||||
+15
-11
@@ -24,6 +24,7 @@ import com.opensymphony.xwork2.ObjectFactory;
|
||||
import com.opensymphony.xwork2.config.entities.ActionConfig;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import org.apache.struts2.StrutsException;
|
||||
import org.apache.struts2.interceptor.ScopedModelDriven;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
@@ -35,7 +36,7 @@ import java.util.Map;
|
||||
*
|
||||
* <p>This interceptor only activates on actions that implement the {@link ScopedModelDriven} interface. If
|
||||
* detected, it will retrieve the model class from the configured scope, then provide it to the Action.</p>
|
||||
*
|
||||
*
|
||||
* <!-- END SNIPPET: description -->
|
||||
*
|
||||
* <p><u>Interceptor parameters:</u></p>
|
||||
@@ -45,7 +46,7 @@ import java.util.Map;
|
||||
* <ul>
|
||||
*
|
||||
* <li>className - The model class name. Defaults to the class name of the object returned by the getModel() method.</li>
|
||||
*
|
||||
*
|
||||
* <li>name - The key to use when storing or retrieving the instance in a scope. Defaults to the model
|
||||
* class name.</li>
|
||||
*
|
||||
@@ -66,42 +67,45 @@ import java.util.Map;
|
||||
*
|
||||
* <pre>
|
||||
* <!-- START SNIPPET: example -->
|
||||
*
|
||||
*
|
||||
* <-- Basic usage -->
|
||||
* <interceptor name="scopedModelDriven" class="com.opensymphony.interceptor.ScopedModelDrivenInterceptor" />
|
||||
*
|
||||
*
|
||||
* <-- Using all available parameters -->
|
||||
* <interceptor name="gangsterForm" class="com.opensymphony.interceptor.ScopedModelDrivenInterceptor">
|
||||
* <param name="scope">session</param>
|
||||
* <param name="name">gangsterForm</param>
|
||||
* <param name="className">com.opensymphony.example.GangsterForm</param>
|
||||
* </interceptor>
|
||||
*
|
||||
*
|
||||
* <!-- END SNIPPET: example -->
|
||||
* </pre>
|
||||
*
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ScopedModelDrivenInterceptor} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class ScopedModelDrivenInterceptor extends AbstractInterceptor {
|
||||
|
||||
private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
|
||||
|
||||
|
||||
private static final String GET_MODEL = "getModel";
|
||||
private String scope;
|
||||
private String name;
|
||||
private String className;
|
||||
private ObjectFactory objectFactory;
|
||||
|
||||
|
||||
@Inject
|
||||
public void setObjectFactory(ObjectFactory factory) {
|
||||
this.objectFactory = factory;
|
||||
}
|
||||
|
||||
|
||||
protected Object resolveModel(ObjectFactory factory, ActionContext actionContext, String modelClassName, String modelScope, String modelName) throws Exception {
|
||||
Object model;
|
||||
Map<String, Object> scopeMap = actionContext.getContextMap();
|
||||
if ("session".equals(modelScope)) {
|
||||
scopeMap = actionContext.getSession();
|
||||
}
|
||||
|
||||
|
||||
model = scopeMap.get(modelName);
|
||||
if (model == null) {
|
||||
model = factory.buildBean(modelClassName, null);
|
||||
@@ -119,7 +123,7 @@ public class ScopedModelDrivenInterceptor extends AbstractInterceptor {
|
||||
if (modelDriven.getModel() == null) {
|
||||
ActionContext ctx = ActionContext.getContext();
|
||||
ActionConfig config = invocation.getProxy().getConfig();
|
||||
|
||||
|
||||
String cName = className;
|
||||
if (cName == null) {
|
||||
try {
|
||||
@@ -161,5 +165,5 @@ public class ScopedModelDrivenInterceptor extends AbstractInterceptor {
|
||||
*/
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -20,11 +20,11 @@ package com.opensymphony.xwork2.interceptor;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.LocalizedTextProvider;
|
||||
import com.opensymphony.xwork2.config.entities.ActionConfig;
|
||||
import com.opensymphony.xwork2.config.entities.Parameterizable;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.ClearableValueStack;
|
||||
import com.opensymphony.xwork2.LocalizedTextProvider;
|
||||
import com.opensymphony.xwork2.util.TextParseUtil;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import com.opensymphony.xwork2.util.ValueStackFactory;
|
||||
@@ -34,6 +34,7 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.dispatcher.HttpParameters;
|
||||
import org.apache.struts2.interceptor.ValidationAware;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
@@ -84,7 +85,10 @@ import java.util.Map;
|
||||
* </pre>
|
||||
*
|
||||
* @author Patrick Lightbody
|
||||
*
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.StaticParametersInterceptor} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public class StaticParametersInterceptor extends AbstractInterceptor {
|
||||
|
||||
private boolean parse;
|
||||
|
||||
@@ -23,109 +23,84 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* ValidationAware classes can accept Action (class level) or field level error messages. Action level messages are kept
|
||||
* in a Collection. Field level error messages are kept in a Map from String field name to a List of field error msgs.
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ValidationAware} instead.
|
||||
*/
|
||||
public interface ValidationAware {
|
||||
@Deprecated
|
||||
public interface ValidationAware extends org.apache.struts2.interceptor.ValidationAware {
|
||||
|
||||
/**
|
||||
* Set the Collection of Action-level String error messages.
|
||||
*
|
||||
* @param errorMessages Collection of String error messages
|
||||
*/
|
||||
void setActionErrors(Collection<String> errorMessages);
|
||||
|
||||
/**
|
||||
* Get the Collection of Action-level error messages for this action. Error messages should not
|
||||
* be added directly here, as implementations are free to return a new Collection or an
|
||||
* Unmodifiable Collection.
|
||||
*
|
||||
* @return Collection of String error messages
|
||||
*/
|
||||
Collection<String> getActionErrors();
|
||||
|
||||
/**
|
||||
* Set the Collection of Action-level String messages (not errors).
|
||||
*
|
||||
* @param messages Collection of String messages (not errors).
|
||||
*/
|
||||
void setActionMessages(Collection<String> messages);
|
||||
|
||||
/**
|
||||
* Get the Collection of Action-level messages for this action. Messages should not be added
|
||||
* directly here, as implementations are free to return a new Collection or an Unmodifiable
|
||||
* Collection.
|
||||
*
|
||||
* @return Collection of String messages
|
||||
*/
|
||||
Collection<String> getActionMessages();
|
||||
|
||||
/**
|
||||
* Set the field error map of fieldname (String) to Collection of String error messages.
|
||||
*
|
||||
* @param errorMap field error map
|
||||
*/
|
||||
void setFieldErrors(Map<String, List<String>> errorMap);
|
||||
|
||||
/**
|
||||
* Get the field specific errors associated with this action. Error messages should not be added
|
||||
* directly here, as implementations are free to return a new Collection or an Unmodifiable
|
||||
* Collection.
|
||||
*
|
||||
* @return Map with errors mapped from fieldname (String) to Collection of String error messages
|
||||
*/
|
||||
Map<String, List<String>> getFieldErrors();
|
||||
|
||||
/**
|
||||
* Add an Action-level error message to this Action.
|
||||
*
|
||||
* @param anErrorMessage the error message
|
||||
*/
|
||||
void addActionError(String anErrorMessage);
|
||||
|
||||
/**
|
||||
* Add an Action-level message to this Action.
|
||||
*
|
||||
* @param aMessage the message
|
||||
*/
|
||||
void addActionMessage(String aMessage);
|
||||
|
||||
/**
|
||||
* Add an error message for a given field.
|
||||
*
|
||||
* @param fieldName name of field
|
||||
* @param errorMessage the error message
|
||||
*/
|
||||
void addFieldError(String fieldName, String errorMessage);
|
||||
|
||||
/**
|
||||
* Check whether there are any Action-level error messages.
|
||||
*
|
||||
* @return true if any Action-level error messages have been registered
|
||||
*/
|
||||
boolean hasActionErrors();
|
||||
|
||||
/**
|
||||
* Checks whether there are any Action-level messages.
|
||||
*
|
||||
* @return true if any Action-level messages have been registered
|
||||
*/
|
||||
boolean hasActionMessages();
|
||||
|
||||
/**
|
||||
* Checks whether there are any action errors or field errors.
|
||||
*
|
||||
* @return <code>(hasActionErrors() || hasFieldErrors())</code>
|
||||
*/
|
||||
default boolean hasErrors() {
|
||||
return hasActionErrors() || hasFieldErrors();
|
||||
static ValidationAware adapt(org.apache.struts2.interceptor.ValidationAware actualValidation) {
|
||||
if (actualValidation instanceof ValidationAware) {
|
||||
return (ValidationAware) actualValidation;
|
||||
}
|
||||
return actualValidation != null ? new LegacyAdapter(actualValidation) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether there are any field errors associated with this action.
|
||||
*
|
||||
* @return whether there are any field errors
|
||||
*/
|
||||
boolean hasFieldErrors();
|
||||
class LegacyAdapter implements ValidationAware {
|
||||
|
||||
private final org.apache.struts2.interceptor.ValidationAware adaptee;
|
||||
|
||||
private LegacyAdapter(org.apache.struts2.interceptor.ValidationAware adaptee) {
|
||||
this.adaptee = adaptee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionErrors(Collection<String> errorMessages) {
|
||||
adaptee.setActionErrors(errorMessages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getActionErrors() {
|
||||
return adaptee.getActionErrors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionMessages(Collection<String> messages) {
|
||||
adaptee.setActionMessages(messages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getActionMessages() {
|
||||
return adaptee.getActionMessages();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFieldErrors(Map<String, List<String>> errorMap) {
|
||||
adaptee.setFieldErrors(errorMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getFieldErrors() {
|
||||
return adaptee.getFieldErrors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addActionError(String anErrorMessage) {
|
||||
adaptee.addActionError(anErrorMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addActionMessage(String aMessage) {
|
||||
adaptee.addActionMessage(aMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFieldError(String fieldName, String errorMessage) {
|
||||
adaptee.addFieldError(fieldName, errorMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasActionErrors() {
|
||||
return adaptee.hasActionErrors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasActionMessages() {
|
||||
return adaptee.hasActionMessages();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFieldErrors() {
|
||||
return adaptee.hasFieldErrors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,22 +19,8 @@
|
||||
package com.opensymphony.xwork2.interceptor;
|
||||
|
||||
/**
|
||||
* ValidationErrorAware classes can be notified about validation errors
|
||||
* before {@link com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor} will return 'inputResultName' result
|
||||
* to allow change or not the result name
|
||||
*
|
||||
* This interface can be only applied to action which already implements {@link ValidationAware} interface!
|
||||
*
|
||||
* @since 2.3.15
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ValidationErrorAware} instead.
|
||||
*/
|
||||
public interface ValidationErrorAware {
|
||||
|
||||
/**
|
||||
* Allows to notify action about occurred action/field errors
|
||||
*
|
||||
* @param currentResultName current result name, action can change it or return the same
|
||||
* @return new result name or passed currentResultName
|
||||
*/
|
||||
String actionErrorOccurred(final String currentResultName);
|
||||
|
||||
@Deprecated
|
||||
public interface ValidationErrorAware extends org.apache.struts2.interceptor.ValidationErrorAware {
|
||||
}
|
||||
|
||||
@@ -19,12 +19,8 @@
|
||||
package com.opensymphony.xwork2.interceptor;
|
||||
|
||||
/**
|
||||
* ValidationWorkflowAware classes can programmatically change result name when errors occurred
|
||||
*
|
||||
* This interface can be only applied to action which already implements {@link ValidationAware} interface!
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.interceptor.ValidationWorkflowAware} instead.
|
||||
*/
|
||||
public interface ValidationWorkflowAware {
|
||||
|
||||
String getInputResultName();
|
||||
|
||||
@Deprecated
|
||||
public interface ValidationWorkflowAware extends org.apache.struts2.interceptor.ValidationWorkflowAware {
|
||||
}
|
||||
|
||||
@@ -70,11 +70,14 @@ public interface WithLazyParams {
|
||||
}
|
||||
|
||||
public Interceptor injectParams(Interceptor interceptor, Map<String, String> params, ActionContext invocationContext) {
|
||||
return (Interceptor) injectParams((org.apache.struts2.interceptor.Interceptor) interceptor, params, invocationContext);
|
||||
}
|
||||
|
||||
public org.apache.struts2.interceptor.Interceptor injectParams(org.apache.struts2.interceptor.Interceptor interceptor, Map<String, String> params, ActionContext invocationContext) {
|
||||
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||
Object paramValue = textParser.evaluate(new char[]{ '$' }, entry.getValue(), valueEvaluator, TextParser.DEFAULT_LOOP_COUNT);
|
||||
ognlUtil.setProperty(entry.getKey(), paramValue, interceptor, invocationContext.getContextMap());
|
||||
}
|
||||
|
||||
return interceptor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,11 +601,23 @@ public class OgnlUtil {
|
||||
if (enableExpressionCache) {
|
||||
tree = expressionCache.get(expr);
|
||||
}
|
||||
if (tree instanceof OgnlException) {
|
||||
// OgnlException was cached, rethrow it with empty stack trace (refilling the stack trace is expensive)
|
||||
clearStackTraceAndRethrow(tree);
|
||||
}
|
||||
if (tree == null) {
|
||||
tree = ognlGuard.parseExpression(expr);
|
||||
try {
|
||||
tree = ognlGuard.parseExpression(expr);
|
||||
} catch (OgnlException e) {
|
||||
tree = e;
|
||||
}
|
||||
if (enableExpressionCache) {
|
||||
expressionCache.put(expr, tree);
|
||||
}
|
||||
if (tree instanceof OgnlException) {
|
||||
// Rethrow OgnlException after caching
|
||||
throw (OgnlException) tree;
|
||||
}
|
||||
}
|
||||
if (EXPR_BLOCKED.equals(tree)) {
|
||||
throw new OgnlException("Expression blocked by OgnlGuard: " + expr);
|
||||
@@ -613,6 +625,15 @@ public class OgnlUtil {
|
||||
return tree;
|
||||
}
|
||||
|
||||
private void clearStackTraceAndRethrow(Object ognlException) throws OgnlException {
|
||||
OgnlException e = (OgnlException) ognlException;
|
||||
e.setStackTrace(new StackTraceElement[0]);
|
||||
if (e.getCause() != null) {
|
||||
e.getCause().setStackTrace(new StackTraceElement[0]);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
public Object compile(String expression, Map<String, Object> context) throws OgnlException {
|
||||
Object tree = toTree(expression);
|
||||
checkEnableEvalExpression(tree, context);
|
||||
|
||||
@@ -160,6 +160,9 @@ public class SecurityMemberAccess implements MemberAccess {
|
||||
public boolean isAccessible(Map context, Object target, Member member, String propertyName) {
|
||||
LOG.debug("Checking access for [target: {}, member: {}, property: {}]", target, member, propertyName);
|
||||
|
||||
if (member == null) {
|
||||
throw new IllegalArgumentException("Member cannot be null!");
|
||||
}
|
||||
if (target != null) {
|
||||
// Special case: Target is a Class object but not Class.class
|
||||
if (Class.class.equals(target.getClass()) && !Class.class.equals(target)) {
|
||||
@@ -228,7 +231,7 @@ public class SecurityMemberAccess implements MemberAccess {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!disallowProxyObjectAccess && target != null && ProxyUtil.isProxy(target)) {
|
||||
if (!disallowProxyObjectAccess && ProxyUtil.isProxy(target)) {
|
||||
// If `disallowProxyObjectAccess` is not set, allow resolving Hibernate entities to their underlying
|
||||
// classes/members. This allows the allowlist capability to continue working and offer some level of
|
||||
// protection in applications where the developer has accepted the risk of allowing OGNL access to Hibernate
|
||||
|
||||
+1
@@ -36,6 +36,7 @@ public class DefaultExcludedPatternsChecker implements ExcludedPatternsChecker {
|
||||
private static final Logger LOG = LogManager.getLogger(DefaultExcludedPatternsChecker.class);
|
||||
|
||||
public static final String[] EXCLUDED_PATTERNS = {
|
||||
"(^|\\%\\{)(#?top\\.)[^\\s]*",
|
||||
"(^|\\%\\{)((#?)(top(\\.|\\['|\\[\")|\\[\\d\\]\\.)?)(dojo|struts|session|request|response|application|servlet(Request|Response|Context)|parameters|context|_memberAccess)(\\.|\\[).*",
|
||||
".*(^|\\.|\\[|\\'|\"|get)class(\\(\\.|\\[|\\'|\").*",
|
||||
"actionErrors|actionMessages|fieldErrors"
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
package com.opensymphony.xwork2.util;
|
||||
|
||||
import com.opensymphony.xwork2.TextProvider;
|
||||
import com.opensymphony.xwork2.interceptor.ValidationAware;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.interceptor.ValidationAware;
|
||||
|
||||
/**
|
||||
* @since 6.5.0
|
||||
@@ -35,7 +35,7 @@ public final class DebugUtils {
|
||||
log.error(message);
|
||||
if (action instanceof ValidationAware) {
|
||||
ValidationAware validationAware = (ValidationAware) action;
|
||||
validationAware.addActionError(message);
|
||||
validationAware.addActionMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ public class ProxyUtil {
|
||||
* @param object the object to check
|
||||
*/
|
||||
public static boolean isProxy(Object object) {
|
||||
if (object == null) return false;
|
||||
Class<?> clazz = object.getClass();
|
||||
Boolean flag = isProxyCache.get(clazz);
|
||||
if (flag != null) {
|
||||
@@ -121,7 +122,7 @@ public class ProxyUtil {
|
||||
*/
|
||||
public static boolean isHibernateProxy(Object object) {
|
||||
try {
|
||||
return HibernateProxy.class.isAssignableFrom(object.getClass());
|
||||
return object != null && HibernateProxy.class.isAssignableFrom(object.getClass());
|
||||
} catch (NoClassDefFoundError ignored) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -20,11 +20,11 @@ package com.opensymphony.xwork2.util;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.ModelDriven;
|
||||
import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
|
||||
import com.opensymphony.xwork2.util.reflection.ReflectionProviderFactory;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.ModelDriven;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.util.Locale;
|
||||
@@ -135,7 +135,7 @@ public class StrutsLocalizedTextProvider extends AbstractLocalizedTextProvider {
|
||||
* object. If so, repeat the entire process from the beginning with the object's class as
|
||||
* aClass and "address.state" as the message key.</li>
|
||||
* <li>If not found, look for the message in aClass' package hierarchy.</li>
|
||||
* <li>If still not found, look for the message in the default resource bundles
|
||||
* <li>If still not found, look for the message in the default resource bundles
|
||||
* (Note: the lookup is not repeated again if {@link #searchDefaultBundlesFirst} was <code>true</code>).</li>
|
||||
* <li>Return defaultMessage</li>
|
||||
* </ol>
|
||||
@@ -190,7 +190,7 @@ public class StrutsLocalizedTextProvider extends AbstractLocalizedTextProvider {
|
||||
* object. If so, repeat the entire process from the beginning with the object's class as
|
||||
* aClass and "address.state" as the message key.</li>
|
||||
* <li>If not found, look for the message in aClass' package hierarchy.</li>
|
||||
* <li>If still not found, look for the message in the default resource bundles
|
||||
* <li>If still not found, look for the message in the default resource bundles
|
||||
* (Note: the lookup is not repeated again if {@link #searchDefaultBundlesFirst} was <code>true</code>).</li>
|
||||
* <li>Return defaultMessage</li>
|
||||
* </ol>
|
||||
|
||||
@@ -23,144 +23,127 @@ import com.opensymphony.xwork2.ActionContext;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* ValueStack allows multiple beans to be pushed in and dynamic EL expressions to be evaluated against it. When
|
||||
* evaluating an expression, the stack will be searched down the stack, from the latest objects pushed in to the
|
||||
* earliest, looking for a bean with a getter or setter for the given property or a method of the given name (depending
|
||||
* on the expression being evaluated).
|
||||
* @deprecated since 6.7.0, use {@link org.apache.struts2.util.ValueStack} instead.
|
||||
*/
|
||||
public interface ValueStack {
|
||||
|
||||
String VALUE_STACK = "com.opensymphony.xwork2.util.ValueStack.ValueStack";
|
||||
|
||||
String REPORT_ERRORS_ON_NO_PROP = "com.opensymphony.xwork2.util.ValueStack.ReportErrorsOnNoProp";
|
||||
|
||||
/**
|
||||
* Gets the context for this value stack. The context holds all the information in the value stack and it's surroundings.
|
||||
*
|
||||
* @return the context.
|
||||
*/
|
||||
Map<String, Object> getContext();
|
||||
@Deprecated
|
||||
public interface ValueStack extends org.apache.struts2.util.ValueStack {
|
||||
|
||||
@Override
|
||||
ActionContext getActionContext();
|
||||
|
||||
/**
|
||||
* Sets the default type to convert to if no type is provided when getting a value.
|
||||
*
|
||||
* @param defaultType the new default type
|
||||
*/
|
||||
void setDefaultType(Class defaultType);
|
||||
static ValueStack adapt(org.apache.struts2.util.ValueStack actualStack) {
|
||||
if (actualStack instanceof ValueStack) {
|
||||
return (ValueStack) actualStack;
|
||||
}
|
||||
return actualStack != null ? new LegacyAdapter(actualStack) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a override map containing <code> key -> values </code> that takes precedent when doing find operations on the ValueStack.
|
||||
* <p>
|
||||
* See the unit test for ValueStackTest for examples.
|
||||
* </p>
|
||||
*
|
||||
* @param overrides overrides map.
|
||||
*/
|
||||
void setExprOverrides(Map<Object, Object> overrides);
|
||||
class LegacyAdapter implements ValueStack {
|
||||
|
||||
/**
|
||||
* Gets the override map if anyone exists.
|
||||
*
|
||||
* @return the override map, <tt>null</tt> if not set.
|
||||
*/
|
||||
Map<Object, Object> getExprOverrides();
|
||||
private final org.apache.struts2.util.ValueStack adaptee;
|
||||
|
||||
/**
|
||||
* Get the CompoundRoot which holds the objects pushed onto the stack
|
||||
*
|
||||
* @return the root
|
||||
*/
|
||||
CompoundRoot getRoot();
|
||||
private LegacyAdapter(org.apache.struts2.util.ValueStack adaptee) {
|
||||
this.adaptee = adaptee;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to set a property on a bean in the stack with the given expression using the default search order.
|
||||
*
|
||||
* @param expr the expression defining the path to the property to be set.
|
||||
* @param value the value to be set into the named property
|
||||
*/
|
||||
void setValue(String expr, Object value);
|
||||
@Override
|
||||
public Map<String, Object> getContext() {
|
||||
return adaptee.getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to set a property on a bean in the stack with the given expression using the default search order.
|
||||
* N.B.: unlike #setValue(String,Object) it doesn't allow eval expression.
|
||||
* @param expr the expression defining the path to the property to be set.
|
||||
* @param value the value to be set into the named property
|
||||
*/
|
||||
void setParameter(String expr, Object value);
|
||||
@Override
|
||||
public ActionContext getActionContext() {
|
||||
return ActionContext.adapt(adaptee.getActionContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to set a property on a bean in the stack with the given expression using the default search order.
|
||||
*
|
||||
* @param expr the expression defining the path to the property to be set.
|
||||
* @param value the value to be set into the named property
|
||||
* @param throwExceptionOnFailure a flag to tell whether an exception should be thrown if there is no property with
|
||||
* the given name.
|
||||
*/
|
||||
void setValue(String expr, Object value, boolean throwExceptionOnFailure);
|
||||
@Override
|
||||
public void setDefaultType(Class defaultType) {
|
||||
adaptee.setDefaultType(defaultType);
|
||||
}
|
||||
|
||||
String findString(String expr);
|
||||
String findString(String expr, boolean throwExceptionOnFailure);
|
||||
@Override
|
||||
public void setExprOverrides(Map<Object, Object> overrides) {
|
||||
adaptee.setExprOverrides(overrides);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a value by evaluating the given expression against the stack in the default search order.
|
||||
*
|
||||
* @param expr the expression giving the path of properties to navigate to find the property value to return
|
||||
* @return the result of evaluating the expression
|
||||
*/
|
||||
Object findValue(String expr);
|
||||
@Override
|
||||
public Map<Object, Object> getExprOverrides() {
|
||||
return adaptee.getExprOverrides();
|
||||
}
|
||||
|
||||
Object findValue(String expr, boolean throwExceptionOnFailure);
|
||||
@Override
|
||||
public CompoundRoot getRoot() {
|
||||
return adaptee.getRoot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a value by evaluating the given expression against the stack in the default search order.
|
||||
*
|
||||
* @param expr the expression giving the path of properties to navigate to find the property value to return
|
||||
* @param asType the type to convert the return value to
|
||||
* @return the result of evaluating the expression
|
||||
*/
|
||||
Object findValue(String expr, Class asType);
|
||||
Object findValue(String expr, Class asType, boolean throwExceptionOnFailure);
|
||||
@Override
|
||||
public void setValue(String expr, Object value) {
|
||||
adaptee.setValue(expr, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object on the top of the stack <b>without</b> changing the stack.
|
||||
*
|
||||
* @return the object on the top.
|
||||
* @see CompoundRoot#peek()
|
||||
*/
|
||||
Object peek();
|
||||
@Override
|
||||
public void setParameter(String expr, Object value) {
|
||||
adaptee.setParameter(expr, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object on the top of the stack and <b>remove</b> it from the stack.
|
||||
*
|
||||
* @return the object on the top of the stack
|
||||
* @see CompoundRoot#pop()
|
||||
*/
|
||||
Object pop();
|
||||
@Override
|
||||
public void setValue(String expr, Object value, boolean throwExceptionOnFailure) {
|
||||
adaptee.setValue(expr, value, throwExceptionOnFailure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put this object onto the top of the stack
|
||||
*
|
||||
* @param o the object to be pushed onto the stack
|
||||
* @see CompoundRoot#push(Object)
|
||||
*/
|
||||
void push(Object o);
|
||||
@Override
|
||||
public String findString(String expr) {
|
||||
return adaptee.findString(expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an object on the stack with the given key
|
||||
* so it is retrievable by {@link #findValue(String)}, {@link #findValue(String, Class)}
|
||||
*
|
||||
* @param key the key
|
||||
* @param o the object
|
||||
*/
|
||||
void set(String key, Object o);
|
||||
@Override
|
||||
public String findString(String expr, boolean throwExceptionOnFailure) {
|
||||
return adaptee.findString(expr, throwExceptionOnFailure);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of objects in the stack
|
||||
*
|
||||
* @return the number of objects in the stack
|
||||
*/
|
||||
int size();
|
||||
@Override
|
||||
public Object findValue(String expr) {
|
||||
return adaptee.findValue(expr);
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
public Object findValue(String expr, boolean throwExceptionOnFailure) {
|
||||
return adaptee.findValue(expr, throwExceptionOnFailure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object findValue(String expr, Class asType) {
|
||||
return adaptee.findValue(expr, asType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object findValue(String expr, Class asType, boolean throwExceptionOnFailure) {
|
||||
return adaptee.findValue(expr, asType, throwExceptionOnFailure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object peek() {
|
||||
return adaptee.peek();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object pop() {
|
||||
return adaptee.pop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void push(Object o) {
|
||||
adaptee.push(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(String key, Object o) {
|
||||
adaptee.set(key, o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return adaptee.size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-4
@@ -18,13 +18,23 @@
|
||||
*/
|
||||
package com.opensymphony.xwork2.validator;
|
||||
|
||||
import com.opensymphony.xwork2.*;
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.CompositeTextProvider;
|
||||
import com.opensymphony.xwork2.LocaleProvider;
|
||||
import com.opensymphony.xwork2.LocaleProviderFactory;
|
||||
import com.opensymphony.xwork2.StrutsTextProviderFactory;
|
||||
import com.opensymphony.xwork2.TextProvider;
|
||||
import com.opensymphony.xwork2.TextProviderFactory;
|
||||
import com.opensymphony.xwork2.interceptor.ValidationAware;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* A default implementation of the {@link ValidatorContext} interface.
|
||||
@@ -233,8 +243,8 @@ public class DelegatingValidatorContext implements ValidatorContext {
|
||||
}
|
||||
|
||||
protected static ValidationAware makeValidationAware(Object object) {
|
||||
if (object instanceof ValidationAware) {
|
||||
return (ValidationAware) object;
|
||||
if (object instanceof org.apache.struts2.interceptor.ValidationAware) {
|
||||
return ValidationAware.adapt((org.apache.struts2.interceptor.ValidationAware) object);
|
||||
} else {
|
||||
return new LoggingValidationAware(object);
|
||||
}
|
||||
|
||||
@@ -20,13 +20,13 @@ package com.opensymphony.xwork2.validator;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.ActionProxy;
|
||||
import com.opensymphony.xwork2.Validateable;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
|
||||
import com.opensymphony.xwork2.interceptor.PrefixMethodInvocationUtil;
|
||||
import com.opensymphony.xwork2.interceptor.ValidationAware;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.Validateable;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: description -->
|
||||
@@ -71,9 +71,9 @@ import org.apache.logging.log4j.Logger;
|
||||
* <li>programmatic - Defaults to true. If true and the action is Validateable call validate(),
|
||||
* and any method that starts with "validate".
|
||||
* </li>
|
||||
*
|
||||
*
|
||||
* <li>declarative - Defaults to true. Perform validation based on xml or annotations.</li>
|
||||
*
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <!-- END SNIPPET: parameters -->
|
||||
@@ -90,14 +90,14 @@ import org.apache.logging.log4j.Logger;
|
||||
*
|
||||
* <pre>
|
||||
* <!-- START SNIPPET: example -->
|
||||
*
|
||||
*
|
||||
* <action name="someAction" class="com.examples.SomeAction">
|
||||
* <interceptor-ref name="params"/>
|
||||
* <interceptor-ref name="validation"/>
|
||||
* <interceptor-ref name="workflow"/>
|
||||
* <result name="success">good_result.ftl</result>
|
||||
* </action>
|
||||
*
|
||||
*
|
||||
* <-- in the following case myMethod of the action class will not
|
||||
* get validated -->
|
||||
* <action name="someAction" class="com.examples.SomeAction">
|
||||
@@ -108,7 +108,7 @@ import org.apache.logging.log4j.Logger;
|
||||
* <interceptor-ref name="workflow"/>
|
||||
* <result name="success">good_result.ftl</result>
|
||||
* </action>
|
||||
*
|
||||
*
|
||||
* <-- in the following case only annotated methods of the action class will
|
||||
* be validated -->
|
||||
* <action name="someAction" class="com.examples.SomeAction">
|
||||
@@ -138,9 +138,9 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
|
||||
private final static String ALT_VALIDATE_PREFIX = "validateDo";
|
||||
|
||||
private boolean validateAnnotatedMethodOnly;
|
||||
|
||||
|
||||
private ActionValidatorManager actionValidatorManager;
|
||||
|
||||
|
||||
private boolean alwaysInvokeValidate = true;
|
||||
private boolean programmatic = true;
|
||||
private boolean declarative = true;
|
||||
@@ -149,11 +149,11 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
|
||||
public void setActionValidatorManager(ActionValidatorManager mgr) {
|
||||
this.actionValidatorManager = mgr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines if {@link Validateable}'s <code>validate()</code> should be called,
|
||||
* as well as methods whose name that start with "validate". Defaults to "true".
|
||||
*
|
||||
*
|
||||
* @param programmatic <tt>true</tt> then <code>validate()</code> is invoked.
|
||||
*/
|
||||
public void setProgrammatic(boolean programmatic) {
|
||||
@@ -161,9 +161,9 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if validation based on annotations or xml should be performed. Defaults
|
||||
* Determines if validation based on annotations or xml should be performed. Defaults
|
||||
* to "true".
|
||||
*
|
||||
*
|
||||
* @param declarative <tt>true</tt> then perform validation based on annotations or xml.
|
||||
*/
|
||||
public void setDeclarative(boolean declarative) {
|
||||
@@ -171,9 +171,9 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if {@link Validateable}'s <code>validate()</code> should always
|
||||
* Determines if {@link Validateable}'s <code>validate()</code> should always
|
||||
* be invoked. Default to "true".
|
||||
*
|
||||
*
|
||||
* @param alwaysInvokeValidate <tt>true</tt> then <code>validate()</code> is always invoked.
|
||||
*/
|
||||
public void setAlwaysInvokeValidate(String alwaysInvokeValidate) {
|
||||
@@ -218,7 +218,7 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Validating {}/{} with method {}.", invocation.getProxy().getNamespace(), invocation.getProxy().getActionName(), method);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (declarative) {
|
||||
if (validateAnnotatedMethodOnly) {
|
||||
@@ -226,12 +226,12 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
|
||||
} else {
|
||||
actionValidatorManager.validate(action, context);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (action instanceof Validateable && programmatic) {
|
||||
// keep exception that might occured in validateXXX or validateDoXXX
|
||||
Exception exception = null;
|
||||
|
||||
Exception exception = null;
|
||||
|
||||
Validateable validateable = (Validateable) action;
|
||||
LOG.debug("Invoking validate() on action {}", validateable);
|
||||
|
||||
@@ -239,19 +239,19 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
|
||||
PrefixMethodInvocationUtil.invokePrefixMethod(invocation, new String[]{VALIDATE_PREFIX, ALT_VALIDATE_PREFIX});
|
||||
}
|
||||
catch(Exception e) {
|
||||
// If any exception occurred while doing reflection, we want
|
||||
// If any exception occurred while doing reflection, we want
|
||||
// validate() to be executed
|
||||
LOG.warn("an exception occured while executing the prefix method", e);
|
||||
exception = e;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (alwaysInvokeValidate) {
|
||||
validateable.validate();
|
||||
}
|
||||
|
||||
if (exception != null) {
|
||||
// rethrow if something is wrong while doing validateXXX / validateDoXXX
|
||||
|
||||
if (exception != null) {
|
||||
// rethrow if something is wrong while doing validateXXX / validateDoXXX
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
@@ -262,7 +262,7 @@ public class ValidationInterceptor extends MethodFilterInterceptor {
|
||||
doBeforeInvocation(invocation);
|
||||
return invocation.invoke();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Returns the context that will be used by the
|
||||
|
||||
@@ -0,0 +1,558 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.opensymphony.xwork2.conversion.impl.ConversionData;
|
||||
import com.opensymphony.xwork2.inject.Container;
|
||||
import org.apache.struts2.action.Action;
|
||||
import org.apache.struts2.dispatcher.HttpParameters;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapping;
|
||||
import org.apache.struts2.util.ValueStack;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* The ActionContext is the context in which an {@link Action} is executed. Each context is basically a
|
||||
* container of objects an action needs for execution like the session, parameters, locale, etc.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The ActionContext is thread local which means that values stored in the ActionContext are
|
||||
* unique per thread. See the {@link ThreadLocal} class for more information. The benefit of
|
||||
* this is you don't need to worry about a user specific action context, you just get it:
|
||||
* </p>
|
||||
*
|
||||
* <code>ActionContext context = ActionContext.getContext();</code>
|
||||
*
|
||||
* <p>
|
||||
* Finally, because of the thread local usage you don't need to worry about making your actions thread safe.
|
||||
* </p>
|
||||
*
|
||||
* @author Patrick Lightbody
|
||||
* @author Bill Lynch (docs)
|
||||
*/
|
||||
public class ActionContext implements Serializable {
|
||||
|
||||
private static final ThreadLocal<ActionContext> actionContext = new ThreadLocal<>();
|
||||
|
||||
/**
|
||||
* Constant for the name of the action being executed.
|
||||
*/
|
||||
private static final String ACTION_NAME = "org.apache.struts2.ActionContext.name";
|
||||
|
||||
/**
|
||||
* Constant for the {@link ValueStack OGNL value stack}.
|
||||
*/
|
||||
private static final String VALUE_STACK = ValueStack.VALUE_STACK;
|
||||
|
||||
/**
|
||||
* Constant for the action's session.
|
||||
*/
|
||||
private static final String SESSION = "org.apache.struts2.ActionContext.session";
|
||||
|
||||
/**
|
||||
* Constant for the action's application context.
|
||||
*/
|
||||
private static final String APPLICATION = "org.apache.struts2.ActionContext.application";
|
||||
|
||||
/**
|
||||
* Constant for the action's parameters.
|
||||
*/
|
||||
private static final String PARAMETERS = "org.apache.struts2.ActionContext.parameters";
|
||||
|
||||
/**
|
||||
* Constant for the action's locale.
|
||||
*/
|
||||
private static final String LOCALE = "org.apache.struts2.ActionContext.locale";
|
||||
|
||||
/**
|
||||
* Constant for the action's {@link ActionInvocation invocation} context.
|
||||
*/
|
||||
private static final String ACTION_INVOCATION = "org.apache.struts2.ActionContext.actionInvocation";
|
||||
|
||||
/**
|
||||
* Constant for the map of type conversion errors.
|
||||
*/
|
||||
private static final String CONVERSION_ERRORS = "org.apache.struts2.ActionContext.conversionErrors";
|
||||
|
||||
/**
|
||||
* Constant for the container
|
||||
*/
|
||||
private static final String CONTAINER = "org.apache.struts2.ActionContext.container";
|
||||
|
||||
private final Map<String, Object> context;
|
||||
|
||||
/**
|
||||
* Creates a new ActionContext initialized with another context.
|
||||
*
|
||||
* @param context a context map.
|
||||
*/
|
||||
protected ActionContext(Map<String, Object> context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ActionContext based on passed in Map
|
||||
*
|
||||
* @param context a map with context values
|
||||
* @return new ActionContext
|
||||
*/
|
||||
public static ActionContext of(Map<String, Object> context) {
|
||||
if (context == null) {
|
||||
throw new IllegalArgumentException("Context cannot be null!");
|
||||
}
|
||||
return new ActionContext(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ActionContext based on empty Map
|
||||
*
|
||||
* @return new ActionContext
|
||||
*/
|
||||
public static ActionContext of() {
|
||||
return of(new HashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the provided context with the current thread
|
||||
*
|
||||
* @param actionContext context to bind to the thread
|
||||
* @return context which was bound to the thread
|
||||
*/
|
||||
public static ActionContext bind(ActionContext actionContext) {
|
||||
ActionContext.setContext(actionContext);
|
||||
return ActionContext.getContext();
|
||||
}
|
||||
|
||||
public static boolean containsValueStack(Map<String, Object> context) {
|
||||
return context != null && context.containsKey(VALUE_STACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds this context with the current thread
|
||||
*
|
||||
* @return this context which was bound to the thread
|
||||
*/
|
||||
public ActionContext bind() {
|
||||
ActionContext.setContext(this);
|
||||
return ActionContext.getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wipes out current ActionContext, use wisely!
|
||||
*/
|
||||
public static void clear() {
|
||||
actionContext.remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the action context for the current thread.
|
||||
*
|
||||
* @param context the action context.
|
||||
*/
|
||||
private static void setContext(ActionContext context) {
|
||||
actionContext.set(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ActionContext specific to the current thread.
|
||||
*
|
||||
* @return the ActionContext for the current thread, is never <tt>null</tt>.
|
||||
*/
|
||||
public static ActionContext getContext() {
|
||||
return actionContext.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the action invocation (the execution state).
|
||||
*
|
||||
* @param actionInvocation the action execution state.
|
||||
*/
|
||||
public ActionContext withActionInvocation(ActionInvocation actionInvocation) {
|
||||
put(ACTION_INVOCATION, actionInvocation);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the action invocation (the execution state).
|
||||
*
|
||||
* @return the action invocation (the execution state).
|
||||
*/
|
||||
public ActionInvocation getActionInvocation() {
|
||||
return (ActionInvocation) get(ACTION_INVOCATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the action's application context.
|
||||
*
|
||||
* @param application the action's application context.
|
||||
*/
|
||||
public ActionContext withApplication(Map<String, Object> application) {
|
||||
put(APPLICATION, application);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Map of the ServletContext when in a servlet environment or a generic application level Map otherwise.
|
||||
*
|
||||
* @return a Map of ServletContext or generic application level Map
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> getApplication() {
|
||||
return (Map<String, Object>) get(APPLICATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the context map.
|
||||
*
|
||||
* @return the context map.
|
||||
*/
|
||||
public Map<String, Object> getContextMap() {
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets conversion errors which occurred when executing the action.
|
||||
*
|
||||
* @param conversionErrors a Map of errors which occurred when executing the action.
|
||||
*/
|
||||
public ActionContext withConversionErrors(Map<String, ConversionData> conversionErrors) {
|
||||
put(CONVERSION_ERRORS, conversionErrors);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the map of conversion errors which occurred when executing the action.
|
||||
*
|
||||
* @return the map of conversion errors which occurred when executing the action or an empty map if
|
||||
* there were no errors.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, ConversionData> getConversionErrors() {
|
||||
Map<String, ConversionData> errors = (Map<String, ConversionData>) get(CONVERSION_ERRORS);
|
||||
|
||||
if (errors == null) {
|
||||
errors = withConversionErrors(new HashMap<>()).getConversionErrors();
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Locale for the current action.
|
||||
*
|
||||
* @param locale the Locale for the current action.
|
||||
*/
|
||||
public ActionContext withLocale(Locale locale) {
|
||||
put(LOCALE, locale);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Locale of the current action. If no locale was ever specified the platform's
|
||||
* {@link Locale#getDefault() default locale} is used.
|
||||
*
|
||||
* @return the Locale of the current action.
|
||||
*/
|
||||
public Locale getLocale() {
|
||||
Locale locale = (Locale) get(LOCALE);
|
||||
|
||||
if (locale == null) {
|
||||
locale = Locale.getDefault();
|
||||
withLocale(locale);
|
||||
}
|
||||
|
||||
return locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the current Action in the ActionContext.
|
||||
*
|
||||
* @param actionName the name of the current action.
|
||||
*/
|
||||
public ActionContext withActionName(String actionName) {
|
||||
put(ACTION_NAME, actionName);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the current Action.
|
||||
*
|
||||
* @return the name of the current action.
|
||||
*/
|
||||
public String getActionName() {
|
||||
return (String) get(ACTION_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the action parameters.
|
||||
*
|
||||
* @param parameters the parameters for the current action.
|
||||
*/
|
||||
public ActionContext withParameters(HttpParameters parameters) {
|
||||
put(PARAMETERS, parameters);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Map of the HttpServletRequest parameters when in a servlet environment or a generic Map of
|
||||
* parameters otherwise.
|
||||
*
|
||||
* @return a Map of HttpServletRequest parameters or a multipart map when in a servlet environment, or a
|
||||
* generic Map of parameters otherwise.
|
||||
*/
|
||||
public HttpParameters getParameters() {
|
||||
return (HttpParameters) get(PARAMETERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a map of action session values.
|
||||
*
|
||||
* @param session the session values.
|
||||
*/
|
||||
public ActionContext withSession(Map<String, Object> session) {
|
||||
put(SESSION, session);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Map of HttpSession values when in a servlet environment or a generic session map otherwise.
|
||||
*
|
||||
* @return the Map of HttpSession values when in a servlet environment or a generic session map otherwise.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> getSession() {
|
||||
return (Map<String, Object>) get(SESSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the OGNL value stack.
|
||||
*
|
||||
* @param valueStack the OGNL value stack.
|
||||
*/
|
||||
public ActionContext withValueStack(ValueStack valueStack) {
|
||||
put(VALUE_STACK, valueStack);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the OGNL value stack.
|
||||
*
|
||||
* @return the OGNL value stack.
|
||||
*/
|
||||
public ValueStack getValueStack() {
|
||||
return (ValueStack) get(VALUE_STACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the container for this request
|
||||
*
|
||||
* @param container The container
|
||||
*/
|
||||
public ActionContext withContainer(Container container) {
|
||||
put(CONTAINER, container);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the container for this request
|
||||
*
|
||||
* @return The container
|
||||
*/
|
||||
public Container getContainer() {
|
||||
return (Container) get(CONTAINER);
|
||||
}
|
||||
|
||||
public <T> T getInstance(Class<T> type) {
|
||||
Container cont = getContainer();
|
||||
if (cont != null) {
|
||||
return cont.getInstance(type);
|
||||
} else {
|
||||
throw new StrutsException("Cannot find an initialized container for this request.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value that is stored in the current ActionContext by doing a lookup using the value's key.
|
||||
*
|
||||
* @param key the key used to find the value.
|
||||
* @return the value that was found using the key or <tt>null</tt> if the key was not found.
|
||||
*/
|
||||
public Object get(String key) {
|
||||
return context.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a value in the current ActionContext. The value can be looked up using the key.
|
||||
*
|
||||
* @param key the key of the value.
|
||||
* @param value the value to be stored.
|
||||
*/
|
||||
public void put(String key, Object value) {
|
||||
context.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets ServletContext associated with current action
|
||||
*
|
||||
* @return current ServletContext
|
||||
*/
|
||||
public ServletContext getServletContext() {
|
||||
return (ServletContext) get(StrutsStatics.SERVLET_CONTEXT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns ServletContext to action context
|
||||
*
|
||||
* @param servletContext associated with current request
|
||||
* @return ActionContext
|
||||
*/
|
||||
public ActionContext withServletContext(ServletContext servletContext) {
|
||||
put(StrutsStatics.SERVLET_CONTEXT, servletContext);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets ServletRequest associated with current action
|
||||
*
|
||||
* @return current ServletRequest
|
||||
*/
|
||||
public HttpServletRequest getServletRequest() {
|
||||
return (HttpServletRequest) get(StrutsStatics.HTTP_REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns ServletRequest to action context
|
||||
*
|
||||
* @param request associated with current request
|
||||
* @return ActionContext
|
||||
*/
|
||||
public ActionContext withServletRequest(HttpServletRequest request) {
|
||||
put(StrutsStatics.HTTP_REQUEST, request);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets ServletResponse associated with current action
|
||||
*
|
||||
* @return current ServletResponse
|
||||
*/
|
||||
public HttpServletResponse getServletResponse() {
|
||||
return (HttpServletResponse) get(StrutsStatics.HTTP_RESPONSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns ServletResponse to action context
|
||||
*
|
||||
* @param response associated with current request
|
||||
* @return ActionContext
|
||||
*/
|
||||
public ActionContext withServletResponse(HttpServletResponse response) {
|
||||
put(StrutsStatics.HTTP_RESPONSE, response);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets PageContext associated with current action
|
||||
*
|
||||
* @return current PageContext
|
||||
*/
|
||||
public PageContext getPageContext() {
|
||||
return (PageContext) get(StrutsStatics.PAGE_CONTEXT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns PageContext to action context
|
||||
*
|
||||
* @param pageContext associated with current request
|
||||
* @return ActionContext
|
||||
*/
|
||||
public ActionContext withPageContext(PageContext pageContext) {
|
||||
put(StrutsStatics.PAGE_CONTEXT, pageContext);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets ActionMapping associated with current action
|
||||
*
|
||||
* @return current ActionMapping
|
||||
*/
|
||||
public ActionMapping getActionMapping() {
|
||||
return (ActionMapping) get(StrutsStatics.ACTION_MAPPING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns ActionMapping to action context
|
||||
*
|
||||
* @param actionMapping associated with current request
|
||||
* @return ActionContext
|
||||
*/
|
||||
public ActionContext withActionMapping(ActionMapping actionMapping) {
|
||||
put(StrutsStatics.ACTION_MAPPING, actionMapping);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns an extra context map to action context
|
||||
*
|
||||
* @param extraContext to add to the current action context
|
||||
* @return ActionContext
|
||||
*/
|
||||
public ActionContext withExtraContext(Map<String, Object> extraContext) {
|
||||
if (extraContext != null) {
|
||||
context.putAll(extraContext);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds arbitrary key to action context
|
||||
*
|
||||
* @param key a string
|
||||
* @param value an object
|
||||
* @return ActionContext
|
||||
*/
|
||||
public ActionContext with(String key, Object value) {
|
||||
put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object obj) {
|
||||
if (!(obj instanceof ActionContext)) {
|
||||
return false;
|
||||
}
|
||||
ActionContext other = (ActionContext) obj;
|
||||
return Objects.equals(getContextMap(), other.getContextMap());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return Objects.hash(getContextMap());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.apache.struts2.util.ValueStack;
|
||||
|
||||
/**
|
||||
* Provides hooks for handling key action events
|
||||
*/
|
||||
public interface ActionEventListener {
|
||||
/**
|
||||
* Called after an action has been created.
|
||||
*
|
||||
* @param action The action
|
||||
* @param stack The current value stack
|
||||
* @return The action to use
|
||||
*/
|
||||
Object prepare(Object action, ValueStack stack);
|
||||
|
||||
/**
|
||||
* Called when an exception is thrown by the action
|
||||
*
|
||||
* @param t The exception/error that was thrown
|
||||
* @param stack The current value stack
|
||||
* @return A result code to execute, can be null
|
||||
*/
|
||||
String handleException(Throwable t, ValueStack stack);
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.apache.struts2.action.Action;
|
||||
import org.apache.struts2.interceptor.PreResultListener;
|
||||
import org.apache.struts2.result.ActionChainResult;
|
||||
import org.apache.struts2.result.Result;
|
||||
import org.apache.struts2.util.ValueStack;
|
||||
|
||||
/**
|
||||
* An {@link ActionInvocation} represents the execution state of an {@link com.opensymphony.xwork2.Action}. It holds the Interceptors and the Action instance.
|
||||
* By repeated re-entrant execution of the <code>invoke()</code> method, initially by the {@link ActionProxy}, then by the Interceptors, the
|
||||
* Interceptors are all executed, and then the {@link Action} and the {@link com.opensymphony.xwork2.Result}.
|
||||
*
|
||||
* @author Jason Carreira
|
||||
* @see ActionProxy
|
||||
*/
|
||||
public interface ActionInvocation {
|
||||
|
||||
/**
|
||||
* Get the Action associated with this ActionInvocation.
|
||||
*
|
||||
* @return the Action
|
||||
*/
|
||||
Object getAction();
|
||||
|
||||
/**
|
||||
* Gets whether this ActionInvocation has executed before.
|
||||
* This will be set after the Action and the Result have executed.
|
||||
*
|
||||
* @return <tt>true</tt> if this ActionInvocation has executed before.
|
||||
*/
|
||||
boolean isExecuted();
|
||||
|
||||
/**
|
||||
* Gets the ActionContext associated with this ActionInvocation. The ActionProxy is
|
||||
* responsible for setting this ActionContext onto the ThreadLocal before invoking
|
||||
* the ActionInvocation and resetting the old ActionContext afterwards.
|
||||
*
|
||||
* @return the ActionContext.
|
||||
*/
|
||||
ActionContext getInvocationContext();
|
||||
|
||||
/**
|
||||
* Get the ActionProxy holding this ActionInvocation.
|
||||
*
|
||||
* @return the ActionProxy.
|
||||
*/
|
||||
ActionProxy getProxy();
|
||||
|
||||
/**
|
||||
* If the ActionInvocation has been executed before and the Result is an instance of {@link ActionChainResult}, this method
|
||||
* will walk down the chain of <code>ActionChainResult</code>s until it finds a non-chain result, which will be returned. If the
|
||||
* ActionInvocation's result has not been executed before, the Result instance will be created and populated with
|
||||
* the result params.
|
||||
*
|
||||
* @return the result.
|
||||
* @throws Exception can be thrown.
|
||||
*/
|
||||
Result getResult() throws Exception;
|
||||
|
||||
/**
|
||||
* Gets the result code returned from this ActionInvocation.
|
||||
*
|
||||
* @return the result code
|
||||
*/
|
||||
String getResultCode();
|
||||
|
||||
/**
|
||||
* Sets the result code, possibly overriding the one returned by the
|
||||
* action.
|
||||
*
|
||||
* <p>
|
||||
* The "intended" purpose of this method is to allow PreResultListeners to
|
||||
* override the result code returned by the Action.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If this method is used before the Action executes, the Action's returned
|
||||
* result code will override what was set. However the Action could (if
|
||||
* specifically coded to do so) inspect the ActionInvocation to see that
|
||||
* someone "upstream" (e.g. an Interceptor) had suggested a value as the
|
||||
* result, and it could therefore return the same value itself.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If this method is called between the Action execution and the Result
|
||||
* execution, then the value set here will override the result code the
|
||||
* action had returned. Creating an Interceptor that implements
|
||||
* {@link PreResultListener} will give you this opportunity.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If this method is called after the Result has been executed, it will
|
||||
* have the effect of raising an IllegalStateException.
|
||||
* </p>
|
||||
*
|
||||
* @param resultCode the result code.
|
||||
* @throws IllegalStateException if called after the Result has been executed.
|
||||
* @see #isExecuted()
|
||||
*/
|
||||
void setResultCode(String resultCode);
|
||||
|
||||
/**
|
||||
* Gets the ValueStack associated with this ActionInvocation.
|
||||
*
|
||||
* @return the ValueStack
|
||||
*/
|
||||
ValueStack getStack();
|
||||
|
||||
/**
|
||||
* Register a {@link PreResultListener} to be notified after the Action is executed and
|
||||
* before the Result is executed.
|
||||
*
|
||||
* <p>
|
||||
* The ActionInvocation implementation must guarantee that listeners will be called in
|
||||
* the order in which they are registered.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Listener registration and execution does not need to be thread-safe.
|
||||
* </p>
|
||||
*
|
||||
* @param listener the listener to add.
|
||||
*/
|
||||
void addPreResultListener(PreResultListener listener);
|
||||
|
||||
/**
|
||||
* Invokes the next step in processing this ActionInvocation.
|
||||
*
|
||||
* <p>
|
||||
* If there are more Interceptors, this will call the next one. If Interceptors choose not to short-circuit
|
||||
* ActionInvocation processing and return their own return code, they will call invoke() to allow the next Interceptor
|
||||
* to execute. If there are no more Interceptors to be applied, the Action is executed.
|
||||
* If the {@link ActionProxy#getExecuteResult()} method returns <tt>true</tt>, the Result is also executed.
|
||||
* </p>
|
||||
*
|
||||
* @throws Exception can be thrown.
|
||||
* @return the return code.
|
||||
*/
|
||||
String invoke() throws Exception;
|
||||
|
||||
/**
|
||||
* Invokes only the Action (not Interceptors or Results).
|
||||
*
|
||||
* <p>
|
||||
* This is useful in rare situations where advanced usage with the interceptor/action/result workflow is
|
||||
* being manipulated for certain functionality.
|
||||
* </p>
|
||||
*
|
||||
* @return the return code.
|
||||
* @throws Exception can be thrown.
|
||||
*/
|
||||
String invokeActionOnly() throws Exception;
|
||||
|
||||
/**
|
||||
* Sets the action event listener to respond to key action events.
|
||||
*
|
||||
* @param listener the listener.
|
||||
*/
|
||||
void setActionEventListener(ActionEventListener listener);
|
||||
|
||||
void init(ActionProxy proxy);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.opensymphony.xwork2.config.entities.ActionConfig;
|
||||
|
||||
/**
|
||||
* ActionProxy is an extra layer between XWork and the action so that different proxies are possible.
|
||||
*
|
||||
* <p>
|
||||
* An example of this would be a remote proxy, where the layer between XWork and the action might be RMI or SOAP.
|
||||
* </p>
|
||||
*
|
||||
* @author Jason Carreira
|
||||
*/
|
||||
public interface ActionProxy {
|
||||
|
||||
/**
|
||||
* Gets the Action instance for this Proxy.
|
||||
*
|
||||
* @return the Action instance
|
||||
*/
|
||||
Object getAction();
|
||||
|
||||
/**
|
||||
* Gets the alias name this ActionProxy is mapped to.
|
||||
*
|
||||
* @return the alias name
|
||||
*/
|
||||
String getActionName();
|
||||
|
||||
/**
|
||||
* Gets the ActionConfig this ActionProxy is built from.
|
||||
*
|
||||
* @return the ActionConfig
|
||||
*/
|
||||
ActionConfig getConfig();
|
||||
|
||||
/**
|
||||
* Sets whether this ActionProxy should also execute the Result after executing the Action.
|
||||
*
|
||||
* @param executeResult <tt>true</tt> to also execute the Result.
|
||||
*/
|
||||
void setExecuteResult(boolean executeResult);
|
||||
|
||||
/**
|
||||
* Gets the status of whether the ActionProxy is set to execute the Result after the Action is executed.
|
||||
*
|
||||
* @return the status
|
||||
*/
|
||||
boolean getExecuteResult();
|
||||
|
||||
ActionInvocation getInvocation();
|
||||
|
||||
/**
|
||||
* Gets the namespace the ActionConfig for this ActionProxy is mapped to.
|
||||
*
|
||||
* @return the namespace
|
||||
*/
|
||||
String getNamespace();
|
||||
|
||||
/**
|
||||
* Execute this ActionProxy. This will set the ActionContext from the ActionInvocation into the ActionContext
|
||||
* ThreadLocal before invoking the ActionInvocation, then set the old ActionContext back into the ThreadLocal.
|
||||
*
|
||||
* @return the result code returned from executing the ActionInvocation
|
||||
* @throws Exception can be thrown.
|
||||
* @see ActionInvocation
|
||||
*/
|
||||
String execute() throws Exception;
|
||||
|
||||
/**
|
||||
* Gets the method name to execute, or <tt>null</tt> if no method has been specified (meaning <code>execute</code> will be invoked).
|
||||
*
|
||||
* @return the method to execute
|
||||
*/
|
||||
String getMethod();
|
||||
|
||||
/**
|
||||
* Gets status of the method value's initialization.
|
||||
*
|
||||
* @return true if the method returned by getMethod() is not a default initializer value.
|
||||
*/
|
||||
boolean isMethodSpecified();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.opensymphony.xwork2.LocaleProvider;
|
||||
import com.opensymphony.xwork2.LocaleProviderFactory;
|
||||
import com.opensymphony.xwork2.TextProvider;
|
||||
import com.opensymphony.xwork2.TextProviderFactory;
|
||||
import com.opensymphony.xwork2.ValidationAwareSupport;
|
||||
import com.opensymphony.xwork2.conversion.impl.ConversionData;
|
||||
import com.opensymphony.xwork2.inject.Container;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.action.Action;
|
||||
import org.apache.struts2.interceptor.ValidationAware;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Provides a default implementation for the most common actions.
|
||||
* See the documentation for all the interfaces this class implements for more detailed information.
|
||||
*/
|
||||
public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(ActionSupport.class);
|
||||
|
||||
private final ValidationAwareSupport validationAware = new ValidationAwareSupport();
|
||||
|
||||
private transient TextProvider textProvider;
|
||||
private transient LocaleProvider localeProvider;
|
||||
|
||||
protected Container container;
|
||||
|
||||
@Override
|
||||
public void setActionErrors(Collection<String> errorMessages) {
|
||||
validationAware.setActionErrors(errorMessages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getActionErrors() {
|
||||
return validationAware.getActionErrors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActionMessages(Collection<String> messages) {
|
||||
validationAware.setActionMessages(messages);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getActionMessages() {
|
||||
return validationAware.getActionMessages();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFieldErrors(Map<String, List<String>> errorMap) {
|
||||
validationAware.setFieldErrors(errorMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<String>> getFieldErrors() {
|
||||
return validationAware.getFieldErrors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale getLocale() {
|
||||
return getLocaleProvider().getLocale();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidLocaleString(String localeStr) {
|
||||
return getLocaleProvider().isValidLocaleString(localeStr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidLocale(Locale locale) {
|
||||
return getLocaleProvider().isValidLocale(locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locale toLocale(String localeStr) {
|
||||
return getLocaleProvider().toLocale(localeStr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasKey(String key) {
|
||||
return getTextProvider().hasKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String aTextName) {
|
||||
return getTextProvider().getText(aTextName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String aTextName, String defaultValue) {
|
||||
return getTextProvider().getText(aTextName, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String aTextName, String defaultValue, String obj) {
|
||||
return getTextProvider().getText(aTextName, defaultValue, obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String aTextName, List<?> args) {
|
||||
return getTextProvider().getText(aTextName, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String key, String[] args) {
|
||||
return getTextProvider().getText(key, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String aTextName, String defaultValue, List<?> args) {
|
||||
return getTextProvider().getText(aTextName, defaultValue, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String key, String defaultValue, String[] args) {
|
||||
return getTextProvider().getText(key, defaultValue, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String key, String defaultValue, List<?> args, ValueStack stack) {
|
||||
return getTextProvider().getText(key, defaultValue, args, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(String key, String defaultValue, String[] args, ValueStack stack) {
|
||||
return getTextProvider().getText(key, defaultValue, args, stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dedicated method to support I10N and conversion errors
|
||||
*
|
||||
* @param key message which contains formatting string
|
||||
* @param expr that should be formatted
|
||||
* @return formatted expr with format specified by key
|
||||
*/
|
||||
public String getFormatted(String key, String expr) {
|
||||
Map<String, ConversionData> conversionErrors = ActionContext.getContext().getConversionErrors();
|
||||
if (conversionErrors.containsKey(expr)) {
|
||||
String[] vals = (String[]) conversionErrors.get(expr).getValue();
|
||||
return vals[0];
|
||||
} else {
|
||||
final ValueStack valueStack = ValueStack.adapt(ActionContext.getContext().getValueStack());
|
||||
final Object val = valueStack.findValue(expr);
|
||||
return getText(key, Arrays.asList(val));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceBundle getTexts() {
|
||||
return getTextProvider().getTexts();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceBundle getTexts(String aBundleName) {
|
||||
return getTextProvider().getTexts(aBundleName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addActionError(String anErrorMessage) {
|
||||
validationAware.addActionError(anErrorMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addActionMessage(String aMessage) {
|
||||
validationAware.addActionMessage(aMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addFieldError(String fieldName, String errorMessage) {
|
||||
validationAware.addFieldError(fieldName, errorMessage);
|
||||
}
|
||||
|
||||
public String input() throws Exception {
|
||||
return INPUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* A default implementation that does nothing an returns "success".
|
||||
*
|
||||
* <p>
|
||||
* Subclasses should override this method to provide their business logic.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* See also {@link Action#execute()}.
|
||||
* </p>
|
||||
*
|
||||
* @return returns {@link #SUCCESS}
|
||||
* @throws Exception can be thrown by subclasses.
|
||||
*/
|
||||
@Override
|
||||
public String execute() throws Exception {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasActionErrors() {
|
||||
return validationAware.hasActionErrors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasActionMessages() {
|
||||
return validationAware.hasActionMessages();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasErrors() {
|
||||
return validationAware.hasErrors();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFieldErrors() {
|
||||
return validationAware.hasFieldErrors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears field errors. Useful for Continuations and other situations
|
||||
* where you might want to clear parts of the state on the same action.
|
||||
*/
|
||||
public void clearFieldErrors() {
|
||||
validationAware.clearFieldErrors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears action errors. Useful for Continuations and other situations
|
||||
* where you might want to clear parts of the state on the same action.
|
||||
*/
|
||||
public void clearActionErrors() {
|
||||
validationAware.clearActionErrors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears messages. Useful for Continuations and other situations
|
||||
* where you might want to clear parts of the state on the same action.
|
||||
*/
|
||||
public void clearMessages() {
|
||||
validationAware.clearMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all errors. Useful for Continuations and other situations
|
||||
* where you might want to clear parts of the state on the same action.
|
||||
*/
|
||||
public void clearErrors() {
|
||||
validationAware.clearErrors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all errors and messages. Useful for Continuations and other situations
|
||||
* where you might want to clear parts of the state on the same action.
|
||||
*/
|
||||
public void clearErrorsAndMessages() {
|
||||
validationAware.clearErrorsAndMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
* A default implementation that validates nothing.
|
||||
* Subclasses should override this method to provide validations.
|
||||
*/
|
||||
@Override
|
||||
public void validate() {
|
||||
// A default implementation that validates nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
return super.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: pause-method -->
|
||||
* Stops the action invocation immediately (by throwing a PauseException) and causes the action invocation to return
|
||||
* the specified result, such as {@link #SUCCESS}, {@link #INPUT}, etc.
|
||||
*
|
||||
* <p>
|
||||
* The next time this action is invoked (and using the same continuation ID), the method will resume immediately
|
||||
* after where this method was called, with the entire call stack in the execute method restored.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Note: this method can <b>only</b> be called within the {@link #execute()} method.
|
||||
* </p>
|
||||
*
|
||||
* <!-- END SNIPPET: pause-method -->
|
||||
*
|
||||
* @param result the result to return - the same type of return value in the {@link #execute()} method.
|
||||
*/
|
||||
public void pause(String result) {
|
||||
}
|
||||
|
||||
/**
|
||||
* If called first time it will create {@link TextProviderFactory},
|
||||
* inject dependency (if {@link Container} is accesible) into in,
|
||||
* then will create new {@link TextProvider} and store it in a field
|
||||
* for future references and at the returns reference to that field
|
||||
*
|
||||
* @return reference to field with TextProvider
|
||||
*/
|
||||
protected TextProvider getTextProvider() {
|
||||
if (textProvider == null) {
|
||||
final TextProviderFactory tpf = getContainer().getInstance(TextProviderFactory.class);
|
||||
textProvider = tpf.createInstance(getClass());
|
||||
}
|
||||
return textProvider;
|
||||
}
|
||||
|
||||
protected LocaleProvider getLocaleProvider() {
|
||||
if (localeProvider == null) {
|
||||
final LocaleProviderFactory localeProviderFactory = getContainer().getInstance(LocaleProviderFactory.class);
|
||||
localeProvider = localeProviderFactory.createLocaleProvider();
|
||||
}
|
||||
return localeProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: This a temporary solution, maybe we should consider stop injecting container into beans
|
||||
*/
|
||||
protected Container getContainer() {
|
||||
if (container == null) {
|
||||
container = ActionContext.getContext().getContainer();
|
||||
if (container != null) {
|
||||
boolean devMode = Boolean.parseBoolean(container.getInstance(String.class, StrutsConstants.STRUTS_DEVMODE));
|
||||
if (devMode) {
|
||||
LOG.warn("Container is null, action was created manually? Fallback to ActionContext");
|
||||
} else {
|
||||
LOG.debug("Container is null, action was created manually? Fallback to ActionContext");
|
||||
}
|
||||
} else {
|
||||
LOG.warn("Container is null, action was created out of ActionContext scope?!?");
|
||||
}
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setContainer(Container container) {
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2;
|
||||
|
||||
import org.apache.struts2.interceptor.parameter.StrutsParameter;
|
||||
|
||||
/**
|
||||
* ModelDriven Actions provide a model object to be pushed onto the ValueStack
|
||||
* in addition to the Action itself, allowing a FormBean type approach like Struts.
|
||||
*
|
||||
* @author Jason Carreira
|
||||
*/
|
||||
public interface ModelDriven<T> {
|
||||
|
||||
/**
|
||||
* Gets the model to be pushed onto the ValueStack instead of the Action itself.
|
||||
* <p>
|
||||
* Please be aware that all setters and getters of every depth on the object returned by this method are available
|
||||
* for user parameter injection!
|
||||
*
|
||||
* @return the model
|
||||
*/
|
||||
@StrutsParameter(depth = Integer.MAX_VALUE)
|
||||
T getModel();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Preparable Actions will have their <code>prepare()</code> method called if the {@link com.opensymphony.xwork2.interceptor.PrepareInterceptor}
|
||||
* is applied to the ActionConfig.
|
||||
*
|
||||
* @author Jason Carreira
|
||||
* @see com.opensymphony.xwork2.interceptor.PrepareInterceptor
|
||||
*/
|
||||
public interface Preparable {
|
||||
|
||||
/**
|
||||
* This method is called to allow the action to prepare itself.
|
||||
*
|
||||
* @throws Exception thrown if a system level exception occurs.
|
||||
*/
|
||||
void prepare() throws Exception;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Simple marker interface to indicate an object should <b>not</b> have its properties copied during chaining.
|
||||
*
|
||||
* @see com.opensymphony.xwork2.interceptor.ChainingInterceptor
|
||||
*/
|
||||
public interface Unchainable {
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2;
|
||||
|
||||
/**
|
||||
* Provides an interface in which a call for a validation check can be done.
|
||||
*
|
||||
* @author Jason Carreira
|
||||
* @see com.opensymphony.xwork2.ActionSupport
|
||||
* @see com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor
|
||||
*/
|
||||
public interface Validateable {
|
||||
|
||||
/**
|
||||
* Performs validation.
|
||||
*/
|
||||
void validate();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.action;
|
||||
|
||||
/**
|
||||
* All actions <b>may</b> implement this interface, which exposes the <code>execute()</code> method.
|
||||
* <p>
|
||||
* However, as of XWork 1.1, this is <b>not</b> required and is only here to assist users. You are free to create POJOs
|
||||
* that honor the same contract defined by this interface without actually implementing the interface.
|
||||
* </p>
|
||||
*/
|
||||
public interface Action {
|
||||
|
||||
/**
|
||||
* The action execution was successful. Show result
|
||||
* view to the end user.
|
||||
*/
|
||||
String SUCCESS = "success";
|
||||
|
||||
/**
|
||||
* The action execution was successful but do not
|
||||
* show a view. This is useful for actions that are
|
||||
* handling the view in another fashion like redirect.
|
||||
*/
|
||||
String NONE = "none";
|
||||
|
||||
/**
|
||||
* The action execution was a failure.
|
||||
* Show an error view, possibly asking the
|
||||
* user to retry entering data.
|
||||
*/
|
||||
String ERROR = "error";
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* The action execution require more input
|
||||
* in order to succeed.
|
||||
* This result is typically used if a form
|
||||
* handling action has been executed so as
|
||||
* to provide defaults for a form. The
|
||||
* form associated with the handler should be
|
||||
* shown to the end user.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This result is also used if the given input
|
||||
* params are invalid, meaning the user
|
||||
* should try providing input again.
|
||||
* </p>
|
||||
*/
|
||||
String INPUT = "input";
|
||||
|
||||
/**
|
||||
* The action could not execute, since the
|
||||
* user most was not logged in. The login view
|
||||
* should be shown.
|
||||
*/
|
||||
String LOGIN = "login";
|
||||
|
||||
|
||||
/**
|
||||
* Where the logic of the action is executed.
|
||||
*
|
||||
* @return a string representing the logical result of the execution.
|
||||
* See constants in this interface for a list of standard result values.
|
||||
* @throws Exception thrown if a system level exception occurs.
|
||||
* <b>Note:</b> Application level exceptions should be handled by returning
|
||||
* an error value, such as <code>Action.ERROR</code>.
|
||||
*/
|
||||
String execute() throws Exception;
|
||||
|
||||
}
|
||||
@@ -215,8 +215,8 @@ public class ActionComponent extends ContextBean {
|
||||
|
||||
HttpParameters.Builder builder = HttpParameters.create().withParent(parentParams);
|
||||
|
||||
if (parameters != null) {
|
||||
builder = builder.withExtraParams(parameters);
|
||||
if (getAttributes() != null) {
|
||||
builder = builder.withExtraParams(getAttributes());
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@@ -71,6 +71,10 @@ public class Component {
|
||||
protected boolean devMode = false;
|
||||
protected boolean escapeHtmlBody = false;
|
||||
protected ValueStack stack;
|
||||
/**
|
||||
* @deprecated use {@link #getAttributes} instead of directly depending on this field
|
||||
*/
|
||||
@Deprecated
|
||||
protected Map<String, Object> parameters;
|
||||
protected ActionMapper actionMapper;
|
||||
protected boolean throwExceptionOnELFailure;
|
||||
@@ -279,7 +283,7 @@ public class Component {
|
||||
*/
|
||||
protected StrutsException fieldError(String field, String errorMsg, Exception e) {
|
||||
String msg = "tag '" + getComponentName() + "', field '" + field +
|
||||
(parameters != null && parameters.containsKey("name") ? "', name '" + parameters.get("name") : "") +
|
||||
(getAttributes() != null && getAttributes().containsKey("name") ? "', name '" + getAttributes().get("name") : "") +
|
||||
"': " + errorMsg;
|
||||
throw new StrutsException(msg, e);
|
||||
}
|
||||
@@ -457,7 +461,7 @@ public class Component {
|
||||
* @param params the parameters to copy.
|
||||
*/
|
||||
public void copyParams(Map<String, Object> params) {
|
||||
stack.push(parameters);
|
||||
stack.push(getAttributes());
|
||||
stack.push(this);
|
||||
try {
|
||||
for (Map.Entry<String, Object> entry : params.entrySet()) {
|
||||
@@ -467,7 +471,7 @@ public class Component {
|
||||
// UI component attributes may contain hypens (e.g. data-ajax), but ognl
|
||||
// can't handle that, and there can't be a component property with a hypen
|
||||
// so into the parameters map it goes. See WW-4493
|
||||
parameters.put(key, entry.getValue());
|
||||
getAttributes().put(key, entry.getValue());
|
||||
} else {
|
||||
stack.setValue(key, entry.getValue());
|
||||
}
|
||||
@@ -496,18 +500,29 @@ public class Component {
|
||||
* Gets the parameters.
|
||||
*
|
||||
* @return the parameters. Is never <tt>null</tt>.
|
||||
* @deprecated since 6.7.0, use {@link #getAttributes()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public Map<String, Object> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the parameters.
|
||||
*
|
||||
* @return the parameters. Is never <tt>null</tt>.
|
||||
*/
|
||||
public Map<String, Object> getAttributes() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all the given parameters to this component's own parameters.
|
||||
*
|
||||
* @param params the parameters to add.
|
||||
*/
|
||||
public void addAllParameters(Map<String, Object> params) {
|
||||
parameters.putAll(params);
|
||||
getAttributes().putAll(params);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -522,7 +537,7 @@ public class Component {
|
||||
*/
|
||||
public void addParameter(String key, Object value) {
|
||||
if (key != null) {
|
||||
Map<String, Object> params = getParameters();
|
||||
Map<String, Object> params = getAttributes();
|
||||
|
||||
if (value == null) {
|
||||
params.remove(key);
|
||||
|
||||
@@ -164,7 +164,7 @@ public abstract class DoubleListUIBean extends ListUIBean {
|
||||
// ok, let's look it up
|
||||
Component form = findAncestor(Form.class);
|
||||
if (form != null) {
|
||||
addParameter("formName", form.getParameters().get("name"));
|
||||
addParameter("formName", form.getAttributes().get("name"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ public abstract class DoubleListUIBean extends ListUIBean {
|
||||
if (doubleId != null) {
|
||||
addParameter("doubleId", findString(doubleId));
|
||||
} else if (form != null) {
|
||||
addParameter("doubleId", form.getParameters().get("id") + "_" + escape(doubleName != null ? findString(doubleName) : null));
|
||||
addParameter("doubleId", form.getAttributes().get("id") + "_" + escape(doubleName != null ? findString(doubleName) : null));
|
||||
} else {
|
||||
addParameter("doubleId", escape(doubleName != null ? findString(doubleName) : null));
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class DoubleSelect extends DoubleListUIBean {
|
||||
public void evaluateExtraParams() {
|
||||
super.evaluateExtraParams();
|
||||
StringBuilder onchangeParam = new StringBuilder();
|
||||
onchangeParam.append(getParameters().get("id")).append("Redirect(this.selectedIndex)");
|
||||
onchangeParam.append(getAttributes().get("id")).append("Redirect(this.selectedIndex)");
|
||||
if(StringUtils.isNotEmpty(this.onchange)) {
|
||||
onchangeParam.append(";").append(this.onchange);
|
||||
}
|
||||
|
||||
@@ -68,13 +68,13 @@ public class File extends UIBean {
|
||||
|
||||
Form form = (Form) findAncestor(Form.class);
|
||||
if (form != null) {
|
||||
String encType = (String) form.getParameters().get("enctype");
|
||||
String encType = (String) form.getAttributes().get("enctype");
|
||||
if (!"multipart/form-data".equals(encType)) {
|
||||
// uh oh, this isn't good! Let's warn the developer
|
||||
LOG.warn("Struts has detected a file upload UI tag (s:file) being used without a form set to enctype 'multipart/form-data'. This is probably an error!");
|
||||
}
|
||||
|
||||
String method = (String) form.getParameters().get("method");
|
||||
String method = (String) form.getAttributes().get("method");
|
||||
if (!"post".equalsIgnoreCase(method)) {
|
||||
// uh oh, this isn't good! Let's warn the developer
|
||||
LOG.warn("Struts has detected a file upload UI tag (s:file) being used without a form set to method 'POST'. This is probably an error!");
|
||||
|
||||
@@ -172,7 +172,7 @@ public class Form extends ClosingUIBean {
|
||||
|
||||
if (name == null) {
|
||||
//make the name the same as the id
|
||||
String id = (String) getParameters().get("id");
|
||||
String id = (String) getAttributes().get("id");
|
||||
if (StringUtils.isNotEmpty(id)) {
|
||||
addParameter("name", id);
|
||||
}
|
||||
@@ -204,7 +204,7 @@ public class Form extends ClosingUIBean {
|
||||
|
||||
// keep a collection of the tag names for anything special the templates might want to do (such as pure client
|
||||
// side validation)
|
||||
if (!parameters.containsKey("tagNames")) {
|
||||
if (!getAttributes().containsKey("tagNames")) {
|
||||
// we have this if check so we don't do this twice (on open and close of the template)
|
||||
addParameter("tagNames", new ArrayList());
|
||||
}
|
||||
@@ -242,7 +242,7 @@ public class Form extends ClosingUIBean {
|
||||
protected void evaluateClientSideJsEnablement(String actionName, String namespace, String actionMethod) {
|
||||
|
||||
// Only evaluate if Client-Side js is to be enable when validate=true
|
||||
Boolean validate = (Boolean) getParameters().get("validate");
|
||||
Boolean validate = (Boolean) getAttributes().get("validate");
|
||||
if (validate != null && validate) {
|
||||
|
||||
addParameter("performValidation", Boolean.FALSE);
|
||||
@@ -270,7 +270,7 @@ public class Form extends ClosingUIBean {
|
||||
}
|
||||
|
||||
public List getValidators(String name) {
|
||||
Class actionClass = (Class) getParameters().get("actionClass");
|
||||
Class actionClass = (Class) getAttributes().get("actionClass");
|
||||
if (actionClass == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
@@ -279,7 +279,7 @@ public class Form extends ClosingUIBean {
|
||||
ActionMapping mapping = actionMapper.getMappingFromActionName(formActionValue);
|
||||
|
||||
if (mapping == null) {
|
||||
mapping = actionMapper.getMappingFromActionName((String) getParameters().get("actionName"));
|
||||
mapping = actionMapper.getMappingFromActionName((String) getAttributes().get("actionName"));
|
||||
}
|
||||
|
||||
if (mapping == null) {
|
||||
|
||||
@@ -58,7 +58,7 @@ public abstract class FormButton extends ClosingUIBean {
|
||||
addParameter("type", submitType);
|
||||
|
||||
if (!BUTTON_TYPE_INPUT.equals(submitType) && (label == null)) {
|
||||
addParameter("label", getParameters().get("nameValue"));
|
||||
addParameter("label", getAttributes().get("nameValue"));
|
||||
}
|
||||
|
||||
if (action != null || method != null) {
|
||||
@@ -101,8 +101,8 @@ public abstract class FormButton extends ClosingUIBean {
|
||||
// this check is needed for backwards compatibility with 2.1.x
|
||||
tmpId = findString(id);
|
||||
} else {
|
||||
if (form != null && form.getParameters().get("id") != null) {
|
||||
tmpId = tmpId + form.getParameters().get("id").toString() + "_";
|
||||
if (form != null && form.getAttributes().get("id") != null) {
|
||||
tmpId = tmpId + form.getAttributes().get("id").toString() + "_";
|
||||
}
|
||||
if (name != null) {
|
||||
tmpId = tmpId + escape(findString(name));
|
||||
|
||||
@@ -137,14 +137,13 @@ public class Include extends Component {
|
||||
urlBuf.append(page);
|
||||
|
||||
// Add request parameters
|
||||
if (parameters.size() > 0) {
|
||||
if (!getAttributes().isEmpty()) {
|
||||
urlBuf.append('?');
|
||||
|
||||
String concat = "";
|
||||
|
||||
// Set parameters
|
||||
for (Object next : parameters.entrySet()) {
|
||||
Map.Entry entry = (Map.Entry) next;
|
||||
for (Map.Entry<String, Object> entry : getAttributes().entrySet()) {
|
||||
Object name = entry.getKey();
|
||||
List values = (List) entry.getValue();
|
||||
|
||||
@@ -234,11 +233,11 @@ public class Include extends Component {
|
||||
// instead, include tag requires that each parameter be a list of objects,
|
||||
// just like the HTTP servlet interfaces are (String[])
|
||||
if (value != null) {
|
||||
List currentValues = (List) parameters.get(key);
|
||||
List currentValues = (List) getAttributes().get(key);
|
||||
|
||||
if (currentValues == null) {
|
||||
currentValues = new ArrayList();
|
||||
parameters.put(key, currentValues);
|
||||
getAttributes().put(key, currentValues);
|
||||
}
|
||||
|
||||
currentValues.add(value);
|
||||
|
||||
@@ -174,7 +174,7 @@ public class InputTransferSelect extends ListUIBean {
|
||||
|
||||
|
||||
// key -> select tag id, value -> headerKey (if exists)
|
||||
Map formInputtransferselectIds = (Map) formAncestor.getParameters().get("inputtransferselectIds");
|
||||
Map formInputtransferselectIds = (Map) formAncestor.getAttributes().get("inputtransferselectIds");
|
||||
|
||||
// init lists
|
||||
if (formInputtransferselectIds == null) {
|
||||
@@ -182,13 +182,13 @@ public class InputTransferSelect extends ListUIBean {
|
||||
}
|
||||
|
||||
// id
|
||||
String tmpId = (String) getParameters().get("id");
|
||||
String tmpHeaderKey = (String) getParameters().get("headerKey");
|
||||
String tmpId = (String) getAttributes().get("id");
|
||||
String tmpHeaderKey = (String) getAttributes().get("headerKey");
|
||||
if (tmpId != null && (! formInputtransferselectIds.containsKey(tmpId))) {
|
||||
formInputtransferselectIds.put(tmpId, tmpHeaderKey);
|
||||
}
|
||||
|
||||
formAncestor.getParameters().put("inputtransferselectIds", formInputtransferselectIds);
|
||||
formAncestor.getAttributes().put("inputtransferselectIds", formInputtransferselectIds);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -306,7 +306,10 @@ public class IteratorComponent extends ContextBean {
|
||||
if ((iterator != null) && iterator.hasNext()) {
|
||||
Object currentValue = iterator.next();
|
||||
stack.push(currentValue);
|
||||
threadAllowlist.allowClass(currentValue.getClass());
|
||||
|
||||
if (currentValue != null) {
|
||||
threadAllowlist.allowClass(currentValue.getClass());
|
||||
}
|
||||
|
||||
String var = getVar();
|
||||
|
||||
|
||||
@@ -81,8 +81,8 @@ public class Label extends UIBean {
|
||||
if (value != null) {
|
||||
addParameter("nameValue", findString(value));
|
||||
} else if (key != null) {
|
||||
Object nameValue = parameters.get("nameValue");
|
||||
if (nameValue == null || nameValue.toString().length() == 0) {
|
||||
Object nameValue = getAttributes().get("nameValue");
|
||||
if (nameValue == null || nameValue.toString().isEmpty()) {
|
||||
// get the label from a TextProvider (default value is the key)
|
||||
String providedLabel = TextProviderHelper.getText(key, key, stack);
|
||||
addParameter("nameValue", providedLabel);
|
||||
|
||||
@@ -67,7 +67,7 @@ public abstract class ListUIBean extends UIBean {
|
||||
Object value = null;
|
||||
|
||||
if (list == null) {
|
||||
list = parameters.get("list");
|
||||
list = getAttributes().get("list");
|
||||
}
|
||||
|
||||
if (list instanceof String) {
|
||||
|
||||
@@ -90,7 +90,7 @@ public class OptGroup extends Component {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Inject
|
||||
public void setContainer(Container container) {
|
||||
container.inject(internalUiBean);
|
||||
@@ -106,7 +106,7 @@ public class OptGroup extends Component {
|
||||
internalUiBean.start(writer);
|
||||
internalUiBean.end(writer, body);
|
||||
|
||||
List listUiBeans = (List) select.getParameters().get(INTERNAL_LIST_UI_BEAN_LIST_PARAMETER_KEY);
|
||||
List listUiBeans = (List) select.getAttributes().get(INTERNAL_LIST_UI_BEAN_LIST_PARAMETER_KEY);
|
||||
if (listUiBeans == null) {
|
||||
listUiBeans = new ArrayList();
|
||||
}
|
||||
|
||||
@@ -287,8 +287,8 @@ public class OptionTransferSelect extends DoubleListUIBean {
|
||||
|
||||
|
||||
// key -> select tag id, value -> headerKey (if exists)
|
||||
Map formOptiontransferselectIds = (Map) formAncestor.getParameters().get("optiontransferselectIds");
|
||||
Map formOptiontransferselectDoubleIds = (Map) formAncestor.getParameters().get("optiontransferselectDoubleIds");
|
||||
Map formOptiontransferselectIds = (Map) formAncestor.getAttributes().get("optiontransferselectIds");
|
||||
Map formOptiontransferselectDoubleIds = (Map) formAncestor.getAttributes().get("optiontransferselectDoubleIds");
|
||||
|
||||
// init lists
|
||||
if (formOptiontransferselectIds == null) {
|
||||
@@ -300,21 +300,21 @@ public class OptionTransferSelect extends DoubleListUIBean {
|
||||
|
||||
|
||||
// id
|
||||
String tmpId = (String) getParameters().get("id");
|
||||
String tmpHeaderKey = (String) getParameters().get("headerKey");
|
||||
String tmpId = (String) getAttributes().get("id");
|
||||
String tmpHeaderKey = (String) getAttributes().get("headerKey");
|
||||
if (tmpId != null && (! formOptiontransferselectIds.containsKey(tmpId))) {
|
||||
formOptiontransferselectIds.put(tmpId, tmpHeaderKey);
|
||||
}
|
||||
|
||||
// doubleId
|
||||
String tmpDoubleId = (String) getParameters().get("doubleId");
|
||||
String tmpDoubleHeaderKey = (String) getParameters().get("doubleHeaderKey");
|
||||
String tmpDoubleId = (String) getAttributes().get("doubleId");
|
||||
String tmpDoubleHeaderKey = (String) getAttributes().get("doubleHeaderKey");
|
||||
if (tmpDoubleId != null && (! formOptiontransferselectDoubleIds.containsKey(tmpDoubleId))) {
|
||||
formOptiontransferselectDoubleIds.put(tmpDoubleId, tmpDoubleHeaderKey);
|
||||
}
|
||||
|
||||
formAncestor.getParameters().put("optiontransferselectIds", formOptiontransferselectIds);
|
||||
formAncestor.getParameters().put("optiontransferselectDoubleIds", formOptiontransferselectDoubleIds);
|
||||
formAncestor.getAttributes().put("optiontransferselectIds", formOptiontransferselectIds);
|
||||
formAncestor.getAttributes().put("optiontransferselectDoubleIds", formOptiontransferselectDoubleIds);
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -174,7 +174,7 @@ public class ServletUrlRenderer implements UrlRenderer {
|
||||
namespace, actionName);
|
||||
if (actionConfig != null) {
|
||||
|
||||
ActionMapping mapping = new ActionMapping(actionName, namespace, actionMethod, formComponent.parameters);
|
||||
ActionMapping mapping = new ActionMapping(actionName, namespace, actionMethod, formComponent.getAttributes());
|
||||
String result = urlHelper.buildUrl(formComponent.actionMapper.getUriFromActionMapping(mapping),
|
||||
formComponent.request, formComponent.response, queryStringResult.getQueryParams(), scheme, formComponent.includeContext, true, false, false);
|
||||
formComponent.addParameter("action", result);
|
||||
|
||||
@@ -50,17 +50,16 @@ import javax.servlet.http.HttpServletResponse;
|
||||
* </pre>
|
||||
*/
|
||||
@StrutsTag(
|
||||
name="textfield",
|
||||
tldTagClass="org.apache.struts2.views.jsp.ui.TextFieldTag",
|
||||
description="Render an HTML input field of type text",
|
||||
allowDynamicAttributes=true)
|
||||
name = "textfield",
|
||||
tldTagClass = "org.apache.struts2.views.jsp.ui.TextFieldTag",
|
||||
description = "Render an HTML input field of type text",
|
||||
allowDynamicAttributes = true)
|
||||
public class TextField extends UIBean {
|
||||
/**
|
||||
* The name of the default template for the TextFieldTag
|
||||
*/
|
||||
final public static String TEMPLATE = "text";
|
||||
|
||||
|
||||
protected String maxlength;
|
||||
protected String readonly;
|
||||
protected String size;
|
||||
@@ -95,27 +94,22 @@ public class TextField extends UIBean {
|
||||
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="HTML maxlength attribute", type="Integer")
|
||||
@StrutsTagAttribute(description = "HTML maxlength attribute", type = "Integer")
|
||||
public void setMaxlength(String maxlength) {
|
||||
this.maxlength = maxlength;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="Deprecated. Use maxlength instead.", type="Integer")
|
||||
public void setMaxLength(String maxlength) {
|
||||
this.maxlength = maxlength;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="Whether the input is readonly", type="Boolean", defaultValue="false")
|
||||
@StrutsTagAttribute(description = "Whether the input is readonly", type = "Boolean", defaultValue = "false")
|
||||
public void setReadonly(String readonly) {
|
||||
this.readonly = readonly;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="HTML size attribute", type="Integer")
|
||||
@StrutsTagAttribute(description = "HTML size attribute", type = "Integer")
|
||||
public void setSize(String size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="Specifies the html5 type element to display. e.g. text, email, url", defaultValue="text")
|
||||
@StrutsTagAttribute(description = "Specifies the html5 type element to display. e.g. text, email, url", defaultValue = "text")
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public class Token extends UIBean {
|
||||
super.evaluateExtraParams();
|
||||
|
||||
String tokenName;
|
||||
Map parameters = getParameters();
|
||||
Map parameters = getAttributes();
|
||||
|
||||
if (parameters.containsKey("name")) {
|
||||
tokenName = (String) parameters.get("name");
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.TextParseUtil;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
@@ -32,6 +31,7 @@ import org.apache.struts2.components.template.Template;
|
||||
import org.apache.struts2.components.template.TemplateEngine;
|
||||
import org.apache.struts2.components.template.TemplateEngineManager;
|
||||
import org.apache.struts2.components.template.TemplateRenderingContext;
|
||||
import org.apache.struts2.dispatcher.AttributeMap;
|
||||
import org.apache.struts2.dispatcher.StaticContentLoader;
|
||||
import org.apache.struts2.util.ComponentUtils;
|
||||
import org.apache.struts2.util.TextProviderHelper;
|
||||
@@ -40,6 +40,7 @@ import org.apache.struts2.views.util.ContextUtil;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.io.Writer;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -47,6 +48,10 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static java.util.Collections.emptyMap;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.struts2.dispatcher.DispatcherConstants.ATTRIBUTES;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* UIBean is the standard superclass of all Struts UI components.
|
||||
@@ -439,6 +444,9 @@ public abstract class UIBean extends Component {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(UIBean.class);
|
||||
|
||||
static final String TEMPLATE_DIR = "templateDir";
|
||||
static final String THEME = "theme";
|
||||
|
||||
protected static final String ATTR_FIELD_VALUE = "fieldValue";
|
||||
protected static final String ATTR_NAME_VALUE = "nameValue";
|
||||
protected static final String ATTR_VALUE = "value";
|
||||
@@ -590,7 +598,7 @@ public abstract class UIBean extends Component {
|
||||
|
||||
LOG.debug("Rendering template {}", template);
|
||||
|
||||
final TemplateRenderingContext context = new TemplateRenderingContext(template, writer, getStack(), getParameters(), this);
|
||||
final TemplateRenderingContext context = new TemplateRenderingContext(template, writer, getStack(), getAttributes(), this);
|
||||
engine.renderTemplate(context);
|
||||
}
|
||||
|
||||
@@ -601,13 +609,18 @@ public abstract class UIBean extends Component {
|
||||
result = findString(this.templateDir);
|
||||
}
|
||||
|
||||
// Check Request, Session, Application scopes
|
||||
if (isBlank(result)) {
|
||||
result = (String) getAttrMap().get(TEMPLATE_DIR);
|
||||
}
|
||||
|
||||
// Default template set
|
||||
if (StringUtils.isBlank(result)) {
|
||||
if (isBlank(result)) {
|
||||
result = defaultTemplateDir;
|
||||
}
|
||||
|
||||
// Defaults to 'template'
|
||||
if (StringUtils.isBlank(result)) {
|
||||
if (isBlank(result)) {
|
||||
result = "template";
|
||||
}
|
||||
|
||||
@@ -621,26 +634,36 @@ public abstract class UIBean extends Component {
|
||||
result = findString(this.theme);
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(result)) {
|
||||
if (isBlank(result)) {
|
||||
Form form = (Form) findAncestor(Form.class);
|
||||
if (form != null) {
|
||||
result = form.getTheme();
|
||||
}
|
||||
}
|
||||
|
||||
// Check Request, Session, Application scopes
|
||||
if (isBlank(result)) {
|
||||
result = (String) getAttrMap().get(THEME);
|
||||
}
|
||||
|
||||
// Default theme set
|
||||
if (StringUtils.isBlank(result)) {
|
||||
if (isBlank(result)) {
|
||||
result = defaultUITheme;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Map<String, Object> getAttrMap() {
|
||||
AttributeMap attrMap = (AttributeMap) getStack().getContext().get(ATTRIBUTES);
|
||||
return attrMap != null ? attrMap : emptyMap();
|
||||
}
|
||||
|
||||
public void evaluateParams() {
|
||||
String gotTheme = getTheme();
|
||||
|
||||
addParameter("templateDir", getTemplateDir());
|
||||
addParameter("theme", gotTheme);
|
||||
addParameter(TEMPLATE_DIR, getTemplateDir());
|
||||
addParameter(THEME, gotTheme);
|
||||
addParameter("template", template != null ? findString(template) : getDefaultTemplate());
|
||||
addParameter("dynamicAttributes", dynamicAttributes);
|
||||
addParameter("themeExpansionToken", uiThemeExpansionToken);
|
||||
@@ -654,7 +677,7 @@ public abstract class UIBean extends Component {
|
||||
if (this.key != null) {
|
||||
|
||||
if(this.name == null) {
|
||||
this.name = key;
|
||||
setName(key);
|
||||
}
|
||||
|
||||
if(this.label == null) {
|
||||
@@ -796,11 +819,11 @@ public abstract class UIBean extends Component {
|
||||
populateComponentHtmlId(form);
|
||||
|
||||
if (form != null ) {
|
||||
addParameter("form", form.getParameters());
|
||||
addParameter("form", form.getAttributes());
|
||||
|
||||
if ( translatedName != null ) {
|
||||
// list should have been created by the form component
|
||||
List<String> tags = (List<String>) form.getParameters().get("tagNames");
|
||||
List<String> tags = (List<String>) form.getAttributes().get("tagNames");
|
||||
tags.add(translatedName);
|
||||
}
|
||||
}
|
||||
@@ -832,19 +855,19 @@ public abstract class UIBean extends Component {
|
||||
}
|
||||
|
||||
//TODO: this is to keep backward compatibility, remove once when tooltipConfig is dropped
|
||||
String jsTooltipEnabled = (String) getParameters().get("jsTooltipEnabled");
|
||||
String jsTooltipEnabled = (String) getAttributes().get("jsTooltipEnabled");
|
||||
if (jsTooltipEnabled != null)
|
||||
this.javascriptTooltip = jsTooltipEnabled;
|
||||
|
||||
//TODO: this is to keep backward compatibility, remove once when tooltipConfig is dropped
|
||||
String tooltipIcon = (String) getParameters().get("tooltipIcon");
|
||||
String tooltipIcon = (String) getAttributes().get("tooltipIcon");
|
||||
if (tooltipIcon != null)
|
||||
this.addParameter("tooltipIconPath", tooltipIcon);
|
||||
if (this.tooltipIconPath != null)
|
||||
this.addParameter("tooltipIconPath", findString(this.tooltipIconPath));
|
||||
|
||||
//TODO: this is to keep backward compatibility, remove once when tooltipConfig is dropped
|
||||
String tooltipDelayParam = (String) getParameters().get("tooltipDelay");
|
||||
String tooltipDelayParam = (String) getAttributes().get("tooltipDelay");
|
||||
if (tooltipDelayParam != null)
|
||||
this.addParameter("tooltipDelay", tooltipDelayParam);
|
||||
if (this.tooltipDelay != null)
|
||||
@@ -863,10 +886,13 @@ public abstract class UIBean extends Component {
|
||||
}
|
||||
|
||||
// to be used with the CSP interceptor - adds the nonce value as a parameter to be accessed from ftl files
|
||||
Map<String, Object> session = stack.getActionContext().getSession();
|
||||
Object nonceValue = session != null ? session.get("nonce") : null;
|
||||
HttpSession session = stack.getActionContext().getServletRequest().getSession(false);
|
||||
Object nonceValue = session != null ? session.getAttribute("nonce") : null;
|
||||
|
||||
if (nonceValue != null) {
|
||||
addParameter("nonce", nonceValue.toString());
|
||||
} else {
|
||||
LOG.debug("Session is not active, cannot obtain nonce value");
|
||||
}
|
||||
|
||||
evaluateExtraParams();
|
||||
@@ -878,8 +904,8 @@ public abstract class UIBean extends Component {
|
||||
*/
|
||||
protected void applyValueParameter(String translatedName) {
|
||||
// see if the value has been specified as a parameter already
|
||||
if (parameters.containsKey(ATTR_VALUE)) {
|
||||
parameters.put(ATTR_NAME_VALUE, parameters.get(ATTR_VALUE));
|
||||
if (getAttributes().containsKey(ATTR_VALUE)) {
|
||||
getAttributes().put(ATTR_NAME_VALUE, getAttributes().get(ATTR_VALUE));
|
||||
} else {
|
||||
if (evaluateNameValue()) {
|
||||
final Class<?> valueClazz = getValueClassType();
|
||||
@@ -965,7 +991,7 @@ public abstract class UIBean extends Component {
|
||||
}
|
||||
|
||||
protected Map<String, String> getTooltipConfig(UIBean component) {
|
||||
Object tooltipConfigObj = component.getParameters().get("tooltipConfig");
|
||||
Object tooltipConfigObj = component.getAttributes().get("tooltipConfig");
|
||||
Map<String, String> result = new LinkedHashMap<>();
|
||||
|
||||
if (tooltipConfigObj instanceof Map) {
|
||||
@@ -1026,7 +1052,7 @@ public abstract class UIBean extends Component {
|
||||
LOG.debug("Cannot determine id attribute for [{}], consider defining id, name or key attribute!", this);
|
||||
tryId = null;
|
||||
} else if (form != null) {
|
||||
tryId = form.getParameters().get("id") + "_" + generatedId;
|
||||
tryId = form.getAttributes().get("id") + "_" + generatedId;
|
||||
} else {
|
||||
tryId = generatedId;
|
||||
}
|
||||
@@ -1133,6 +1159,13 @@ public abstract class UIBean extends Component {
|
||||
|
||||
@StrutsTagAttribute(description="The name to set for element")
|
||||
public void setName(String name) {
|
||||
if (name != null && name.startsWith("$")) {
|
||||
LOG.error("The name attribute should not usually be a templating variable." +
|
||||
" This can cause a critical vulnerability if the resolved value is derived from user input." +
|
||||
" If you are certain that you require this behaviour, please use OGNL expression syntax ( %{expr} ) instead.",
|
||||
new IllegalStateException());
|
||||
return;
|
||||
}
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ public class URL extends ContextBean {
|
||||
|
||||
public URL(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
|
||||
super(stack);
|
||||
urlProvider = new ComponentUrlProvider(this, this.parameters);
|
||||
urlProvider = new ComponentUrlProvider(this, this.getAttributes());
|
||||
urlProvider.setHttpServletRequest(req);
|
||||
urlProvider.setHttpServletResponse(res);
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ import java.util.Map;
|
||||
* {@literal @}s.tag name="updownselect" tld-body-content="JSP" tld-tag-class="org.apache.struts2.views.jsp.ui.UpDownSelectTag"
|
||||
* description="Render a up down select element"
|
||||
*/
|
||||
@StrutsTag(name="updownselect", tldTagClass="org.apache.struts2.views.jsp.ui.UpDownSelectTag",
|
||||
@StrutsTag(name="updownselect", tldTagClass="org.apache.struts2.views.jsp.ui.UpDownSelectTag",
|
||||
description="Create a Select component with buttons to move the elements in the select component up and down")
|
||||
public class UpDownSelect extends Select {
|
||||
|
||||
@@ -136,13 +136,13 @@ public class UpDownSelect extends Select {
|
||||
// inform form ancestor that we are using a custom onSubmit
|
||||
enableAncestorFormCustomOnsubmit();
|
||||
|
||||
Map m = (Map) ancestorForm.getParameters().get("updownselectIds");
|
||||
Map m = (Map) ancestorForm.getAttributes().get("updownselectIds");
|
||||
if (m == null) {
|
||||
// map with key -> id , value -> headerKey
|
||||
m = new LinkedHashMap();
|
||||
}
|
||||
m.put(getParameters().get("id"), getParameters().get("headerKey"));
|
||||
ancestorForm.getParameters().put("updownselectIds", m);
|
||||
m.put(getAttributes().get("id"), getAttributes().get("headerKey"));
|
||||
ancestorForm.getAttributes().put("updownselectIds", m);
|
||||
}
|
||||
else {
|
||||
if (LOG.isWarnEnabled()) {
|
||||
|
||||
@@ -86,7 +86,7 @@ public class AttributeMap extends AbstractMap<String, Object> {
|
||||
|
||||
PageContext pc = getPageContext();
|
||||
|
||||
if (pc == null) {
|
||||
if (pc == null || pc.getRequest() == null) {
|
||||
RequestMap request = (RequestMap) context.get(DispatcherConstants.REQUEST);
|
||||
SessionMap session = (SessionMap) context.get(DispatcherConstants.SESSION);
|
||||
ApplicationMap application = (ApplicationMap) context.get(DispatcherConstants.APPLICATION);
|
||||
|
||||
@@ -112,7 +112,7 @@ public class Dispatcher {
|
||||
*/
|
||||
public static final String REQUEST_POST_METHOD = "POST";
|
||||
|
||||
public static final String MULTIPART_FORM_DATA_REGEX = "^multipart/form-data(?:\\s*;\\s*boundary=[0-9a-zA-Z'()+_,\\-./:=?]{1,70})?(?:\\s*;\\s*charset=[a-zA-Z\\-0-9]{3,14})?";
|
||||
public static final String MULTIPART_FORM_DATA_REGEX = "^multipart/form-data(?:\\s*;\\s*boundary=[0-9a-zA-Z'\"()+_,\\-./:=?]{1,70})?(?:\\s*;\\s*charset=[a-zA-Z\\-0-9]{3,14})?";
|
||||
|
||||
private static final String CONFIG_SPLIT_REGEX = "\\s*,\\s*";
|
||||
|
||||
@@ -734,7 +734,7 @@ public class Dispatcher {
|
||||
// if the ActionMapping says to go straight to a result, do it!
|
||||
if (mapping.getResult() != null) {
|
||||
Result result = mapping.getResult();
|
||||
result.execute(proxy.getInvocation());
|
||||
result.execute((org.apache.struts2.ActionInvocation) proxy.getInvocation());
|
||||
} else {
|
||||
proxy.execute();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user