Compare commits

...

234 Commits

Author SHA1 Message Date
Lukasz Lenart 18a72c3dff [maven-release-plugin] prepare release STRUTS_6_1_0 2022-11-08 15:49:42 +01:00
Lukasz Lenart 6ea50122d6 Merge pull request #634 from apache/WW-5259-parser
[WW-5259] Extracts UrlHelper#parseQueryString into a dedicated bean
2022-11-08 07:43:59 +01:00
Lukasz Lenart ea7fba2846 WW-5259 Extracts UrlHelper#parseQueryString into a dedicated bean 2022-11-07 12:13:43 +01:00
Lukasz Lenart 4ab427f2f2 Merge pull request #633 from apache/WW-5258-annotations
[WW-5258] Upgrades Struts Annotations to version 1.0.8
2022-11-06 18:01:20 +01:00
Lukasz Lenart 0a30eb44e6 Merge pull request #632 from apache/WW-5257-checkbox
[WW-5257] Cleans up template
2022-11-06 18:00:08 +01:00
Lukasz Lenart 138a8d74f0 WW-5257 Cleans up template 2022-11-06 17:03:48 +01:00
Lukasz Lenart 341a8f20e0 Cleans remote before uploading new packages 2022-11-06 11:13:26 +01:00
Lukasz Lenart 9a431ea470 Packages with assembly before publishing nightlies 2022-11-06 10:14:17 +01:00
Lukasz Lenart 0fe27a673d Merge pull request #631 from apache/WW-5240-doubleselect
[WW-5240] Uses doubleOn* attributes in the template
2022-11-06 09:57:14 +01:00
Lukasz Lenart 35a50ea836 Merge pull request #630 from apache/WW-4514-url
[WW-4514] Fixes building query string with empty parameters
2022-11-06 09:50:51 +01:00
Lukasz Lenart 927c58b7d3 WW-5258 Upgrades Struts Annotations to version 1.0.8 2022-11-05 09:34:29 +01:00
Lukasz Lenart ac168968a0 WW-5240 Uses doubleOn* attributes in the template
This allows assign custom JS event handlers to the second select box
2022-11-05 08:37:26 +01:00
Lukasz Lenart 5a30cdbede Merge pull request #629 from apache/WW-5255-script-link
[WW-5255] Fixes <s:script/> and <s:link/> and uses them across tags
2022-11-05 08:28:57 +01:00
Lukasz Lenart bfcc0b5898 Swaps expected with actual 2022-11-04 09:03:54 +01:00
Lukasz Lenart 4a51aacf40 WW-4514 Avoids logging user provided data 2022-11-04 09:02:46 +01:00
Lukasz Lenart 728edbef56 Increases sleep to avoid false test failures 2022-11-04 09:00:26 +01:00
Lukasz Lenart 6135a71335 WW-4514 Extracts parameters string building into a dedicated class with a proper extension point 2022-11-04 08:49:57 +01:00
Lukasz Lenart 6330bb1ce3 WW-4514 Fixes building query string with empty parameters 2022-11-04 07:58:47 +01:00
Lukasz Lenart 4a585347ed WW-5255 Fixes debug console and validators' details page 2022-11-02 12:20:33 +01:00
Lukasz Lenart 4bb81d5909 WW-5255 Fixes <s:script/> and <s:link/> and uses them across tags 2022-11-02 12:20:33 +01:00
Lukasz Lenart 054f1f4cdb Includes apps in code Coverage scan 2022-11-02 11:54:35 +01:00
Lukasz Lenart 79a84a8f02 Merge pull request #628 from apache/WW-5252-external
[WW-5252] Disables parsing external entities
2022-11-02 10:32:36 +01:00
Lukasz Lenart 2660aaec56 [WW-4692] Extracts Url encoder/decoder into dedicated interfaces/classes (#626)
* WW-4692 Extracts Url encoder/decoder into dedicated interfaces/classes

* WW-4692 Removes code smells reported by Sonar and adds additional test case

* WW-4692 Adds missing header with license

* WW-4692 Prevents int promotion behaviour

* WW-4692 Drops unused imports

* WW-4692 Fixes int promotion behaviour

* WW-4692 Improves code coverage
2022-11-02 10:32:13 +01:00
Lukasz Lenart 34aeeded55 Merge pull request #627 from apache/WW-4440-readme
[WW-4440] Adds basic README.md to all submodules
2022-11-02 10:31:49 +01:00
Lukasz Lenart 8d2d996056 WW-5252 Reuses factory method 2022-10-30 12:37:23 +01:00
Lukasz Lenart 6658c6360e WW-5252 Disables parsing external entities 2022-10-27 13:35:10 +02:00
Lukasz Lenart 9c078aef14 WW-4440 Adds basic README.md to all submodules 2022-10-27 12:53:05 +02:00
Lukasz Lenart eb51594ed3 Adds proper header with Apache 2.0 license 2022-10-25 13:40:35 +02:00
Lukasz Lenart b536136191 Introduces CodeQL analyses 2022-10-25 13:29:21 +02:00
Lukasz Lenart c74287f741 Merge pull request #625 from apache/WW-4173-disable
[WW-4173] Adds support to disable processing a given interceptor
2022-10-24 10:24:57 +02:00
Lukasz Lenart 9e7e0b395d Merge pull request #624 from apache/WW-5137-class
[WW-5137] Removes deprecated class attribute
2022-10-24 10:24:19 +02:00
Lukasz Lenart 784293e46f Merge pull request #623 from apache/WW-3725-remove
[WW-3725] Removes unused template
2022-10-24 10:13:13 +02:00
Lukasz Lenart 58dcc830ea Merge pull request #622 from apache/WW-5133-labelposition
[WW-5133] Drops labelposition attribute
2022-10-24 10:12:39 +02:00
Lukasz Lenart 936481e7ea Adds badge with OSSF CII best practises scoring 2022-10-24 09:33:47 +02:00
Lukasz Lenart a02cc6507c Defines OSSF Scorecard action to perform analysis 2022-10-24 08:30:09 +02:00
Lukasz Lenart 084c257d6e WW-4173 Passes current ActionInvocation to allow based disabling interceptor on it 2022-10-24 08:27:12 +02:00
Lukasz Lenart 94a0c6e425 WW-4173 Adds support to disable processing a given interceptor 2022-10-21 21:12:41 +02:00
Lukasz Lenart 3e30d0c375 WW-5137 Removes deprecated class attribute 2022-10-21 13:33:11 +02:00
Lukasz Lenart 9568888700 WW-3725 Removes unused template 2022-10-21 11:36:54 +02:00
Lukasz Lenart 943cb62953 WW-5133 Drops labelposition attribute 2022-10-21 10:49:31 +02:00
Lukasz Lenart 79d6c07a57 Merge pull request #621 from apache/WW-3737-custom-separator
[WW-3737] Allows to define a custom separator used to split patterns
2022-10-21 09:23:52 +02:00
Lukasz Lenart 7064c53f5c Merge pull request #620 from apache/WW-3529-named-pattern
[WW-3529] Fixes usage of RegEx related characters in named pattern
2022-10-21 07:16:43 +02:00
Lukasz Lenart 3fdb918127 Merge pull request #619 from apache/WW-5230-ognl
[WW-5230] Upgrades OGNL to version 3.3.4
2022-10-20 19:18:47 +02:00
Lukasz Lenart 1069cf8c09 Merge pull request #615 from apache/WW-2815-xstream
[WW-2815] Refactors XStreamHandler to allow to provide a custom configuration
2022-10-20 13:15:03 +02:00
Lukasz Lenart c41f05fe68 WW-3737 Allows to define a custom separator used to split patterns 2022-10-19 13:57:59 +02:00
Lukasz Lenart 993c4c4cab WW-3529 Fixes using RegEx related characters in named pattern 2022-10-19 12:22:31 +02:00
Lukasz Lenart 01164c4d74 WW-5230 Upgrades OGNL to version 3.3.4 2022-10-19 11:38:50 +02:00
Lukasz Lenart 738d27952f Merge pull request #618 from apache/WW-5245-jackson-databind
[WW-5245] Upgrades Jackson Databind to version 2.13.4.2
2022-10-19 09:07:57 +02:00
Lukasz Lenart 984f8eff2e WW-5245 Upgrades Jackson Databind to version 2.13.4.2 2022-10-19 08:49:37 +02:00
Lukasz Lenart 802afb0cc0 WW-2815 Drops unused import 2022-10-17 10:55:46 +02:00
Lukasz Lenart 339c30320a WW-2815 Drops clearing existing permissions to avoid messing with user provided configuration 2022-10-17 10:14:51 +02:00
Lukasz Lenart a562f8f806 WW-2815 Fixes support for Collections and String 2022-10-17 09:52:07 +02:00
Lukasz Lenart ac13c32bdb WW-2815 Drops deprecated API 2022-10-17 09:47:37 +02:00
Lukasz Lenart bb71610296 WW-2815 Refactors XStreamHandler to allow to provide a custom configuration 2022-10-17 08:54:03 +02:00
Lukasz Lenart 3d7f66f428 Merge pull request #614 from apache/WW-5244-commons-text
[WW-5244] Upgrades commons-text to version 1.10.0
2022-10-17 08:14:16 +02:00
Lukasz Lenart 50842e8d19 WW-5242 Marks constant definition as deprecated 2022-10-16 08:55:27 +02:00
Lukasz Lenart cca986df35 Merge pull request #613 from apache/WW-5242-cross-action
[WW-5242] Marks struts.mapper.action.prefix.crossNamespaces as deprecated
2022-10-16 08:53:23 +02:00
Lukasz Lenart 511ec62105 Merge pull request #611 from apache/WW-5241-exec-and-wait
[WW-5241] Fixes issue with includeParams=all when using exec & wait
2022-10-16 08:52:07 +02:00
Lukasz Lenart 2cb0d28960 WW-5244 Upgrades commons-text to version 1.10.0 2022-10-16 08:51:09 +02:00
Lukasz Lenart e783d18715 WW-5242 Marks struts.mapper.action.prefix.crossNamespaces as deprecated 2022-10-14 12:49:22 +02:00
Lukasz Lenart 864f513365 WW-5241 Adds test cases to cover DMI when mapping action 2022-10-14 12:29:40 +02:00
Lukasz Lenart 9dd2560172 WW-5241 Adds test cases to cover checking namespace, action and method names 2022-10-14 12:03:02 +02:00
Lukasz Lenart 415e0fbd44 WW-5241 Ignores calls to append !method when DMI is disabled 2022-10-14 11:32:10 +02:00
Lukasz Lenart 26effbf05d WW-5241 Improves Exec&Wait example in Showcase app 2022-10-13 15:39:07 +02:00
Lukasz Lenart 4c8cc361d5 Merge pull request #609 from apache/WW-3691-executor
WW-3691 Converts BackgroundProcess into interface and uses Executor to execute BackgroundProcess
2022-10-13 08:07:50 +02:00
Lukasz Lenart a21bd994eb WW-5238 Uses proper order of mapping functions to support action: prefix 2022-10-06 08:54:14 +02:00
Lukasz Lenart 8f0db1d22a WW-3691 Converts BackgroundProcess into interface and uses Executor to execute BackgroundProcess 2022-10-05 09:10:24 +02:00
Lukasz Lenart 58f287bf4a Merge pull request #607 from apache/WW-5184-log
[WW-5184] Uses debug log level when parameter value was not accepted
2022-09-30 11:21:34 +02:00
Lukasz Lenart e0da03c262 Sets proper Sonar options in Jenkins pipeline and removes duplicated sonar properties 2022-09-30 10:38:15 +02:00
Lukasz Lenart 04cf1dae5f Puts back JaCoCo report generation 2022-09-30 09:50:51 +02:00
Lukasz Lenart 5338b44c23 WW-5184 Reduces code complexity when handling excluded/accepted values patterns 2022-09-30 08:25:44 +02:00
Lukasz Lenart 2217e2c1ca Disables Code quality step in Jenkins pipeline to avoid overriding GH Actions results 2022-09-30 08:19:09 +02:00
Lukasz Lenart cbfd3a7ab9 WW-5184 Improves logging around excluding/accepting values of incoming parameters 2022-09-30 08:12:35 +02:00
Lukasz Lenart 097297affd WW-5232 Stop generating Jacoco reports which are not used 2022-09-28 11:32:01 +02:00
Lukasz Lenart ddfaa1683c Merge pull request #606 from apache/WW-5235-ognl
[WW-5235] Uses debug log level when setting expression max length to avoid cluttering logs
2022-09-28 11:13:58 +02:00
Lukasz Lenart ddbd02e6bb WW-5184 Uses debug log level when parameter value was not accepted 2022-09-28 11:09:16 +02:00
Lukasz Lenart 6887ef900b WW-5235 Uses debug log level when setting expression max length to avoid cluttering logs 2022-09-28 10:58:26 +02:00
Lukasz Lenart 326de812ac Merge pull request #605 from apache/WW-5232-coverage
[WW-5232] Applies proper coverage settings for Jacoco plugin and Sonar
2022-09-28 10:34:35 +02:00
Lukasz Lenart 32201b2ef2 WW-5232 Applies proper coverage settings for Jacoco plugin and Sonar 2022-09-28 10:02:55 +02:00
Lukasz Lenart a4fe51f5b3 Merge pull request #604 from apache/WW-5234-dtds
[WW-5234] Improves DTD definitions to use proper URL
2022-09-27 09:49:33 +02:00
Lukasz Lenart 3774ffa7c3 WW-5234 Improves DTD definitions to use proper URL 2022-09-27 09:21:03 +02:00
Lukasz Lenart cf2078d1de Merge pull request #603 from apache/lukaszlenart-patch-1
Replaces Travis badge with GH Actions badge
2022-09-25 10:29:54 +02:00
Lukasz Lenart 7183d32caf Replaces Travis badge with GH Actions badge 2022-09-25 10:09:02 +02:00
Lukasz Lenart e0e7e3cb20 Merge pull request #602 from apache/WW-5232-gh-actions
[WW-5232] Introduces GH Actions build instead of using Travis
2022-09-25 10:06:59 +02:00
Lukasz Lenart eb68368280 WW-5232 Avoids building assemblies 2022-09-21 22:29:14 +02:00
Lukasz Lenart 296b3cc89c Uses SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }} 2022-09-21 17:27:20 +02:00
Lukasz Lenart 9fb86054bb Reverts back to SONAR_TOKEN 2022-09-21 17:17:07 +02:00
Lukasz Lenart 0fc71949ca WW-5232 Uses Apache specific SONARCLOUD_TOKEN secret 2022-09-21 15:44:47 +02:00
Lukasz Lenart 9faa002fa7 Merge pull request #601 from apache/WW-5231-rat
[WW-5231] Upgrades apache-rat-plugin to version 0.15
2022-09-21 07:30:13 +02:00
Lukasz Lenart 88bc5c6802 Merge pull request #600 from apache/WW-5228-owasp
[WW-5228] Upgrades OWASP dependency-check-maven to version 7.2.0
2022-09-21 07:29:56 +02:00
Lukasz Lenart dc1a663d69 WW-5232 Uses default SONAR_TOKEN name 2022-09-20 16:22:59 +02:00
Lukasz Lenart 36ac23acf5 WW-5232 Uses Sonar Coverage badge instead of Travis on 2022-09-20 16:18:17 +02:00
Lukasz Lenart 6b2cc20b2d WW-5232 Defines default ENV settings 2022-09-20 16:08:32 +02:00
Lukasz Lenart ab22c7377d WW-5232 Introduces GH Actions build instead of using Travis 2022-09-20 15:48:21 +02:00
Lukasz Lenart 062b76718b WW-5231 Upgrades apache-rat-plugin to version 0.15 2022-09-20 15:33:11 +02:00
Lukasz Lenart dc5dac7be2 WW-5228 Upgrades OWASP dependency-check-maven to version 7.2.0 2022-09-20 15:27:39 +02:00
Lukasz Lenart 6334a3e19e Merge pull request #599 from apache/WW-5229-spring
[WW-5229] Upgrades Spring to version 5.3.23
2022-09-20 15:25:48 +02:00
Lukasz Lenart 858f19557d WW-5229 Upgrades Spring to version 5.3.23 2022-09-20 11:13:18 +02:00
Lukasz Lenart d97fa1eb38 Merge pull request #598 from apache/WW-5227-log4j
[WW-5227] Upgrades Log4j to version 2.19.0
2022-09-20 11:05:04 +02:00
Lukasz Lenart b9cd7d8159 Merge pull request #597 from apache/WW-5226-weld
[WW-5226] Upgrade weld-core to version 2.4.8.Final
2022-09-20 11:04:53 +02:00
Lukasz Lenart 03edeee0d8 WW-5227 Upgrades Log4j to version 2.19.0 2022-09-18 15:43:37 +02:00
Lukasz Lenart f04b68db03 Blocks force pushes to the master branch 2022-09-17 10:02:31 +02:00
Lukasz Lenart 7b655207ec Includes commons-text in minimal library set 2022-09-17 09:40:54 +02:00
Lukasz Lenart c9c39130f6 WW-5226 Upgrades Weld to version 2.4.8.Final 2022-09-17 09:40:38 +02:00
Lukasz Lenart 12beb20949 Merge pull request #596 from apache/WW-5213-javax-el
[WW-5213] Upgrades javax.el to 3.0.1-b12
2022-09-14 20:18:03 +02:00
Lukasz Lenart a5899726a0 Merge pull request #559 from brianandle/WW-5184_v2
WW-5184 - Add optional parameter value check to ParametersInterceptor
2022-09-14 16:53:10 +02:00
Lukasz Lenart 22a80f9c51 WW-5213 Upgrades javax.el to 3.0.1-b12 2022-09-14 16:49:50 +02:00
Lukasz Lenart 854572905e Merge pull request #595 from apache/WW-5220-move-junit
WW-5220 Moves JUnit related test into the JUnit plugin
2022-09-14 16:37:34 +02:00
Lukasz Lenart b40f3efc74 Merge pull request #594 from apache/WW-5219-move-testng
WW-5219 Moves TestNG related classes into TestNG plugin
2022-09-14 16:37:11 +02:00
Lukasz Lenart 980387e91c WW-5220 Moves JUnit related test into the JUnit plugin
Also moves all the plugin classes under junit package
2022-09-04 11:59:01 +02:00
Lukasz Lenart 5a3d2c4eb9 WW-5219 Moves TestNG related classes into TestNG plugin
Also moves test classes under testng package
2022-09-04 11:15:28 +02:00
Lukasz Lenart 8514406142 Removes duplicated code coverage badge 2022-09-04 10:59:52 +02:00
Lukasz Lenart bbb5b6bb37 Adds OpenSSF Scorecard badge 2022-09-04 10:58:58 +02:00
Lukasz Lenart ce2975e2f0 Updates supported versions 2022-09-03 08:47:41 +02:00
Lukasz Lenart 49240c50a2 [maven-release-plugin] prepare for next development iteration 2022-09-02 14:41:56 +02:00
Lukasz Lenart 941d88d115 [maven-release-plugin] prepare release STRUTS_6_0_3 2022-09-02 14:41:49 +02:00
Lukasz Lenart 8c4a90f6e3 Merge pull request #593 from apache/WW-5218-disable
[WW-5218] Allows to disable CSP related interceptors
2022-09-02 10:19:48 +02:00
Lukasz Lenart 16c2948f1a WW-5218 Allows to disable CSP related interceptors 2022-09-01 08:15:48 +02:00
Lukasz Lenart 58a76162a6 Merge pull request #592 from apache/upgrade-spring
[WW-5212] Upgrades to Spring 5.3.22
2022-08-29 08:29:17 +02:00
Lukasz Lenart b5e802174a WW-5212 Upgrades to Spring 5.3.22 2022-08-29 08:03:02 +02:00
Lukasz Lenart cdb70e6bed [maven-release-plugin] prepare for next development iteration 2022-08-25 07:39:48 +02:00
Lukasz Lenart 1380802b75 [maven-release-plugin] prepare release STRUTS_6_0_2 2022-08-25 07:39:40 +02:00
Lukasz Lenart 253d8558e5 Merge pull request #590 from apache/WW-5215-csp-session
[WW-5215] Checks if session was already created before applying CSP settings
2022-08-25 07:30:17 +02:00
Lukasz Lenart a97ee9e9cb Merge pull request #591 from sepe81/patch-1
Update maven-enforcer-plugin to 3.1.0
2022-08-25 07:30:04 +02:00
Sebastian Peters 23969abc19 Update maven-enforcer-plugin to 3.1.0 2022-08-24 22:54:37 +02:00
Lukasz Lenart 2707bf0489 WW-5215 Explicitly creates session in test 2022-08-23 20:50:39 +02:00
Lukasz Lenart 74d4e23716 WW-5215 Checks is session was already created before applying CSP settings 2022-08-23 20:31:39 +02:00
Yasser Zamani 2a03047e9e Merge pull request #573 from JCgH4164838Gh792C124B5/localS2_WW5173_Upd1
[WW-5173] - Attempt to fix DI behaviour for custom cache factories
2022-08-21 13:33:04 +04:30
Lukasz Lenart b1c1be6e40 [maven-release-plugin] prepare for next development iteration 2022-08-12 17:26:55 +02:00
Lukasz Lenart 6536dc65d8 [maven-release-plugin] prepare release STRUTS_6_0_1 2022-08-12 17:26:47 +02:00
Lukasz Lenart 915386816b Merge pull request #588 from apache/WW-5203-lazy-builder
[WW-5203] Re-builds policy string on each call
2022-08-11 13:43:18 +02:00
Lukasz Lenart 80c2de9e92 Merge pull request #586 from apache/WW-5207-asm-9
[WW-5207] Uses ASM 9 by default
2022-08-11 13:43:01 +02:00
Lukasz Lenart b62e583646 WW-5203 Re-builds policy string on each call 2022-08-09 15:19:02 +02:00
Lukasz Lenart 8b359383a1 Merge pull request #587 from sepe81/update-maven-surefire-plugin-to-3.0.0-M7
Update maven-surefire-plugin to 3.0.0-M7
2022-08-09 15:01:08 +02:00
Lukasz Lenart 11e716f979 Merge pull request #584 from sepe81/update-travis
Add openjdk17 to build, remove oraclejdk9 (EOL) and switch from oraclejdk to openjdk to fix Travis CI build
2022-08-09 15:00:34 +02:00
Sebastian Peters 71c7064f29 Update maven-surefire-plugin to 3.0.0-M7
see https://github.com/apache/maven-surefire/releases/tag/surefire-3.0.0-M7
2022-08-08 22:27:47 +02:00
Sebastian Peters 09472808aa Add openjdk17 to build, remove oraclejdk9 (EOL)
and switch from oraclejdk to openjdk
to fix Travis CI build
2022-08-08 22:20:53 +02:00
Sebastian Peters d119ba8e13 Migrate vom ubuntu trusty to jammy
see https://docs.travis-ci.com/user/reference/jammy/
2022-08-08 22:20:52 +02:00
Lukasz Lenart 86b45e96fc WW-5207 Uses ASM 9 by default 2022-08-08 17:00:42 +02:00
Lukasz Lenart 3c9465b857 Merge pull request #580 from rproserpio/patch-1
[WW-5205] - Reverting injection refactor of internal bean
2022-08-08 16:37:43 +02:00
Lukasz Lenart 0c73cf2e05 Merge pull request #583 from sepe81/update-hibernate-validator-to.6.2.x
WW-5208 Update hibernate-validator to 6.2.4
2022-08-07 10:47:38 +02:00
Lukasz Lenart 6785997412 Merge pull request #582 from sepe81/update-mvn-to-3.8.6
Update maven wrapper to 3.8.6
2022-08-07 10:45:12 +02:00
Sebastian Peters 5a7fce066f WW-5208 Update hibernate-validator to 6.2.4
b/c 6.1 has reached its end-of-life according to
https://hibernate.org/validator/releases/6.1/

