Compare commits

...

202 Commits

Author SHA1 Message Date
Lukasz Lenart e903739624 [maven-release-plugin] prepare release STRUTS_6_1_2 2023-03-08 17:27:52 +01:00
Lukasz Lenart a85328e74e Sets proper SNAPSHOT version to start release process 2023-03-08 17:23:24 +01:00
Lukasz Lenart c3deb39237 WW-5285 Uses Long and null to check if option has been defined 2023-03-08 17:15:40 +01:00
Lukasz Lenart 483a0c8d01 WW-5285 Limits max number of files to upload at once
Upgrades commons-fileupload to ver. 1.5 and sets default limit to 256 files
2023-03-08 17:15:29 +01:00
Lukasz Lenart f5c0aa5f3a [maven-release-plugin] prepare release STRUTS_6_1_1 2022-11-15 15:30:05 +01:00
Lukasz Lenart a77a80a803 Refactors name/value calculation logic 2022-11-13 10:39:37 +01:00
Lukasz Lenart 4d58dd1960 Merge pull request #636 from apache/WW-5260-global-submit-unchecked
[WW-5260] Introduces a constant to set submitUnchecked attribute of checkbox tag globally
2022-11-13 09:42:40 +01:00
Lukasz Lenart 09da11ba06 Merge pull request #635 from apache/WW-4173-optional
[WW-4173] Introduces a dedicated interface to allow conditionally disabling a given interceptor
2022-11-13 09:42:21 +01:00
Lukasz Lenart bcfa8113ac WW-4173 Introduces a dedicated interface to allow conditionally executing a given interceptor 2022-11-11 15:48:41 +01:00
Lukasz Lenart 65ae2b7e4f WW-5260 Introduces a constant to set submitUnchecked attribute of checkbox tag globally 2022-11-11 09:30:55 +01:00
Lukasz Lenart 1af3e31548 [maven-release-plugin] prepare for next development iteration 2022-11-08 15:49:51 +01:00
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
565 changed files with 21923 additions and 23715 deletions
+2
View File
@@ -12,3 +12,5 @@ notifications:
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.5/apache-maven-3.8.5-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
-29
View File
@@ -1,29 +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 jdk 9 and 11 tests prospered
script:
- if [ "$STRUTS_IT" == "true" ]; then
./mvnw clean install -DskipTests -DskipAssembly -B;
./mvnw test org.jacoco:jacoco-maven-plugin:report org.jacoco:jacoco-maven-plugin:report-integration org.eluder.coveralls:coveralls-maven-plugin:report -Ptravis-coveralls -DskipAssembly -B;
else
./mvnw clean package test -DskipAssembly -B;
fi;
cache:
directories:
- $HOME/.m2
Vendored
+5 -3
View File
@@ -79,7 +79,7 @@ pipeline {
}
stage('Test') {
steps {
sh './mvnw -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 './mvnw 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'
}
}
}
@@ -160,6 +160,7 @@ pipeline {
branch 'master'
}
steps {
sh './mvnw -B package -DskipTests'
sshPublisher(publishers: [
sshPublisherDesc(
configName: 'Nightlies',
@@ -167,7 +168,8 @@ pipeline {
sshTransfer(
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</version>
<version>6.1.2</version>
</parent>
<artifactId>struts2-apps</artifactId>
<packaging>pom</packaging>
+3 -2
View File
@@ -24,12 +24,12 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>6.0.0</version>
<version>6.1.2</version>
</parent>
<artifactId>struts2-rest-showcase</artifactId>
<packaging>war</packaging>
<version>6.0.0</version>
<version>6.1.2</version>
<name>Struts 2 Rest Showcase Webapp</name>
<description>Struts 2 Rest Showcase Example</description>
@@ -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>
+15 -7
View File
@@ -24,7 +24,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>6.0.0</version>
<version>6.1.2</version>
</parent>
<artifactId>struts2-showcase</artifactId>
@@ -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>
@@ -150,9 +155,9 @@
<!-- BeanValidation Example -->
<dependency>
<groupId>org.hibernate</groupId>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.2.Final</version>
<version>${hibernate-validator.version}</version>
</dependency>
</dependencies>
@@ -167,6 +172,9 @@
<includes>
<include>it.org.apache.struts2.showcase.*Test</include>
</includes>
<systemPropertyVariables>
<http.port>8090</http.port>
</systemPropertyVariables>
</configuration>
<executions>
<execution>
@@ -191,15 +199,14 @@
<stopKey>CTRL+C</stopKey>
<stopPort>8999</stopPort>
<systemProperties>
<systemProperty>
<name>log4j.configuration</name>
<value>file:${basedir}/src/main/resources/log4j2.xml</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>
@@ -230,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">
@@ -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>
@@ -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());
}
}
}
+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</version>
<version>6.1.2</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</version>
<version>6.1.2</version>
<packaging>pom</packaging>
<name>Struts 2 Bill of Materials</name>
@@ -44,7 +44,7 @@
</licenses>
<properties>
<struts-version.version>6.0.0</struts-version.version>
<struts-version.version>6.1.2</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>STRUTS_6_0_0</tag>
<tag>STRUTS_6_1_2</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</version>
<version>6.1.2</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</version>
<version>6.1.2</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>
+2 -2
View File
@@ -24,12 +24,12 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.0.0</version>
<version>6.1.2</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>
+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
+4 -7
View File
@@ -24,14 +24,14 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>6.0.0</version>
<version>6.1.2</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>
@@ -339,8 +337,7 @@
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<scope>compile</scope>
<optional>true</optional>
<scope>test</scope>
</dependency>
<!-- SLF4J support -->
@@ -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();
@@ -24,6 +24,7 @@ import com.opensymphony.xwork2.config.entities.InterceptorMapping;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.ConditionalInterceptor;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.interceptor.PreResultListener;
import com.opensymphony.xwork2.interceptor.WithLazyParams;
@@ -73,7 +74,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 +102,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 +112,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 +215,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 +249,12 @@ public class DefaultActionInvocation implements ActionInvocation {
if (interceptor instanceof WithLazyParams) {
interceptor = lazyParamInjector.injectParams(interceptor, interceptorMapping.getParams(), invocationContext);
}
resultCode = interceptor.intercept(DefaultActionInvocation.this);
if (interceptor instanceof ConditionalInterceptor) {
resultCode = executeConditional((ConditionalInterceptor) interceptor);
} else {
LOG.debug("Executing normal interceptor: {}", interceptorMapping.getName());
resultCode = interceptor.intercept(this);
}
} else {
resultCode = invokeActionOnly();
}
@@ -268,9 +274,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);
}
}
@@ -289,6 +293,16 @@ public class DefaultActionInvocation implements ActionInvocation {
return resultCode;
}
protected String executeConditional(ConditionalInterceptor conditionalInterceptor) throws Exception {
if (conditionalInterceptor.shouldIntercept(this)) {
LOG.debug("Executing conditional interceptor: {}", conditionalInterceptor.getClass().getSimpleName());
return conditionalInterceptor.intercept(this);
} else {
LOG.debug("Interceptor: {} is disabled, skipping to next", conditionalInterceptor.getClass().getSimpleName());
return this.invoke();
}
}
public String invokeActionOnly() throws Exception {
return invokeAction(getAction(), proxy.getConfig());
}
@@ -314,7 +328,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 +377,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 +478,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 +491,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());
@@ -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<>();
@@ -23,23 +23,39 @@ import com.opensymphony.xwork2.ActionInvocation;
/**
* Provides default implementations of optional lifecycle methods
*/
public abstract class AbstractInterceptor implements Interceptor {
public abstract class AbstractInterceptor implements ConditionalInterceptor {
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;
/**
* Allows to skip executing a given interceptor, just define {@code <param name="disabled">true</param>}
* or use other way to override interceptor's parameters, see
* <a href="https://struts.apache.org/core-developers/interceptors#interceptor-parameter-overriding">docs</a>.
* @param disable if set to true, execution of a given interceptor will be skipped.
*/
public void setDisabled(String disable) {
this.disabled = Boolean.parseBoolean(disable);
}
@Override
public boolean shouldIntercept(ActionInvocation invocation) {
return !this.disabled;
}
}
@@ -0,0 +1,39 @@
/*
* 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;
import com.opensymphony.xwork2.ActionInvocation;
/**
* A marking interface, when implemented allows to conditionally execute a given interceptor
* within the current action invocation.
*
* @since Struts 6.1.1
*/
public interface ConditionalInterceptor extends Interceptor {
/**
* Determines if a given interceptor should be executed in the current processing of action invocation.
*
* @param invocation current {@link ActionInvocation} to determine if the interceptor should be executed
* @return true if the given interceptor should be included in the current action invocation
* @since 6.1.1
*/
boolean shouldIntercept(ActionInvocation invocation);
}
@@ -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());
}
}
@@ -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);
}
}
}
@@ -82,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>());
}
/**
@@ -96,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<>());
@@ -108,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
@@ -262,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.
@@ -21,7 +21,7 @@ package com.opensymphony.xwork2.security;
/**
* Used across different places to check if given string is not excluded and is accepted
* @see <a href="https://securitylab.github.com/research/apache-struts-double-evaluation/">here</a>
* @since 2.6
* @since 6.0.0
*/
public interface NotExcludedAcceptedPatternsChecker extends ExcludedPatternsChecker, AcceptedPatternsChecker {
@@ -235,7 +235,7 @@ abstract class AbstractLocalizedTextProvider implements LocalizedTextProvider {
*
* @param bundleName The bundle to remove from the bundle map
*
* @deprecated A "no-op" since 2.6. Use {@link #clearBundle(java.lang.String, java.util.Locale)} instead.
* @deprecated A "no-op" since 6.0.0. Use {@link #clearBundle(java.lang.String, java.util.Locale)} instead.
*/
public void clearBundle(final String bundleName) {
LOG.debug("No-op. Did NOT clear resource bundle [{}], result: false.", bundleName);
@@ -248,7 +248,7 @@ abstract class AbstractLocalizedTextProvider implements LocalizedTextProvider {
* @param bundleName The bundle (combined with locale) to remove from the bundle map
* @param locale Provides the locale to combine with the bundle to get the key
*
* @since 2.6
* @since 6.0.0
*/
protected void clearBundle(final String bundleName, Locale locale) {
final String key = createMissesKey(String.valueOf(getCurrentThreadContextClassLoader().hashCode()), bundleName, locale);
@@ -266,7 +266,7 @@ abstract class AbstractLocalizedTextProvider implements LocalizedTextProvider {
* {@link AbstractLocalizedTextProvider} has already been used for failed bundle
* lookups of a given key, or some transitory state made a bundle lookup fail.
*
* @since 2.6
* @since 6.0.0
*/
protected void clearMissingBundlesCache() {
missingBundles.clear();
@@ -313,7 +313,7 @@ abstract class AbstractLocalizedTextProvider implements LocalizedTextProvider {
* The <code>clearCache()</code> methods have been available since Java 1.6, so
* it is anticipated the logic will work on any subsequent JVM versions.
*
* @since 2.6
* @since 6.0.0
*/
private void clearResourceBundleClassloaderCaches() {
final ClassLoader ccl = getCurrentThreadContextClassLoader();
@@ -436,7 +436,7 @@ abstract class AbstractLocalizedTextProvider implements LocalizedTextProvider {
*
* @param searchDefaultBundlesFirst provide {@link String} "true" or "false" to set the flag state accordingly.
*
* @since 2.6
* @since 6.0.0
*/
@Inject(value = StrutsConstants.STRUTS_I18N_SEARCH_DEFAULTBUNDLES_FIRST, required = false)
public void setSearchDefaultBundlesFirst(String searchDefaultBundlesFirst) {
@@ -28,9 +28,17 @@ import org.apache.struts2.StrutsException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.*;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.TransformerFactory;
@@ -48,28 +56,24 @@ import java.util.Map;
public class DomHelper {
private static final Logger LOG = LogManager.getLogger(DomHelper.class);
public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/";
public static Location getLocationObject(Element element) {
return LocationAttributes.getLocation(element);
}
/**
* Creates a W3C Document that remembers the location of each element in
* the source file. The location of element nodes can then be retrieved
* using the {@link #getLocationObject(Element)} method.
*
* @param inputSource the inputSource to read the document from
*
* @return the W3C Document
*/
public static Document parse(InputSource inputSource) {
return parse(inputSource, null);
}
/**
* Creates a W3C Document that remembers the location of each element in
* the source file. The location of element nodes can then be retrieved
@@ -77,17 +81,16 @@ public class DomHelper {
*
* @param inputSource the inputSource to read the document from
* @param dtdMappings a map of DTD names and public ids
*
* @return the W3C Document
*/
public static Document parse(InputSource inputSource, Map<String, String> dtdMappings) {
SAXParserFactory factory = null;
String parserProp = System.getProperty("xwork.saxParserFactory");
if (parserProp != null) {
try {
ObjectFactory objectFactory = ActionContext.getContext().getContainer().getInstance(ObjectFactory.class);
Class clazz = objectFactory.getClassInstance(parserProp);
Class<?> clazz = objectFactory.getClassInstance(parserProp);
factory = (SAXParserFactory) clazz.newInstance();
} catch (Exception e) {
LOG.error("Unable to load saxParserFactory set by system property 'xwork.saxParserFactory': {}", parserProp, e);
@@ -98,6 +101,13 @@ public class DomHelper {
factory = SAXParserFactory.newInstance();
}
try {
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
} catch (ParserConfigurationException | SAXNotRecognizedException | SAXNotSupportedException e) {
throw new StrutsException("Unable to disable resolving external entities!", e);
}
factory.setValidating((dtdMappings != null));
factory.setNamespaceAware(true);
@@ -107,22 +117,22 @@ public class DomHelper {
} catch (Exception ex) {
throw new StrutsException("Unable to create SAX parser", ex);
}
DOMBuilder builder = new DOMBuilder();
// Enhance the sax stream with location information
ContentHandler locationHandler = new LocationAttributes.Pipe(builder);
try {
parser.parse(inputSource, new StartHandler(locationHandler, dtdMappings));
} catch (Exception ex) {
throw new StrutsException(ex);
}
return builder.getDocument();
}
/**
* The <code>DOMBuilder</code> is a utility class that will generate a W3C
* DOM Document from SAX events.
@@ -130,27 +140,35 @@ public class DomHelper {
* @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
*/
static public class DOMBuilder implements ContentHandler {
/** The default transformer factory shared by all instances */
/**
* The default transformer factory shared by all instances
*/
protected static SAXTransformerFactory FACTORY;
/** The transformer factory */
/**
* The transformer factory
*/
protected SAXTransformerFactory factory;
/** The result */
/**
* The result
*/
protected DOMResult result;
/** The parentNode */
/**
* The parentNode
*/
protected Node parentNode;
protected ContentHandler nextHandler;
static {
String parserProp = System.getProperty("xwork.saxTransformerFactory");
if (parserProp != null) {
try {
ObjectFactory objectFactory = ActionContext.getContext().getContainer().getInstance(ObjectFactory.class);
Class clazz = objectFactory.getClassInstance(parserProp);
Class<?> clazz = objectFactory.getClassInstance(parserProp);
FACTORY = (SAXTransformerFactory) clazz.newInstance();
} catch (Exception e) {
LOG.error("Unable to load SAXTransformerFactory set by system property 'xwork.saxTransformerFactory': {}", parserProp, e);
@@ -158,7 +176,7 @@ public class DomHelper {
}
if (FACTORY == null) {
FACTORY = (SAXTransformerFactory) TransformerFactory.newInstance();
FACTORY = (SAXTransformerFactory) TransformerFactory.newInstance();
}
}
@@ -168,15 +186,16 @@ public class DomHelper {
public DOMBuilder() {
this((Node) null);
}
/**
* Construct a new instance of this DOMBuilder.
*
* @param factory the SAX transformer factory
*/
public DOMBuilder(SAXTransformerFactory factory) {
this(factory, null);
}
/**
* Constructs a new instance that appends nodes to the given parent node.
*
@@ -185,19 +204,19 @@ public class DomHelper {
public DOMBuilder(Node parentNode) {
this(null, parentNode);
}
/**
* Construct a new instance of this DOMBuilder.
*
* @param factory the SAX transformer factory
* @param factory the SAX transformer factory
* @param parentNode the parent node
*/
public DOMBuilder(SAXTransformerFactory factory, Node parentNode) {
this.factory = factory == null? FACTORY: factory;
this.factory = factory == null ? FACTORY : factory;
this.parentNode = parentNode;
setup();
}
/**
* Setup this instance transformer and result objects.
*/
@@ -215,7 +234,7 @@ public class DomHelper {
throw new StrutsException("Fatal-Error: Unable to get transformer handler", local);
}
}
/**
* Return the newly built Document.
*
@@ -230,60 +249,61 @@ public class DomHelper {
return this.result.getNode().getOwnerDocument();
}
}
public void setDocumentLocator(Locator locator) {
nextHandler.setDocumentLocator(locator);
}
public void startDocument() throws SAXException {
nextHandler.startDocument();
}
public void endDocument() throws SAXException {
nextHandler.endDocument();
}
public void startElement(String uri, String loc, String raw, Attributes attrs) throws SAXException {
nextHandler.startElement(uri, loc, raw, attrs);
}
public void endElement(String arg0, String arg1, String arg2) throws SAXException {
nextHandler.endElement(arg0, arg1, arg2);
}
public void startPrefixMapping(String arg0, String arg1) throws SAXException {
nextHandler.startPrefixMapping(arg0, arg1);
}
public void endPrefixMapping(String arg0) throws SAXException {
nextHandler.endPrefixMapping(arg0);
}
public void characters(char[] arg0, int arg1, int arg2) throws SAXException {
nextHandler.characters(arg0, arg1, arg2);
}
public void ignorableWhitespace(char[] arg0, int arg1, int arg2) throws SAXException {
nextHandler.ignorableWhitespace(arg0, arg1, arg2);
}
public void processingInstruction(String arg0, String arg1) throws SAXException {
nextHandler.processingInstruction(arg0, arg1);
}
public void skippedEntity(String arg0) throws SAXException {
nextHandler.skippedEntity(arg0);
}
}
public static class StartHandler extends DefaultHandler {
private ContentHandler nextHandler;
private Map<String, String> dtdMappings;
private final ContentHandler nextHandler;
private final Map<String, String> dtdMappings;
/**
* Create a filter that is chained to another handler.
* @param next the next handler in the chain.
*
* @param next the next handler in the chain.
* @param dtdMappings map of DTD mappings
*/
public StartHandler(ContentHandler next, Map<String, String> dtdMappings) {
@@ -295,12 +315,12 @@ public class DomHelper {
public void setDocumentLocator(Locator locator) {
nextHandler.setDocumentLocator(locator);
}
@Override
public void startDocument() throws SAXException {
nextHandler.startDocument();
}
@Override
public void endDocument() throws SAXException {
nextHandler.endDocument();
@@ -345,7 +365,7 @@ public class DomHelper {
public void skippedEntity(String arg0) throws SAXException {
nextHandler.skippedEntity(arg0);
}
@Override
public InputSource resolveEntity(String publicId, String systemId) {
if (dtdMappings != null && dtdMappings.containsKey(publicId)) {
@@ -356,7 +376,7 @@ public class DomHelper {
}
return null;
}
@Override
public void warning(SAXParseException exception) {
}
@@ -18,6 +18,8 @@
*/
package com.opensymphony.xwork2.util;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -57,7 +59,7 @@ import java.util.regex.Pattern;
* </table>
*
* <p>
* Excaping hasn't been implemented since the intended use of these patterns will be in matching URLs.
* Escaping hasn't been implemented since the intended use of these patterns will be in matching URLs.
* </p>
*
* @since 2.1
@@ -75,38 +77,47 @@ public class NamedVariablePatternMatcher implements PatternMatcher<NamedVariable
* @return The compiled pattern, null if the pattern was null or empty
*/
public CompiledPattern compilePattern(String data) {
StringBuilder regex = new StringBuilder();
if (data != null && data.length() > 0) {
List<String> varNames = new ArrayList<>();
StringBuilder varName = null;
for (int x=0; x<data.length(); x++) {
char c = data.charAt(x);
switch (c) {
case '{' : varName = new StringBuilder(); break;
case '}' : if (varName == null) {
throw new IllegalArgumentException("Mismatched braces in pattern");
}
varNames.add(varName.toString());
regex.append("([^/]+)");
varName = null;
break;
default : if (varName == null) {
regex.append(c);
} else {
varName.append(c);
}
}
}
return new CompiledPattern(Pattern.compile(regex.toString()), varNames);
if (StringUtils.isEmpty(data)) {
return null;
}
return null;
int len = data.length();
StringBuilder regex = new StringBuilder();
List<String> varNames = new ArrayList<>();
int s = 0;
while (s < len) {
int e = data.indexOf('{', s);
if (e < 0 && data.indexOf('}') > -1) {
throw new IllegalArgumentException("Missing openning '{' in [" + data + "]!");
}
if (e < 0) {
regex.append(Pattern.quote(data.substring(s)));
break;
}
if (e > s) {
regex.append(Pattern.quote(data.substring(s, e)));
}
s = e + 1;
e = data.indexOf('}', s);
if (e < 0) {
return null;
}
String varName = data.substring(s, e);
if (StringUtils.isEmpty(varName)) {
throw new IllegalArgumentException("Missing variable name in [" + data + "]!");
}
varNames.add(varName);
regex.append("([^/]+)");
s = e + 1;
}
return new CompiledPattern(Pattern.compile(regex.toString()), varNames);
}
/**
* Tries to process the data against the compiled expression. If successful, the map will contain
* the matched data, using the specified variable names in the original pattern.
*
* @param map The map of variables
* @param map The map of variables
* @param data The data to match
* @param expr The compiled pattern
* @return True if matched, false if not matched, the data was null, or the data was an empty string
@@ -116,8 +127,8 @@ public class NamedVariablePatternMatcher implements PatternMatcher<NamedVariable
if (data != null && data.length() > 0) {
Matcher matcher = expr.getPattern().matcher(data);
if (matcher.matches()) {
for (int x=0; x<expr.getVariableNames().size(); x++) {
map.put(expr.getVariableNames().get(x), matcher.group(x+1));
for (int x = 0; x < expr.getVariableNames().size(); x++) {
map.put(expr.getVariableNames().get(x), matcher.group(x + 1));
}
return true;
}
@@ -129,8 +140,8 @@ public class NamedVariablePatternMatcher implements PatternMatcher<NamedVariable
* Stores the compiled pattern and the variable names matches will correspond to.
*/
public static class CompiledPattern {
private Pattern pattern;
private List<String> variableNames;
private final Pattern pattern;
private final List<String> variableNames;
public CompiledPattern(Pattern pattern, List<String> variableNames) {
@@ -29,11 +29,11 @@ import java.util.List;
/**
* ClassFinder searches the classpath of the specified ClassLoaderInterface for
* packages, classes, constructors, methods, or fields with specific annotations.
*
* <p>
* For security reasons ASM is used to find the annotations. Classes are not
* loaded unless they match the requirements of a called findAnnotated* method.
* Once loaded, these classes are cached.
*
* <p>
* The getClassesNotLoaded() method can be used immediately after any find*
* method to get a list of classes which matched the find requirements (i.e.
* contained the annotation), but were unable to be loaded.
@@ -67,32 +67,32 @@ public interface ClassFinder {
List<Package> findAnnotatedPackages(Class<? extends Annotation> annotation);
List<Class> findAnnotatedClasses(Class<? extends Annotation> annotation);
List<Class<?>> findAnnotatedClasses(Class<? extends Annotation> annotation);
List<Method> findAnnotatedMethods(Class<? extends Annotation> annotation);
List<Constructor> findAnnotatedConstructors(Class<? extends Annotation> annotation);
List<Constructor<?>> findAnnotatedConstructors(Class<? extends Annotation> annotation);
List<Field> findAnnotatedFields(Class<? extends Annotation> annotation);
List<Class> findClassesInPackage(String packageName, boolean recursive);
List<Class<?>> findClassesInPackage(String packageName, boolean recursive);
List<Class> findClasses(Test<ClassInfo> test);
List<Class<?>> findClasses(Test<ClassInfo> test);
List<Class> findClasses();
List<Class<?>> findClasses();
ClassLoaderInterface getClassLoaderInterface();
public static interface Info {
interface Info {
String getName();
List<AnnotationInfo> getAnnotations();
}
public class AnnotationInfo extends Annotatable implements Info {
class AnnotationInfo extends Annotatable implements Info {
private final String name;
public AnnotationInfo(Annotation annotation){
public AnnotationInfo(Annotation annotation) {
this(annotation.getClass().getName());
}
@@ -116,7 +116,7 @@ public interface ClassFinder {
}
}
public class Annotatable {
class Annotatable {
private final List<AnnotationInfo> annotations = new ArrayList<>();
public Annotatable(AnnotatedElement element) {
@@ -134,12 +134,12 @@ public interface ClassFinder {
}
public class PackageInfo extends Annotatable implements Info {
class PackageInfo extends Annotatable implements Info {
private final String name;
private final ClassInfo info;
private final Package pkg;
public PackageInfo(Package pkg){
public PackageInfo(Package pkg) {
super(pkg);
this.pkg = pkg;
this.name = pkg.getName();
@@ -157,11 +157,11 @@ public interface ClassFinder {
}
public Package get() throws ClassNotFoundException {
return (pkg != null)?pkg:info.get().getPackage();
return (pkg != null) ? pkg : info.get().getPackage();
}
}
public class ClassInfo extends Annotatable implements Info {
class ClassInfo extends Annotatable implements Info {
private final String name;
private final List<MethodInfo> methods = new ArrayList<>();
private final List<MethodInfo> constructors = new ArrayList<>();
@@ -169,17 +169,18 @@ public interface ClassFinder {
private final List<String> interfaces = new ArrayList<>();
private final List<String> superInterfaces = new ArrayList<>();
private final List<FieldInfo> fields = new ArrayList<>();
private final ClassFinder classFinder;
private Class<?> clazz;
private ClassFinder classFinder;
private ClassNotFoundException notFound;
public ClassInfo(Class clazz, ClassFinder classFinder) {
public ClassInfo(Class<?> clazz, ClassFinder classFinder) {
super(clazz);
this.clazz = clazz;
this.classFinder = classFinder;
this.name = clazz.getName();
Class superclass = clazz.getSuperclass();
this.superType = superclass != null ? superclass.getName(): null;
Class<?> superclass = clazz.getSuperclass();
this.superType = superclass != null ? superclass.getName() : null;
}
public ClassInfo(String name, String superType, ClassFinder classFinder) {
@@ -188,8 +189,8 @@ public interface ClassFinder {
this.classFinder = classFinder;
}
public String getPackageName(){
return name.indexOf('.') > 0 ? name.substring(0, name.lastIndexOf('.')) : "" ;
public String getPackageName() {
return name.indexOf('.') > 0 ? name.substring(0, name.lastIndexOf('.')) : "";
}
public List<MethodInfo> getConstructors() {
@@ -220,7 +221,7 @@ public interface ClassFinder {
return superType;
}
public Class get() throws ClassNotFoundException {
public Class<?> get() throws ClassNotFoundException {
if (clazz != null) return clazz;
if (notFound != null) throw notFound;
try {
@@ -239,20 +240,20 @@ public interface ClassFinder {
}
}
public class MethodInfo extends Annotatable implements Info {
class MethodInfo extends Annotatable implements Info {
private final ClassInfo declaringClass;
private final String returnType;
private final String name;
private final List<List<AnnotationInfo>> parameterAnnotations = new ArrayList<>();
public MethodInfo(ClassInfo info, Constructor constructor){
public MethodInfo(ClassInfo info, Constructor<?> constructor) {
super(constructor);
this.declaringClass = info;
this.name = "<init>";
this.returnType = Void.TYPE.getName();
}
public MethodInfo(ClassInfo info, Method method){
public MethodInfo(ClassInfo info, Method method) {
super(method);
this.declaringClass = info;
this.name = method.getName();
@@ -297,12 +298,12 @@ public interface ClassFinder {
}
}
public class FieldInfo extends Annotatable implements Info {
class FieldInfo extends Annotatable implements Info {
private final String name;
private final String type;
private final ClassInfo declaringClass;
public FieldInfo(ClassInfo info, Field field){
public FieldInfo(ClassInfo info, Field field) {
super(field);
this.declaringClass = info;
this.name = field.getName();
@@ -222,7 +222,7 @@ import com.opensymphony.xwork2.util.ValueStack;
* &lt;!-- START SNIPPET: exShortCircuitingValidators --&gt;
* &lt;!DOCTYPE validators PUBLIC
* &quot;-//Apache Struts//XWork Validator 1.0.3//EN&quot;
* &quot;http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd&quot;&gt;
* &quot;https://struts.apache.org/dtds/xwork-validator-1.0.3.dtd&quot;&gt;
* &lt;validators&gt;
* &lt;!-- Field Validators for email field --&gt;
* &lt;field name=&quot;email&quot;&gt;
@@ -115,7 +115,7 @@ package com.opensymphony.xwork2.validator;
* <pre>
* <!-- START SNIPPET: exValidationRules1 -->
* &lt;!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"&gt;
"https://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"&gt;
* &lt;validators&gt;
* &lt;field name="bar"&gt;
* &lt;field-validator type="required"&gt;
@@ -43,7 +43,7 @@ public final class StrutsConstants {
* Note: This control flag may not be meaningful to all provider implementations, and should be false by default.
* </p>
*
* @since 2.6
* @since 6.0.0
*/
public static final String STRUTS_I18N_SEARCH_DEFAULTBUNDLES_FIRST = "struts.i18n.search.defaultbundles.first";
@@ -56,6 +56,9 @@ public final class StrutsConstants {
/** Comma separated list of patterns (java.util.regex.Pattern) to be excluded from Struts2-processing */
public static final String STRUTS_ACTION_EXCLUDE_PATTERN = "struts.action.excludePattern";
/** A custom separator used to split list of patterns (java.util.regex.Pattern) to be excluded from Struts2-processing */
public static final String STRUTS_ACTION_EXCLUDE_PATTERN_SEPARATOR = "struts.action.excludePattern.separator";
/** Whether to use the response encoding (JSP page encoding) for s:include tag processing (false - use STRUTS_I18N_ENCODING - by default) */
public static final String STRUTS_TAG_INCLUDETAG_USERESPONSEENCODING = "struts.tag.includetag.useResponseEncoding";
@@ -139,6 +142,9 @@ public final class StrutsConstants {
/** The maximize size of a multipart request (file upload) */
public static final String STRUTS_MULTIPART_MAXSIZE = "struts.multipart.maxSize";
/** The maximized number of files allowed to upload */
public static final String STRUTS_MULTIPART_MAXFILES = "struts.multipart.maxFiles";
/** The directory to use for storing uploaded files */
public static final String STRUTS_MULTIPART_SAVEDIR = "struts.multipart.saveDir";
@@ -254,7 +260,7 @@ public final class StrutsConstants {
* Specifies an OGNL expression cache factory implementation. A default implementation is provided, but
* could be replaced by a custom one if desired.
*
* @since 2.6
* @since 6.0.0
*/
public static final String STRUTS_OGNL_EXPRESSION_CACHE_FACTORY = "struts.ognl.expressionCacheFactory";
@@ -262,7 +268,7 @@ public final class StrutsConstants {
* Specifies an OGNL BeanInfo cache factory implementation. A default implementation is provided, but
* could be replaced by a custom one if desired.
*
* @since 2.6
* @since 6.0.0
*/
public static final String STRUTS_OGNL_BEANINFO_CACHE_FACTORY = "struts.ognl.beanInfoCacheFactory";
@@ -275,7 +281,7 @@ public final class StrutsConstants {
* For the optional LRU cache, once the maximum is reached, the least-recently-used (LRU) entry will be
* removed when a new entry needs to be added (cache is fully-utilized).
*
* @since 2.6
* @since 6.0.0
*/
public static final String STRUTS_OGNL_BEANINFO_CACHE_MAXSIZE = "struts.ognl.beanInfoCacheMaxSize";
@@ -287,32 +293,32 @@ public final class StrutsConstants {
* Note: When enabling LRU cache mode you must also set a maximum size (via {@link #STRUTS_OGNL_BEANINFO_CACHE_MAXSIZE})
* for it to be effective. Otherwise, there is no condition to evict a LRU entry (cache has no limit).
*
* @since 2.6
* @since 6.0.0
*/
public static final String STRUTS_OGNL_BEANINFO_CACHE_LRU_MODE = "struts.ognl.beanInfoCacheLRUMode";
/**
* Logs properties that are not found (very verbose)
* @since 2.6
* @since 6.0.0
*/
public static final String STRUTS_OGNL_LOG_MISSING_PROPERTIES = "struts.ognl.logMissingProperties";
/**
* Logs properties that are not found (very verbose)
* @deprecated as of 2.6. Use {@link #STRUTS_OGNL_LOG_MISSING_PROPERTIES} instead.
* @deprecated as of 6.0.0. Use {@link #STRUTS_OGNL_LOG_MISSING_PROPERTIES} instead.
*/
@Deprecated
public static final String STRUTS_LOG_MISSING_PROPERTIES = STRUTS_OGNL_LOG_MISSING_PROPERTIES;
/**
* Enables caching of parsed OGNL expressions
* @since 2.6
* @since 6.0.0
*/
public static final String STRUTS_OGNL_ENABLE_EXPRESSION_CACHE = "struts.ognl.enableExpressionCache";
/**
* Enables caching of parsed OGNL expressions
* @deprecated as of 2.6. Use {@link #STRUTS_OGNL_ENABLE_EXPRESSION_CACHE} instead.
* @deprecated as of 6.0.0. Use {@link #STRUTS_OGNL_ENABLE_EXPRESSION_CACHE} instead.
*/
public static final String STRUTS_ENABLE_OGNL_EXPRESSION_CACHE = STRUTS_OGNL_ENABLE_EXPRESSION_CACHE;
@@ -325,7 +331,7 @@ public final class StrutsConstants {
* For the optional LRU cache, once the maximum is reached, the least-recently-used (LRU) entry will be
* removed when a new entry needs to be added (cache is fully-utilized).
*
* @since 2.6
* @since 6.0.0
*/
public static final String STRUTS_OGNL_EXPRESSION_CACHE_MAXSIZE = "struts.ognl.expressionCacheMaxSize";
@@ -337,19 +343,19 @@ public final class StrutsConstants {
* Note: When enabling LRU cache mode you must also set a maximum size (via {@link #STRUTS_OGNL_EXPRESSION_CACHE_MAXSIZE})
* for it to be effective. Otherwise, there is no condition to evict a LRU entry (cache has no limit).
*
* @since 2.6
* @since 6.0.0
*/
public static final String STRUTS_OGNL_EXPRESSION_CACHE_LRU_MODE = "struts.ognl.expressionCacheLRUMode";
/**
* Enables evaluation of OGNL expressions
* @since 2.6
* @since 6.0.0
*/
public static final String STRUTS_OGNL_ENABLE_EVAL_EXPRESSION = "struts.ognl.enableEvalExpression";
/**
* Enables evaluation of OGNL expressions
* @deprecated as of 2.6. Use {@link #STRUTS_OGNL_ENABLE_EVAL_EXPRESSION} instead.
* @deprecated as of 6.0.0. Use {@link #STRUTS_OGNL_ENABLE_EVAL_EXPRESSION} instead.
*/
public static final String STRUTS_ENABLE_OGNL_EVAL_EXPRESSION = STRUTS_OGNL_ENABLE_EVAL_EXPRESSION;
@@ -376,7 +382,7 @@ public final class StrutsConstants {
public static final String STRUTS_CONVERTER_FILE_PROCESSOR = "struts.converter.file.processor";
public static final String STRUTS_CONVERTER_ANNOTATION_PROCESSOR = "struts.converter.annotation.processor";
public static final String STRUTS_CONVERTER_CREATOR = "struts.converter.creator";
public static final String STRUTS_CONVERTER_HOLDER = "struts..converter.holder";
public static final String STRUTS_CONVERTER_HOLDER = "struts.converter.holder";
public static final String STRUTS_EXPRESSION_PARSER = "struts.expression.parser";
@@ -398,7 +404,11 @@ public final class StrutsConstants {
/** Enables action: prefix */
public static final String STRUTS_MAPPER_ACTION_PREFIX_ENABLED = "struts.mapper.action.prefix.enabled";
/** Enables access to actions in other namespaces than current with action: prefix */
/**
* Enables access to actions in other namespaces than current with action: prefix
* @deprecated it will be removed soon, please refactor your application
*/
@Deprecated
public static final String STRUTS_MAPPER_ACTION_PREFIX_CROSSNAMESPACES = "struts.mapper.action.prefix.crossNamespaces";
public static final String DEFAULT_TEMPLATE_TYPE_CONFIG_KEY = "struts.ui.templateSuffix";
@@ -450,4 +460,12 @@ public final class StrutsConstants {
/** See {@link org.apache.struts2.components.Date#setDateFormatter(DateFormatter)} */
public static final String STRUTS_DATE_FORMATTER = "struts.date.formatter";
public static final String STRUTS_URL_QUERY_STRING_BUILDER = "struts.url.queryStringBuilder";
public static final String STRUTS_URL_QUERY_STRING_PARSER = "struts.url.queryStringParser";
public static final String STRUTS_URL_ENCODER = "struts.url.encoder";
public static final String STRUTS_URL_DECODER = "struts.url.decoder";
/** A global flag to set property {@link org.apache.struts2.components.Checkbox#setSubmitUnchecked(String)} */
public static final String STRUTS_UI_CHECKBOX_SUBMIT_UNCHECKED = "struts.ui.checkbox.submitUnchecked";
}
@@ -29,7 +29,7 @@ import java.util.Map;
* Please note that the {@link CookieInterceptor} needs to be
* activated to receive a cookies map.
*
* @since 2.6
* @since 6.0.0
*/
public interface CookiesAware {
/**
@@ -37,4 +37,4 @@ public interface CookiesAware {
* @param cookies the cookies
*/
void withCookies(Map<String, String> cookies);
}
}
@@ -28,7 +28,7 @@ import org.apache.struts2.dispatcher.HttpParameters;
* One common use for this is to have the action propagate parameters to internally instantiated data
* objects.
*
* @since 2.6
* @since 6.0.0
*/
public interface ParametersAware {
@@ -23,7 +23,7 @@ import javax.servlet.ServletContext;
/**
* For components that have a dependence on the Servlet context.
*
* @since 2.6
* @since 6.0.0
*/
public interface ServletContextAware {
@@ -18,13 +18,14 @@
*/
package org.apache.struts2.components;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.views.annotations.StrutsTag;
import org.apache.struts2.views.annotations.StrutsTagAttribute;
import com.opensymphony.xwork2.util.ValueStack;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* <!-- START SNIPPET: javadoc -->
@@ -46,15 +47,19 @@ import com.opensymphony.xwork2.util.ValueStack;
*
* <!-- END SNIPPET: example -->
* </pre>
*
*/
@StrutsTag(
name="checkbox",
tldTagClass="org.apache.struts2.views.jsp.ui.CheckboxTag",
description="Render a checkbox input field",
allowDynamicAttributes=true)
name = "checkbox",
tldTagClass = "org.apache.struts2.views.jsp.ui.CheckboxTag",
description = "Render a checkbox input field",
allowDynamicAttributes = true)
public class Checkbox extends UIBean {
final public static String TEMPLATE = "checkbox";
private static final String ATTR_SUBMIT_UNCHECKED = "submitUnchecked";
public static final String TEMPLATE = "checkbox";
private String submitUncheckedGlobal;
protected String fieldValue;
protected String submitUnchecked;
@@ -69,46 +74,45 @@ public class Checkbox extends UIBean {
protected void evaluateExtraParams() {
if (fieldValue != null) {
addParameter("fieldValue", findString(fieldValue));
addParameter(ATTR_FIELD_VALUE, findString(fieldValue));
} else {
addParameter("fieldValue", "true");
addParameter(ATTR_FIELD_VALUE, "true");
}
if (submitUnchecked != null) {
Object parsedValue = findValue(submitUnchecked, Boolean.class);
addParameter("submitUnchecked", parsedValue == null ? Boolean.valueOf(submitUnchecked) : parsedValue);
addParameter(ATTR_SUBMIT_UNCHECKED, parsedValue == null ? Boolean.valueOf(submitUnchecked) : parsedValue);
} else if (submitUncheckedGlobal != null) {
addParameter(ATTR_SUBMIT_UNCHECKED, Boolean.parseBoolean(submitUncheckedGlobal));
} else {
addParameter("submitUnchecked", false);
addParameter(ATTR_SUBMIT_UNCHECKED, false);
}
}
protected Class getValueClassType() {
@Override
protected Class<?> getValueClassType() {
return Boolean.class; // for checkboxes, everything needs to end up as a Boolean
}
@StrutsTagAttribute(description="The actual HTML value attribute of the checkbox.", defaultValue="true")
@Inject(value = StrutsConstants.STRUTS_UI_CHECKBOX_SUBMIT_UNCHECKED, required = false)
public void setSubmitUncheckedGlobal(String submitUncheckedGlobal) {
this.submitUncheckedGlobal = submitUncheckedGlobal;
}
@StrutsTagAttribute(description = "The actual HTML value attribute of the checkbox.", defaultValue = "true")
public void setFieldValue(String fieldValue) {
this.fieldValue = fieldValue;
}
@StrutsTagAttribute(description="If set to true, unchecked elements will be submitted with the form.", type="Boolean", defaultValue="false")
@StrutsTagAttribute(description = "If set to true, unchecked elements will be submitted with the form. " +
"Since Struts 6.1.1 you can use a constant \"" + StrutsConstants.STRUTS_UI_CHECKBOX_SUBMIT_UNCHECKED + "\" to set this attribute globally",
type = "Boolean", defaultValue = "false")
public void setSubmitUnchecked(String submitUnchecked) {
this.submitUnchecked = submitUnchecked;
}
/**
* Deprecated since 2.5.27
* @deprecated use {@link #setLabelPosition(String)} instead
*/
@Deprecated
@Override
@StrutsTagAttribute(description="(Deprecated) Define label position of form element (top/left), also 'right' is supported when using 'xhtml' theme")
public void setLabelposition(String labelPosition) {
super.setLabelPosition(labelPosition);
}
@Override
@StrutsTagAttribute(description="Define label position of form element (top/left), also 'right' is supported when using 'xhtml' theme")
@StrutsTagAttribute(description = "Define label position of form element (top/left), also 'right' is supported when using 'xhtml' theme")
public void setLabelPosition(String labelPosition) {
super.setLabelPosition(labelPosition);
}
@@ -538,7 +538,7 @@ public class Component {
* Override to set if body content should be HTML-escaped.
*
* @return always true (default) for this component.
* @since 2.6
* @since 6.0.0
*/
public boolean escapeHtmlBody() {
return escapeHtmlBody;
@@ -600,7 +600,7 @@ public class Component {
*
* @param expression of the component
* @return true|false
* @since 2.6
* @since 6.0.0
*/
protected boolean isAcceptableExpression(String expression) {
NotExcludedAcceptedPatternsChecker.IsAllowed isAllowed = notExcludedAcceptedPatterns.isAllowed(expression);
@@ -59,7 +59,7 @@ import java.util.List;
* </p>
*
* <p>
* <b>Note</b>: Since Struts 2.6 a new Java 8 API has been used to format the Date, it's based on
* <b>Note</b>: Since Struts 6.0.0 a new Java 8 API has been used to format the Date, it's based on
* <a href="https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html">DateTimeFormatter</a>
* which uses a bit different patterns.
* </p>
@@ -293,7 +293,9 @@ public class Date extends ContextBean {
final ZoneId tz = getTimeZone();
// find the name on the valueStack
Object dateObject = findValue(name);
if (dateObject instanceof java.util.Date) {
if (dateObject instanceof java.sql.Date) {
date = ((java.sql.Date) dateObject).toLocalDate().atStartOfDay(tz);
} else if (dateObject instanceof java.util.Date) {
date = ((java.util.Date) dateObject).toInstant().atZone(tz);
} else if (dateObject instanceof Calendar) {
date = ((Calendar) dateObject).toInstant().atZone(tz);
@@ -21,5 +21,7 @@ package org.apache.struts2.components;
import java.util.Map;
public interface ExtraParameterProvider {
public Map getExtraParameters();
Map<String, Object> getExtraParameters();
}

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