Compare commits

...

207 Commits

Author SHA1 Message Date
Lukasz Lenart 8fb9aba74b [maven-release-plugin] prepare release STRUTS_6_7_4 2025-02-20 13:20:46 +01:00
Lukasz Lenart c45664a330 Merge pull request #1226 from apache/fix/WW-5529-maxlength-s6
WW-5529 Adds autogenerated files with updated desc
2025-02-20 13:05:57 +01:00
Lukasz Lenart 91c9314176 WW-5529 Adds autogenerated files with updated desc 2025-02-20 12:21:58 +01:00
Kusal Kithul-Godage a4e9902d94 Merge pull request #1225 from apache/WW-5531-jre8-compat
WW-5531 Enforce JRE8 compatibility (when compiled on JDK9+)
2025-02-20 17:22:42 +11:00
Kusal Kithul-Godage fe5b197738 WW-5531 Enforce JRE8 compatibility (when compiled on JDK9+) 2025-02-20 16:23:10 +11:00
Lukasz Lenart 87e322dbe2 [maven-release-plugin] prepare for next development iteration 2025-02-17 11:34:19 +01:00
Lukasz Lenart 7909f43237 [maven-release-plugin] prepare release STRUTS_6_7_3 2025-02-17 11:34:11 +01:00
Lukasz Lenart 1fe822cca0 WW-5529 Drops unused misleading setter setMaxLength in favour of setMaxlength (#1221) (#1222) 2025-02-17 10:27:04 +01:00
Kusal Kithul-Godage ef90b3ba3c Merge pull request #1220 from apache/WW-5525-proxyutil-npe-67
6.7: WW-5525 Fix NPE in ProxyUtil for SecurityMemberAccess originating static members
2025-02-17 19:11:21 +11:00
Lukasz Lenart d35ec15c76 WW-5525 Fixes NPE when checking if expressions is acceptable
(cherry picked from commit 9fee06cea0)
2025-02-17 18:57:27 +11:00
Kusal Kithul-Godage 583b174fe6 WW-5525 Fix NPE in ProxyUtil for SecurityMemberAccess originating static members 2025-02-17 18:57:27 +11:00
Lukasz Lenart 9b044377ac WW-5501 Reverts all changes related to WW-5501 (#1218)
* Reverts all changes related to WW-5501

* Fixes CodeQL scan by using proper versions of actions

* WW-5501 Uses FilenameUtils instead of a custom code
2025-02-16 12:05:49 +01:00
Kusal Kithul-Godage 58f37babbf Merge pull request #1215 from apache/WW-5528-multipart-illegal-char-errors-67 2025-02-09 23:44:10 +11:00
Kusal Kithul-Godage fe3dd6ba9f WW-5528 Ensure multipart upload illegal characters reported as error 2025-02-07 12:40:42 +11:00
Lukasz Lenart 7a77c7a82c [maven-release-plugin] prepare for next development iteration 2025-02-04 07:39:44 +01:00
Lukasz Lenart 5038a9209f [maven-release-plugin] prepare release STRUTS_6_7_2 2025-02-04 07:39:35 +01:00
Lukasz Lenart 2135ebf651 WW-5501 Ignores DMI related action field (#1211) 2025-02-04 06:47:43 +01:00
Kusal Kithul-Godage c0dd8dd80c Merge pull request #1210 from apache/WW-5516-attrmap-npe-67 2025-02-04 01:19:16 +11:00
Kusal Kithul-Godage c36eafa37a WW-5516 Fix AttributeMap NPE when PageContext has no request 2025-02-04 01:00:36 +11:00
Lukasz Lenart 07603b9591 [maven-release-plugin] prepare for next development iteration 2025-02-02 10:16:30 +01:00
Lukasz Lenart 3227d5929a [maven-release-plugin] prepare release STRUTS_6_7_1 2025-02-02 10:16:20 +01:00
Lukasz Lenart 4a8ddbb274 Merge pull request #1202 from apache/fix/bom-version
Defines proper snapshot version for BOM
2025-02-02 10:10:35 +01:00
Lukasz Lenart 67ba458d03 Defines proper snapshot version for BOM 2025-02-02 10:00:09 +01:00
Lukasz Lenart 959b2182b2 Merge pull request #1195 from apache/fix/proper-version
Defines proper snapshot version
2025-01-24 08:28:32 +01:00
Lukasz Lenart 6de93e77db Defines proper snapshot version 2025-01-24 07:58:39 +01:00
Lukasz Lenart 59dc9301e0 Merge pull request #1194 from apache/fix/jenkinsfile-67x
Simplifies Jenkinsfile to build Struts 6.x
2025-01-22 08:18:56 +01:00
Lukasz Lenart 2fc4a822a4 Simplifies Jenkinsfile to build Struts 6.x 2025-01-22 07:52:34 +01:00
Kusal Kithul-Godage 6a6270f62a Merge pull request #1190 from apache/WW-5516-fix-temp-theme-fallback
WW-5516 Fix TemplateDir and Theme fallback to Request/Session/Application attributes
2025-01-22 13:24:09 +11:00
Lukasz Lenart 9153228b6a Merge pull request #1192 from apache/fix/nightlies-67x
Fixes nightlies builds
2025-01-21 20:31:59 +01:00
Lukasz Lenart 5713a74edc Fixes nightlies builds 2025-01-21 18:06:11 +01:00
Kusal Kithul-Godage 32071c71ad WW-5516 Fix TemplateDir and Theme fallback to Request/Session/Application attributes 2025-01-21 20:05:24 +11:00
Lukasz Lenart 7e4791985b Merge pull request #1175 from apache/feature/WW-5512-optional-inject
WW-5512 Extends the container to support injecting optional parameters into constructor
2025-01-21 07:25:58 +01:00
Lukasz Lenart 3c1e44ca2d WW-5512 Supports mixing required and optional parameters in any order 2025-01-19 09:53:01 +01:00
Lukasz Lenart 2ba8d97ad0 WW-5512 Supports mixing required and optional parameters 2025-01-19 09:36:27 +01:00
Lukasz Lenart cba0db0b07 Merge pull request #1181 from apache/fix/WW-5501-exclude
WW-5501 Only exclude malicious file names
2025-01-16 07:28:46 +01:00
Lukasz Lenart 688162cae2 WW-5501 Only exclude malicious file names 2025-01-14 07:47:39 +01:00
Lukasz Lenart a33c162f53 WW-5512 Extends the container to support injecting optional parameters into constructor 2025-01-05 17:45:11 +01:00
Lukasz Lenart c7a6daf5ce Merge pull request #1169 from apache/fix/WW-5500
WW-5500 Extends pattern to validate multipart uploads
2025-01-05 09:20:33 +01:00
Lukasz Lenart 370c7ce17a Merge pull request #1168 from apache/fix/WW-5498
WW-5498 Adds devMode errors as action messages to avoid breaking validation logic
2025-01-05 09:16:44 +01:00
Lukasz Lenart 55989befce Merge pull request #1167 from apache/fix/excluded-packages
Excludes new & old packages
2025-01-04 14:37:47 +01:00
Lukasz Lenart 2e4a4b5e36 Excludes new & old packages 2025-01-04 13:56:31 +01:00
Lukasz Lenart 9d07c3b4c3 WW-5498 Adds devMode errors as action messages to avoid breaking validation logic 2025-01-03 17:14:12 +01:00
Lukasz Lenart 575e4e8c9b WW-5500 Extends pattern to validate multipart uploads 2025-01-03 17:10:59 +01:00
Lukasz Lenart 74388dfba7 Merge pull request #1158 from apache/fix/updates-asf-yaml
Updates .asf.yaml to match main
2024-12-23 16:11:55 +01:00
Lukasz Lenart 4ee8b02262 Updates .asf.yaml to match main 2024-12-23 15:24:10 +01:00
Lukasz Lenart c8febc2050 Merge pull request #1156 from apache/feature/WW-5501-exclude
WW-5501 Exclude malicious names
2024-12-23 15:08:58 +01:00
Lukasz Lenart 3ea126388c WW-5501 Uses StringUtils.normalizeSpace instead of sanitizeNewlines 2024-12-23 14:13:26 +01:00
Lukasz Lenart 09993e3476 WW-5501 Exclude malicious names 2024-12-23 12:05:15 +01:00
Lukasz Lenart f5688e680b Merge pull request #1150 from apache/feature/prepare-development
Sets version to 6.7.1-SNAPSHOT to prepare for another development cycle
2024-12-18 15:42:21 +01:00
Lukasz Lenart 60a3db0a63 Sets version to 6.7.1-SNAPSHOT to prepare for another development cycle 2024-12-18 14:43:29 +01:00
Lukasz Lenart 4714d27678 Merge pull request #1141 from apache/fix/WW-5493-parameters
WW-5493 Restores parameters and uses getAttributes()
2024-12-18 07:42:47 +01:00
Lukasz Lenart 4feceee5f1 WW-5493 Restores parameters and uses getAttributes()
Instead of using parameters field directly, this PR uses getAttributes() instead to avoid coupling with internal Component state
2024-12-04 08:19:34 +01:00
Lukasz Lenart 1f5305c249 [maven-release-plugin] prepare release STRUTS_6_7_0 2024-11-17 10:57:09 +01:00
Lukasz Lenart 1903e0ef33 Merge pull request #1126 from apache/feature/WW-5484-dwr
WW-5484 Marks the DWR plugin as deprecated
2024-11-14 15:55:01 +01:00
Lukasz Lenart 8a2f494c12 WW-5484 Marks the DWR plugin as deprecated 2024-11-11 17:49:54 +01:00
Lukasz Lenart 6b2e5ecd9b Merge pull request #1125 from apache/dependabot/github_actions/github/codeql-action-3.27.1
Bump github/codeql-action from 3.27.0 to 3.27.1
2024-11-11 07:37:48 +01:00
dependabot[bot] cb08d18b5a Bump github/codeql-action from 3.27.0 to 3.27.1
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.27.0 to 3.27.1.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Commits](https://github.com/github/codeql-action/compare/v3.27.0...v3.27.1)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 01:45:38 +00:00
Kusal Kithul-Godage 1e2517b59e Merge pull request #1117 from apache/WW-3714-overriding-behaviour
WW-3714 Ensure correct delegation of deprecated API methods
2024-11-03 21:06:59 +11:00
Kusal Kithul-Godage 8d6ecee849 Merge pull request #1116 from apache/WW-5459-repkg-action-chain-2 2024-11-03 18:53:21 +11:00
Kusal Kithul-Godage 570bf46a7f Merge pull request #1115 from apache/WW-5459-repkg-action-chain 2024-11-03 18:52:42 +11:00
Kusal Kithul-Godage be82a72403 WW-3714 Ensure correct delegation of new Interceptor API 2024-11-03 11:47:34 +11:00
Kusal Kithul-Godage 6fbd9e5321 WW-3714 Ensure correct delegation of new Result API 2024-11-03 11:26:14 +11:00
Kusal Kithul-Godage b0a4c4f417 WW-5459 Deprecate and repackage ActionChainResult 2024-11-03 11:25:46 +11:00
Kusal Kithul-Godage b001c61f89 WW-5459 Move new Action class into action package 2024-11-03 10:49:36 +11:00
Kusal Kithul-Godage 2beac8eba4 Merge pull request #1109 from apache/WW-3714-result-repackage
WW-3714 Move new Result class into result package
2024-11-03 10:46:42 +11:00
Kusal Kithul-Godage d351843ecd WW-3714 Move new Result class into result package 2024-11-02 23:01:07 +11:00
Kusal Kithul-Godage 22036174c7 Merge pull request #1108 from apache/WW-5480-templating-warning
WW-5480 Warn against potential templating bug
2024-11-02 22:58:34 +11:00
Kusal Kithul-Godage ced44650ec WW-5480 Warn against potential templating bug 2024-11-02 14:42:07 +11:00
Kusal Kithul-Godage 1908cbab8f Merge pull request #1105 from apache/WW-5476-defaultresultfactory
WW-5478 Deprecate DefaultResultFactory
2024-11-02 14:05:37 +11:00
Kusal Kithul-Godage c176390926 WW-5478 Fix ActionContext equals/hashCode contract 2024-11-02 14:01:37 +11:00
Kusal Kithul-Godage fe46ad9f4a WW-5478 Deprecate DefaultResultFactory 2024-11-02 14:01:36 +11:00
Kusal Kithul-Godage a0dc19c4be Merge pull request #1104 from apache/WW-5468-modeldriven-strutsparameter-fix 2024-11-01 23:19:43 +11:00
Kusal Kithul-Godage 7cdcd84b83 Merge pull request #1072 from apache/fix/WW-5468-modeldriven-2
WW-5468 Exempt ModelDriven Actions from @StrutsParameter requirement
2024-11-01 19:17:21 +11:00
Lukasz Lenart 8566c14648 Merge pull request #1096 from apache/feature/WW-5476-deprecate
WW-5476 Deprecates tag's parameters as replaced with attributes
2024-10-30 06:43:07 +01:00
Lukasz Lenart c75ddbbf3e Merge pull request #1098 from apache/dependabot/maven/asm.version-9.7.1
Bump asm.version from 9.7 to 9.7.1
2024-10-29 16:00:40 +01:00
Lukasz Lenart b15dc458cf Merge pull request #1102 from apache/dependabot/github_actions/github/codeql-action-3.27.0
Bump github/codeql-action from 3.26.13 to 3.27.0
2024-10-29 16:00:12 +01:00
dependabot[bot] 3f74923099 Bump github/codeql-action from 3.26.13 to 3.27.0
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.13 to 3.27.0.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Commits](https://github.com/github/codeql-action/compare/v3.26.13...v3.27.0)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-28 01:54:27 +00:00
dependabot[bot] 5b2f63fa7e Bump asm.version from 9.7 to 9.7.1
Bumps `asm.version` from 9.7 to 9.7.1.

Updates `org.ow2.asm:asm` from 9.7 to 9.7.1

Updates `org.ow2.asm:asm-commons` from 9.7 to 9.7.1

---
updated-dependencies:
- dependency-name: org.ow2.asm:asm
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.ow2.asm:asm-commons
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-28 01:50:03 +00:00
Lukasz Lenart d9d580ae3d Merge pull request #1094 from apache/dependabot/maven/org.apache.commons-commons-lang3-3.17.0
WW-5477 Bump org.apache.commons:commons-lang3 from 3.15.0 to 3.17.0
2024-10-27 09:01:15 +01:00
Lukasz Lenart 67e0477993 WW-5476 Deprecates tag's parameters as replaced with attributes 2024-10-25 08:28:18 +02:00
Kusal Kithul-Godage 89bcbecc70 Merge pull request #1085 from apache/kusal-depr-apis-7
WW-3714 Deprecate and repackage common APIs part 6
2024-10-25 12:13:09 +11:00
Kusal Kithul-Godage 67ee1b2d67 Merge pull request #1084 from apache/kusal-depr-apis-6 2024-10-23 21:12:42 +11:00
Kusal Kithul-Godage 5b81ec0852 Merge pull request #1083 from apache/kusal-depr-apis-5
WW-3714 Deprecate and repackage common APIs part 4
2024-10-22 23:11:23 +11:00
Kusal Kithul-Godage 266cd1333c Merge pull request #1082 from apache/kusal-depr-apis-4
WW-3714 Deprecate and repackage common APIs part 3
2024-10-22 23:11:07 +11:00
Kusal Kithul-Godage 323267fa88 Merge pull request #1087 from apache/kusal-depr-apis-3.5
WW-3714 Deprecate and repackage common APIs part 2.5
2024-10-22 23:10:48 +11:00
Kusal Kithul-Godage 2432449975 WW-3714 Update StrutsResultSupport to allow overriding new signature 2024-10-22 18:50:56 +11:00
Kusal Kithul-Godage 45a1f5efc6 WW-3714 Deprecate and migrate assorted Interceptors 2024-10-22 18:50:56 +11:00
Kusal Kithul-Godage b488c80aa2 Merge pull request #1081 from apache/kusal-depr-apis-3
WW-3714 Deprecate and repackage common APIs part 2
2024-10-22 18:03:00 +11:00
Lukasz Lenart 144010c3b7 Merge pull request #1093 from apache/dependabot/maven/org.apache.maven.doxia-doxia-core-2.0.0
Bump org.apache.maven.doxia:doxia-core from 1.12.0 to 2.0.0
2024-10-22 08:27:26 +02:00
Lukasz Lenart 9b87e88bb0 Merge pull request #1095 from apache/dependabot/maven/org.apache.maven.plugins-maven-failsafe-plugin-3.5.1
Bump org.apache.maven.plugins:maven-failsafe-plugin from 3.3.1 to 3.5.1
2024-10-22 08:27:07 +02:00
Lukasz Lenart 117e84f246 Merge pull request #1092 from apache/dependabot/maven/maven-surefire-plugin.version-3.5.1
Bump maven-surefire-plugin.version from 3.5.0 to 3.5.1
2024-10-22 08:26:39 +02:00
Lukasz Lenart a28f22605c Merge pull request #1090 from apache/dependabot/github_actions/github/codeql-action-3.26.13
Bump github/codeql-action from 3.26.12 to 3.26.13
2024-10-22 08:26:02 +02:00
Kusal Kithul-Godage deb6c09bce WW-3714 Replace deprecated APIs in new ActionSupport 2024-10-22 17:02:11 +11:00
Kusal Kithul-Godage f95f9a7cd3 WW-3714 Add alternative constructors in InterceptorMapping 2024-10-22 17:02:11 +11:00
Kusal Kithul-Godage 9e23fbe665 WW-3714 Deprecate and migrate AbstractInterceptor and MethodFilterInterceptor 2024-10-22 17:02:11 +11:00
Kusal Kithul-Godage a623842bce WW-3714 Deprecate and migrate ActionSupport 2024-10-22 17:02:11 +11:00
Kusal Kithul-Godage 2757c23572 WW-3714 Fix replacement ValidationAware marker not recognised 2024-10-22 17:01:57 +11:00
Kusal Kithul-Godage ebedd7391f WW-3714 Marker interface migration follow-up 2024-10-22 13:55:46 +11:00
Kusal Kithul-Godage 7ce8f484e0 WW-3714 Shortcut adapters 2024-10-22 13:55:46 +11:00
Kusal Kithul-Godage dfd07190bd WW-3714 Update new ActionContext with new ValueStack 2024-10-22 13:55:46 +11:00
Kusal Kithul-Godage 111bc25650 WW-3714 Deprecate and migrate assorted marker interfaces 2024-10-22 13:55:46 +11:00
Kusal Kithul-Godage 8ba8ee5fe6 WW-3714 Deprecate and migrate ValueStack 2024-10-22 13:55:46 +11:00
Kusal Kithul-Godage 14bd4b80cf WW-3714 Deprecate and migrate ActionProxy 2024-10-22 13:55:19 +11:00
Kusal Kithul-Godage bbca2717f9 WW-3714 Deprecate and migrate ActionEventListener 2024-10-22 13:55:19 +11:00
Kusal Kithul-Godage b622e5d725 WW-3714 Ensure ReflectionExceptionHandler, WithLazyParams, ParamNameAwareResult marker interfaces respected 2024-10-22 13:50:45 +11:00
Kusal Kithul-Godage efa447af21 Merge pull request #1079 from apache/kusal-depr-apis
WW-3714 Deprecate and repackage common APIs part 1
2024-10-22 10:53:36 +11:00
dependabot[bot] cf6cbf3816 Bump org.apache.maven.plugins:maven-failsafe-plugin from 3.3.1 to 3.5.1
Bumps [org.apache.maven.plugins:maven-failsafe-plugin](https://github.com/apache/maven-surefire) from 3.3.1 to 3.5.1.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.3.1...surefire-3.5.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 01:48:11 +00:00
dependabot[bot] 48ee44bbc2 Bump org.apache.commons:commons-lang3 from 3.15.0 to 3.17.0
Bumps org.apache.commons:commons-lang3 from 3.15.0 to 3.17.0.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-lang3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 01:48:04 +00:00
dependabot[bot] b18fbda1f7 Bump org.apache.maven.doxia:doxia-core from 1.12.0 to 2.0.0
Bumps [org.apache.maven.doxia:doxia-core](https://github.com/apache/maven-doxia) from 1.12.0 to 2.0.0.
- [Release notes](https://github.com/apache/maven-doxia/releases)
- [Commits](https://github.com/apache/maven-doxia/compare/doxia-1.12.0...doxia-2.0.0)

---
updated-dependencies:
- dependency-name: org.apache.maven.doxia:doxia-core
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 01:48:01 +00:00
dependabot[bot] 28c8f1503d Bump maven-surefire-plugin.version from 3.5.0 to 3.5.1
Bumps `maven-surefire-plugin.version` from 3.5.0 to 3.5.1.

Updates `org.apache.maven.surefire:surefire-junit47` from 3.5.0 to 3.5.1

Updates `org.apache.maven.plugins:maven-surefire-plugin` from 3.5.0 to 3.5.1
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.5.0...surefire-3.5.1)

---
updated-dependencies:
- dependency-name: org.apache.maven.surefire:surefire-junit47
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.apache.maven.plugins:maven-surefire-plugin
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 01:47:53 +00:00
dependabot[bot] d1695f7a4d Bump github/codeql-action from 3.26.12 to 3.26.13
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.12 to 3.26.13.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Commits](https://github.com/github/codeql-action/compare/v3.26.12...v3.26.13)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-21 01:29:19 +00:00
Lukasz Lenart b359da5517 Merge pull request #1068 from JCgH4164838Gh792C124B5/localS2_66_JakartaMulipartRequestFix1
Potential mitigation for WW-5466
2024-10-20 11:09:53 +02:00
Kusal Kithul-Godage 36a890ba69 WW-3714 Add factory support for new Interceptor, Result interfaces 2024-10-17 20:23:48 +11:00
Kusal Kithul-Godage e3fbe88355 WW-3714 Update new ActionContext with new ActionInvocation 2024-10-17 17:32:09 +11:00
Kusal Kithul-Godage 272c2e7bba WW-3714 Deprecate and migrate PreResultListener 2024-10-17 15:04:53 +11:00
Kusal Kithul-Godage 60095a6934 WW-3714 Deprecate and migrate ActionInvocation 2024-10-17 15:03:53 +11:00
Kusal Kithul-Godage ae9dc42da7 WW-3714 Deprecate and migrate ConditionalInterceptor 2024-10-17 14:22:30 +11:00
Kusal Kithul-Godage 8da6a79926 WW-3714 Deprecate and migrate ActionContext 2024-10-17 13:38:26 +11:00
Kusal Kithul-Godage 7deb481298 WW-3714 Deprecate and migrate Action, Interceptor, Result 2024-10-17 13:38:26 +11:00
Lukasz Lenart 9f2770b2c3 Merge pull request #1075 from apache/feature/WW-5471-deprecate-sitemesh
WW-5471 Marks Sitemesh plugin as deprecated
2024-10-15 16:16:44 +02:00
Lukasz Lenart 78451db87e Merge pull request #1062 from apache/dependabot/maven/jackson.version-2.18.0
WW-5469 Bump jackson.version from 2.17.2 to 2.18.0
2024-10-14 08:08:01 +02:00
Lukasz Lenart 49ddf6130a WW-5471 Marks Sitemesh plugin as deprecated 2024-10-14 07:55:05 +02:00
dependabot[bot] 1bcadd4682 Bump jackson.version from 2.17.2 to 2.18.0
Bumps `jackson.version` from 2.17.2 to 2.18.0.

Updates `com.fasterxml.jackson.core:jackson-core` from 2.17.2 to 2.18.0
- [Commits](https://github.com/FasterXML/jackson-core/compare/jackson-core-2.17.2...jackson-core-2.18.0)

Updates `com.fasterxml.jackson.core:jackson-databind` from 2.17.2 to 2.18.0
- [Commits](https://github.com/FasterXML/jackson/commits)

Updates `com.fasterxml.jackson.dataformat:jackson-dataformat-xml` from 2.17.2 to 2.18.0
- [Commits](https://github.com/FasterXML/jackson-dataformat-xml/compare/jackson-dataformat-xml-2.17.2...jackson-dataformat-xml-2.18.0)

---
updated-dependencies:
- dependency-name: com.fasterxml.jackson.core:jackson-core
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: com.fasterxml.jackson.core:jackson-databind
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: com.fasterxml.jackson.dataformat:jackson-dataformat-xml
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-14 05:40:12 +00:00
Lukasz Lenart b115a510a6 Merge pull request #1064 from apache/dependabot/maven/log4j2.version-2.24.1
WW-5470 Bump log4j2.version from 2.23.1 to 2.24.1
2024-10-14 07:39:16 +02:00
Lukasz Lenart fbab5d4df9 Merge pull request #1065 from apache/dependabot/maven/org.apache.maven.plugins-maven-project-info-reports-plugin-3.7.0
Bump org.apache.maven.plugins:maven-project-info-reports-plugin from 3.6.2 to 3.7.0
2024-10-14 07:28:01 +02:00
Lukasz Lenart cd7f1097e2 Merge pull request #1061 from apache/dependabot/maven/commons-logging-commons-logging-1.3.4
Bump commons-logging:commons-logging from 1.3.3 to 1.3.4
2024-10-14 07:27:47 +02:00
Lukasz Lenart 2eff2da4fd Merge pull request #1074 from apache/dependabot/github_actions/actions/upload-artifact-4.4.3
Bump actions/upload-artifact from 4.4.0 to 4.4.3
2024-10-14 07:24:46 +02:00
Lukasz Lenart b3629460e6 Merge pull request #1073 from apache/dependabot/github_actions/github/codeql-action-3.26.12
Bump github/codeql-action from 3.26.8 to 3.26.12
2024-10-14 07:24:29 +02:00
dependabot[bot] 3528b88327 Bump actions/upload-artifact from 4.4.0 to 4.4.3
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.4.0 to 4.4.3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/50769540e7f4bd5e21e526ee35c689e35e0d6874...b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-14 01:45:55 +00:00
dependabot[bot] 3e04197ba7 Bump github/codeql-action from 3.26.8 to 3.26.12
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.8 to 3.26.12.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Commits](https://github.com/github/codeql-action/compare/v3.26.8...v3.26.12)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-14 01:45:53 +00:00
JCgH4164838Gh792C124B5 09eb286020 Initial Commit:
- Fix for boundary condition bug in JakartaMultipartRequest that results
in a NPE when struts.multipart.maxStringLength is not explicitly set, and
normal fields are processed along with a file upload.
- Additional unit tests for file upload interceptors to confirm
functionality with-or-without max parameters being set when a file upload
is processed alone as well as with normal fields.
2024-10-06 15:37:16 -04:00
Lukasz Lenart d33be1d43c [maven-release-plugin] prepare for next development iteration 2024-10-05 16:08:38 +02:00
Lukasz Lenart c812450292 [maven-release-plugin] prepare release STRUTS_6_6_1 2024-10-05 16:08:26 +02:00
Lukasz Lenart 75cc664fda Merge pull request #1060 from apache/fix/WW-5297-invalid-session
WW-5297 Fixes checking nonce of invalidated session
2024-10-01 06:44:58 +02:00
dependabot[bot] 9d903ddf96 Bump org.apache.maven.plugins:maven-project-info-reports-plugin
Bumps [org.apache.maven.plugins:maven-project-info-reports-plugin](https://github.com/apache/maven-project-info-reports-plugin) from 3.6.2 to 3.7.0.
- [Commits](https://github.com/apache/maven-project-info-reports-plugin/compare/maven-project-info-reports-plugin-3.6.2...maven-project-info-reports-plugin-3.7.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-30 01:12:53 +00:00
dependabot[bot] 4ccde0087e Bump log4j2.version from 2.23.1 to 2.24.1
Bumps `log4j2.version` from 2.23.1 to 2.24.1.

Updates `org.apache.logging.log4j:log4j-api` from 2.23.1 to 2.24.1

Updates `org.apache.logging.log4j:log4j-core` from 2.23.1 to 2.24.1

Updates `org.apache.logging.log4j:log4j-jcl` from 2.23.1 to 2.24.1

Updates `org.apache.logging.log4j:log4j-slf4j-impl` from 2.23.1 to 2.24.1

---
updated-dependencies:
- dependency-name: org.apache.logging.log4j:log4j-api
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: org.apache.logging.log4j:log4j-core
  dependency-type: direct:production
  update-type: version-update:semver-minor
- dependency-name: org.apache.logging.log4j:log4j-jcl
  dependency-type: direct:development
  update-type: version-update:semver-minor
- dependency-name: org.apache.logging.log4j:log4j-slf4j-impl
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-30 01:12:30 +00:00
dependabot[bot] 7473b4cef9 Bump commons-logging:commons-logging from 1.3.3 to 1.3.4
Bumps commons-logging:commons-logging from 1.3.3 to 1.3.4.

---
updated-dependencies:
- dependency-name: commons-logging:commons-logging
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-30 01:11:56 +00:00
Lukasz Lenart 0bd4266d2f WW-5297 Fixes checking nonce of invalidated session 2024-09-24 07:31:12 +02:00
Lukasz Lenart 48c4e3b6a0 Merge pull request #1058 from apache/dependabot/github_actions/github/codeql-action-3.26.8
Bump github/codeql-action from 3.26.6 to 3.26.8
2024-09-23 19:25:25 +02:00
Lukasz Lenart 40b4395801 Merge pull request #1057 from apache/dependabot/maven/org.codehaus.mojo-exec-maven-plugin-3.4.1
Bump org.codehaus.mojo:exec-maven-plugin from 3.3.0 to 3.4.1
2024-09-23 19:24:59 +02:00
Lukasz Lenart 0ce2c7b5dd Merge pull request #1054 from apache/dependabot/maven/org.owasp-dependency-check-maven-10.0.4
Bump org.owasp:dependency-check-maven from 10.0.3 to 10.0.4
2024-09-23 19:24:13 +02:00
Lukasz Lenart 2924208228 Merge pull request #1053 from apache/dependabot/maven/org.apache.maven.plugins-maven-site-plugin-3.20.0
Bump org.apache.maven.plugins:maven-site-plugin from 3.12.1 to 3.20.0
2024-09-23 19:23:29 +02:00
dependabot[bot] 3c71b2ed8c Bump github/codeql-action from 3.26.6 to 3.26.8
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.6 to 3.26.8.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Commits](https://github.com/github/codeql-action/compare/v3.26.6...v3.26.8)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-23 01:08:01 +00:00
dependabot[bot] d7626ed7d6 Bump org.codehaus.mojo:exec-maven-plugin from 3.3.0 to 3.4.1
Bumps [org.codehaus.mojo:exec-maven-plugin](https://github.com/mojohaus/exec-maven-plugin) from 3.3.0 to 3.4.1.
- [Release notes](https://github.com/mojohaus/exec-maven-plugin/releases)
- [Commits](https://github.com/mojohaus/exec-maven-plugin/compare/3.3.0...3.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 01:55:27 +00:00
dependabot[bot] fda2c546b3 Bump org.owasp:dependency-check-maven from 10.0.3 to 10.0.4
Bumps [org.owasp:dependency-check-maven](https://github.com/jeremylong/DependencyCheck) from 10.0.3 to 10.0.4.
- [Release notes](https://github.com/jeremylong/DependencyCheck/releases)
- [Changelog](https://github.com/jeremylong/DependencyCheck/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jeremylong/DependencyCheck/compare/v10.0.3...v10.0.4)

---
updated-dependencies:
- dependency-name: org.owasp:dependency-check-maven
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 01:55:12 +00:00
dependabot[bot] f03d36c46b Bump org.apache.maven.plugins:maven-site-plugin from 3.12.1 to 3.20.0
Bumps [org.apache.maven.plugins:maven-site-plugin](https://github.com/apache/maven-site-plugin) from 3.12.1 to 3.20.0.
- [Release notes](https://github.com/apache/maven-site-plugin/releases)
- [Commits](https://github.com/apache/maven-site-plugin/compare/maven-site-plugin-3.12.1...maven-site-plugin-3.20.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 01:55:09 +00:00
Lukasz Lenart 90f984ca85 Merge pull request #1050 from apache/dependabot/maven/org.awaitility-awaitility-4.2.2
Bump org.awaitility:awaitility from 4.2.1 to 4.2.2
2024-09-10 18:42:27 +02:00
Lukasz Lenart 0f83b83972 Merge pull request #1048 from apache/dependabot/maven/org.apache.maven.plugins-maven-dependency-plugin-3.8.0
Bump org.apache.maven.plugins:maven-dependency-plugin from 3.6.1 to 3.8.0
2024-09-10 18:42:10 +02:00
Lukasz Lenart c352fb59c1 Merge pull request #1047 from apache/dependabot/maven/org.assertj-assertj-core-3.26.3
Bump org.assertj:assertj-core from 3.25.3 to 3.26.3
2024-09-10 18:41:51 +02:00
Lukasz Lenart 3d155048da Merge pull request #1046 from apache/dependabot/maven/maven-surefire-plugin.version-3.5.0
Bump maven-surefire-plugin.version from 3.4.0 to 3.5.0
2024-09-10 18:41:29 +02:00
Lukasz Lenart 9a06e7c983 Merge pull request #1049 from apache/dependabot/maven/org.jfree-jfreechart-1.5.5
Bump org.jfree:jfreechart from 1.5.4 to 1.5.5
2024-09-10 18:40:41 +02:00
dependabot[bot] 280c3e4f5f Bump org.awaitility:awaitility from 4.2.1 to 4.2.2
Bumps [org.awaitility:awaitility](https://github.com/awaitility/awaitility) from 4.2.1 to 4.2.2.
- [Changelog](https://github.com/awaitility/awaitility/blob/master/changelog.txt)
- [Commits](https://github.com/awaitility/awaitility/compare/awaitility-4.2.1...awaitility-4.2.2)

---
updated-dependencies:
- dependency-name: org.awaitility:awaitility
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-09 01:41:29 +00:00
dependabot[bot] 4c95983abb Bump org.jfree:jfreechart from 1.5.4 to 1.5.5
Bumps [org.jfree:jfreechart](https://github.com/jfree/jfreechart) from 1.5.4 to 1.5.5.
- [Release notes](https://github.com/jfree/jfreechart/releases)
- [Commits](https://github.com/jfree/jfreechart/compare/v1.5.4...v1.5.5)

---
updated-dependencies:
- dependency-name: org.jfree:jfreechart
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-09 01:41:23 +00:00
dependabot[bot] 3111c4b86f Bump org.apache.maven.plugins:maven-dependency-plugin
Bumps [org.apache.maven.plugins:maven-dependency-plugin](https://github.com/apache/maven-dependency-plugin) from 3.6.1 to 3.8.0.
- [Release notes](https://github.com/apache/maven-dependency-plugin/releases)
- [Commits](https://github.com/apache/maven-dependency-plugin/compare/maven-dependency-plugin-3.6.1...maven-dependency-plugin-3.8.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-09 01:41:19 +00:00
dependabot[bot] efab3fc6fa Bump org.assertj:assertj-core from 3.25.3 to 3.26.3
Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.25.3 to 3.26.3.
- [Release notes](https://github.com/assertj/assertj/releases)
- [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.25.3...assertj-build-3.26.3)

---
updated-dependencies:
- dependency-name: org.assertj:assertj-core
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-09 01:41:13 +00:00
dependabot[bot] 0c69993cd7 Bump maven-surefire-plugin.version from 3.4.0 to 3.5.0
Bumps `maven-surefire-plugin.version` from 3.4.0 to 3.5.0.

Updates `org.apache.maven.surefire:surefire-junit47` from 3.4.0 to 3.5.0

Updates `org.apache.maven.plugins:maven-surefire-plugin` from 3.4.0 to 3.5.0
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.4.0...surefire-3.5.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-09 01:41:09 +00:00
Lukasz Lenart b04ad6b412 Merge pull request #1040 from apache/fix/WW-5461-input-name
WW-5461 Extends UploadedFile with inputName field
2024-09-06 20:16:13 +02:00
Lukasz Lenart 735d1bc88d WW-5461 Extends UploadedFile with inputName field 2024-09-03 07:40:17 +02:00
Lukasz Lenart f388f6a679 Merge pull request #1030 from apache/dependabot/maven/spring.platformVersion-5.3.39
Bump spring.platformVersion from 5.3.37 to 5.3.39
2024-09-02 08:26:44 +02:00
Lukasz Lenart e74d21befb Merge pull request #1038 from apache/dependabot/github_actions/github/codeql-action-3.26.6
Bump github/codeql-action from 3.26.2 to 3.26.6
2024-09-02 08:18:20 +02:00
Lukasz Lenart 93c9856527 Merge pull request #1037 from apache/dependabot/github_actions/actions/upload-artifact-4.4.0
Bump actions/upload-artifact from 4.3.6 to 4.4.0
2024-09-02 08:18:04 +02:00
Lukasz Lenart f05a4d1c83 Merge pull request #1031 from apache/dependabot/maven/org.apache.commons-commons-compress-1.27.1
Bump org.apache.commons:commons-compress from 1.26.2 to 1.27.1
2024-09-02 08:16:53 +02:00
dependabot[bot] e4872ecf8e Bump spring.platformVersion from 5.3.37 to 5.3.39
Bumps `spring.platformVersion` from 5.3.37 to 5.3.39.

Updates `org.springframework:spring-core` from 5.3.37 to 5.3.39
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.37...v5.3.39)

Updates `org.springframework:spring-context` from 5.3.37 to 5.3.39
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.37...v5.3.39)

Updates `org.springframework:spring-aop` from 5.3.37 to 5.3.39
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.37...v5.3.39)

Updates `org.springframework:spring-aspects` from 5.3.37 to 5.3.39
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.37...v5.3.39)

Updates `org.springframework:spring-beans` from 5.3.37 to 5.3.39
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.37...v5.3.39)

Updates `org.springframework:spring-test` from 5.3.37 to 5.3.39
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.37...v5.3.39)

Updates `org.springframework:spring-context-support` from 5.3.37 to 5.3.39
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.37...v5.3.39)

Updates `org.springframework:spring-web` from 5.3.37 to 5.3.39
- [Release notes](https://github.com/spring-projects/spring-framework/releases)
- [Commits](https://github.com/spring-projects/spring-framework/compare/v5.3.37...v5.3.39)

---
updated-dependencies:
- dependency-name: org.springframework:spring-core
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: org.springframework:spring-context
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework:spring-aop
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework:spring-aspects
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework:spring-beans
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework:spring-test
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.springframework:spring-context-support
  dependency-type: direct:development
  update-type: version-update:semver-patch
- dependency-name: org.springframework:spring-web
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-02 06:14:58 +00:00
Lukasz Lenart f6a60fc66f Merge pull request #1028 from apache/dependabot/maven/slf4j.version-2.0.16
Bump slf4j.version from 2.0.13 to 2.0.16
2024-09-02 08:13:56 +02:00
dependabot[bot] 00f0942449 Bump github/codeql-action from 3.26.2 to 3.26.6
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.2 to 3.26.6.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Commits](https://github.com/github/codeql-action/compare/v3.26.2...v3.26.6)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-02 01:21:36 +00:00
dependabot[bot] 8c7c39424f Bump actions/upload-artifact from 4.3.6 to 4.4.0
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.6 to 4.4.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/834a144ee995460fba8ed112a2fc961b36a5ec5a...50769540e7f4bd5e21e526ee35c689e35e0d6874)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-02 01:21:24 +00:00
dependabot[bot] ad7f3e3523 Bump org.apache.commons:commons-compress from 1.26.2 to 1.27.1
Bumps org.apache.commons:commons-compress from 1.26.2 to 1.27.1.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-compress
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-26 01:18:06 +00:00
dependabot[bot] 5a50bd312d Bump slf4j.version from 2.0.13 to 2.0.16
Bumps `slf4j.version` from 2.0.13 to 2.0.16.

Updates `org.slf4j:slf4j-api` from 2.0.13 to 2.0.16

Updates `org.slf4j:slf4j-simple` from 2.0.13 to 2.0.16

---
updated-dependencies:
- dependency-name: org.slf4j:slf4j-api
  dependency-type: direct:production
  update-type: version-update:semver-patch
- dependency-name: org.slf4j:slf4j-simple
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-26 01:17:36 +00:00
Lukasz Lenart 5b68d4bd59 Merge pull request #1025 from apache/dependabot/maven/org.apache.maven.plugins-maven-release-plugin-3.1.1
Bump org.apache.maven.plugins:maven-release-plugin from 3.0.1 to 3.1.1
2024-08-19 10:28:23 +02:00
Lukasz Lenart 64a3d0c32f Merge pull request #1020 from apache/dependabot/maven/org.easymock-easymock-5.4.0
Bump org.easymock:easymock from 5.2.0 to 5.4.0
2024-08-19 10:27:42 +02:00
Lukasz Lenart 6f135ea4d8 Merge pull request #1022 from apache/dependabot/maven/maven-surefire-plugin.version-3.4.0
Bump maven-surefire-plugin.version from 3.3.1 to 3.4.0
2024-08-19 10:23:23 +02:00
Lukasz Lenart bdace9bbad Merge pull request #1026 from apache/dependabot/github_actions/github/codeql-action-3.26.2
Bump github/codeql-action from 3.26.0 to 3.26.2
2024-08-19 10:23:00 +02:00
dependabot[bot] 9765edf2ea Bump github/codeql-action from 3.26.0 to 3.26.2
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.26.0 to 3.26.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Commits](https://github.com/github/codeql-action/compare/v3.26.0...v3.26.2)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-19 01:52:03 +00:00
dependabot[bot] e81adc11eb Bump org.apache.maven.plugins:maven-release-plugin from 3.0.1 to 3.1.1
Bumps [org.apache.maven.plugins:maven-release-plugin](https://github.com/apache/maven-release) from 3.0.1 to 3.1.1.
- [Release notes](https://github.com/apache/maven-release/releases)
- [Commits](https://github.com/apache/maven-release/compare/maven-release-3.0.1...maven-release-3.1.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-19 01:25:44 +00:00
dependabot[bot] 0d84319dbf Bump maven-surefire-plugin.version from 3.3.1 to 3.4.0
Bumps `maven-surefire-plugin.version` from 3.3.1 to 3.4.0.

Updates `org.apache.maven.surefire:surefire-junit47` from 3.3.1 to 3.4.0

Updates `org.apache.maven.plugins:maven-surefire-plugin` from 3.3.1 to 3.4.0
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.3.1...surefire-3.4.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-19 01:25:04 +00:00
Kusal Kithul-Godage 9b259ae43a Merge pull request #1021 from apache/WW-4062-ognl-exc-cache
WW-4062 Further optimisation of OgnlException caching
2024-08-13 19:22:28 +10:00
Kusal Kithul-Godage 0fd85517e9 WW-4062 Further optimisation of OgnlException caching 2024-08-13 19:15:43 +10:00
Lukasz Lenart 8d07694be6 Merge pull request #1019 from apache/dependabot/maven/org.apache.maven.plugins-maven-failsafe-plugin-3.3.1
Bump org.apache.maven.plugins:maven-failsafe-plugin from 3.3.0 to 3.3.1
2024-08-12 07:42:45 +02:00
Lukasz Lenart d42e530c89 Merge pull request #1018 from apache/dependabot/maven/org.codehaus.mojo-versions-maven-plugin-2.17.1
Bump org.codehaus.mojo:versions-maven-plugin from 2.16.2 to 2.17.1
2024-08-12 07:42:29 +02:00
Lukasz Lenart ea9d4774dd Merge pull request #1017 from apache/dependabot/maven/org.apache.maven.plugins-maven-wrapper-plugin-3.3.2
Bump org.apache.maven.plugins:maven-wrapper-plugin from 3.2.0 to 3.3.2
2024-08-12 07:42:09 +02:00
Lukasz Lenart 9948258fca Merge pull request #1016 from apache/dependabot/maven/commons-logging-commons-logging-1.3.3
Bump commons-logging:commons-logging from 1.3.0 to 1.3.3
2024-08-12 07:41:53 +02:00
Lukasz Lenart 8bbe215b6a Merge pull request #1015 from apache/dependabot/github_actions/github/codeql-action-3.26.0
Bump github/codeql-action from 3.25.15 to 3.26.0
2024-08-12 07:41:31 +02:00
Lukasz Lenart 90fca13568 Merge pull request #1014 from apache/dependabot/github_actions/actions/upload-artifact-4.3.6
Bump actions/upload-artifact from 4.3.5 to 4.3.6
2024-08-12 07:41:21 +02:00
dependabot[bot] d2d222e05d Bump org.easymock:easymock from 5.2.0 to 5.4.0
Bumps [org.easymock:easymock](https://github.com/easymock/easymock) from 5.2.0 to 5.4.0.
- [Release notes](https://github.com/easymock/easymock/releases)
- [Changelog](https://github.com/easymock/easymock/blob/master/ReleaseNotes.md)
- [Commits](https://github.com/easymock/easymock/compare/easymock-5.2.0...easymock-5.4.0)

---
updated-dependencies:
- dependency-name: org.easymock:easymock
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 01:46:09 +00:00
dependabot[bot] dc03a83f61 Bump org.apache.maven.plugins:maven-failsafe-plugin from 3.3.0 to 3.3.1
Bumps [org.apache.maven.plugins:maven-failsafe-plugin](https://github.com/apache/maven-surefire) from 3.3.0 to 3.3.1.
- [Release notes](https://github.com/apache/maven-surefire/releases)
- [Commits](https://github.com/apache/maven-surefire/compare/surefire-3.3.0...surefire-3.3.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 01:45:57 +00:00
dependabot[bot] c067e25b2c Bump org.codehaus.mojo:versions-maven-plugin from 2.16.2 to 2.17.1
Bumps [org.codehaus.mojo:versions-maven-plugin](https://github.com/mojohaus/versions) from 2.16.2 to 2.17.1.
- [Release notes](https://github.com/mojohaus/versions/releases)
- [Changelog](https://github.com/mojohaus/versions/blob/master/ReleaseNotes.md)
- [Commits](https://github.com/mojohaus/versions/compare/2.16.2...2.17.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 01:45:53 +00:00
dependabot[bot] acd6ebeb6b Bump org.apache.maven.plugins:maven-wrapper-plugin from 3.2.0 to 3.3.2
Bumps [org.apache.maven.plugins:maven-wrapper-plugin](https://github.com/apache/maven-wrapper) from 3.2.0 to 3.3.2.
- [Release notes](https://github.com/apache/maven-wrapper/releases)
- [Commits](https://github.com/apache/maven-wrapper/compare/maven-wrapper-3.2.0...maven-wrapper-3.3.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 01:45:48 +00:00
dependabot[bot] 89154e0479 Bump commons-logging:commons-logging from 1.3.0 to 1.3.3
Bumps commons-logging:commons-logging from 1.3.0 to 1.3.3.

---
updated-dependencies:
- dependency-name: commons-logging:commons-logging
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 01:45:42 +00:00
dependabot[bot] 107810dce2 Bump github/codeql-action from 3.25.15 to 3.26.0
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.25.15 to 3.26.0.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Commits](https://github.com/github/codeql-action/compare/v3.25.15...v3.26.0)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 01:15:10 +00:00
dependabot[bot] 1536a7e04b Bump actions/upload-artifact from 4.3.5 to 4.3.6
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.5 to 4.3.6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/89ef406dd8d7e03cfd12d9e0a4a378f454709029...834a144ee995460fba8ed112a2fc961b36a5ec5a)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-12 01:14:58 +00:00
Kusal Kithul-Godage 663dd3a50c Merge pull request #1013 from apache/WW-4062-ognl-exc-cache
WW-4062 Cache OgnlException thrown on compilation
2024-08-10 19:00:41 +10:00
Kusal Kithul-Godage 6caa932fff WW-4062 Cache OgnlException thrown on compilation 2024-08-09 20:34:52 +10:00
Lukasz Lenart a4464099d9 Merge pull request #1006 from apache/dependabot/github_actions/ossf/scorecard-action-2.4.0
Bump ossf/scorecard-action from 2.3.3 to 2.4.0
2024-08-05 07:24:54 +02:00
Lukasz Lenart 932eed204d Merge pull request #998 from apache/dependabot/maven/org.owasp-dependency-check-maven-10.0.3
Bump org.owasp:dependency-check-maven from 9.2.0 to 10.0.3
2024-08-05 07:23:24 +02:00
Lukasz Lenart e7cce1bcd7 Merge pull request #997 from apache/dependabot/maven/org.apache.maven.plugins-maven-project-info-reports-plugin-3.6.2
Bump org.apache.maven.plugins:maven-project-info-reports-plugin from 3.5.0 to 3.6.2
2024-08-05 07:22:53 +02:00
Lukasz Lenart 9280a478c3 Merge pull request #1012 from apache/dependabot/github_actions/actions/upload-artifact-4.3.5
Bump actions/upload-artifact from 4.3.4 to 4.3.5
2024-08-05 07:22:30 +02:00
Lukasz Lenart adbfab8cf1 Merge pull request #1011 from apache/dependabot/github_actions/github/codeql-action-3.25.15
Bump github/codeql-action from 2.22.11 to 3.25.15
2024-08-05 07:21:57 +02:00
dependabot[bot] b8da13c235 Bump actions/upload-artifact from 4.3.4 to 4.3.5
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.4 to 4.3.5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/0b2256b8c012f0828dc542b3febcab082c67f72b...89ef406dd8d7e03cfd12d9e0a4a378f454709029)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 01:55:15 +00:00
dependabot[bot] 0d3358b035 Bump github/codeql-action from 2.22.11 to 3.25.15
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.22.11 to 3.25.15.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Commits](https://github.com/github/codeql-action/compare/v2.22.11...v3.25.15)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-05 01:55:12 +00:00
Lukasz Lenart 935868c756 Merge pull request #1008 from apache/feature/WW-5451-null-iterator
WW-5451 Fixes NPE when iterator starts with null
2024-08-01 12:01:46 +02:00
Lukasz Lenart 479a9d86ed WW-5451 Fixes NPE when iterator starts with null 2024-07-31 16:53:01 +02:00
dependabot[bot] eeb1d8e0ca Bump ossf/scorecard-action from 2.3.3 to 2.4.0
Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.3.3 to 2.4.0.
- [Release notes](https://github.com/ossf/scorecard-action/releases)
- [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md)
- [Commits](https://github.com/ossf/scorecard-action/compare/dc50aa9510b46c811795eb24b2f1ba02a914e534...62b2cac7ed8198b15735ed49ab1e5cf35480ba46)

---
updated-dependencies:
- dependency-name: ossf/scorecard-action
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-29 01:44:54 +00:00
Lukasz Lenart e3e854a67b Merge pull request #1000 from apache/dependabot/maven/org.apache.commons-commons-lang3-3.15.0
Bump org.apache.commons:commons-lang3 from 3.14.0 to 3.15.0
2024-07-25 20:05:11 +02:00
dependabot[bot] 7e5e49e811 Bump org.apache.commons:commons-lang3 from 3.14.0 to 3.15.0
Bumps org.apache.commons:commons-lang3 from 3.14.0 to 3.15.0.

---
updated-dependencies:
- dependency-name: org.apache.commons:commons-lang3
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-22 01:30:09 +00:00
dependabot[bot] 8c10a303d0 Bump org.owasp:dependency-check-maven from 9.2.0 to 10.0.3
Bumps [org.owasp:dependency-check-maven](https://github.com/jeremylong/DependencyCheck) from 9.2.0 to 10.0.3.
- [Release notes](https://github.com/jeremylong/DependencyCheck/releases)
- [Changelog](https://github.com/jeremylong/DependencyCheck/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jeremylong/DependencyCheck/compare/v9.2.0...v10.0.3)

---
updated-dependencies:
- dependency-name: org.owasp:dependency-check-maven
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-22 01:29:54 +00:00
dependabot[bot] dbd74ae3a3 Bump org.apache.maven.plugins:maven-project-info-reports-plugin
Bumps [org.apache.maven.plugins:maven-project-info-reports-plugin](https://github.com/apache/maven-project-info-reports-plugin) from 3.5.0 to 3.6.2.
- [Commits](https://github.com/apache/maven-project-info-reports-plugin/compare/maven-project-info-reports-plugin-3.5.0...maven-project-info-reports-plugin-3.6.2)

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

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-22 01:29:50 +00:00
Lukasz Lenart f977f0c0e5 [maven-release-plugin] prepare for next development iteration 2024-07-20 08:28:46 +02:00
251 changed files with 7892 additions and 2875 deletions
+11 -1
View File
@@ -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
+20 -13
View File
@@ -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}}"
+3 -3
View File
@@ -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
View File
@@ -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
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.6.0</version>
<version>6.7.4</version>
</parent>
<artifactId>struts2-apps</artifactId>
<packaging>pom</packaging>
+2 -2
View File
@@ -24,12 +24,12 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>6.6.0</version>
<version>6.7.4</version>
</parent>
<artifactId>struts2-rest-showcase</artifactId>
<packaging>war</packaging>
<version>6.6.0</version>
<version>6.7.4</version>
<name>Struts 2 Rest Showcase Webapp</name>
<description>Struts 2 Rest Showcase Example</description>
+2 -2
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>6.6.0</version>
<version>6.7.4</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>
@@ -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();
}
}
@@ -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
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.6.0</version>
<version>6.7.4</version>
</parent>
<artifactId>struts2-assembly</artifactId>
+4 -4
View File
@@ -25,11 +25,11 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.6.0</version>
<version>6.7.4</version>
</parent>
<artifactId>struts2-bom</artifactId>
<version>6.6.0</version>
<version>6.7.4</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.4</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_4</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>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-osgi-bundles</artifactId>
<version>6.6.0</version>
<version>6.7.4</version>
</parent>
<artifactId>struts2-osgi-admin-bundle</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-osgi-bundles</artifactId>
<version>6.6.0</version>
<version>6.7.4</version>
</parent>
<artifactId>struts2-osgi-demo-bundle</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.6.0</version>
<version>6.7.4</version>
</parent>
<artifactId>struts2-osgi-bundles</artifactId>
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.6.0</version>
<version>6.7.4</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 -->
* &lt;package name="public" extends="struts-default"&gt;
* &lt;!-- Chain creatAccount to login, using the default parameter --&gt;
* &lt;action name="createAccount" class="..."&gt;
* &lt;result type="chain"&gt;login&lt;/result&gt;
* &lt;/action&gt;
*
* &lt;action name="login" class="..."&gt;
* &lt;!-- Chain to another namespace --&gt;
* &lt;result type="chain"&gt;
* &lt;param name="actionName"&gt;dashboard&lt;/param&gt;
* &lt;param name="namespace"&gt;/secure&lt;/param&gt;
* &lt;/result&gt;
* &lt;/action&gt;
* &lt;/package&gt;
*
* &lt;package name="secure" extends="struts-default" namespace="/secure"&gt;
* &lt;action name="dashboard" class="..."&gt;
* &lt;result&gt;dashboard.jsp&lt;/result&gt;
* &lt;/action&gt;
* &lt;/package&gt;
* <!-- 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);
@@ -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);
}
}
}
@@ -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";
@@ -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;
@@ -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>
* &lt;action name=&quot;myAction&quot; class=&quot;myActionClass&quot;&gt;
* &lt;interceptor-ref name=&quot;exception&quot;/&gt;
* &lt;interceptor-ref name=&quot;alias&quot;/&gt;
* &lt;interceptor-ref name=&quot;params&quot;/&gt;
* &lt;interceptor-ref name=&quot;servletConfig&quot;/&gt;
* &lt;interceptor-ref name=&quot;prepare&quot;/&gt;
* &lt;interceptor-ref name=&quot;i18n&quot;/&gt;
* &lt;interceptor-ref name=&quot;chain&quot;/&gt;
* &lt;interceptor-ref name=&quot;modelDriven&quot;/&gt;
* &lt;interceptor-ref name=&quot;fileUpload&quot;/&gt;
* &lt;interceptor-ref name=&quot;staticParams&quot;/&gt;
* &lt;interceptor-ref name=&quot;params&quot;/&gt;
* &lt;interceptor-ref name=&quot;conversionError&quot;/&gt;
* &lt;interceptor-ref name=&quot;validation&quot;&gt;
* &lt;param name=&quot;excludeMethods&quot;&gt;myValidationExcudeMethod&lt;/param&gt;
* &lt;/interceptor-ref&gt;
* &lt;interceptor-ref name=&quot;workflow&quot;&gt;
* &lt;param name=&quot;excludeMethods&quot;&gt;myWorkflowExcludeMethod&lt;/param&gt;
* &lt;/interceptor-ref&gt;
* &lt;/action&gt;
* </pre>
*
* <b>Method 2:</b>
* <pre>
* &lt;action name=&quot;myAction&quot; class=&quot;myActionClass&quot;&gt;
* &lt;interceptor-ref name=&quot;defaultStack&quot;&gt;
* &lt;param name=&quot;validation.excludeMethods&quot;&gt;myValidationExcludeMethod&lt;/param&gt;
* &lt;param name=&quot;workflow.excludeMethods&quot;&gt;myWorkflowExcludeMethod&lt;/param&gt;
* &lt;/interceptor-ref&gt;
* &lt;/action&gt;
* </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>
* &lt;interceptor-name&gt;.&lt;parameter-name&gt;
* </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>
* &lt;interceptor name=&quot;interceptor1&quot; class=&quot;foo.bar.Interceptor1&quot; /&gt;
* &lt;interceptor name=&quot;interceptor2&quot; class=&quot;foo.bar.Interceptor2&quot; /&gt;
* &lt;interceptor name=&quot;interceptor3&quot; class=&quot;foo.bar.Interceptor3&quot; /&gt;
* &lt;interceptor name=&quot;interceptor4&quot; class=&quot;foo.bar.Interceptor4&quot; /&gt;
* &lt;interceptor-stack name=&quot;stack1&quot;&gt;
* &lt;interceptor-ref name=&quot;interceptor1&quot; /&gt;
* &lt;/interceptor-stack&gt;
* &lt;interceptor-stack name=&quot;stack2&quot;&gt;
* &lt;interceptor-ref name=&quot;intercetor2&quot; /&gt;
* &lt;interceptor-ref name=&quot;stack1&quot; /&gt;
* &lt;/interceptor-stack&gt;
* &lt;interceptor-stack name=&quot;stack3&quot;&gt;
* &lt;interceptor-ref name=&quot;interceptor3&quot; /&gt;
* &lt;interceptor-ref name=&quot;stack2&quot; /&gt;
* &lt;/interceptor-stack&gt;
* &lt;interceptor-stack name=&quot;stack4&quot;&gt;
* &lt;interceptor-ref name=&quot;interceptor4&quot; /&gt;
* &lt;interceptor-ref name=&quot;stack3&quot; /&gt;
* &lt;/interceptor-stack&gt;
* </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>
* &lt;action ... &gt;
* &lt;!-- to override parameters of interceptor located directly in the stack --&gt;
* &lt;interceptor-ref name=&quot;stack4&quot;&gt;
* &lt;param name=&quot;interceptor4.param4&quot;&gt; ... &lt;/param&gt;
* &lt;/interceptor-ref&gt;
* &lt;/action&gt;
*
* &lt;action ... &gt;
* &lt;!-- to override parameters of interceptor located under nested stack --&gt;
* &lt;interceptor-ref name=&quot;stack4&quot;&gt;
* &lt;param name=&quot;stack3.interceptor3.param3&quot;&gt; ... &lt;/param&gt;
* &lt;param name=&quot;stack3.stack2.interceptor2.param2&quot;&gt; ... &lt;/param&gt;
* &lt;param name=&quot;stack3.stack2.stack1.interceptor1.param1&quot;&gt; ... &lt;/param&gt;
* &lt;/interceptor-ref&gt;
* &lt;/action&gt;
* </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 ";
@@ -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;
}
@@ -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;
* &lt;/action&gt;
* <!-- 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;
@@ -66,7 +66,10 @@ import java.util.Set;
* ...
* &lt;/action&gt;
* </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);
}
}
}
@@ -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> {
}
@@ -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 -->
*
*
* &lt;-- Basic usage --&gt;
* &lt;interceptor name="scopedModelDriven" class="com.opensymphony.interceptor.ScopedModelDrivenInterceptor" /&gt;
*
*
* &lt;-- Using all available parameters --&gt;
* &lt;interceptor name="gangsterForm" class="com.opensymphony.interceptor.ScopedModelDrivenInterceptor"&gt;
* &lt;param name="scope"&gt;session&lt;/param&gt;
* &lt;param name="name"&gt;gangsterForm&lt;/param&gt;
* &lt;param name="className"&gt;com.opensymphony.example.GangsterForm&lt;/param&gt;
* &lt;/interceptor&gt;
*
*
* <!-- 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;
}
}
}
@@ -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
@@ -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 -&gt; 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();
}
}
}
@@ -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 -->
*
*
* &lt;action name=&quot;someAction&quot; class=&quot;com.examples.SomeAction&quot;&gt;
* &lt;interceptor-ref name=&quot;params&quot;/&gt;
* &lt;interceptor-ref name=&quot;validation&quot;/&gt;
* &lt;interceptor-ref name=&quot;workflow&quot;/&gt;
* &lt;result name=&quot;success&quot;&gt;good_result.ftl&lt;/result&gt;
* &lt;/action&gt;
*
*
* &lt;-- in the following case myMethod of the action class will not
* get validated --&gt;
* &lt;action name=&quot;someAction&quot; class=&quot;com.examples.SomeAction&quot;&gt;
@@ -108,7 +108,7 @@ import org.apache.logging.log4j.Logger;
* &lt;interceptor-ref name=&quot;workflow&quot;/&gt;
* &lt;result name=&quot;success&quot;&gt;good_result.ftl&lt;/result&gt;
* &lt;/action&gt;
*
*
* &lt;-- in the following case only annotated methods of the action class will
* be validated --&gt;
* &lt;action name=&quot;someAction&quot; class=&quot;com.examples.SomeAction&quot;&gt;
@@ -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