6.2 is compatible with the given Java and Jakarta
versions and supports `javax.validation.*` according to
https://hibernate.org/validator/releases/6.2/
2022-08-06 14:33:00 +02:00
Sebastian Peters 4fbada4cd9 Update maven wrapper to 3.8.6 2022-08-06 14:09:54 +02:00
JCgH4164838Gh792C124B5 15bbf0ef1d Updated commit:
- Incorporate changes from Y. Zamani's PR #581 manually, which appears to
fix the previous issue that prevented customized cache factory
implementations from being used (tested with sample app).
Credit goes to Yasser Zamani for the fixes.
- Updated unit tests and slight modifications to the changes from the
PR #581.
2022-07-31 18:26:48 -04:00
rproserpio 3119eb65db Reverting injection refactor of internal bean
In commit e9d0a5518c ContentTypeHandlerManager has been changed from setter-injected to constructor-injected.
However, at least with spring as the object factory, that bean was an internal bean not available from the factory, injected post construction.
In the 6.0.0 implementation ContentTypeInterceptor cannot be instantiated since its dependency cannot be resolved:
```
org.springframework.beans.factory.UnsatisfiedDependencyException

Error creating bean with name 'org.apache.struts2.rest.ContentTypeInterceptor': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.apache.struts2.rest.ContentTypeHandlerManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
```
This commit attempts to revert that change.
2022-07-25 01:11:46 +02:00
Lukasz Lenart de3dabbe44 Merge pull request #579 from apache/WW-5204-ognl-3-3-3
[WW-5204] Upgrades OGNL to version 3.3.3
2022-07-11 10:49:38 +02:00
Lukasz Lenart 82f7904206 WW-5204 Upgrades OGNL to version 3.3.3 2022-07-11 10:28:58 +02:00
Lukasz Lenart 42e3da550f Merge pull request #577 from apache/WW-5192-radio
[WW-5192] Fixes broken radio tag when using with enums
2022-07-11 10:27:06 +02:00
Lukasz Lenart f3cb89202d Merge pull request #571 from apache/WW-5190-match-action-proxy
[WW-5190] Fixes StackOverflowException when dispatching request
2022-07-11 10:25:16 +02:00
Lukasz Lenart 836a27692e Merge pull request #578 from sepe81/update-jasperreports
WW-5202 Update jasperreports to 6.19.1 and exclude optional itext from jasperreports
2022-07-08 17:19:41 +02:00
Sebastian Peters 6312572331 Exclude itext from jasperreports
b/c it's an optional dependency
and version 2.1.7.js9 is missing on maven central
2022-07-08 14:09:47 +02:00
Sebastian Peters e7db7ade62 Update jasperreports to 6.19.1 2022-07-08 14:08:46 +02:00
Lukasz Lenart b77c2f476a Uses different port for Jetty during integration testing to avoid clash 2022-07-08 08:21:16 +02:00
Lukasz Lenart e6c1cec7f8 WW-5192 Fixes brok radio tag when using with enums 2022-07-07 21:34:43 +02:00
Lukasz Lenart a781b5a27b Merge pull request #576 from apache/hiberante-validator
[WW-5193] Uses proper org.hibernate.validator groupId and upgrade to version 6.1.3.Final
2022-07-07 15:11:35 +02:00
Lukasz Lenart b71732fa14 WW-5193 Uses proper org.hibernate.validator groupId and upgrade to version 6.1.3.Final 2022-07-07 14:55:19 +02:00
Lukasz Lenart 3f79d64e6a Merge pull request #575 from apache/upgrade-log4j
[WW-5201] Upgrades log4j2 to version 2.18.0
2022-07-07 14:54:08 +02:00
Lukasz Lenart 039fd9f4ee WW-5201 Upgrades log4j2 to version 2.18.0 2022-07-07 14:12:12 +02:00
Lukasz Lenart 393d5be50c Merge pull request #574 from tobiasstadler/WW-5197
WW-5197 Adds support for java.sql.Date
2022-07-07 14:06:22 +02:00
JCgH4164838Gh792C124B5 24e279b165 Update:
- Added arbitrary code coverage test.
2022-07-03 17:37:58 -04:00
Lukasz Lenart cb59974903 WW-5190 Marks all Struts related filters with <async-supported/> 2022-06-27 09:44:51 +02:00
Lukasz Lenart ecfdee137d WW-5190 Disables test which won't pass without refactoring the prepare and execute filters 2022-06-27 09:37:17 +02:00
Lukasz Lenart 8c37b1523f WW-5190 Uses proper order of servlets and filters 2022-06-22 07:58:12 +02:00
Lukasz Lenart 62b83021a2 Merge pull request #569 from apache/WW-5188-since-6
[WW-5188] Replaces since 2.6 with 6.0
2022-06-21 10:39:47 +02:00
Tobias Stadler f3f2d52a1c Added test case for java.sql.Date 2022-06-21 10:23:17 +02:00
Tobias Stadler 61ded9a3e7 WW-5197 Adds support for java.sql.Date 2022-06-21 10:09:31 +02:00
JCgH4164838Gh792C124B5 963b473e6c Initial commit:
- Update to use consistent name for expression and BeanInfo factories in
default configuration implementation and provider.
- Add inject annotation to the non-default constructor to ensure the proper
constructor is called during DI for containers.
- Use fully-qualified factory names for defaults in default.properties.
- Ensure unique types for each cache factory in struts-default.xml
2022-06-20 17:07:57 -04:00
Lukasz Lenart d639b59f6d Merge branch 'master' into WW-5190-match-action-proxy 2022-06-18 09:45:20 +02:00
Lukasz Lenart 8e468a368e WW-5190 Defines two examples with Dispatcher result and integration tests 2022-06-18 09:45:10 +02:00
Lukasz Lenart ebe1b80ed2 WW-5190 Adds a new test to cover new logic of comparing ActionProxies 2022-06-18 08:12:29 +02:00
Lukasz Lenart 957292ecdb Simplifies logging pattern in Showcase app 2022-06-18 07:27:32 +02:00
Lukasz Lenart 06290cef91 Fixes showing configuration of an action in Showcase app 2022-06-18 07:26:13 +02:00
Lukasz Lenart a6a4529503 Fixes logging in Showcase app 2022-06-18 07:25:26 +02:00
Yasser Zamani 64d054221f Merge pull request #566 from apache/WW-5185-struts-resource
[WW-5185] Reintroduces proper implementation of Tiles resource to support wildcard matching of Tiles definitions
2022-06-17 11:16:38 +04:30
Yasser Zamani dc4e403d30 Merge pull request #570 from apache/WW-5187-velocity
[WW-5187] Comments out Velocity based PageFilter
2022-06-17 11:15:21 +04:30
Yasser Zamani e6bc93daf2 Merge pull request #572 from apache/WW-5191-textarea-max-length
[WW-5191] Fixes placement of maxLength and minLength attributes in <s:textarea/> tag
2022-06-17 11:13:09 +04:30
Lukasz Lenart 0e4d5962e1 WW-5191 Fixes placement of maxLength and minLength attributes in <s:textarea/> tag 2022-06-15 15:18:46 +02:00
Lukasz Lenart 69102e9075 WW-5190 Uses wrapped request only when processing request by Struts 2022-06-15 11:07:53 +02:00
Lukasz Lenart 1c2b491a27 WW-5190 Reuses action proxy if namespace, name and method are match 2022-06-15 11:07:29 +02:00
Lukasz Lenart 5af840b160 WW-5190 Extracts method name from config for known action name 2022-06-15 11:06:45 +02:00
Lukasz Lenart b6b74a46ea WW-5188 Replaces since 2.6 with 6.0 2022-06-14 13:34:27 +02:00
Lukasz Lenart fc2aebd10a WW-5187 Comments out Velocity based PageFilter 2022-06-14 13:17:19 +02:00
Lukasz Lenart ba041e1ee6 Merge pull request #568 from tobiasstadler/master
Add async and velocity plugin to bom
2022-06-14 11:43:49 +02:00
Tobias Stadler 0c3534e8b4 Added async and velocity plugin to bom 2022-06-14 09:53:10 +02:00
Lukasz Lenart 9a2996f9b7 Uses proper Servlet API 3.1 headers 2022-06-10 16:06:27 +02:00
Lukasz Lenart 3825229f44 WW-5185 Reintroduces proper implementation of Tiles resource to support wildcard matching of Tiles definitions
It was broken after refactoring related to WW-5011
2022-06-10 16:06:10 +02:00
Brian Andle 584634a9b5 WW-5184 - Added ParameterValueAware interface and unit test 2022-06-07 21:50:34 -07:00
Brian Andle 5763476830 WW-5184 - Change info to warn from peer review 2022-06-06 11:11:20 -07:00
Brian Andle 105b22fb9a WW-5184 - Add optional parameter value check to ParametersInterceptor 2022-06-04 18:03:57 -07:00
Lukasz Lenart 4b3ee53f93 [maven-release-plugin] prepare for next development iteration 2022-06-02 09:11:11 +02:00
Lukasz Lenart 68fb49c10e [maven-release-plugin] prepare release STRUTS_6_0_0 2022-06-02 09:11:02 +02:00
Lukasz Lenart 77c175c7be Merge pull request #555 from hboutemy/patch-4
upgrade Felix m-bundle-p: reproducible builds
2022-05-25 10:42:55 +02:00
Hervé Boutemy 65b7e8c36f upgrade Felix m-bundle-p: reproducible builds 2022-05-25 10:00:15 +02:00
Lukasz Lenart 735bbc283e [maven-release-plugin] prepare for next development iteration 2022-05-24 13:59:32 +02:00
Lukasz Lenart 981885fd6a [maven-release-plugin] prepare release STRUTS_6_0_0_RC4 2022-05-24 13:59:22 +02:00
Lukasz Lenart 07b88fcc35 Upgrades integration tests config to match Spring and Jetty 2022-05-24 09:51:42 +02:00
Lukasz Lenart 2cbe47297e Merge pull request #554 from gregh3269/More_localdatetime_support
Add basic LocalDateTime support WW-5175
2022-05-23 07:35:43 +02:00
Lukasz Lenart 545add9365 Merge pull request #553 from apache/WW-5179-max-length
[WW-5179] Set default value of struts.ognl.expressionMaxLength to 256
2022-05-23 07:34:17 +02:00
Lukasz Lenart ebecc7d39d Merge pull request #552 from apache/WW-5165-upgrade-spring
[WW-5165] Upgrades Spring to version 5.3.20
2022-05-23 07:34:05 +02:00
Greg Huber 226a1d49ce Add basic LocalDateTime support WW-5175 2022-05-20 11:47:08 +01:00
Greg Huber 075ef7c4e1 Add basic LocalDateTime support WW-5175 2022-05-19 10:30:36 +01:00
Lukasz Lenart 1237110652 WW-5179 Adjusts test to match new default value 2022-05-17 21:17:56 +02:00
Lukasz Lenart 3f2518afa8 WW-5179 Set default value of struts.ognl.expressionMaxLength to 256 2022-05-17 20:59:51 +02:00
Lukasz Lenart 9f9edf4705 WW-5165 Upgrades Spring to version 5.3.20 2022-05-17 07:37:39 +02:00
gregh3269 7e912742ed Basic LocalDateTime support (#532)
* Basic LocalDateTime support

* Basic LocalDateTime support

* Basic LocalDateTime support

* Basic LocalDateTime support

* Basic LocalDateTime support

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

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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-04 08:52:18 +00:00
Lukasz Lenart d07a496d5c Uses common Maven Compiler plugin to set proper source and target version 2022-05-04 10:45:02 +02:00
Lukasz Lenart bef1f67d4a Upgrades Maven Jetty Plugin to work with JDK8+ 2022-05-04 10:44:54 +02:00
Lukasz Lenart e2718aa482 Enables branch autodeleting after PR has been merged 2022-04-07 14:43:38 +02:00
Lukasz Lenart b73fec4de0 Drops unused class 2022-04-04 17:12:33 +02:00
Lukasz Lenart c2795d2e30 Uses project specific folder 2022-03-28 13:09:21 +02:00
Lukasz Lenart a987e31a0e Upgrades OWASP Dependency Check plugin to version 7.0.1 2022-03-28 07:45:51 +02:00
Lukasz Lenart 6aff5b7faa WW-5174 Upgrades Jackson-Core to version 2.13.2 and Jackson-Databind to 2.13.2.1 2022-03-28 07:26:50 +02:00
Lukasz Lenart 5b40f9f48e WW-5172 Upgrades Freemarker to 2.3.31 version 2022-03-15 14:32:02 +01:00
Lukasz Lenart e9d0a5518c Cleans up code 2022-03-15 14:27:57 +01:00
597 changed files with 23540 additions and 24529 deletions
+6
View File
@@ -1,3 +1,4 @@
# Documentation https://s.apache.org/asfyaml
notifications:
commits: commits@struts.apache.org
# Send all issue emails (new, closed, comments) to issues@
@@ -8,3 +9,8 @@ notifications:
pullrequests_comment: issues@struts.apache.org
# Link opened PRs with JIRA
jira_options: link label worklog
github:
del_branch_on_merge: true
protected_branches:
master: { }
+47
View File
@@ -0,0 +1,47 @@
# 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.
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'java' ]
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@v2
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"
+57
View File
@@ -0,0 +1,57 @@
# 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.
name: Java Build
on:
pull_request:
push:
branches:
- master
env:
MAVEN_OPTS: -Xmx2048m -Xms1024m
LANG: en_US.utf8
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
java: [ '8', '11', '17' ]
steps:
- name: Checkout code
uses: actions/checkout@v3.0.2
- name: Set up cache
uses: actions/cache@v3.0.8
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v3
with:
distribution: adopt
java-version: ${{ matrix.java }}
- name: Build with Maven on Java ${{ matrix.java }}
if: matrix.java != '11'
run: mvn -B -V -DskipAssembly test --no-transfer-progress
- name: Code coverage on Java ${{ matrix.java }}
if: matrix.java == '11'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }}
run: mvn -B -V -Pcoverage -DskipAssembly verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar --no-transfer-progress
@@ -0,0 +1,69 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache license, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the license for the specific language governing permissions and
# limitations under the license.
name: "Scorecards supply-chain security"
on:
branch_protection_rule:
schedule:
- cron: "30 1 * * 6" # Weekly on Saturdays
push:
branches: [ "master" ]
permissions: read-all
jobs:
analysis:
name: "Scorecards analysis"
runs-on: ubuntu-latest
permissions:
# Needed to upload the results to the code-scanning dashboard.
security-events: write
actions: read
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
steps:
- name: "Checkout code"
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # 3.1.0
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@99c53751e09b9529366343771cc321ec74e9bd3d # 2.0.6
with:
results_file: results.sarif
results_format: sarif
# A read-only PAT token, which is sufficient for the action to function.
# The relevant discussion: https://github.com/ossf/scorecard-action/issues/188
repo_token: ${{ secrets.GITHUB_TOKEN }}
# Publish the results for public repositories to enable scorecard badges.
# For more details: https://github.com/ossf/scorecard-action#publishing-results
publish_results: true
- name: "Upload artifact"
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # 3.1.0
with:
name: SARIF file
path: results.sarif
retention-days: 5
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@b398f525a5587552e573b247ac661067fafa920b # 2.1.22
with:
sarif_file: results.sarif
+1 -1
View File
@@ -14,5 +14,5 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
-32
View File
@@ -1,32 +0,0 @@
dist: trusty
language: java
sudo: false
jdk:
- oraclejdk9
- oraclejdk11
install: true
env:
global:
- secure: iI7IpfDtS+LUyS2yNuRCR3KelNyvBHuoMQ3gb1UNmR5SSL7jO/p3olQWrQROs28FJ+dpE3lHyIjoHrebKQGJHHAgTG2XWxn+G3fDsf+wSSFSLoDGj0o2SgGXooBbR2dccnNZHCyQaOyE2cIPWaOxrQZFE4No70LQB4mrP/gdkoc=
matrix:
include:
- jdk: oraclejdk8
env: STRUTS_IT=true # do integration tests and coverage reports when jdk7,9 and 11 tests prospered
script:
- if [ "$STRUTS_IT" == "true" ]; then
./mvnw clean verify org.jacoco:jacoco-maven-plugin:report org.jacoco:jacoco-maven-plugin:report-integration org.eluder.coveralls:coveralls-maven-plugin:report -Ptravis-coveralls -DskipAssembly -B;
else
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
./mvnw test -DskipAssembly -B;
else
./mvnw test -DskipAssembly -Dupdate-impact -B;
fi;
fi;
cache:
directories:
- $HOME/.m2
Vendored
+13 -11
View File
@@ -39,12 +39,12 @@ pipeline {
stages {
stage('Build') {
steps {
sh 'mvn -B clean install -DskipTests -DskipAssembly'
sh './mvnw -B clean install -DskipTests -DskipAssembly'
}
}
stage('Test') {
steps {
sh 'mvn -B test'
sh './mvnw -B test'
}
post {
always {
@@ -74,12 +74,12 @@ pipeline {
stages {
stage('Build') {
steps {
sh 'mvn -B clean install -DskipTests -DskipAssembly'
sh './mvnw -B clean install -DskipTests -DskipAssembly'
}
}
stage('Test') {
steps {
sh 'mvn -B test'
sh './mvnw -B verify -Pcoverage -DskipAssembly'
}
post {
always {
@@ -94,7 +94,7 @@ pipeline {
}
steps {
withCredentials([string(credentialsId: 'asf-struts-sonarcloud', variable: 'SONARCLOUD_TOKEN')]) {
sh 'mvn sonar:sonar -DskipAssembly -Dsonar.login=${SONARCLOUD_TOKEN}'
sh './mvnw -B -Pcoverage -DskipAssembly -Dsonar.login=${SONARCLOUD_TOKEN} verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar'
}
}
}
@@ -119,12 +119,12 @@ pipeline {
stages {
stage('Build') {
steps {
sh 'mvn -B clean install -DskipTests -DskipAssembly'
sh './mvnw -B clean install -DskipTests -DskipAssembly'
}
}
stage('Test') {
steps {
sh 'mvn -B test'
sh './mvnw -B test'
// step([$class: 'JiraIssueUpdater', issueSelector: [$class: 'DefaultIssueSelector'], scm: scm])
}
post {
@@ -142,7 +142,7 @@ pipeline {
dir("local-snapshots-dir/") {
deleteDir()
}
sh 'mvn -B source:jar javadoc:jar -DskipAssembbly'
sh './mvnw -B source:jar javadoc:jar -DskipTests -DskipAssembly'
}
}
stage('Deploy Snapshot') {
@@ -151,7 +151,7 @@ pipeline {
}
steps {
withCredentials([file(credentialsId: 'lukaszlenart-repository-access-token', variable: 'CUSTOM_SETTINGS')]) {
sh 'mvn -s \${CUSTOM_SETTINGS} deploy'
sh './mvnw -s \${CUSTOM_SETTINGS} deploy -DskipTests -DskipAssembly'
}
}
}
@@ -160,14 +160,16 @@ pipeline {
branch 'master'
}
steps {
sh './mvnw -B package -DskipTests'
sshPublisher(publishers: [
sshPublisherDesc(
configName: 'Nightlies',
transfers: [
sshTransfer(
remoteDirectory: '/x1/dist/struts',
remoteDirectory: '/struts/snapshot',
removePrefix: 'assembly/target/assembly/out',
sourceFiles: 'assembly/target/assembly/out/struts-*.zip'
sourceFiles: 'assembly/target/assembly/out/struts-*.zip',
cleanRemote: true
)
],
verbose: true
+5 -3
View File
@@ -17,11 +17,13 @@
The Apache Struts web framework
-------------------------------
[![Build Status @ Jenkins](https://builds.apache.org/buildStatus/icon?job=Struts%2FStruts+Core%2Fmaster)](https://ci-builds.apache.org/job/Struts/job/Struts%20Core/job/master/)
[![Build Status @ Travis](https://travis-ci.com/apache/struts.svg?branch=master)](https://app.travis-ci.com/apache/struts)
[![Jenkins Build](https://builds.apache.org/buildStatus/icon?job=Struts%2FStruts+Core%2Fmaster)](https://ci-builds.apache.org/job/Struts/job/Struts%20Core/job/master/)
[![Java Build](https://github.com/apache/struts/actions/workflows/maven.yml/badge.svg)](https://github.com/apache/struts/actions/workflows/maven.yml)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.struts/struts2-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.apache.struts/struts2-core/)
[![Javadocs](https://javadoc.io/badge/org.apache.struts/struts2-core.svg)](https://javadoc.io/doc/org.apache.struts/struts2-core)
[![Coverage Status](https://coveralls.io/repos/github/apache/struts/badge.svg)](https://coveralls.io/github/apache/struts)
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=apache_struts&metric=coverage)](https://sonarcloud.io/summary/new_code?id=apache_struts)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/apache/struts/badge)](https://deps.dev/maven/org.apache.struts%3Astruts2-core)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6618/badge)](https://bestpractices.coreinfrastructure.org/projects/6618)
[![License](http://img.shields.io/:license-apache-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html)
The Apache Struts web framework is a free open-source solution for creating Java web applications.
+2 -2
View File
@@ -7,8 +7,8 @@ and what potential vulnerability it can have:
| Version | Supported |
| ------- | ------------------ |
| 2.5.20 | :white_check_mark: |
| 2.3.37 | :white_check_mark: |
| 6.0.0 | :white_check_mark: |
| 2.5.30 | :white_check_mark: |
## Reporting New Security Issues with thr Apache Struts
+12
View File
@@ -0,0 +1,12 @@
# Struts 2 Apps
These module consists of two example applications, which were built using the Apache Struts project.
One is an old-fashioned Web application and another is a modern REST based single page app.
## Installation
Enter a given folder, either `showcase/` or `rest-showcase/` and start the app using Maven:
```
mvn jetty:run
```
then open your browser at http://localhost:8080 and navigate to a proper context.
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.0.0-SNAPSHOT</version>
<version>6.1.0</version>
</parent>
<artifactId>struts2-apps</artifactId>
<packaging>pom</packaging>
+5 -4
View File
@@ -24,12 +24,12 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>6.0.0-SNAPSHOT</version>
<version>6.1.0</version>
</parent>
<artifactId>struts2-rest-showcase</artifactId>
<packaging>war</packaging>
<version>6.0.0-SNAPSHOT</version>
<version>6.1.0</version>
<name>Struts 2 Rest Showcase Webapp</name>
<description>Struts 2 Rest Showcase Example</description>
@@ -108,9 +108,9 @@
<finalName>struts2-rest-showcase</finalName>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.16.v20140903</version>
<version>9.4.46.v20220331</version>
<configuration>
<stopKey>CTRL+C</stopKey>
<stopPort>8999</stopPort>
@@ -125,6 +125,7 @@
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>@{argLine}</argLine>
<excludes>
<exclude>it/**</exclude>
<exclude>**/*$*</exclude>
@@ -21,7 +21,7 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
@@ -41,4 +41,4 @@
<package name="rest-showcase" extends="rest-default">
<global-allowed-methods>index,show,create,update,destroy,deleteConfirm,edit,editNew</global-allowed-methods>
</package>
</struts>
</struts>
@@ -19,13 +19,14 @@
* under the License.
*/
-->
<web-app id="starter" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>Struts 2 Rest Example</display-name>
<!-- Filters -->
<!-- START SNIPPET: filter -->
<filter>
+21 -25
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>6.0.0-SNAPSHOT</version>
<version>6.1.0</version>
</parent>
<artifactId>struts2-showcase</artifactId>
@@ -101,7 +101,7 @@
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
@@ -121,6 +121,11 @@
<artifactId>log4j-jcl</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j2.version}</version>
</dependency>
<dependency>
<groupId>opensymphony</groupId>
@@ -144,24 +149,15 @@
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>2.39.0</version>
<version>2.61.0</version>
<scope>test</scope>
</dependency>
<!-- BeanValidation Example -->
<dependency>
<groupId>org.hibernate</groupId>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.2.Final</version>
</dependency>
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
This is only necessary in tests-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
<version>${hibernate-validator.version}</version>
</dependency>
</dependencies>
@@ -171,11 +167,14 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.0.0-M4</version>
<version>3.0.0-M6</version>
<configuration>
<includes>
<include>it.org.apache.struts2.showcase.*Test</include>
</includes>
<systemPropertyVariables>
<http.port>8090</http.port>
</systemPropertyVariables>
</configuration>
<executions>
<execution>
@@ -193,22 +192,21 @@
</executions>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.16.v20140903</version>
<version>9.4.46.v20220331</version>
<configuration>
<stopKey>CTRL+C</stopKey>
<stopPort>8999</stopPort>
<systemProperties>
<systemProperty>
<name>log4j.configuration</name>
<value>file:${basedir}/src/main/resources/log4j.properties</value>
</systemProperty>
<systemProperty>
<name>slf4j</name>
<value>false</value>
</systemProperty>
</systemProperties>
<httpConnector>
<port>8090</port>
</httpConnector>
<scanIntervalSeconds>10</scanIntervalSeconds>
<webAppSourceDirectory>${basedir}/src/main/webapp/</webAppSourceDirectory>
<webAppConfig>
@@ -223,11 +221,8 @@
<goals>
<!-- stop any previous instance to free up the port -->
<goal>stop</goal>
<goal>run-forked</goal>
<goal>start</goal>
</goals>
<configuration>
<waitForChild>false</waitForChild>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
@@ -242,6 +237,7 @@
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>@{argLine}</argLine>
<excludes>
<exclude>it/**</exclude>
<exclude>**/*$*</exclude>
@@ -22,16 +22,13 @@ package org.apache.struts2.showcase.source;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.action.ServletContextAware;
import javax.servlet.ServletContext;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
@@ -42,202 +39,192 @@ import java.util.List;
*/
public class ViewSourceAction extends ActionSupport implements ServletContextAware {
private String page;
private String className;
private String config;
private String page;
private String className;
private String config;
private List pageLines;
private List classLines;
private List configLines;
private List<String> pageLines;
private List<String> classLines;
private List<String> configLines;
private int configLine;
private int padding = 10;
private int configLine;
private int padding = 10;
private ServletContext servletContext;
private ServletContext servletContext;
public String execute() throws MalformedURLException, IOException {
public String execute() throws IOException {
if (page != null) {
if (page != null) {
InputStream in = ClassLoaderUtil.getResourceAsStream(page.substring(page.indexOf("//") + 1), getClass());
page = page.replace("//", "/");
InputStream in = ClassLoaderUtil.getResourceAsStream(page.substring(page.indexOf("//") + 1), getClass());
page = page.replace("//", "/");
if (in == null) {
in = servletContext.getResourceAsStream(page);
while (in == null && page.indexOf('/', 1) > 0) {
page = page.substring(page.indexOf('/', 1));
in = servletContext.getResourceAsStream(page);
}
}
pageLines = read(in, -1);
if (in == null) {
in = servletContext.getResourceAsStream(page);
while (in == null && page.indexOf('/', 1) > 0) {
page = page.substring(page.indexOf('/', 1));
in = servletContext.getResourceAsStream(page);
}
}
pageLines = read(in, -1);
if (in != null) {
in.close();
}
}
if (in != null) {
in.close();
}
}
if (className != null) {
className = "/" + className.replace('.', '/') + ".java";
InputStream in = getClass().getResourceAsStream(className);
if (in == null) {
in = servletContext.getResourceAsStream("/WEB-INF/src" + className);
}
classLines = read(in, -1);
if (className != null) {
className = "/" + className.replace('.', '/') + ".java";
InputStream in = getClass().getResourceAsStream(className);
if (in == null) {
in = servletContext.getResourceAsStream("/WEB-INF/src/java" + className);
}
classLines = read(in, -1);
if (in != null) {
in.close();
}
}
if (in != null) {
in.close();
}
}
final String rootPath = ServletActionContext.getServletContext().getRealPath("/");
final String rootPathUnix = (rootPath != null ? rootPath.replace(File.separator, "/") : null); // Make path Unix-like for comparison (e.g. on Windows)
final String rootPathFileURI = "file://" + rootPathUnix;
final String collapsedRootPathFileURI = rootPathFileURI.replace("//", "/"); // Config string may have been transformed
final String rootPathWarFileURI = "war:file://" + rootPathUnix;
final String collapsedRootPathWarFileURI = rootPathWarFileURI.replace("//", "/"); // Config string may have been transformed
if (config != null && (rootPath == null || config.startsWith(rootPath) ||
config.startsWith(rootPathFileURI) || config.startsWith(collapsedRootPathFileURI) ||
config.startsWith(rootPathWarFileURI) || config.startsWith(collapsedRootPathWarFileURI))) {
int pos = config.lastIndexOf(':');
configLine = Integer.parseInt(config.substring(pos + 1));
config = config.substring(0, pos).replace("//", "/");
configLines = read(new URL(config).openStream(), configLine);
}
return SUCCESS;
}
if (config != null && config.startsWith("file:/")) {
int pos = config.lastIndexOf(':');
configLine = Integer.parseInt(config.substring(pos + 1));
configLines = read(new URL(config.substring(0, pos)).openStream(), configLine);
}
return SUCCESS;
}
/**
* @param className the className to set
*/
public void setClassName(String className) {
if (className != null && className.trim().length() > 0) {
this.className = className;
}
}
/**
* @param className the className to set
*/
public void setClassName(String className) {
if (className != null && className.trim().length() > 0) {
this.className = className;
}
}
/**
* @param config the config to set
*/
public void setConfig(String config) {
if (config != null && config.trim().length() > 0) {
this.config = config;
}
}
/**
* @param config the config to set
*/
public void setConfig(String config) {
if (config != null && config.trim().length() > 0) {
this.config = config;
}
}
/**
* @param page the page to set
*/
public void setPage(String page) {
if (page != null && page.trim().length() > 0) {
this.page = page;
}
}
/**
* @param page the page to set
*/
public void setPage(String page) {
if (page != null && page.trim().length() > 0) {
this.page = page;
}
}
/**
* @param padding the padding to set
*/
public void setPadding(int padding) {
this.padding = padding;
}
/**
* @param padding the padding to set
*/
public void setPadding(int padding) {
this.padding = padding;
}
/**
* @return the classLines
*/
public List getClassLines() {
return classLines;
}
/**
* @return the classLines
*/
public List<String> getClassLines() {
return classLines;
}
/**
* @return the configLines
*/
public List getConfigLines() {
return configLines;
}
/**
* @return the configLines
*/
public List<String> getConfigLines() {
return configLines;
}
/**
* @return the pageLines
*/
public List getPageLines() {
return pageLines;
}
/**
* @return the pageLines
*/
public List<String> getPageLines() {
return pageLines;
}
/**
* @return the className
*/
public String getClassName() {
return className;
}
/**
* @return the className
*/
public String getClassName() {
return className;
}
/**
* @return the config
*/
public String getConfig() {
return config;
}
/**
* @return the config
*/
public String getConfig() {
return config;
}
/**
* @return the page
*/
public String getPage() {
return page;
}
/**
* @return the page
*/
public String getPage() {
return page;
}
/**
* @return the configLine
*/
public int getConfigLine() {
return configLine;
}
/**
* @return the configLine
*/
public int getConfigLine() {
return configLine;
}
/**
* @return the padding
*/
public int getPadding() {
return padding;
}
/**
* @return the padding
*/
public int getPadding() {
return padding;
}
/**
* Reads in a stream, optionally only including the target line number
* and its padding
*
* @param in The input stream
* @param targetLineNumber The target line number, negative to read all
* @return A list of lines
*/
private List read(InputStream in, int targetLineNumber) {
List snippet = null;
if (in != null) {
snippet = new ArrayList();
int startLine = 0;
int endLine = Integer.MAX_VALUE;
if (targetLineNumber > 0) {
startLine = targetLineNumber - padding;
endLine = targetLineNumber + padding;
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
/**
* Reads in a stream, optionally only including the target line number
* and its padding
*
* @param in The input stream
* @param targetLineNumber The target line number, negative to read all
* @return A list of lines
*/
private List<String> read(InputStream in, int targetLineNumber) {
List<String> snippet = null;
if (in != null) {
snippet = new ArrayList<>();
int startLine = 0;
int endLine = Integer.MAX_VALUE;
if (targetLineNumber > 0) {
startLine = targetLineNumber - padding;
endLine = targetLineNumber + padding;
}
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
int lineno = 0;
String line;
while ((line = reader.readLine()) != null) {
lineno++;
if (lineno >= startLine && lineno <= endLine) {
snippet.add(line);
}
}
} catch (Exception ex) {
// ignoring as snippet not available isn't a big deal
}
}
return snippet;
}
int lineno = 0;
String line;
while ((line = reader.readLine()) != null) {
lineno++;
if (lineno >= startLine && lineno <= endLine) {
snippet.add(line);
}
}
} catch (Exception ex) {
// ignoring as snippet not available isn't a big deal
}
}
return snippet;
}
public void withServletContext(ServletContext arg0) {
this.servletContext = arg0;
}
public void withServletContext(ServletContext arg0) {
this.servletContext = arg0;
}
}
@@ -0,0 +1,56 @@
/*
* 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.showcase.wait;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.interceptor.exec.ExecutorProvider;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExecutorProvider implements ExecutorProvider {
private static final Logger LOG = LogManager.getLogger(ThreadPoolExecutorProvider.class);
private final ExecutorService executor;
public ThreadPoolExecutorProvider() {
this.executor = new ThreadPoolExecutor(1, 2, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>());
}
@Override
public void execute(Runnable task) {
LOG.info("Executing task: {}", task);
executor.execute(task);
}
@Override
public boolean isShutdown() {
return executor.isShutdown();
}
@Override
public void shutdown() {
LOG.info("Shutting down executor");
executor.shutdown();
}
}
+4 -5
View File
@@ -22,15 +22,14 @@
<Configuration>
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
<PatternLayout pattern="[%-5p] %C{2} (%F:%L) - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="com.opensymphony.xwork2" level="info"/>
<Logger name="org.apache.struts2" level="info"/>
<Logger name="org.springframework" level="info"/>
<Root level="info">
<AppenderRef ref="STDOUT"/>
</Root>
<Logger name="org.apache.struts2" level="info"/>
<Logger name="com.opensymphony.xwork2" level="info"/>
</Loggers>
</Configuration>
</Configuration>
@@ -21,31 +21,31 @@
-->
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.2//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
<field name="description1">
<field-validator type="requiredstring">
<message>Description1 Is Required !!!</message>
</field-validator>
</field>
<field name="description2">
<field-validator type="requiredstring">
<message>Description2 Is Required !!!</message>
</field-validator>
</field>
<field name="description3">
<field-validator type="requiredstring">
<message>Description3 Is Required !!!</message>
</field-validator>
</field>
<field name="description4">
<field-validator type="requiredstring">
<message>Description4 Is Required !!!</message>
</field-validator>
</field>
</validators>
</validators>
@@ -19,7 +19,7 @@
* under the License.
*/
-->
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.dtd">
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "https://struts.apache.org/dtds/xwork-validator-1.0.dtd">
<validators>
<!-- Field-Validator Syntax -->
<field name="currentEmployee.empId">
@@ -19,7 +19,7 @@
* under the License.
*/
-->
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.dtd">
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "https://struts.apache.org/dtds/xwork-validator-1.0.dtd">
<validators>
<!-- Field-Validator Syntax -->
<field name="currentSkill.name">
@@ -21,7 +21,7 @@
-->
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.2//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
<field name="upload">
@@ -35,5 +35,4 @@
<message>Caption cannot be empty</message>
</field-validator>
</field>
</validators>
</validators>
@@ -19,7 +19,7 @@
* under the License.
*/
-->
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.dtd">
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "https://struts.apache.org/dtds/xwork-validator-1.0.dtd">
<validators>
<field name="person">
<field-validator type="visitor">
@@ -19,7 +19,7 @@
* under the License.
*/
-->
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.dtd">
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "https://struts.apache.org/dtds/xwork-validator-1.0.dtd">
<validators>
<field name="name">
<field-validator type="requiredstring">
@@ -21,8 +21,8 @@
-->
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.2//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
<field name="value">
<field-validator type="requiredstring">
@@ -30,13 +30,13 @@
<message>Value must not be empty</message>
</field-validator>
</field>
<field name="count">
<field-validator type="int">
<message>Count must be an integer</message>
</field-validator>
</field-validator>
</field>
</validators>
</validators>
@@ -21,10 +21,10 @@
-->
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<!-- START SNIPPET: fieldValidatorsExample -->
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<!-- START SNIPPET: fieldValidatorsExample -->
<validators>
<field name="requiredValidatorField">
<field-validator type="required">
@@ -19,12 +19,12 @@
* under the License.
*/
-->
<!DOCTYPE validators PUBLIC
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<!-- START SNIPPET: fieldValidatorsExample -->
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<!-- START SNIPPET: fieldValidatorsExample -->
<validators>
<field name="requiredValidatorField">
<field-validator type="required">
@@ -19,13 +19,13 @@
* under the License.
*/
-->
<!DOCTYPE validators PUBLIC
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<!-- START SNIPPET: nonFieldValidatorsExample -->
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<!-- START SNIPPET: nonFieldValidatorsExample -->
<validators>
<validator type="expression">
<param name="expression"><![CDATA[ ( (someText == someTextRetype) && (someTextRetype == someTextRetypeAgain) ) ]]></param>
@@ -19,11 +19,11 @@
* under the License.
*/
-->
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN" "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<!-- START SNIPPET: quizValidators -->
<!--
Add the following DOCTYPE declaration as first line of your XXX-validation.xml file:
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN" "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
-->
<validators>
<field name="name">
@@ -21,7 +21,7 @@
-->
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
<field name="name">
@@ -19,17 +19,17 @@
* under the License.
*/
-->
<!DOCTYPE validators PUBLIC
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<validators>
<field name="name">
<field-validator type="requiredstring">
<message>Name Required</message>
</field-validator>
</field>
<field name="age">
<field name="age">
<field-validator type="int">
<param name="min">1</param>
<param name="max">100</param>
@@ -41,6 +41,6 @@
<message>Birthday Required</message>
</field-validator>
</field>
</validators>
</validators>
@@ -19,10 +19,10 @@
* under the License.
*/
-->
<!DOCTYPE validators PUBLIC
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
<!-- START SNIPPET: visitorValidatorsExample -->
<validators>
@@ -21,12 +21,12 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="actionchaining" extends="struts-default" namespace="/actionchaining">
<action name="actionChain1" class="org.apache.struts2.showcase.actionchaining.ActionChain1">
<result type="chain">actionChain2</result>
<result type="chain">actionChain2</result>
</action>
<action name="actionChain2" class="org.apache.struts2.showcase.actionchaining.ActionChain2">
<result type="chain">actionChain3</result>
@@ -21,7 +21,7 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="async" extends="json-default" namespace="/async">
@@ -21,15 +21,15 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="conversion" namespace="/conversion" extends="struts-default">
<action name="index">
<result>/WEB-INF/conversion/index.jsp</result>
</action>
<!-- Example populating a List inside an Action -->
<action name="enterPersonsInfo" method="input"
class="org.apache.struts2.showcase.conversion.PersonAction">
@@ -49,8 +49,8 @@
<action name="showPersonJavaCode">
<result type="plainText">/WEB-INF/conversion/Person.java.txt</result>
</action>
<!-- Example populating a Set inside an Action -->
<action name="enterAddressesInfo" class="org.apache.struts2.showcase.conversion.AddressAction" method="input">
<result>/WEB-INF/conversion/enterAddressInfo.jsp</result>
@@ -68,9 +68,9 @@
<action name="showAddressJavaCode">
<result type="plainText">/WEB-INF/conversion/Address.java.txt</result>
</action>
<!-- Example populating a List with Tiger 5 Enum -->
<!-- Example populating a List with Tiger 5 Enum -->
<action name="enterOperationEnumInfo" class="org.apache.struts2.showcase.conversion.OperationsEnumAction" method="input">
<result>/WEB-INF/conversion/enterOperations.jsp</result>
</action>
@@ -93,6 +93,6 @@
<action name="showOperationsEnumActionConversionProperties">
<result type="plainText">/WEB-INF/conversion/OperationsEnumActionConversion.txt</result>
</action>
</package>
</struts>
</struts>
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="dispatcher" extends="struts-default" namespace="/dispatcher">
<action name="dispatch">
<result type="dispatcher">
/WEB-INF/dispatcher/dispatch-result.jsp
</result>
</action>
<action name="forward">
<result type="dispatcher">/dispatcher/dispatch.action</result>
</action>
</package>
</struts>
@@ -21,7 +21,7 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="filedownload" extends="struts-default" namespace="/filedownload">
@@ -21,11 +21,11 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="fileupload" extends="struts-default" namespace="/fileupload">
<action name="upload" class="org.apache.struts2.showcase.fileupload.FileUploadAction" method="input">
<result>/WEB-INF/fileupload/upload.jsp</result>
</action>
@@ -34,11 +34,11 @@
<result name="input">/WEB-INF/fileupload/upload.jsp</result>
<result>/WEB-INF/fileupload/upload-success.jsp</result>
</action>
<action name="multipleUploadUsingList">
<result>/WEB-INF/fileupload/multipleUploadUsingList.jsp</result>
</action>
<action name="doMultipleUploadUsingList" class="org.apache.struts2.showcase.fileupload.MultipleFileUploadUsingListAction" method="upload">
<result name="input">/WEB-INF/fileupload/multipleUploadUsingList.jsp</result>
<result>/WEB-INF/fileupload/multiple-success.jsp</result>
@@ -21,16 +21,16 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="freemarker" namespace="/freemarker" extends="struts-default">
<action name="customFreemarkerManagerDemo">
<result type="freemarker">/WEB-INF/freemarker/customFreemarkerManagerUsage.ftl</result>
</action>
<action name="standardTags" class="org.apache.struts2.showcase.freemarker.StandardTagsAction">
<result type="freemarker">/WEB-INF/freemarker/standardTags.ftl</result>
</action>
</package>
</struts>
</struts>
@@ -21,7 +21,7 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="hangman" extends="struts-default" namespace="/hangman">
@@ -41,9 +41,9 @@
<result type="freemarker">/WEB-INF/hangman/hangmanNonAjax.ftl</result>
</action>
</package>
<package name="hangman-ajax" extends="struts-default" namespace="/hangman/ajax">
<action name="blank">
<result type="freemarker">/WEB-INF/hangman/blank.ftl</result>
@@ -61,4 +61,4 @@
<result type="freemarker">/WEB-INF/hangman/updateGuessLeft.ftl</result>
</action>
</package>
</struts>
</struts>
@@ -21,7 +21,7 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="interactive" namespace="/interactive" extends="struts-default">
@@ -38,4 +38,4 @@
</action>
<action name="example" class="org.apache.struts2.showcase.action.ExampleAction" />
</package>
</struts>
</struts>
@@ -21,7 +21,7 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="modelDriven" extends="struts-default" namespace="/modelDriven">
@@ -29,11 +29,10 @@
<action name="modelDriven" class="org.apache.struts2.showcase.modelDriven.ModelDrivenAction" method="input">
<result>/WEB-INF/modelDriven/modelDriven.jsp</result>
</action>
<!-- Display the result page whose content is populated using the Model-Driven technique -->
<action name="modelDrivenResult" class="org.apache.struts2.showcase.modelDriven.ModelDrivenAction">
<result>/WEB-INF/modelDriven/modelDrivenResult.jsp</result>
</action>
</package>
</struts>
</struts>
@@ -21,7 +21,7 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<!-- START SNIPPET: xworkSample -->
@@ -21,14 +21,14 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!-- ================================== -->
<!-- === Package for ActionTag Demo === -->
<!-- ================================== -->
<package name="actionTag" extends="struts-default" namespace="/tags/non-ui/actionTag">
<action name="showActionTagDemo" class="org.apache.struts2.showcase.tag.nonui.actiontag.ActionTagDemo" method="show">
<result>/WEB-INF/tags/non-ui/actionTag/showActionTagDemo.jsp</result>
@@ -46,11 +46,11 @@
<result type="plainText">/WEB-INF/tags/non-ui/actionTag/showActionTagDemo.jsp</result>
</action>
</package>
<!-- ==================================== -->
<!-- === Package for IteratorGeneratorTag Demo === -->
<!-- ==================================== -->
<package name="iteratorGeneratorTag" extends="struts-default" namespace="/tags/non-ui/iteratorGeneratorTag">
<action name="showGeneratorTagDemo" class="org.apache.struts2.showcase.tag.nonui.iteratortag.IteratorGeneratorTagDemo" method="input">
<result>/WEB-INF/tags/non-ui/iteratorTag/showIteratorGeneratorTagDemo.jsp</result>
@@ -60,8 +60,8 @@
<result>/WEB-INF/tags/non-ui/iteratorTag/iteratorGeneratorTagDemoResult.jsp</result>
</action>
</package>
<!-- ===================================== -->
<!-- === Package for AppendIteratorTag Demo === -->
<!-- ========================================== -->
@@ -74,8 +74,8 @@
<result>/WEB-INF/tags/non-ui/iteratorTag/appendIteratorTagDemoResult.jsp</result>
</action>
</package>
<!-- ====================================== -->
<!-- === Package for MergeIteratorTag Demo === -->
<!-- ========================================= -->
@@ -88,7 +88,7 @@
<result>/WEB-INF/tags/non-ui/iteratorTag/mergeIteratorTagDemoResult.jsp</result>
</action>
</package>
<!-- ============================================= -->
<!-- === Package for SubsetIteratorTag Demo === -->
<!-- =========================================== -->
@@ -101,14 +101,14 @@
<result>/WEB-INF/tags/non-ui/iteratorTag/subsetIteratorTagDemoResult.jsp</result>
</action>
</package>
<!-- ========================================= -->
<!-- === Package for Action Prefix Example === -->
<!-- ========================================= -->
<package name="actionPrefix" extends="struts-default" namespace="/tags/non-ui/actionPrefix">
<action name="actionPrefixExampleUsingFreemarker">
<result type="freemarker">/WEB-INF/tags/non-ui/actionPrefix/actionPrefixExample.ftl</result>
</action>
</action>
<action name="submit" class="org.apache.struts2.showcase.tag.nonui.actionPrefix.SubmitAction">
<result type="freemarker">/WEB-INF/tags/non-ui/actionPrefix/normalSubmit.ftl</result>
</action>
@@ -131,7 +131,7 @@
<result type="plainText">/WEB-INF/tags/non-ui/actionPrefix/actionPrefixExample.ftl</result>
</action>
</package>
<!-- ========================================== -->
<!-- === Package for If Tag Test / Examples === -->
<!-- ========================================== -->
@@ -21,7 +21,7 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="ui-tags" extends="velocity-default" namespace="/tags/ui">
@@ -21,7 +21,7 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<include file="struts-tags-ui.xml"/>
@@ -21,7 +21,7 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="tiles" extends="tiles-default" namespace="/tiles">
@@ -21,7 +21,7 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="token" extends="struts-default" namespace="/token">
@@ -21,8 +21,8 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<constant name="struts.beanValidation.providerClass" value="org.hibernate.validator.HibernateValidator"/>
@@ -74,7 +74,7 @@
<action name="ajaxFormSubmitSuccess" class="org.apache.struts2.showcase.validation.AjaxFormSubmitSuccessAction">
<result>/WEB-INF/validation/ajaxFormSubmitSuccess.jsp</result>
</action>
</package>
@@ -83,46 +83,46 @@
<action name="list">
<result>index.jsp</result>
</action>
<!-- ======================== -->
<!-- === Field Validators === -->
<!-- ======================== -->
<action name="showFieldValidatorsExamples" class="org.apache.struts2.showcase.validation.FieldValidatorsExampleAction" method="input">
<result name="input" type="dispatcher">/WEB-INF/validation/fieldValidatorsExample.jsp</result>
</action>
<action name="submitFieldValidatorsExamples" class="org.apache.struts2.showcase.validation.FieldValidatorsExampleAction" method="submit">
<result name="input" type="dispatcher">/WEB-INF/validation/fieldValidatorsExample.jsp</result>
<result type="dispatcher">/WEB-INF/validation/successFieldValidatorsExample.jsp</result>
</action>
<!-- ============================ -->
<!-- === Non Field Validators === -->
<!-- ============================ -->
<action name="showNonFieldValidatorsExamples" class="org.apache.struts2.showcase.validation.NonFieldValidatorsExampleAction" method="input">
<result name="input">/WEB-INF/validation/nonFieldValidatorsExample.jsp</result>
</action>
<action name="submitNonFieldValidatorsExamples" class="org.apache.struts2.showcase.validation.NonFieldValidatorsExampleAction" method="submit">
<result name="input">/WEB-INF/validation/nonFieldValidatorsExample.jsp</result>
<result>/WEB-INF/validation/successNonFieldValidatorsExample.jsp</result>
</action>
<!-- ========================== -->
<!-- === Visitor Validators === -->
<!-- ========================== -->
<action name="showVisitorValidatorsExamples" class="org.apache.struts2.showcase.validation.VisitorValidatorsExampleAction" method="input">
<result name="input">/WEB-INF/validation/visitorValidatorsExample.jsp</result>
</action>
<action name="submitVisitorValidatorsExamples" class="org.apache.struts2.showcase.validation.VisitorValidatorsExampleAction" method="submit">
<result name="input">/WEB-INF/validation/visitorValidatorsExample.jsp</result>
<result>/WEB-INF/validation/successVisitorValidatorsExample.jsp</result>
@@ -146,7 +146,7 @@
<!-- =========================================== -->
<!-- === Store Error Messages Across Request === -->
<!-- =========================================== -->
<action name="submitApplication" class="org.apache.struts2.showcase.validation.SubmitApplication" method="submitApplication">
<interceptor-ref name="store">
<param name="operationMode">STORE</param>
@@ -173,7 +173,7 @@
<action name="cancelApplication" class="org.apache.struts2.showcase.validation.SubmitApplication" method="cancelApplication">
<result>/WEB-INF/validation/storeErrorsAcrossRequestCancel.jsp</result>
</action>
</package>
</struts>
@@ -21,10 +21,17 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<bean type="org.apache.struts2.interceptor.exec.ExecutorProvider" class="org.apache.struts2.showcase.wait.ThreadPoolExecutorProvider"/>
<package name="wait" extends="struts-default" namespace="/wait">
<default-action-ref name="index"/>
<action name="index">
<result>/WEB-INF/wait/index.jsp</result>
</action>
<action name="example1">
<result>/WEB-INF/wait/example1.jsp</result>
@@ -21,7 +21,7 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="xslt" extends="struts-default" namespace="/xslt">
@@ -36,7 +36,7 @@
<param name="exposedValue">info.classpath</param>
</result>
</action>
<action name="jvmInfoRaw" class="org.apache.struts2.showcase.xslt.JVMAction">
<result type="xslt">
<param name="exposedValue">info</param>
+3 -1
View File
@@ -21,7 +21,7 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<!-- START SNIPPET: xworkSample -->
<struts>
@@ -78,6 +78,8 @@
<include file="struts-async.xml" />
<include file="struts-dispatcher.xml" />
<package name="default" extends="struts-default">
<interceptors>
<interceptor-stack name="crudStack">
@@ -45,66 +45,46 @@
</bean>
<bean id="chatLoginAction" class="org.apache.struts2.showcase.chat.ChatLoginAction" scope="prototype">
<constructor-arg index="0">
<ref local="chatService"/>
</constructor-arg>
<constructor-arg index="0" ref="chatService"/>
</bean>
<bean id="chatLogoutAction" class="org.apache.struts2.showcase.chat.ChatLogoutAction" scope="prototype">
<constructor-arg index="0">
<ref local="chatService"/>
</constructor-arg>
<constructor-arg index="0" ref="chatService"/>
</bean>
<bean id="usersAvailableAction" class="org.apache.struts2.showcase.chat.UsersAvailableAction" scope="prototype">
<constructor-arg index="0">
<ref local="chatService"/>
</constructor-arg>
<constructor-arg index="0" ref="chatService"/>
</bean>
<bean id="roomsAvailableAction" class="org.apache.struts2.showcase.chat.RoomsAvailableAction" scope="prototype">
<constructor-arg index="0">
<ref local="chatService"/>
</constructor-arg>
<constructor-arg index="0" ref="chatService"/>
</bean>
<bean id="crudRoomAction" class="org.apache.struts2.showcase.chat.CrudRoomAction" scope="prototype">
<constructor-arg index="0">
<ref local="chatService"/>
</constructor-arg>
<constructor-arg index="0" ref="chatService"/>
</bean>
<bean id="enterRoomAction" class="org.apache.struts2.showcase.chat.EnterRoomAction" scope="prototype">
<constructor-arg index="0">
<ref local="chatService"/>
</constructor-arg>
<constructor-arg index="0" ref="chatService"/>
</bean>
<bean id="messagesAvailableInRoomAction" class="org.apache.struts2.showcase.chat.MessagesAvailableInRoomAction"
scope="prototype">
<constructor-arg index="0">
<ref local="chatService"/>
</constructor-arg>
<constructor-arg index="0" ref="chatService"/>
</bean>
<bean id="sendMessageToRoomAction" class="org.apache.struts2.showcase.chat.SendMessageToRoomAction"
scope="prototype">
<constructor-arg index="0">
<ref local="chatService"/>
</constructor-arg>
<constructor-arg index="0" ref="chatService"/>
</bean>
<bean id="usersAvailableInRoomAction" class="org.apache.struts2.showcase.chat.UsersAvailableInRoomAction"
scope="prototype">
<constructor-arg index="0">
<ref local="chatService"/>
</constructor-arg>
<constructor-arg index="0" ref="chatService"/>
</bean>
<bean id="exitRoomAction" class="org.apache.struts2.showcase.chat.ExitRoomAction" scope="prototype">
<constructor-arg index="0">
<ref local="chatService"/>
</constructor-arg>
<constructor-arg index="0" ref="chatService"/>
</bean>
@@ -129,9 +109,7 @@
</bean>
<bean id="startHangmanAction" class="org.apache.struts2.showcase.hangman.StartHangmanAction" scope="prototype">
<constructor-arg index="0">
<ref local="hangmanService"/>
</constructor-arg>
<constructor-arg index="0" ref="hangmanService"/>
</bean>
<bean id="guessCharacterAction" class="org.apache.struts2.showcase.hangman.GuessCharacterAction" scope="prototype"/>
@@ -64,14 +64,14 @@
<title><decorator:title default="Struts2 Showcase"/></title>
<s:url var="bootstrapCss" value='/styles/bootstrap.css' encode='false' includeParams='none'/>
<s:link href="%{bootstrapCss}" rel="stylesheet" type="text/css" media="all"></s:link>
<s:link href="%{bootstrapCss}" rel="stylesheet" type="text/css" media="all"/>
<s:url var="mainCss" value='/styles/main.css' encode='false' includeParams='none'/>
<s:link href="%{mainCss}" rel="stylesheet" type="text/css" media="all"></s:link>
<s:link href="%{mainCss}" rel="stylesheet" type="text/css" media="all"/>
<s:url var="jqueryJs" value='/js/jquery-2.1.4.min.js' encode='false' includeParams='none'/>
<s:script src="%{jqueryJs}"></s:script>
<s:script src="%{jqueryJs}"/>
<s:url var="bootstrapJs" value='/js/bootstrap.min.js' encode='false' includeParams='none'/>
<s:script src="%{bootstrapJs}"></s:script>
<s:script src="%{bootstrapJs}"/>
<s:script type="text/javascript">
$(function () {
var alerts = $('ul.alert').wrap('<div />');
@@ -82,19 +82,22 @@
<!-- Prettify -->
<s:url var="prettifyCss" value='/styles/prettify.css' encode='false' includeParams='none'/>
<s:link href="%{prettifyCss}" rel="stylesheet"></s:link>
<s:link href="%{prettifyCss}" rel="stylesheet"/>
<s:url var="prettifyJs" value='/js/prettify.js' encode='false' includeParams='none'/>
<s:script src="%{prettifyJs}"></s:script>
<s:script src="%{prettifyJs}"/>
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<s:script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></s:script>
<s:script src="http://html5shim.googlecode.com/svn/trunk/html5.js"/>
<![endif]-->
<s:script>
jQuery(document).ready(function() { prettyPrint(); } );
</s:script>
<decorator:head/>
</head>
<body id="page-home" onload="prettyPrint();">
<body id="page-home">
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
@@ -239,11 +242,13 @@
</li>
<li><s:a value="/person/index.html">Person Manager</s:a></li>
<li><s:a value="/skill/index.html">CRUD</s:a></li>
<li><s:a value="/wait/index.html">Execute &amp; Wait</s:a></li>
<li><s:a value="/wait/index">Execute &amp; Wait</s:a></li>
<li><s:a value="/token/index.html">Token</s:a></li>
<li><s:url var="url" namespace="/modelDriven" action="modelDriven"/><s:a
href="%{url}">Model Driven</s:a></li>
<li><s:a value="/async/index.html">Async</s:a></li>
<li><s:a value="/dispatcher/dispatch.action">Dispatcher result - dispatch</s:a></li>
<li><s:a value="/dispatcher/forward.action">Dispatcher result - forward</s:a></li>
</ul>
</li>
<li class="dropdown">
@@ -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.
*/
-->
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Struts2 Showcase - Dispatcher result Example</title>
<s:head theme="xhtml"/>
</head>
<body>
<div class="page-header">
<h1>Dispatcher Result Example</h1>
</div>
<div class="container-fluid">
<div class="row">
<div id="dispatcher-result" class="col-md-12">
This page is a result of &quot;dispatching&quot; to it from an action
</div>
</div>
</div>
</body>
</html>
@@ -1,19 +1,19 @@
<!--
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* 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
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
@@ -26,49 +26,46 @@
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<h1>View Sources</h1>
<div class="row">
<div class="col-md-12">
<h1>View Sources</h1>
<ul class="nav nav-tabs" id="codeTab">
<li class="active"><a href="#page">Page</a></li>
<li><a href="#config">Configuration</a></li>
<li><a href="#java">Java Action</a></li>
</ul>
<ul class="nav nav-tabs" id="codeTab">
<li class="active"><a href="#page">Page</a></li>
<li><a href="#config">Configuration</a></li>
<li><a href="#java">Java Action</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="page">
<h3><s:property default="Unknown page" value="page"/></h3>
<pre class="prettyprint lang-html linenums">
<s:iterator value="pageLines" status="row">
<div class="tab-content">
<div class="tab-pane active" id="page">
<h3><s:property default="Unknown page" value="page"/></h3>
<pre class="prettyprint lang-html linenums"><s:iterator value="pageLines" status="row">
<s:property/></s:iterator>
</pre>
</div>
<div class="tab-pane" id="config">
<h3><s:property default="Unknown configuration" value="config"/></h3>
<pre class="prettyprint lang-xml linenums">
<s:iterator value="configLines" status="row">
</pre>
</div>
<div class="tab-pane" id="config">
<h3><s:property default="Unknown configuration" value="config"/></h3>
<pre class="prettyprint lang-xml linenums"><s:iterator value="configLines" status="row">
<s:property/></s:iterator>
</pre>
</div>
<div class="tab-pane" id="java">
<h3><s:property default="Unknown or unavailable Action class" value="className"/></h3>
<pre class="prettyprint lang-java linenums">
<s:iterator value="classLines" status="row">
</pre>
</div>
<div class="tab-pane" id="java">
<h3><s:property default="Unknown or unavailable Action class" value="className"/></h3>
<pre class="prettyprint lang-java linenums"><s:iterator value="classLines" status="row">
<s:property/></s:iterator>
</pre>
</div>
</div>
</div>
</div>
</pre>
</div>
</div>
</div>
</div>
</div>
<s:script>
$('#codeTab a').click(function (e) {
e.preventDefault();
$(this).tab('show');
})
$('#codeTab a').click(function (e) {
e.preventDefault();
$(this).tab('show');
})
</s:script>
</body>
</html>
@@ -1,19 +1,19 @@
<!--
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* 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
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
@@ -21,25 +21,26 @@
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Struts2 Showcase - Execute and Wait Examples - Complete</title>
<title>Struts2 Showcase - Execute and Wait Examples - Complete</title>
</head>
<body>
<div class="page-header">
<h1>The process is complete</h1>
<h1>The process is complete</h1>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-12" style="text-align: center;">
<div class="row">
<div class="col-md-12" style="text-align: center;">
<b>We have processed your request.</b>
<p/>
Click here to <s:url var="back" value="/wait/index.html"/><s:a href="%{back}" cssClass="btn btn-link">return</s:a>.
<div class="panel">We have processed your request.</div>
</div>
</div>
<s:url var="back" value="/wait/index"/>
Click here to <s:a href="%{back}" cssClass="btn btn-primary">return</s:a>
</div>
</div>
</div>
</body>
</html>
@@ -0,0 +1,53 @@
<!--
/*
* 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.
*/
-->
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Struts2 Showcase - Execute and Wait Examples</title>
</head>
<body>
<div class="page-header">
<h1>Execute and Wait Examples</h1>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-12" style="text-align: center;">
<p>
These examples illustrate Struts build in support for execute and wait.
<p/>
<p>
When you have a process that takes a long time your users can be impatient and starts to submit/click
again.
<br/> A good solution is to show the user a progress page (wait page) while the process takes it time.
<p/>
<br/>
<br/><a href='<s:url value="example1"/>'>Example 1 (no delay)</a>
<br/><a href='<s:url value="example2"/>'>Example 2 (with delay)</a>
<br/><a href='<s:url value="example3"/>'>Example 3 (with longer check delay)</a>
</div>
</div>
</div>
</body>
</html>
@@ -1,19 +1,19 @@
<!--
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* 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
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* 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
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
@@ -21,53 +21,33 @@
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Struts2 Showcase - Execute and Wait Examples - Wait</title>
</head>
<body>
<div class="page-header">
<h1>Execute and Wait Examples - Wait</h1>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-12" style="text-align: center;">
<p class="well">
We are processing your request. Please wait.
</p>
<div class="progress progress-striped active">
<div class="bar" style="width: 50%;"></div>
</div>
<p/>
You can click this link to <a href="<s:url includeParams="all"/>">refresh</a>.
<b>We have processed your request.</b>
<p/>
Click here to <s:url var="back" value="/wait/index.html"/><s:a href="%{back}" cssClass="btn btn-link">return</s:a>.
</div>
</div>
</div>
</body>
</html>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Struts2 Showcase - Execute and Wait Examples - Wait</title>
<meta http-equiv="refresh" content="5;url=<s:url includeParams="all"/>"/>
</head>
<body>
<p style="border: 1px solid silver; padding: 5px; background: #ffd; text-align: center;">
We are processing your request. Please wait.
</p>
<div class="page-header">
<h1>Execute and Wait Examples - Wait</h1>
</div>
<p/>
You can click this link to <a href="<s:url includeParams="all"/>">refresh</a>.
<div class="container-fluid">
<div class="row">
<div class="col-md-12" style="text-align: center;">
<p class="well">
We are processing your request. Please wait.
</p>
<div class="progress progress-striped active">
<div class="bar progress-bar progress-bar-success" style="width: 50%;"></div>
</div>
<div class="panel">
You can click this link to <a href="<s:url includeParams="all"/>">refresh</a>.
</div>
</div>
</div>
</div>
</body>
</html>
+39 -34
View File
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -16,20 +17,16 @@
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
-->
<web-app id="starter" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>Struts Showcase Application</display-name>
<context-param>
<param-name>org.apache.tiles.definition.DefinitionsFactory.DEFINITIONS_CONFIG</param-name>
<param-value>
/WEB-INF/tiles.xml
</param-value>
</context-param>
<filter>
<filter-name>async</filter-name>
<filter-class>org.apache.struts2.showcase.async.AsyncFilter</filter-class>
@@ -39,18 +36,20 @@
<filter>
<filter-name>struts-prepare</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter>
<filter-name>struts-execute</filter-name>
<filter-class>org.apache.struts2.dispatcher.filter.StrutsExecuteFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
</filter>
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
<async-supported>true</async-supported>
</filter>
<filter-mapping>
<filter-name>async</filter-name>
@@ -60,16 +59,22 @@
<filter-mapping>
<filter-name>struts-prepare</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>sitemesh</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>struts-execute</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<listener>
@@ -81,18 +86,18 @@
org.apache.struts2.tiles.StrutsTilesListener
</listener-class>
</listener>
<!-- Chat Example in Showcase -->
<listener>
<listener-class>
org.apache.struts2.showcase.chat.ChatSessionListener
</listener-class>
<listener-class>
org.apache.struts2.showcase.chat.ChatSessionListener
</listener-class>
</listener>
<listener>
<listener-class>org.apache.struts2.dispatcher.listener.StrutsListener</listener-class>
</listener>
<!-- SNIPPET START: dwr -->
<servlet>
@@ -103,13 +108,20 @@
<param-value>true</param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>JspSupportServlet</servlet-name>
<servlet-class>org.apache.struts2.views.JspSupportServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>JspSupportServlet</servlet-name>
<servlet-class>org.apache.struts2.views.JspSupportServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Sitemesh Freemarker and Velocity Decorator Servlets. Shares configuration with Struts.-->
<servlet>
<servlet-name>strutsServlet</servlet-name>
<servlet-class>org.apache.struts2.dispatcher.servlet.StrutsServlet</servlet-class>
<load-on-startup>2</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<!-- Sitemesh Freemarker and Velocity Decorator Servlets. Shares configuration with Struts.-->
<servlet>
<servlet-name>sitemesh-freemarker</servlet-name>
<servlet-class>org.apache.struts2.sitemesh.FreemarkerDecoratorServlet</servlet-class>
@@ -117,7 +129,7 @@
<param-name>default_encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<load-on-startup>3</load-on-startup>
</servlet>
<servlet>
@@ -127,14 +139,7 @@
<param-name>default_encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>strutsServlet</servlet-name>
<servlet-class>org.apache.struts2.dispatcher.servlet.StrutsServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
<load-on-startup>4</load-on-startup>
</servlet>
<servlet-mapping>
@@ -1,53 +0,0 @@
<!--
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
-->
<html>
<head>
<title>Struts2 Showcase - Execute and Wait Examples</title>
</head>
<body>
<div class="page-header">
<h1>Execute and Wait Examples</h1>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-12" style="text-align: center;">
<p>
These examples illustrate Struts build in support for execute and wait.
<p/>
<p>
When you have a process that takes a long time your users can be impatient and starts to submit/click again.
<br/> A good solution is to show the user a progress page (wait page) while the process takes it time.
<p/>
<br/>
<br/><a href="example1.action">Example 1 (no delay)</a>
<br/><a href="example2.action">Example 2 (with delay)</a>
<br/><a href="example3.action">Example 3 (with longer check delay)</a>
</div>
</div>
</div>
</body>
</html>
@@ -32,7 +32,7 @@ public class ActionChainingTest {
try (final WebClient webClient = new WebClient()) {
final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/actionchaining/actionChain1!input");
final String pageAsText = page.asText();
final String pageAsText = page.asNormalizedText();
Assert.assertTrue(pageAsText.contains("Action Chain 1 Property 1: Property Set In Action Chain 1"));
Assert.assertTrue(pageAsText.contains("Action Chain 2 Property 1: Property Set in Action Chain 2"));
Assert.assertTrue(pageAsText.contains("Action Chain 3 Property 1: Property set in Action Chain 3"));
@@ -32,7 +32,7 @@ public class ActionTagExampleTest {
try (final WebClient webClient = new WebClient()) {
final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/tags/ui/actionTagExample!input.action");
final String pageAsText = page.asText();
final String pageAsText = page.asNormalizedText();
Assert.assertTrue(pageAsText.contains("This text is from the called class"));
}
}
@@ -46,7 +46,7 @@ public class AsyncTest {
final DomElement msgs = page2.getElementById("msgs");
Assert.assertEquals("hello", msgs.asText());
Assert.assertEquals("hello", msgs.asNormalizedText());
}
}
}
@@ -44,7 +44,7 @@ public class CRUDTest {
final HtmlSubmitInput button = form.getInputByValue("Save");
final HtmlPage page2 = button.click();
final String page2Text = page2.asText();
final String page2Text = page2.asNormalizedText();
Assert.assertTrue(page2Text.contains("somename1"));
Assert.assertTrue(page2Text.contains("somedescription1"));
@@ -33,7 +33,7 @@ public class ComponentTagExampleTest {
final HtmlPage page = webClient
.getPage(ParameterUtils.getBaseUrl() + "/tags/ui/componentTagExample.action");
final String pageAsText = page.asText();
final String pageAsText = page.asNormalizedText();
Assert.assertTrue(pageAsText.contains("Freemarker Custom Template - parameter 'paramName' - paramValue1"));
Assert.assertTrue(pageAsText.contains("Freemarker Custom Template - parameter 'paramName' - paramValue4"));
Assert.assertTrue(pageAsText.contains("JSP Custom Template - parameter 'paramName' - paramValue2"));
@@ -46,7 +46,7 @@ public class ConversionTest {
final HtmlSubmitInput button = form.getInputByValue("Submit");
final HtmlPage page2 = button.click();
final String page2Text = page2.asText();
final String page2Text = page2.asNormalizedText();
Assert.assertTrue(page2Text.contains("SET 0 Name: name0"));
Assert.assertTrue(page2Text.contains("SET 0 Age: 0"));
@@ -71,7 +71,7 @@ public class ConversionTest {
final HtmlSubmitInput button = form.getInputByValue("Submit");
final HtmlPage page2 = button.click();
final String page2Text = page2.asText();
final String page2Text = page2.asNormalizedText();
Assert.assertTrue(page2Text.contains("id0 -> address0"));
Assert.assertTrue(page2Text.contains("id1 -> address1"));
@@ -92,7 +92,7 @@ public class ConversionTest {
final HtmlSubmitInput button = form.getInputByValue("Submit");
final HtmlPage page2 = button.click();
final String page2Text = page2.asText();
final String page2Text = page2.asNormalizedText();
Assert.assertTrue(page2Text.contains("ADD"));
Assert.assertTrue(page2Text.contains("MINUS"));
@@ -0,0 +1,56 @@
/*
* 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 it.org.apache.struts2.showcase;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import org.junit.Assert;
import org.junit.Test;
public class DispatcherResultTest {
@Test
public void testDispatchingToJSP() throws Exception {
try (final WebClient webClient = new WebClient()) {
final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/dispatcher/dispatch.action");
DomElement div = page.getElementById("dispatcher-result");
Assert.assertEquals("This page is a result of \"dispatching\" to it from an action", div.asNormalizedText());
}
}
@Test
public void testDispatchingToAction() throws Exception {
try (final WebClient webClient = new WebClient()) {
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/dispatcher/forward.action");
//DomElement div = page.getElementById("dispatcher-result");
//Assert.assertEquals("This page is a result of \"dispatching\" to it from an action", div.asNormalizedText());
// support for forwarding to another action is broken on StrutsPrepareFilter/StrutsExecuteFilter
// it only works in StrutsPrepareAndExecuteFilter
// this will be fixed in Struts 6.1.x
Assert.assertEquals(404, page.getWebResponse().getStatusCode());
}
}
}
@@ -43,12 +43,12 @@ public class ExecAndWaitTest {
final HtmlSubmitInput button = form.getInputByValue("submit");
final HtmlPage page2 = button.click();
Assert.assertTrue(page2.asText().contains("We are processing your request. Please wait."));
Assert.assertTrue(page2.asNormalizedText().contains("We are processing your request. Please wait."));
// hit it again
final HtmlPage page3 = webClient
.getPage(ParameterUtils.getBaseUrl() + "/wait/longProcess1.action?time=1000");
Assert.assertTrue(page3.asText().contains("We are processing your request. Please wait."));
Assert.assertTrue(page3.asNormalizedText().contains("We are processing your request. Please wait."));
}
}
}
@@ -43,6 +43,7 @@ public class FileDownloadTest {
}
}
@Test
public void testZip() throws Exception {
try (final WebClient webClient = new WebClient()) {
final Page page = webClient.getPage(ParameterUtils.getBaseUrl() + "/filedownload/download2.action");
@@ -36,11 +36,11 @@ public class FreeMarkerManagerTest {
final DomElement date = page.getElementById("todaysDate");
Assert.assertNotNull(date);
Assert.assertTrue(date.asText().length() > 0);
Assert.assertTrue(date.asNormalizedText().length() > 0);
final DomElement time = page.getElementById("timeNow");
Assert.assertNotNull(time);
Assert.assertTrue(time.asText().length() > 0);
Assert.assertTrue(time.asNormalizedText().length() > 0);
}
}
@@ -33,26 +33,23 @@ public class StaticContentTest {
webClient.getPage(ParameterUtils.getBaseUrl() + "/struts..");
Assert.fail("Previous request should have failed");
} catch (FailingHttpStatusCodeException e) {
Assert.assertEquals("Not Found", e.getStatusMessage());
Assert.assertEquals(404, e.getStatusCode());
}
}
}
@Test
public void testInvalidRersources2() throws Exception {
try (final WebClient webClient = new WebClient()) {
try {
webClient.getPage(ParameterUtils.getBaseUrl() + "/static/..%252f");
Assert.fail("Previous request should have failed");
} catch (FailingHttpStatusCodeException e) {
Assert.assertEquals("Not Found", e.getStatusMessage());
Assert.assertEquals(404, e.getStatusCode());
}
}
}
/*public void testInvalidRersources3() throws IOException {
try {
beginAt("/static/..%252f..%252f..%252fWEB-INF/classes/org/apache/struts2/showcase/action/EmployeeAction.class/");
fail("Previous request should have failed");
} catch (TestingEngineResponseException ex) {
// ok
}
}*/
}
@@ -65,11 +65,11 @@ public class UITagExampleTest {
final HtmlSubmitInput button = form.getInputByValue("Submit");
final HtmlPage page2 = button.click();
Assert.assertEquals("name", page2.getElementById("name").asText());
Assert.assertEquals("bio", page2.getElementById("bio").asText());
Assert.assertEquals("Red", page2.getElementById("favouriteColor").asText());
Assert.assertEquals("[Patrick, Jason]", page2.getElementById("friends").asText());
Assert.assertEquals("true", page2.getElementById("legalAge").asText());
Assert.assertEquals("name", page2.getElementById("name").asNormalizedText());
Assert.assertEquals("bio", page2.getElementById("bio").asNormalizedText());
Assert.assertEquals("Red", page2.getElementById("favouriteColor").asNormalizedText());
Assert.assertEquals("[Patrick, Jason]", page2.getElementById("friends").asNormalizedText());
Assert.assertEquals("true", page2.getElementById("legalAge").asNormalizedText());
}
}
}
@@ -47,7 +47,7 @@ public class ValidationTest {
final HtmlSubmitInput button = form.getInputByValue("Submit");
final HtmlPage page2 = button.click();
final String page2Text = page2.asText();
final String page2Text = page2.asNormalizedText();
Assert.assertTrue(page2Text.contains("Invalid field value for field \"dateValidatorField\""));
Assert.assertTrue(page2Text.contains("Invalid field value for field \"integerValidatorField\""));
+3
View File
@@ -0,0 +1,3 @@
# Struts 2 Assemblies
This module is used to prepare ZIP archives with different set of JARs, like code source, Javadocs, etc.
It's a part of the release process, it shouldn't be used directly by users.
+1 -1
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.0.0-SNAPSHOT</version>
<version>6.1.0</version>
</parent>
<artifactId>struts2-assembly</artifactId>
+1
View File
@@ -36,6 +36,7 @@
<include>org.apache.struts:struts2-core</include>
<include>org.freemarker:freemarker</include>
<include>org.apache.commons:commons-lang3</include>
<include>org.apache.commons:commons-text</include>
<include>org.apache.logging.log4j:log4j-api</include>
<include>ognl:ognl</include>
<include>commons-fileupload:commons-fileupload</include>
+20
View File
@@ -0,0 +1,20 @@
# Struts 2 BOM
This is a Bill-Of-Materials to be used with Maven based project. It allows to import all the Struts 2
dependencies at once and used them in your project where needed.
## Installation
You must add a proper import statement into your `pom.xml` as presented below:
```xml
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-bom</artifactId>
<version>${struts2.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
```
+13 -3
View File
@@ -29,7 +29,7 @@
</parent>
<artifactId>struts2-bom</artifactId>
<version>6.0.0-SNAPSHOT</version>
<version>6.1.0</version>
<packaging>pom</packaging>
<name>Struts 2 Bill of Materials</name>
@@ -44,7 +44,7 @@
</licenses>
<properties>
<struts-version.version>6.0.0-SNAPSHOT</struts-version.version>
<struts-version.version>6.1.0</struts-version.version>
<maven.site.skip>true</maven.site.skip>
<maven.site.deploy.skip>true</maven.site.deploy.skip>
</properties>
@@ -56,6 +56,11 @@
<artifactId>struts2-core</artifactId>
<version>${struts-version.version}</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-async-plugin</artifactId>
<version>${struts-version.version}</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-bean-validation-plugin</artifactId>
@@ -171,11 +176,16 @@
<artifactId>struts2-tiles-plugin</artifactId>
<version>${struts-version.version}</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-velocity-plugin</artifactId>
<version>${struts-version.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<scm>
<tag>HEAD</tag>
<tag>STRUTS_6_1_0</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>
+2 -2
View File
@@ -24,12 +24,12 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-osgi-bundles</artifactId>
<version>6.0.0-SNAPSHOT</version>
<version>6.1.0</version>
</parent>
<artifactId>struts2-osgi-admin-bundle</artifactId>
<packaging>bundle</packaging>
<name>DEPRECATED: Struts 2 OSGi Admin Bundle - since 2.6</name>
<name>DEPRECATED: Struts 2 OSGi Admin Bundle - since 6.0.0</name>
<dependencies>
<dependency>
+2 -2
View File
@@ -22,13 +22,13 @@
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<package name="bundle-admin" namespace="/osgi/admin" extends="osgi-default" strict-method-invocation="true">
<default-action-ref name="bundles" />
<action name="bundle_*!*" class="org.apache.struts2.osgi.admin.actions.BundlesAction" method="{2}">
<param name="id">{1}</param>
<result type="freemarker">viewBundle.ftl</result>
+2 -2
View File
@@ -24,12 +24,12 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-osgi-bundles</artifactId>
<version>6.0.0-SNAPSHOT</version>
<version>6.1.0</version>
</parent>
<artifactId>struts2-osgi-demo-bundle</artifactId>
<packaging>bundle</packaging>
<name>DEPRECATED: Struts 2 OSGi Demo Bundle - since 2.6</name>
<name>DEPRECATED: Struts 2 OSGi Demo Bundle - since 6.0.0</name>
<dependencies>
+4 -4
View File
@@ -21,11 +21,11 @@
-->
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
"https://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<!-- Set some Struts 2 constants relevant to the OSGi Plugin.
Note: The constant definitions specified here (within the demo bundle) may also need to be
<!-- Set some Struts 2 constants relevant to the OSGi Plugin.
Note: The constant definitions specified here (within the demo bundle) may also need to be
duplicated in the struts.xml configuration of the outer project that packages the demo
bundle JAR file within it.
-->
@@ -52,4 +52,4 @@
</action>
</package>
</struts>
</struts>
+3 -5
View File
@@ -24,12 +24,12 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.0.0-SNAPSHOT</version>
<version>6.1.0</version>
</parent>
<artifactId>struts2-osgi-bundles</artifactId>
<packaging>pom</packaging>
<name>DEPRECATED: Struts 2 OSGi Bundles - since 2.6</name>
<name>DEPRECATED: Struts 2 OSGi Bundles - since 6.0.0</name>
<modules>
<module>admin</module>
@@ -53,12 +53,10 @@
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<reporting>
+6
View File
@@ -0,0 +1,6 @@
# Struts 2 Core
This is a core of the Apache Struts framework and all other modules depend on it.
It requires Java 8 at minimum and a Servlet container supporting Java Servlet API 3.1 at least.
## Installation
Just drop this plugin into `WEB-INF/lib` folder or add it as Maven dependency
+15 -17
View File
@@ -24,14 +24,14 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.0.0-SNAPSHOT</version>
<version>6.1.0</version>
</parent>
<artifactId>struts2-core</artifactId>
<packaging>jar</packaging>
<name>Struts 2 Core</name>
<properties>
<tlib.version>2.6</tlib.version>
<tlib.version>6.0</tlib.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
@@ -41,6 +41,7 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>@{argLine}</argLine>
<properties>
<property>
<name>maven.testng.output.dir</name>
@@ -54,9 +55,6 @@
<element>${project.build.testOutputDirectory}/xwork - jar.jar</element>
<element>${project.build.testOutputDirectory}/xwork - zip.zip</element>
</additionalClasspathElements>
<includes>
<include>**/*Test.java</include>
</includes>
<excludes>
<exclude>**/XWorkTestCase.java</exclude>
<exclude>**/TestBean.java</exclude>
@@ -188,7 +186,7 @@
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
@@ -242,6 +240,16 @@
<artifactId>spring-web</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
@@ -329,8 +337,7 @@
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>compile</scope>
<optional>true</optional>
<scope>test</scope>
</dependency>
<!-- SLF4J support -->
@@ -345,15 +352,6 @@
<scope>test</scope>
</dependency>
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
This is only necessary in tests-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
@@ -24,7 +24,7 @@ import java.util.concurrent.Callable;
* Adds support for invoke async actions. This allows us to support action methods that return {@link Callable}
* as well as invoking them in separate not-container thread then executing the result in another container thread.
*
* @since 2.6
* @since 6.0.0
*/
public interface AsyncManager {
boolean hasAsyncActionResult();
@@ -73,7 +73,7 @@ public class DefaultActionInvocation implements ActionInvocation {
protected UnknownHandlerManager unknownHandlerManager;
protected OgnlUtil ognlUtil;
protected AsyncManager asyncManager;
protected Callable asyncAction;
protected Callable<?> asyncAction;
protected WithLazyParams.LazyParamInjector lazyParamInjector;
public DefaultActionInvocation(final Map<String, Object> extraContext, final boolean pushAction) {
@@ -101,7 +101,7 @@ public class DefaultActionInvocation implements ActionInvocation {
this.container = cont;
}
@Inject(required=false)
@Inject(required = false)
public void setActionEventListener(ActionEventListener listener) {
this.actionEventListener = listener;
}
@@ -111,7 +111,7 @@ public class DefaultActionInvocation implements ActionInvocation {
this.ognlUtil = ognlUtil;
}
@Inject(required=false)
@Inject(required = false)
public void setAsyncManager(AsyncManager asyncManager) {
this.asyncManager = asyncManager;
}
@@ -214,7 +214,7 @@ public class DefaultActionInvocation implements ActionInvocation {
} catch (NullPointerException e) {
LOG.debug("Got NPE trying to read result configuration for resultCode [{}]", resultCode);
}
if (resultConfig == null) {
// If no result is found for the given resultCode, try to get a wildcard '*' match.
resultConfig = results.get("*");
@@ -248,7 +248,12 @@ public class DefaultActionInvocation implements ActionInvocation {
if (interceptor instanceof WithLazyParams) {
interceptor = lazyParamInjector.injectParams(interceptor, interceptorMapping.getParams(), invocationContext);
}
resultCode = interceptor.intercept(DefaultActionInvocation.this);
if (interceptor.isDisabled(this)) {
LOG.debug("Interceptor: {} is disabled, skipping to next", interceptor.getClass().getSimpleName());
resultCode = this.invoke();
} else {
resultCode = interceptor.intercept(this);
}
} else {
resultCode = invokeActionOnly();
}
@@ -268,9 +273,7 @@ public class DefaultActionInvocation implements ActionInvocation {
if (preResultListeners != null) {
LOG.trace("Executing PreResultListeners for result [{}]", result);
for (Object preResultListener : preResultListeners) {
PreResultListener listener = (PreResultListener) preResultListener;
for (PreResultListener listener : preResultListeners) {
listener.beforeResult(this, resultCode);
}
}
@@ -314,7 +317,7 @@ public class DefaultActionInvocation implements ActionInvocation {
gripe = "Unable to instantiate Action, " + proxy.getConfig().getClassName() + ", defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'";
}
gripe += (((" -- " + e.getMessage()) != null) ? e.getMessage() : " [no message in exception]");
gripe += e.getMessage();
throw new StrutsException(gripe, e, proxy.getConfig());
}
@@ -363,7 +366,7 @@ public class DefaultActionInvocation implements ActionInvocation {
result.execute(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());
+ " and result " + getResultCode(), proxy.getConfig());
} else {
if (LOG.isDebugEnabled()) {
LOG.debug("No result returned for action {} at {}", getAction().getClass().getName(), proxy.getConfig().getLocation());
@@ -464,6 +467,7 @@ public class DefaultActionInvocation implements ActionInvocation {
/**
* Save the result to be used later.
*
* @param actionConfig current ActionConfig
* @param methodResult the result of the action.
* @return the result code to process.
@@ -476,7 +480,7 @@ public class DefaultActionInvocation implements ActionInvocation {
container.inject(explicitResult);
return null;
} else if (methodResult instanceof Callable) {
asyncAction = (Callable) methodResult;
asyncAction = (Callable<?>) methodResult;
return null;
} else {
return (String) methodResult;
@@ -34,22 +34,22 @@ import java.util.Locale;
import java.util.Map;
/**
* Base JUnit TestCase to extend for XWork specific JUnit tests. Uses
* Base JUnit TestCase to extend for XWork specific JUnit tests. Uses
* the generic test setup for logic.
*
* @author plightbo
*/
public abstract class XWorkTestCase extends TestCase {
protected ConfigurationManager configurationManager;
protected Configuration configuration;
protected Container container;
protected ActionProxyFactory actionProxyFactory;
public XWorkTestCase() {
super();
}
@Override
protected void setUp() throws Exception {
configurationManager = XWorkTestCaseHelper.setUp();
@@ -57,7 +57,7 @@ public abstract class XWorkTestCase extends TestCase {
container = configuration.getContainer();
actionProxyFactory = container.getInstance(ActionProxyFactory.class);
}
@Override
protected void tearDown() throws Exception {
XWorkTestCaseHelper.tearDown(configurationManager);
@@ -66,34 +66,33 @@ public abstract class XWorkTestCase extends TestCase {
container = null;
actionProxyFactory = null;
}
protected void loadConfigurationProviders(ConfigurationProvider... providers) {
configurationManager = XWorkTestCaseHelper.loadConfigurationProviders(configurationManager, providers);
configuration = configurationManager.getConfiguration();
container = configuration.getContainer();
actionProxyFactory = container.getInstance(ActionProxyFactory.class);
}
protected void loadButAdd(final Class<?> type, final Object impl) {
protected <T> void loadButAdd(final Class<T> type, final T impl) {
loadButAdd(type, Container.DEFAULT_NAME, impl);
}
protected void loadButAdd(final Class<?> type, final String name, final Object impl) {
protected <T> void loadButAdd(final Class<T> type, final String name, final T impl) {
loadConfigurationProviders(new StubConfigurationProvider() {
@Override
public void register(ContainerBuilder builder,
LocatableProperties props) throws ConfigurationException {
public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {
if (impl instanceof String || ClassUtils.isPrimitiveOrWrapper(impl.getClass())) {
props.setProperty(name, "" + impl);
} else {
builder.factory(type, name, new Factory() {
public Object create(Context context) throws Exception {
builder.factory(type, name, new Factory<T>() {
public T create(Context context) throws Exception {
return impl;
}
@Override
public Class type() {
return impl.getClass();
public Class<T> type() {
return (Class<T>) impl.getClass();
}
}, Scope.SINGLETON);
}
@@ -20,26 +20,18 @@ package com.opensymphony.xwork2.config.entities;
import com.opensymphony.xwork2.util.location.Located;
import com.opensymphony.xwork2.util.location.Location;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.Serializable;
import java.util.*;
/**
* Configuration for Package.
*
* <p>
* In the xml configuration file this is defined as the <code>package</code> tag.
* </p>
*
* @author Rainer Hermanns
* @version $Revision$
*/
public class PackageConfig extends Located implements Comparable, Serializable, InterceptorLocator {
private static final Logger LOG = LogManager.getLogger(PackageConfig.class);
public class PackageConfig extends Located implements Comparable<PackageConfig>, Serializable, InterceptorLocator {
protected Map<String, ActionConfig> actionConfigs;
protected Map<String, ResultConfig> globalResultConfigs;
@@ -422,8 +414,7 @@ public class PackageConfig extends Located implements Comparable, Serializable,
return "PackageConfig: [" + name + "] for namespace [" + namespace + "] with parents [" + parents + "]";
}
public int compareTo(Object o) {
PackageConfig other = (PackageConfig) o;
public int compareTo(PackageConfig other) {
String full = namespace + "!" + name;
String otherFull = other.namespace + "!" + other.name;
@@ -443,7 +434,6 @@ public class PackageConfig extends Located implements Comparable, Serializable,
public static class Builder implements InterceptorLocator {
protected PackageConfig target;
private boolean strictDMI = true;
public Builder(String name) {
target = new PackageConfig(name);
@@ -298,8 +298,8 @@ public class DefaultConfiguration implements Configuration {
builder.factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON);
builder.factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON);
builder.factory(ExpressionCacheFactory.class, "defaultOgnlExpressionCacheFactory", DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON);
builder.factory(BeanInfoCacheFactory.class, "defaultOgnlBeanInfoCacheFactory", DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON);
builder.factory(ExpressionCacheFactory.class, DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON);
builder.factory(BeanInfoCacheFactory.class, DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON);
builder.factory(OgnlUtil.class, Scope.SINGLETON);
builder.factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON);
@@ -21,26 +21,16 @@ package com.opensymphony.xwork2.config.providers;
import com.opensymphony.xwork2.ActionProxyFactory;
import com.opensymphony.xwork2.DefaultActionProxyFactory;
import com.opensymphony.xwork2.DefaultLocaleProviderFactory;
import com.opensymphony.xwork2.LocaleProviderFactory;
import com.opensymphony.xwork2.StrutsTextProviderFactory;
import com.opensymphony.xwork2.TextProviderFactory;
import com.opensymphony.xwork2.factory.DefaultUnknownHandlerFactory;
import com.opensymphony.xwork2.factory.UnknownHandlerFactory;
import com.opensymphony.xwork2.ognl.BeanInfoCacheFactory;
import com.opensymphony.xwork2.ognl.ExpressionCacheFactory;
import com.opensymphony.xwork2.ognl.accessor.HttpParametersPropertyAccessor;
import com.opensymphony.xwork2.ognl.accessor.ParameterPropertyAccessor;
import com.opensymphony.xwork2.security.AcceptedPatternsChecker;
import com.opensymphony.xwork2.security.DefaultAcceptedPatternsChecker;
import com.opensymphony.xwork2.security.DefaultExcludedPatternsChecker;
import com.opensymphony.xwork2.DefaultTextProvider;
import com.opensymphony.xwork2.DefaultUnknownHandlerManager;
import com.opensymphony.xwork2.security.DefaultNotExcludedAcceptedPatternsChecker;
import com.opensymphony.xwork2.security.ExcludedPatternsChecker;
import com.opensymphony.xwork2.FileManager;
import com.opensymphony.xwork2.FileManagerFactory;
import com.opensymphony.xwork2.LocaleProviderFactory;
import com.opensymphony.xwork2.LocalizedTextProvider;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.StrutsTextProviderFactory;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.TextProviderFactory;
import com.opensymphony.xwork2.UnknownHandlerManager;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationException;
@@ -57,14 +47,7 @@ import com.opensymphony.xwork2.conversion.impl.CollectionConverter;
import com.opensymphony.xwork2.conversion.impl.DateConverter;
import com.opensymphony.xwork2.conversion.impl.DefaultConversionAnnotationProcessor;
import com.opensymphony.xwork2.conversion.impl.DefaultConversionFileProcessor;
import com.opensymphony.xwork2.security.NotExcludedAcceptedPatternsChecker;
import org.apache.struts2.components.date.DateFormatter;
import org.apache.struts2.components.date.DateTimeFormatterAdapter;
import org.apache.struts2.components.date.SimpleDateFormatAdapter;
import org.apache.struts2.conversion.StrutsConversionPropertiesProcessor;
import com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer;
import org.apache.struts2.conversion.StrutsTypeConverterCreator;
import org.apache.struts2.conversion.StrutsTypeConverterHolder;
import com.opensymphony.xwork2.conversion.impl.InstantiatingNullHandler;
import com.opensymphony.xwork2.conversion.impl.NumberConverter;
import com.opensymphony.xwork2.conversion.impl.StringConverter;
@@ -73,34 +56,45 @@ import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
import com.opensymphony.xwork2.factory.ActionFactory;
import com.opensymphony.xwork2.factory.ConverterFactory;
import com.opensymphony.xwork2.factory.DefaultActionFactory;
import com.opensymphony.xwork2.factory.StrutsConverterFactory;
import com.opensymphony.xwork2.factory.DefaultInterceptorFactory;
import com.opensymphony.xwork2.factory.DefaultResultFactory;
import com.opensymphony.xwork2.factory.DefaultUnknownHandlerFactory;
import com.opensymphony.xwork2.factory.InterceptorFactory;
import com.opensymphony.xwork2.factory.ResultFactory;
import com.opensymphony.xwork2.factory.StrutsConverterFactory;
import com.opensymphony.xwork2.factory.UnknownHandlerFactory;
import com.opensymphony.xwork2.inject.ContainerBuilder;
import com.opensymphony.xwork2.inject.Scope;
import com.opensymphony.xwork2.ognl.BeanInfoCacheFactory;
import com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory;
import com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory;
import com.opensymphony.xwork2.ognl.ExpressionCacheFactory;
import com.opensymphony.xwork2.ognl.ObjectProxy;
import com.opensymphony.xwork2.ognl.OgnlReflectionContextFactory;
import com.opensymphony.xwork2.ognl.OgnlReflectionProvider;
import com.opensymphony.xwork2.ognl.OgnlUtil;
import com.opensymphony.xwork2.ognl.OgnlValueStackFactory;
import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor;
import com.opensymphony.xwork2.ognl.accessor.HttpParametersPropertyAccessor;
import com.opensymphony.xwork2.ognl.accessor.ObjectAccessor;
import com.opensymphony.xwork2.ognl.accessor.ObjectProxyPropertyAccessor;
import com.opensymphony.xwork2.ognl.accessor.ParameterPropertyAccessor;
import com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor;
import com.opensymphony.xwork2.ognl.accessor.XWorkEnumerationAccessor;
import com.opensymphony.xwork2.ognl.accessor.XWorkIteratorPropertyAccessor;
import com.opensymphony.xwork2.ognl.accessor.XWorkListPropertyAccessor;
import com.opensymphony.xwork2.ognl.accessor.XWorkMapPropertyAccessor;
import com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor;
import com.opensymphony.xwork2.security.AcceptedPatternsChecker;
import com.opensymphony.xwork2.security.DefaultAcceptedPatternsChecker;
import com.opensymphony.xwork2.security.DefaultExcludedPatternsChecker;
import com.opensymphony.xwork2.security.DefaultNotExcludedAcceptedPatternsChecker;
import com.opensymphony.xwork2.security.ExcludedPatternsChecker;
import com.opensymphony.xwork2.security.NotExcludedAcceptedPatternsChecker;
import com.opensymphony.xwork2.util.CompoundRoot;
import com.opensymphony.xwork2.LocalizedTextProvider;
import com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory;
import com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory;
import com.opensymphony.xwork2.util.StrutsLocalizedTextProvider;
import com.opensymphony.xwork2.util.OgnlTextParser;
import com.opensymphony.xwork2.util.PatternMatcher;
import com.opensymphony.xwork2.util.StrutsLocalizedTextProvider;
import com.opensymphony.xwork2.util.TextParser;
import com.opensymphony.xwork2.util.ValueStackFactory;
import com.opensymphony.xwork2.util.WildcardHelper;
@@ -119,8 +113,19 @@ import com.opensymphony.xwork2.validator.ValidatorFileParser;
import ognl.MethodAccessor;
import ognl.PropertyAccessor;
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.dispatcher.HttpParameters;
import org.apache.struts2.dispatcher.Parameter;
import org.apache.struts2.url.QueryStringBuilder;
import org.apache.struts2.url.QueryStringParser;
import org.apache.struts2.url.StrutsQueryStringBuilder;
import org.apache.struts2.url.StrutsQueryStringParser;
import org.apache.struts2.url.StrutsUrlDecoder;
import org.apache.struts2.url.StrutsUrlEncoder;
import org.apache.struts2.url.UrlDecoder;
import org.apache.struts2.url.UrlEncoder;
import java.util.ArrayList;
import java.util.Collection;
@@ -153,88 +158,90 @@ public class StrutsDefaultConfigurationProvider implements ConfigurationProvider
@Override
public void register(ContainerBuilder builder, LocatableProperties props)
throws ConfigurationException {
throws ConfigurationException {
builder
.factory(ObjectFactory.class)
.factory(ActionFactory.class, DefaultActionFactory.class)
.factory(ResultFactory.class, DefaultResultFactory.class)
.factory(InterceptorFactory.class, DefaultInterceptorFactory.class)
.factory(com.opensymphony.xwork2.factory.ValidatorFactory.class, com.opensymphony.xwork2.factory.DefaultValidatorFactory.class)
.factory(ConverterFactory.class, StrutsConverterFactory.class)
.factory(UnknownHandlerFactory.class, DefaultUnknownHandlerFactory.class)
.factory(ObjectFactory.class)
.factory(ActionFactory.class, DefaultActionFactory.class)
.factory(ResultFactory.class, DefaultResultFactory.class)
.factory(InterceptorFactory.class, DefaultInterceptorFactory.class)
.factory(com.opensymphony.xwork2.factory.ValidatorFactory.class, com.opensymphony.xwork2.factory.DefaultValidatorFactory.class)
.factory(ConverterFactory.class, StrutsConverterFactory.class)
.factory(UnknownHandlerFactory.class, DefaultUnknownHandlerFactory.class)
.factory(ActionProxyFactory.class, DefaultActionProxyFactory.class, Scope.SINGLETON)
.factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON)
.factory(ActionProxyFactory.class, DefaultActionProxyFactory.class, Scope.SINGLETON)
.factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON)
.factory(XWorkConverter.class, Scope.SINGLETON)
.factory(XWorkBasicConverter.class, Scope.SINGLETON)
.factory(ConversionPropertiesProcessor.class, StrutsConversionPropertiesProcessor.class, Scope.SINGLETON)
.factory(ConversionFileProcessor.class, DefaultConversionFileProcessor.class, Scope.SINGLETON)
.factory(ConversionAnnotationProcessor.class, DefaultConversionAnnotationProcessor.class, Scope.SINGLETON)
.factory(TypeConverterCreator.class, StrutsTypeConverterCreator.class, Scope.SINGLETON)
.factory(TypeConverterHolder.class, StrutsTypeConverterHolder.class, Scope.SINGLETON)
.factory(XWorkConverter.class, Scope.SINGLETON)
.factory(XWorkBasicConverter.class, Scope.SINGLETON)
.factory(ConversionPropertiesProcessor.class, StrutsConversionPropertiesProcessor.class, Scope.SINGLETON)
.factory(ConversionFileProcessor.class, DefaultConversionFileProcessor.class, Scope.SINGLETON)
.factory(ConversionAnnotationProcessor.class, DefaultConversionAnnotationProcessor.class, Scope.SINGLETON)
.factory(TypeConverterCreator.class, StrutsTypeConverterCreator.class, Scope.SINGLETON)
.factory(TypeConverterHolder.class, StrutsTypeConverterHolder.class, Scope.SINGLETON)
.factory(FileManager.class, "system", DefaultFileManager.class, Scope.SINGLETON)
.factory(FileManagerFactory.class, DefaultFileManagerFactory.class, Scope.SINGLETON)
.factory(ValueStackFactory.class, OgnlValueStackFactory.class, Scope.SINGLETON)
.factory(ValidatorFactory.class, DefaultValidatorFactory.class, Scope.SINGLETON)
.factory(ValidatorFileParser.class, DefaultValidatorFileParser.class, Scope.SINGLETON)
.factory(PatternMatcher.class, WildcardHelper.class, Scope.SINGLETON)
.factory(ReflectionProvider.class, OgnlReflectionProvider.class, Scope.SINGLETON)
.factory(ReflectionContextFactory.class, OgnlReflectionContextFactory.class, Scope.SINGLETON)
.factory(FileManager.class, "system", DefaultFileManager.class, Scope.SINGLETON)
.factory(FileManagerFactory.class, DefaultFileManagerFactory.class, Scope.SINGLETON)
.factory(ValueStackFactory.class, OgnlValueStackFactory.class, Scope.SINGLETON)
.factory(ValidatorFactory.class, DefaultValidatorFactory.class, Scope.SINGLETON)
.factory(ValidatorFileParser.class, DefaultValidatorFileParser.class, Scope.SINGLETON)
.factory(PatternMatcher.class, WildcardHelper.class, Scope.SINGLETON)
.factory(ReflectionProvider.class, OgnlReflectionProvider.class, Scope.SINGLETON)
.factory(ReflectionContextFactory.class, OgnlReflectionContextFactory.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, Object.class.getName(), ObjectAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, Iterator.class.getName(), XWorkIteratorPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, Enumeration.class.getName(), XWorkEnumerationAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, Object.class.getName(), ObjectAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, Iterator.class.getName(), XWorkIteratorPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, Enumeration.class.getName(), XWorkEnumerationAccessor.class, Scope.SINGLETON)
.factory(UnknownHandlerManager.class, DefaultUnknownHandlerManager.class, Scope.SINGLETON)
.factory(UnknownHandlerManager.class, DefaultUnknownHandlerManager.class, Scope.SINGLETON)
// silly workarounds for ognl since there is no way to flush its caches
.factory(PropertyAccessor.class, List.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, ArrayList.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, HashSet.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, Set.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, HashMap.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, Map.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, Collection.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, ObjectProxy.class.getName(), ObjectProxyPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, HttpParameters.class.getName(), HttpParametersPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, Parameter.class.getName(), ParameterPropertyAccessor.class, Scope.SINGLETON)
// silly workarounds for ognl since there is no way to flush its caches
.factory(PropertyAccessor.class, List.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, ArrayList.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, HashSet.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, Set.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, HashMap.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, Map.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, Collection.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, ObjectProxy.class.getName(), ObjectProxyPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, HttpParameters.class.getName(), HttpParametersPropertyAccessor.class, Scope.SINGLETON)
.factory(PropertyAccessor.class, Parameter.class.getName(), ParameterPropertyAccessor.class, Scope.SINGLETON)
.factory(MethodAccessor.class, Object.class.getName(), XWorkMethodAccessor.class, Scope.SINGLETON)
.factory(MethodAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON)
.factory(MethodAccessor.class, Object.class.getName(), XWorkMethodAccessor.class, Scope.SINGLETON)
.factory(MethodAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON)
.factory(TextParser.class, OgnlTextParser.class, Scope.SINGLETON)
.factory(TextParser.class, OgnlTextParser.class, Scope.SINGLETON)
.factory(NullHandler.class, Object.class.getName(), InstantiatingNullHandler.class, Scope.SINGLETON)
.factory(ActionValidatorManager.class, AnnotationActionValidatorManager.class, Scope.SINGLETON)
.factory(ActionValidatorManager.class, "no-annotations", DefaultActionValidatorManager.class, Scope.SINGLETON)
.factory(NullHandler.class, Object.class.getName(), InstantiatingNullHandler.class, Scope.SINGLETON)
.factory(ActionValidatorManager.class, AnnotationActionValidatorManager.class, Scope.SINGLETON)
.factory(ActionValidatorManager.class, "no-annotations", DefaultActionValidatorManager.class, Scope.SINGLETON)
.factory(TextProvider.class, "system", DefaultTextProvider.class, Scope.SINGLETON)
.factory(LocalizedTextProvider.class, StrutsLocalizedTextProvider.class, Scope.SINGLETON)
.factory(TextProviderFactory.class, StrutsTextProviderFactory.class, Scope.SINGLETON)
.factory(LocaleProviderFactory.class, DefaultLocaleProviderFactory.class, Scope.SINGLETON)
.factory(TextProvider.class, "system", DefaultTextProvider.class, Scope.SINGLETON)
.factory(LocalizedTextProvider.class, StrutsLocalizedTextProvider.class, Scope.SINGLETON)
.factory(TextProviderFactory.class, StrutsTextProviderFactory.class, Scope.SINGLETON)
.factory(LocaleProviderFactory.class, DefaultLocaleProviderFactory.class, Scope.SINGLETON)
.factory(ExpressionCacheFactory.class, "defaultOgnlExpressionCacheFactory", DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON)
.factory(BeanInfoCacheFactory.class, "defaultOgnlBeanInfoCacheFactory", DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON)
.factory(OgnlUtil.class, Scope.SINGLETON)
.factory(CollectionConverter.class, Scope.SINGLETON)
.factory(ArrayConverter.class, Scope.SINGLETON)
.factory(DateConverter.class, Scope.SINGLETON)
.factory(NumberConverter.class, Scope.SINGLETON)
.factory(StringConverter.class, Scope.SINGLETON)
.factory(ExpressionCacheFactory.class, DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON)
.factory(BeanInfoCacheFactory.class, DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON)
.factory(OgnlUtil.class, Scope.SINGLETON)
.factory(CollectionConverter.class, Scope.SINGLETON)
.factory(ArrayConverter.class, Scope.SINGLETON)
.factory(DateConverter.class, Scope.SINGLETON)
.factory(NumberConverter.class, Scope.SINGLETON)
.factory(StringConverter.class, Scope.SINGLETON)
.factory(ExcludedPatternsChecker.class, DefaultExcludedPatternsChecker.class, Scope.PROTOTYPE)
.factory(AcceptedPatternsChecker.class, DefaultAcceptedPatternsChecker.class, Scope.PROTOTYPE)
.factory(NotExcludedAcceptedPatternsChecker.class, DefaultNotExcludedAcceptedPatternsChecker.class
, Scope.SINGLETON)
.factory(ExcludedPatternsChecker.class, DefaultExcludedPatternsChecker.class, Scope.PROTOTYPE)
.factory(AcceptedPatternsChecker.class, DefaultAcceptedPatternsChecker.class, Scope.PROTOTYPE)
.factory(NotExcludedAcceptedPatternsChecker.class, DefaultNotExcludedAcceptedPatternsChecker.class
, Scope.SINGLETON)
.factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON)
.factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON)
.factory(DateFormatter.class, "simpleDateFormatter", SimpleDateFormatAdapter.class, Scope.SINGLETON)
.factory(DateFormatter.class, "dateTimeFormatter", DateTimeFormatterAdapter.class, Scope.SINGLETON)
.factory(QueryStringBuilder.class, StrutsQueryStringBuilder.class, Scope.SINGLETON)
.factory(QueryStringParser.class, StrutsQueryStringParser.class, Scope.SINGLETON)
.factory(UrlEncoder.class, StrutsUrlEncoder.class, Scope.SINGLETON)
.factory(UrlDecoder.class, StrutsUrlDecoder.class, Scope.SINGLETON)
;
props.setProperty(StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION, Boolean.FALSE.toString());
@@ -244,7 +251,6 @@ public class StrutsDefaultConfigurationProvider implements ConfigurationProvider
props.setProperty(StrutsConstants.STRUTS_OGNL_ENABLE_EXPRESSION_CACHE, Boolean.TRUE.toString());
props.setProperty(StrutsConstants.STRUTS_OGNL_ENABLE_EVAL_EXPRESSION, Boolean.FALSE.toString());
props.setProperty(StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD, Boolean.FALSE.toString());
props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS, Boolean.FALSE.toString());
props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS, Boolean.TRUE.toString());
props.setProperty(StrutsConstants.STRUTS_MATCHER_APPEND_NAMED_PARAMETERS, Boolean.TRUE.toString());
}
@@ -18,28 +18,36 @@
*/
package com.opensymphony.xwork2.conversion.impl;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.conversion.TypeConversionException;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.util.ValueStack;
import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.conversion.TypeConversionException;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.util.ValueStack;
public class DateConverter extends DefaultTypeConverter {
private final static Logger LOG = LogManager.getLogger(DateConverter.class);
@Override
public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName, Object value, Class toType) {
public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName,
Object value, Class toType) {
Date result = null;
if (value instanceof String && ((String) value).length() > 0) {
@@ -52,15 +60,12 @@ public class DateConverter extends DefaultTypeConverter {
} else if (java.sql.Timestamp.class == toType) {
Date check = null;
SimpleDateFormat dtfmt = (SimpleDateFormat) DateFormat.getDateTimeInstance(DateFormat.SHORT,
DateFormat.MEDIUM,
locale);
SimpleDateFormat fullfmt = new SimpleDateFormat(dtfmt.toPattern() + MILLISECOND_FORMAT,
locale);
DateFormat.MEDIUM, locale);
SimpleDateFormat fullfmt = new SimpleDateFormat(dtfmt.toPattern() + MILLISECOND_FORMAT, locale);
SimpleDateFormat dfmt = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT,
locale);
SimpleDateFormat dfmt = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale);
SimpleDateFormat[] fmts = {fullfmt, dtfmt, dfmt};
SimpleDateFormat[] fmts = { fullfmt, dtfmt, dfmt };
for (SimpleDateFormat fmt : fmts) {
try {
check = fmt.parse(sa);
@@ -85,8 +90,39 @@ public class DateConverter extends DefaultTypeConverter {
} catch (ParseException ignore) {
}
}
} else if (java.time.LocalDateTime.class == toType || java.time.LocalDate.class == toType
|| java.time.LocalTime.class == toType) {
DateTimeFormatter dtf = null;
TemporalAccessor check = null;
DateTimeFormatter[] dfs = getDateTimeFormats(ActionContext.of(context), locale);
for (DateTimeFormatter df1 : dfs) {
try {
check = df1.parseBest(sa, LocalDateTime::from, LocalDate::from, LocalTime::from);
dtf = df1;
if (check != null) {
break;
}
} catch (DateTimeParseException ignore) {
}
}
try {
if (dtf != null && check instanceof LocalDateTime) {
return LocalDateTime.parse(sa, dtf);
} else if (dtf != null && check instanceof LocalDate) {
return LocalDate.parse(sa, dtf);
} else if (dtf != null && check instanceof LocalTime) {
return LocalTime.parse(sa, dtf);
} else {
throw new TypeConversionException("Could not parse date");
}
} catch (DateTimeParseException e) {
throw new TypeConversionException("Could not parse date", e);
}
}
//final fallback for dates without time
// final fallback for dates without time
if (df == null) {
df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
}
@@ -95,15 +131,17 @@ public class DateConverter extends DefaultTypeConverter {
result = df.parse(sa);
if (!(Date.class == toType)) {
try {
Constructor<?> constructor = toType.getConstructor(new Class[]{long.class});
return constructor.newInstance(new Object[]{Long.valueOf(result.getTime())});
Constructor<?> constructor = toType.getConstructor(new Class[] { long.class });
return constructor.newInstance(new Object[] { Long.valueOf(result.getTime()) });
} catch (Exception e) {
throw new TypeConversionException("Couldn't create class " + toType + " using default (long) constructor", e);
throw new TypeConversionException(
"Couldn't create class " + toType + " using default (long) constructor", e);
}
}
} catch (ParseException e) {
throw new TypeConversionException("Could not parse date", e);
}
} else if (Date.class.isAssignableFrom(value.getClass())) {
result = (Date) value;
}
@@ -111,16 +149,16 @@ public class DateConverter extends DefaultTypeConverter {
}
/**
* The user defined global date format,
* see {@link org.apache.struts2.components.Date#DATETAG_PROPERTY}
* The user defined global date format, see
* {@link org.apache.struts2.components.Date#DATETAG_PROPERTY}
*
* @param context current ActionContext
* @param locale current Locale to convert to
* @return defined global format
*
* @return defined global date string format
*/
protected DateFormat getGlobalDateFormat(ActionContext context, Locale locale) {
protected String getGlobalDateString(ActionContext context) {
final String dateTagProperty = org.apache.struts2.components.Date.DATETAG_PROPERTY;
SimpleDateFormat globalDateFormat = null;
String globalDateString = null;
final TextProvider tp = findProviderInStack(context.getValueStack());
@@ -130,23 +168,28 @@ public class DateConverter extends DefaultTypeConverter {
// is the same as input = DATETAG_PROPERTY
if (globalFormat != null && !dateTagProperty.equals(globalFormat)) {
LOG.debug("Found \"{}\" as \"{}\"", dateTagProperty, globalFormat);
globalDateFormat = new SimpleDateFormat(globalFormat, locale);
globalDateString = globalFormat;
} else {
LOG.debug("\"{}\" has not been defined, ignoring it", dateTagProperty);
}
}
return globalDateFormat;
return globalDateString;
}
/**
* Retrieves the list of date formats to be used when converting dates
*
* @param context the current ActionContext
* @param locale the current locale of the action
* @param locale the current locale of the action
* @return a list of DateFormat to be used for date conversion
*/
private DateFormat[] getDateFormats(ActionContext context, Locale locale) {
DateFormat globalDateFormat = getGlobalDateFormat(context, locale);
DateFormat globalDateFormat = null;
String globalFormat = getGlobalDateString(context);
if (globalFormat != null) {
globalDateFormat = new SimpleDateFormat(globalFormat, locale);
}
DateFormat dt1 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, locale);
DateFormat dt2 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, locale);
@@ -156,15 +199,46 @@ public class DateConverter extends DefaultTypeConverter {
DateFormat d2 = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
DateFormat d3 = DateFormat.getDateInstance(DateFormat.LONG, locale);
DateFormat rfc3339 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
DateFormat rfc3339 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
DateFormat rfc3339dateOnly = new SimpleDateFormat("yyyy-MM-dd");
final DateFormat[] dateFormats;
if (globalDateFormat == null) {
dateFormats = new DateFormat[]{dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly};
dateFormats = new DateFormat[] { dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly };
} else {
dateFormats = new DateFormat[]{globalDateFormat, dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly};
dateFormats = new DateFormat[] { globalDateFormat, dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly };
}
return dateFormats;
}
/**
* Retrieves the list of date time formats to be used when converting dates
*
* @param context the current ActionContext
* @param locale the current locale of the action
*
* @return a list of DateTimeFormatter to be used for date conversion
*/
protected DateTimeFormatter[] getDateTimeFormats(ActionContext context, Locale locale) {
DateTimeFormatter globalDateFormat = null;
String globalFormat = getGlobalDateString(context);
if (globalFormat != null) {
globalDateFormat = DateTimeFormatter.ofPattern(globalFormat, locale);
}
DateTimeFormatter df1 = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
DateTimeFormatter df2 = DateTimeFormatter.ISO_LOCAL_DATE;
DateTimeFormatter df3 = DateTimeFormatter.ISO_LOCAL_TIME;
final DateTimeFormatter[] dateFormats;
if (globalDateFormat == null) {
dateFormats = new DateTimeFormatter[] { df1, df2, df3 };
} else {
dateFormats = new DateTimeFormatter[] { globalDateFormat, df1, df2, df3 };
}
return dateFormats;
@@ -25,6 +25,7 @@ import com.opensymphony.xwork2.inject.Inject;
import org.apache.struts2.StrutsConstants;
import java.lang.reflect.Member;
import java.time.LocalDateTime;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
@@ -99,6 +100,8 @@ public class XWorkBasicConverter extends DefaultTypeConverter {
result = doConvertToArray(context, o, member, propertyName, value, toType);
} else if (Date.class.isAssignableFrom(toType)) {
result = doConvertToDate(context, value, toType);
} else if (LocalDateTime.class.isAssignableFrom(toType)) {
result = doConvertToDate(context, value, toType);
} else if (Calendar.class.isAssignableFrom(toType)) {
result = doConvertToCalendar(context, value);
} else if (Collection.class.isAssignableFrom(toType)) {
@@ -19,10 +19,26 @@ import com.opensymphony.xwork2.inject.util.ReferenceCache;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ReflectPermission;
import java.security.AccessControlException;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Default {@link Container} implementation.
@@ -39,11 +55,7 @@ class ContainerImpl implements Container {
this.factories = factories;
final Map<Class<?>, Set<String>> map = new HashMap<>();
for (Key<?> key : factories.keySet()) {
Set<String> names = map.get(key.getType());
if (names == null) {
names = new HashSet<>();
map.put(key.getType(), names);
}
Set<String> names = map.computeIfAbsent(key.getType(), k -> new HashSet<>());
names.add(key.getName());
}
@@ -63,20 +75,20 @@ class ContainerImpl implements Container {
* Field and method injectors.
*/
final Map<Class<?>, List<Injector>> injectors =
new ReferenceCache<Class<?>, List<Injector>>() {
@Override
protected List<Injector> create(Class<?> key) {
List<Injector> injectors = new ArrayList<>();
addInjectors(key, injectors);
return injectors;
}
};
new ReferenceCache<Class<?>, List<Injector>>() {
@Override
protected List<Injector> create(Class<?> key) {
List<Injector> injectors = new ArrayList<>();
addInjectors(key, injectors);
return injectors;
}
};
/**
* Recursively adds injectors for fields and methods from the given class to the given list. Injects parent classes
* before sub classes.
*/
void addInjectors(Class clazz, List<Injector> injectors) {
void addInjectors(Class<?> clazz, List<Injector> injectors) {
if (clazz == Object.class) {
return;
}
@@ -97,38 +109,24 @@ class ContainerImpl implements Container {
addInjectorsForMethods(clazz.getDeclaredMethods(), true, injectors);
}
callInContext(new ContextualCallable<Void>() {
public Void call(InternalContext context) {
for (Injector injector : injectors) {
injector.inject(context, null);
}
return null;
callInContext((ContextualCallable<Void>) context -> {
for (Injector injector : injectors) {
injector.inject(context, null);
}
return null;
});
}
void addInjectorsForMethods(Method[] methods, boolean statics, List<Injector> injectors) {
addInjectorsForMembers(Arrays.asList(methods), statics, injectors,
new InjectorFactory<Method>() {
public Injector create(ContainerImpl container, Method method,
String name) throws MissingDependencyException {
return new MethodInjector(container, method, name);
}
});
addInjectorsForMembers(Arrays.asList(methods), statics, injectors, MethodInjector::new);
}
void addInjectorsForFields(Field[] fields, boolean statics, List<Injector> injectors) {
addInjectorsForMembers(Arrays.asList(fields), statics, injectors,
new InjectorFactory<Field>() {
public Injector create(ContainerImpl container, Field field,
String name) throws MissingDependencyException {
return new FieldInjector(container, field, name);
}
});
addInjectorsForMembers(Arrays.asList(fields), statics, injectors, FieldInjector::new);
}
<M extends Member & AnnotatedElement> void addInjectorsForMembers(
List<M> members, boolean statics, List<Injector> injectors, InjectorFactory<M> injectorFactory) {
List<M> members, boolean statics, List<Injector> injectors, InjectorFactory<M> injectorFactory) {
for (M member : members) {
if (isStatic(member) == statics) {
Inject inject = member.getAnnotation(Inject.class);
@@ -148,12 +146,12 @@ class ContainerImpl implements Container {
interface InjectorFactory<M extends Member & AnnotatedElement> {
Injector create(ContainerImpl container, M member, String name)
throws MissingDependencyException;
throws MissingDependencyException;
}
/**
* Determines if a given {@link Member} is static or not.
*
*
* @param member checked for the static modifier.
* @return true if member is static, false otherwise.
*/
@@ -163,13 +161,13 @@ class ContainerImpl implements Container {
/**
* Determines if a given {@link Member} is considered to be public for reflection usage or not.
*
*
* @param member checked to see if it is public for reflection usage.
* @return true if member is public for reflection usage, false otherwise.
*/
private static boolean isPublicForReflection(Member member) {
return Modifier.isPublic(member.getModifiers()) &&
Modifier.isPublic(member.getDeclaringClass().getModifiers());
Modifier.isPublic(member.getDeclaringClass().getModifiers());
}
static class FieldInjector implements Injector {
@@ -179,7 +177,7 @@ class ContainerImpl implements Container {
final ExternalContext<?> externalContext;
public FieldInjector(ContainerImpl container, Field field, String name)
throws MissingDependencyException {
throws MissingDependencyException {
this.field = field;
if (!isPublicForReflection(field) && !field.isAccessible()) {
SecurityManager sm = System.getSecurityManager();
@@ -190,7 +188,7 @@ class ContainerImpl implements Container {
field.setAccessible(true);
} catch (AccessControlException e) {
throw new DependencyException("Security manager in use, could not access field: "
+ field.getDeclaringClass().getName() + "(" + field.getName() + ")", e);
+ field.getDeclaringClass().getName() + "(" + field.getName() + ")", e);
}
}
@@ -225,8 +223,12 @@ class ContainerImpl implements Container {
* @param parameterTypes parameter types
* @return injections
*/
<M extends AccessibleObject & Member> ParameterInjector<?>[]
getParametersInjectors(M member, Annotation[][] annotations, Class[] parameterTypes, String defaultName) throws MissingDependencyException {
<M extends AccessibleObject & Member> ParameterInjector<?>[] getParametersInjectors(
M member,
Annotation[][] annotations,
Class<?>[] parameterTypes,
String defaultName
) throws MissingDependencyException {
final List<ParameterInjector<?>> parameterInjectors = new ArrayList<>();
final Iterator<Annotation[]> annotationsIterator = Arrays.asList(annotations).iterator();
@@ -247,12 +249,11 @@ class ContainerImpl implements Container {
}
final ExternalContext<T> externalContext = ExternalContext.newInstance(member, key, this);
return new ParameterInjector<T>(externalContext, factory);
return new ParameterInjector<>(externalContext, factory);
}
@SuppressWarnings("unchecked")
private ParameterInjector<?>[] toArray(List<ParameterInjector<?>> parameterInjections) {
return parameterInjections.toArray(new ParameterInjector[parameterInjections.size()]);
return parameterInjections.toArray(new ParameterInjector[0]);
}
/**
@@ -261,7 +262,7 @@ class ContainerImpl implements Container {
Inject findInject(Annotation[] annotations) {
for (Annotation annotation : annotations) {
if (annotation.annotationType() == Inject.class) {
return Inject.class.cast(annotation);
return (Inject) annotation;
}
}
return null;
@@ -283,7 +284,7 @@ class ContainerImpl implements Container {
method.setAccessible(true);
} catch (AccessControlException e) {
throw new DependencyException("Security manager in use, could not access method: "
+ name + "(" + method.getName() + ")", e);
+ name + "(" + method.getName() + ")", e);
}
}
@@ -292,7 +293,7 @@ class ContainerImpl implements Container {
throw new DependencyException(method + " has no parameters to inject.");
}
parameterInjectors = container.getParametersInjectors(
method, method.getParameterAnnotations(), parameterTypes, name);
method, method.getParameterAnnotations(), parameterTypes, name);
}
@Override
@@ -305,14 +306,12 @@ class ContainerImpl implements Container {
}
}
Map<Class<?>, ConstructorInjector> constructors =
new ReferenceCache<Class<?>, ConstructorInjector>() {
@Override
@SuppressWarnings("unchecked")
protected ConstructorInjector<?> create(Class<?> implementation) {
return new ConstructorInjector(ContainerImpl.this, implementation);
}
};
Map<Class<?>, ConstructorInjector<?>> constructors = new ReferenceCache<Class<?>, ConstructorInjector<?>>() {
@Override
protected ConstructorInjector<?> create(Class<?> implementation) {
return new ConstructorInjector<>(ContainerImpl.this, implementation);
}
};
static class ConstructorInjector<T> {
@@ -334,7 +333,7 @@ class ContainerImpl implements Container {
constructor.setAccessible(true);
} catch (AccessControlException e) {
throw new DependencyException("Security manager in use, could not access constructor: "
+ implementation.getName() + "(" + constructor.getName() + ")", e);
+ implementation.getName() + "(" + constructor.getName() + ")", e);
}
}
@@ -359,14 +358,14 @@ class ContainerImpl implements Container {
}
ParameterInjector<?>[] constructParameterInjector(
Inject inject, ContainerImpl container, Constructor<T> constructor) throws MissingDependencyException {
Inject inject, ContainerImpl container, Constructor<T> constructor) throws MissingDependencyException {
return constructor.getParameterTypes().length == 0
? null // default constructor.
: container.getParametersInjectors(
constructor,
constructor.getParameterAnnotations(),
constructor.getParameterTypes(),
inject.value()
? null // default constructor.
: container.getParametersInjectors(
constructor,
constructor.getParameterAnnotations(),
constructor.getParameterTypes(),
inject.value()
);
}
@@ -378,7 +377,7 @@ class ContainerImpl implements Container {
if (constructor.getAnnotation(Inject.class) != null) {
if (found != null) {
throw new DependencyException("More than one constructor annotated"
+ " with @Inject found in " + implementation + ".");
+ " with @Inject found in " + implementation + ".");
}
found = constructor;
}
@@ -466,7 +465,7 @@ class ContainerImpl implements Container {
}
}
private static Object[] getParameters(Member member, InternalContext context, ParameterInjector[] parameterInjectors) {
private static Object[] getParameters(Member member, InternalContext context, ParameterInjector<?>[] parameterInjectors) {
if (parameterInjectors == null) {
return null;
}
@@ -494,13 +493,12 @@ class ContainerImpl implements Container {
}
}
@SuppressWarnings("unchecked")
<T> T getInstance(Class<T> type, String name, InternalContext context) {
final ExternalContext<?> previous = context.getExternalContext();
final Key<T> key = Key.newInstance(type, name);
context.setExternalContext(ExternalContext.newInstance(null, key, this));
try {
final InternalFactory o = getFactory(key);
final InternalFactory<? extends T> o = getFactory(key);
if (o != null) {
return getFactory(key).create(context);
} else {
@@ -517,39 +515,25 @@ class ContainerImpl implements Container {
@Override
public void inject(final Object o) {
callInContext(new ContextualCallable<Void>() {
public Void call(InternalContext context) {
inject(o, context);
return null;
}
callInContext((ContextualCallable<Void>) context -> {
inject(o, context);
return null;
});
}
@Override
public <T> T inject(final Class<T> implementation) {
return callInContext(new ContextualCallable<T>() {
public T call(InternalContext context) {
return inject(implementation, context);
}
});
return callInContext(context -> inject(implementation, context));
}
@Override
public <T> T getInstance(final Class<T> type, final String name) {
return callInContext(new ContextualCallable<T>() {
public T call(InternalContext context) {
return getInstance(type, name, context);
}
});
return callInContext(context -> getInstance(type, name, context));
}
@Override
public <T> T getInstance(final Class<T> type) {
return callInContext(new ContextualCallable<T>() {
public T call(InternalContext context) {
return getInstance(type, context);
}
});
return callInContext(context -> getInstance(type, context));
}
@Override
@@ -561,12 +545,7 @@ class ContainerImpl implements Container {
return names;
}
ThreadLocal<Object[]> localContext = new ThreadLocal<Object[]>() {
@Override
protected Object[] initialValue() {
return new Object[1];
}
};
ThreadLocal<Object[]> localContext = ThreadLocal.withInitial(() -> new Object[1]);
/**
* Looks up thread local context. Creates (and removes) a new context if necessary.
@@ -598,7 +577,7 @@ class ContainerImpl implements Container {
*/
@SuppressWarnings("unchecked")
<T> ConstructorInjector<T> getConstructor(Class<T> implementation) {
return constructors.get(implementation);
return (ConstructorInjector<T>) constructors.get(implementation);
}
final ThreadLocal<Object> localScopeStrategy = new ThreadLocal<>();
@@ -25,21 +25,31 @@ import com.opensymphony.xwork2.ActionInvocation;
*/
public abstract class AbstractInterceptor implements Interceptor {
private boolean disabled;
/**
* Does nothing
*/
public void init() {
}
/**
* Does nothing
*/
public void destroy() {
}
/**
* Override to handle interception
*/
public abstract String intercept(ActionInvocation invocation) throws Exception;
public void setDisabled(String disable) {
this.disabled = Boolean.parseBoolean(disable);
}
@Override
public boolean isDisabled(ActionInvocation invocation) {
return this.disabled;
}
}
@@ -219,4 +219,12 @@ public interface Interceptor extends Serializable {
*/
String intercept(ActionInvocation invocation) throws Exception;
/**
* Allows to disable processing a given interceptor
*
* @param invocation current {@link ActionInvocation} to determine if the interceptor should be executed
* @return true if the given interceptor should be skipped
* @since 6.1.0
*/
boolean isDisabled(ActionInvocation invocation);
}
@@ -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 com.opensymphony.xwork2.interceptor;
/**
* This interface is implemented by actions that want to declare acceptable parameter value. Works in conjunction with {@link
* ParametersInterceptor}. For example, actions may want to create a white list of parameter values they will accept or a
* blacklist of parameter values they will reject to prevent clients from setting other unexpected (and possibly dangerous)
* parameter values.
*/
public interface ParameterValueAware {
/**
* Tests if the the action will accept the parameter with the given value.
*
* @param parameterValue the parameter value
* @return <tt>true</tt> if accepted, <tt>false</tt> otherwise
*/
boolean acceptableParameterValue(String parameterValue);
}
@@ -26,6 +26,7 @@ import com.opensymphony.xwork2.security.AcceptedPatternsChecker;
import com.opensymphony.xwork2.security.ExcludedPatternsChecker;
import com.opensymphony.xwork2.util.ClearableValueStack;
import com.opensymphony.xwork2.util.MemberAccessValueStack;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;
import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
@@ -33,12 +34,15 @@ import org.apache.commons.lang3.BooleanUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.dispatcher.Parameter;
import org.apache.struts2.dispatcher.HttpParameters;
import org.apache.struts2.dispatcher.Parameter;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Pattern;
@@ -62,6 +66,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
private ValueStackFactory valueStackFactory;
private ExcludedPatternsChecker excludedPatterns;
private AcceptedPatternsChecker acceptedPatterns;
private Set<Pattern> excludedValuePatterns = null;
private Set<Pattern> acceptedValuePatterns = null;
@Inject
public void setValueStackFactory(ValueStackFactory valueStackFactory) {
@@ -183,8 +189,10 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
for (Map.Entry<String, Parameter> entry : params.entrySet()) {
String parameterName = entry.getKey();
boolean isAcceptableParameter = isAcceptableParameter(parameterName, action);
isAcceptableParameter &= isAcceptableParameterValue(entry.getValue(), action);
if (isAcceptableParameter(parameterName, action)) {
if (isAcceptableParameter) {
acceptableParameters.put(parameterName, entry.getValue());
}
}
@@ -201,7 +209,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
ReflectionContextState.setReportingConversionErrors(context, true);
//keep locale from original context
newStack.getActionContext().withLocale(stack.getActionContext().getLocale());
newStack.getActionContext().withLocale(stack.getActionContext().getLocale()).withValueStack(stack);
}
boolean memberAccessStack = newStack instanceof MemberAccessValueStack;
@@ -237,8 +245,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
if (action instanceof TextProvider) {
TextProvider tp = (TextProvider) action;
developerNotification = tp.getText("devmode.notification",
"Developer Notification:\n{0}",
new String[]{developerNotification}
"Developer Notification:\n{0}",
new String[]{developerNotification}
);
}
@@ -264,6 +272,23 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
return acceptableName(name) && (parameterNameAware == null || parameterNameAware.acceptableParameterName(name));
}
/**
* Checks if parameter value can be accepted or thrown away
*
* @param param the parameter
* @param action current action
* @return true if parameter is accepted
*/
protected boolean isAcceptableParameterValue(Parameter param, Object action) {
ParameterValueAware parameterValueAware = (action instanceof ParameterValueAware) ? (ParameterValueAware) action : null;
boolean acceptableParamValue = (parameterValueAware == null || parameterValueAware.acceptableParameterValue(param.getValue()));
if (hasParamValuesToExclude() || hasParamValuesToAccept()) {
// Additional validations to process
acceptableParamValue &= acceptableValue(param.getName(), param.getValue());
}
return acceptableParamValue;
}
/**
* Gets an instance of the comparator to use for the ordered sorting. Override this
* method to customize the ordering of the parameters as they are set to the
@@ -291,6 +316,15 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
return logEntry.toString();
}
/**
* Validates the name passed is:
* * Within the max length of a parameter name
* * Is not excluded
* * Is accepted
*
* @param name - Name to check
* @return true if accepted
*/
protected boolean acceptableName(String name) {
if (isIgnoredDMI(name)) {
LOG.trace("DMI is enabled, ignoring DMI method: {}", name);
@@ -311,14 +345,37 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
}
}
/**
* Validates:
* * Value is null/blank
* * Value is not excluded
* * Value is accepted
*
* @param name - Param name (for logging)
* @param value - value to check
* @return true if accepted
*/
protected boolean acceptableValue(String name, String value) {
boolean accepted = (value == null || value.isEmpty() || (!isParamValueExcluded(value) && isParamValueAccepted(value)));
if (!accepted) {
String message = "Value [{}] of parameter [{}] was not accepted and will be dropped!";
if (devMode) {
LOG.warn(message, value, name);
} else {
LOG.debug(message, value, name);
}
}
return accepted;
}
protected boolean isWithinLengthLimit(String name) {
boolean matchLength = name.length() <= paramNameMaxLength;
if (!matchLength) {
if (devMode) { // warn only when in devMode
LOG.warn("Parameter [{}] is too long, allowed length is [{}]. Use Interceptor Parameter Overriding " +
"to override the limit, see more at\n" +
"https://struts.apache.org/core-developers/interceptors.html#interceptor-parameter-overriding",
name, paramNameMaxLength);
"to override the limit, see more at\n" +
"https://struts.apache.org/core-developers/interceptors.html#interceptor-parameter-overriding",
name, paramNameMaxLength);
} else {
LOG.warn("Parameter [{}] is too long, allowed length is [{}]", name, paramNameMaxLength);
}
@@ -332,8 +389,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
return true;
} else if (devMode) { // warn only when in devMode
LOG.warn("Parameter [{}] didn't match accepted pattern [{}]! See Accepted / Excluded patterns at\n" +
"https://struts.apache.org/security/#accepted--excluded-patterns",
paramName, result.getAcceptedPattern());
"https://struts.apache.org/security/#accepted--excluded-patterns",
paramName, result.getAcceptedPattern());
} else {
LOG.debug("Parameter [{}] didn't match accepted pattern [{}]!", paramName, result.getAcceptedPattern());
}
@@ -345,8 +402,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
if (result.isExcluded()) {
if (devMode) { // warn only when in devMode
LOG.warn("Parameter [{}] matches excluded pattern [{}]! See Accepted / Excluded patterns at\n" +
"https://struts.apache.org/security/#accepted--excluded-patterns",
paramName, result.getExcludedPattern());
"https://struts.apache.org/security/#accepted--excluded-patterns",
paramName, result.getExcludedPattern());
} else {
LOG.debug("Parameter [{}] matches excluded pattern [{}]!", paramName, result.getExcludedPattern());
}
@@ -355,6 +412,54 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
return false;
}
protected boolean isParamValueExcluded(String value) {
if (!hasParamValuesToExclude()) {
LOG.debug("'excludedValuePatterns' not defined so anything is allowed");
return false;
}
for (Pattern excludedValuePattern : excludedValuePatterns) {
if (excludedValuePattern.matcher(value).matches()) {
if (devMode) {
LOG.warn("Parameter value [{}] matches excluded pattern [{}]! See Accepting/Excluding parameter values at\n" +
"https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values",
value, excludedValuePatterns);
} else {
LOG.debug("Parameter value [{}] matches excluded pattern [{}]", value, excludedValuePattern);
}
return true;
}
}
return false;
}
protected boolean isParamValueAccepted(String value) {
if (!hasParamValuesToAccept()) {
LOG.debug("'acceptedValuePatterns' not defined so anything is allowed");
return true;
}
for (Pattern acceptedValuePattern : acceptedValuePatterns) {
if (acceptedValuePattern.matcher(value).matches()) {
return true;
}
}
if (devMode) {
LOG.warn("Parameter value [{}] didn't match accepted pattern [{}]! See Accepting/Excluding parameter values at\n" +
"https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values",
value, acceptedValuePatterns);
} else {
LOG.debug("Parameter value [{}] was not accepted!", value);
}
return false;
}
private boolean hasParamValuesToExclude() {
return excludedValuePatterns != null && excludedValuePatterns.size() > 0;
}
private boolean hasParamValuesToAccept() {
return acceptedValuePatterns != null && acceptedValuePatterns.size() > 0;
}
/**
* Whether to order the parameters or not
*
@@ -397,4 +502,53 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
excludedPatterns.setExcludedPatterns(commaDelim);
}
/**
* Sets a comma-delimited list of regular expressions to match
* values of parameters that should be accepted and included in the parameter map.
*
* @param commaDelimitedPatterns A comma-delimited set of regular expressions
*/
public void setAcceptedValuePatterns(String commaDelimitedPatterns) {
Set<String> patterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns);
if (acceptedValuePatterns == null) {
// Limit unwanted log entries (for 1st call, acceptedValuePatterns null)
LOG.debug("Sets accepted value patterns to [{}], note this may impact the safety of your application!", patterns);
} else {
LOG.warn("Replacing accepted patterns [{}] with [{}], be aware that this may impact safety of your application!",
acceptedValuePatterns, patterns);
}
acceptedValuePatterns = new HashSet<>(patterns.size());
try {
for (String pattern : patterns) {
acceptedValuePatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE));
}
} finally {
acceptedValuePatterns = Collections.unmodifiableSet(acceptedValuePatterns);
}
}
/**
* Sets a comma-delimited list of regular expressions to match
* values of parameters that should be removed from the parameter map.
*
* @param commaDelimitedPatterns A comma-delimited set of regular expressions
*/
public void setExcludedValuePatterns(String commaDelimitedPatterns) {
Set<String> patterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns);
if (excludedValuePatterns == null) {
// Limit unwanted log entries (for 1st call, excludedValuePatterns null)
LOG.debug("Setting excluded value patterns to [{}]", patterns);
} else {
LOG.warn("Replacing excluded value patterns [{}] with [{}], be aware that this may impact safety of your application!",
excludedValuePatterns, patterns);
}
excludedValuePatterns = new HashSet<>(patterns.size());
try {
for (String pattern : patterns) {
excludedValuePatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE));
}
} finally {
excludedValuePatterns = Collections.unmodifiableSet(excludedValuePatterns);
}
}
}
@@ -73,7 +73,6 @@ public class OgnlUtil {
private Container container;
private boolean allowStaticFieldAccess = true;
private boolean allowStaticMethodAccess;
private boolean disallowProxyMemberAccess;
/**
@@ -83,7 +82,9 @@ public class OgnlUtil {
*/
@Deprecated
public OgnlUtil() {
this(null, null); // Instantiate default Expression and BeanInfo caches (null factories)
// Instantiate default Expression and BeanInfo caches (factories must be non-null).
this(new DefaultOgnlExpressionCacheFactory<String, Object>(),
new DefaultOgnlBeanInfoCacheFactory<Class<?>, BeanInfo>());
}
/**
@@ -97,10 +98,17 @@ public class OgnlUtil {
* @param ognlExpressionCacheFactory factory for Expression cache instance. If null, it uses a default
* @param ognlBeanInfoCacheFactory factory for BeanInfo cache instance. If null, it uses a default
*/
@Inject
public OgnlUtil(
@Inject(value = StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_FACTORY, required = false) ExpressionCacheFactory<String, Object> ognlExpressionCacheFactory,
@Inject(value = StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_FACTORY, required = false) BeanInfoCacheFactory<Class<?>, BeanInfo> ognlBeanInfoCacheFactory
@Inject ExpressionCacheFactory<String, Object> ognlExpressionCacheFactory,
@Inject BeanInfoCacheFactory<Class<?>, BeanInfo> ognlBeanInfoCacheFactory
) {
if (ognlExpressionCacheFactory == null) {
throw new IllegalArgumentException("ExpressionCacheFactory parameter cannot be null");
}
if (ognlBeanInfoCacheFactory == null) {
throw new IllegalArgumentException("BeanInfoCacheFactory parameter cannot be null");
}
excludedClasses = Collections.unmodifiableSet(new HashSet<>());
excludedPackageNamePatterns = Collections.unmodifiableSet(new HashSet<>());
excludedPackageNames = Collections.unmodifiableSet(new HashSet<>());
@@ -109,11 +117,8 @@ public class OgnlUtil {
devModeExcludedPackageNamePatterns = Collections.unmodifiableSet(new HashSet<>());
devModeExcludedPackageNames = Collections.unmodifiableSet(new HashSet<>());
OgnlCacheFactory<String, Object> ognlExpressionCacheFactory1 = (ognlExpressionCacheFactory != null ? ognlExpressionCacheFactory : new DefaultOgnlExpressionCacheFactory<>());
OgnlCacheFactory<Class<?>, BeanInfo> ognlBeanInfoCacheFactory1 = (ognlBeanInfoCacheFactory != null ? ognlBeanInfoCacheFactory : new DefaultOgnlBeanInfoCacheFactory<>());
this.expressionCache = ognlExpressionCacheFactory1.buildOgnlCache();
this.beanInfoCache = ognlBeanInfoCacheFactory1.buildOgnlCache();
this.expressionCache = ognlExpressionCacheFactory.buildOgnlCache();
this.beanInfoCache = ognlBeanInfoCacheFactory.buildOgnlCache();
}
@Inject
@@ -250,11 +255,6 @@ public class OgnlUtil {
this.allowStaticFieldAccess = BooleanUtils.toBoolean(allowStaticFieldAccess);
}
@Inject(value = StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS, required = false)
protected void setAllowStaticMethodAccess(String allowStaticMethodAccess) {
this.allowStaticMethodAccess = BooleanUtils.toBoolean(allowStaticMethodAccess);
}
@Inject(value = StrutsConstants.STRUTS_DISALLOW_PROXY_MEMBER_ACCESS, required = false)
protected void setDisallowProxyMemberAccess(String disallowProxyMemberAccess) {
this.disallowProxyMemberAccess = BooleanUtils.toBoolean(disallowProxyMemberAccess);
@@ -268,10 +268,10 @@ public class OgnlUtil {
try {
if (maxLength == null || maxLength.isEmpty()) {
Ognl.applyExpressionMaxLength(null);
LOG.info("OGNL Expression Max Length disabled.");
LOG.warn("OGNL Expression Max Length disabled.");
} else {
Ognl.applyExpressionMaxLength(Integer.parseInt(maxLength));
LOG.info("OGNL Expression Max Length enabled with {}.", maxLength);
LOG.debug("OGNL Expression Max Length enabled with {}.", maxLength);
}
} catch (Exception ex) {
LOG.error("Unable to set OGNL Expression Max Length {}.", maxLength); // Help configuration debugging.
@@ -836,7 +836,7 @@ public class OgnlUtil {
resolver = container.getInstance(CompoundRootAccessor.class);
}
SecurityMemberAccess memberAccess = new SecurityMemberAccess(allowStaticMethodAccess, allowStaticFieldAccess);
SecurityMemberAccess memberAccess = new SecurityMemberAccess(allowStaticFieldAccess);
memberAccess.setDisallowProxyMemberAccess(disallowProxyMemberAccess);
if (devMode) {

Some files were not shown because too many files have changed in this diff Show More