Compare commits

...

199 Commits

Author SHA1 Message Date
Musachy Barroso daa62ed42a [maven-release-plugin] copy for tag STRUTS_2_1_3
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3@729398 13f79535-47bb-0310-9956-ffa450edef68
2008-12-25 06:41:44 +00:00
Musachy Barroso 86b9438c95 [maven-release-plugin] prepare release STRUTS_2_1_3
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@729397 13f79535-47bb-0310-9956-ffa450edef68
2008-12-25 06:34:10 +00:00
Musachy Barroso 6aa62bed80 WW-2623 rollback maven release commit
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@729395 13f79535-47bb-0310-9956-ffa450edef68
2008-12-25 06:13:39 +00:00
Musachy Barroso 3607a431d8 [maven-release-plugin] prepare for next development iteration
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@729374 13f79535-47bb-0310-9956-ffa450edef68
2008-12-24 20:28:53 +00:00
Musachy Barroso 56e16de9c1 [maven-release-plugin] copy for tag STRUTS_2_1_3
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3@729373 13f79535-47bb-0310-9956-ffa450edef68
2008-12-24 20:28:36 +00:00
Musachy Barroso 25168e8db3 [maven-release-plugin] prepare release STRUTS_2_1_3
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@729372 13f79535-47bb-0310-9956-ffa450edef68
2008-12-24 20:20:05 +00:00
Musachy Barroso 93153bee52 WW-2623 rolling back some of the release changes...keep trying
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@729363 13f79535-47bb-0310-9956-ffa450edef68
2008-12-24 19:34:53 +00:00
Musachy Barroso c213d2fa6c WW-2623 de-attach assembly from packing phase
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@729358 13f79535-47bb-0310-9956-ffa450edef68
2008-12-24 19:08:36 +00:00
Musachy Barroso 23cb69662f WW-2623 comment IT tests out (using external plugin repo)
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@729230 13f79535-47bb-0310-9956-ffa450edef68
2008-12-24 04:59:40 +00:00
Musachy Barroso b9b7b14444 move jdk4 dependencies into the j4 profile
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@729221 13f79535-47bb-0310-9956-ffa450edef68
2008-12-24 04:34:47 +00:00
Musachy Barroso 198a388fb4 leave just tomcat5x on IT test for now (getting failures on linux)
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@729205 13f79535-47bb-0310-9956-ffa450edef68
2008-12-24 03:23:35 +00:00
Musachy Barroso 8014b1bdce WW-2623 update dependency on struts annotations
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@729196 13f79535-47bb-0310-9956-ffa450edef68
2008-12-24 02:37:34 +00:00
Musachy Barroso d2f09a8c54 WW-2872 Merge release enhancement branch into trunk
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@729136 13f79535-47bb-0310-9956-ffa450edef68
2008-12-23 21:52:06 +00:00
Musachy Barroso fe040f475b WW-2623 update version in site
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@729030 13f79535-47bb-0310-9956-ffa450edef68
2008-12-23 16:22:15 +00:00
David Newton a80c3217bc Removed override annotations.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@728752 13f79535-47bb-0310-9956-ffa450edef68
2008-12-22 19:38:13 +00:00
Musachy Barroso 3f39accc97 Add convention and javatemplates plugins to plugins modules, and assembly descriptor
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@728745 13f79535-47bb-0310-9956-ffa450edef68
2008-12-22 19:15:11 +00:00
Musachy Barroso 2bb92b0afc WW-2933 Move Java Templates plugin out of the sandbox
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@728738 13f79535-47bb-0310-9956-ffa450edef68
2008-12-22 18:32:23 +00:00
Musachy Barroso c3d9bd313b WW-2717 Upgrade tiles plugin to tiles 2.0.6
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@728727 13f79535-47bb-0310-9956-ffa450edef68
2008-12-22 17:09:38 +00:00
Nils-Helge Garli 71c6669067 WW-2932 Change setParameters back to String, String[]
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@728521 13f79535-47bb-0310-9956-ffa450edef68
2008-12-21 21:51:53 +00:00
Nils-Helge Garli f43d64ab54 WW-2874 Only log configuration exception as error if in devMode.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@728486 13f79535-47bb-0310-9956-ffa450edef68
2008-12-21 20:04:33 +00:00
Nils-Helge Garli 6d189742cd WW-2720 Adding the old stack to the top of the stack. Patch by Herbert Poul. Thanks.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@728480 13f79535-47bb-0310-9956-ffa450edef68
2008-12-21 19:27:22 +00:00
Musachy Barroso 254df5ef9b WW-2931 Make convention plugin reload the configuration when a class that contains actions changes in the file system
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@728469 13f79535-47bb-0310-9956-ffa450edef68
2008-12-21 18:30:18 +00:00
Rainer Hermanns 6103113e9b WW-2623 Upgrading xwork dep to the just released 2.1.2 version
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@728457 13f79535-47bb-0310-9956-ffa450edef68
2008-12-21 16:29:03 +00:00
Musachy Barroso 8d6b944946 WW-2930 Apply css and style attributes to ul tags, instead if li in actionerror and actionmessage
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@728303 13f79535-47bb-0310-9956-ffa450edef68
2008-12-20 17:05:17 +00:00
Musachy Barroso a83155009c Remove codebehind settings
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@728042 13f79535-47bb-0310-9956-ffa450edef68
2008-12-19 15:04:09 +00:00
Musachy Barroso f41ffc2421 WW-2926 Port rest-showcase to use convention plugin
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@728041 13f79535-47bb-0310-9956-ffa450edef68
2008-12-19 15:03:25 +00:00
Musachy Barroso 33113a90c6 WW-2926 Port rest-showcase to use convention plugin
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@727908 13f79535-47bb-0310-9956-ffa450edef68
2008-12-19 03:15:23 +00:00
Musachy Barroso 7b0ae6e96a Update test for changes in xwork
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@727840 13f79535-47bb-0310-9956-ffa450edef68
2008-12-18 22:19:49 +00:00
Musachy Barroso d4e3b19c9f Add error field names to the available params
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@727803 13f79535-47bb-0310-9956-ffa450edef68
2008-12-18 19:55:40 +00:00
Musachy Barroso 7dafbb773f WW-2732 Add a "searchValueStack" to "text" tag
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@727558 13f79535-47bb-0310-9956-ffa450edef68
2008-12-17 22:38:40 +00:00
Musachy Barroso 5ebf37efba WW-2732 Document that the Text tag will search the stack if a key is not found on a resource
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@727533 13f79535-47bb-0310-9956-ffa450edef68
2008-12-17 22:05:17 +00:00
Musachy Barroso f8166d5e8b Add convention to plugins modules and assembly
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@727472 13f79535-47bb-0310-9956-ffa450edef68
2008-12-17 19:06:53 +00:00
Musachy Barroso 352fdb5300 WW-2922 move convention plugin out of sandbox
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@727418 13f79535-47bb-0310-9956-ffa450edef68
2008-12-17 15:39:34 +00:00
Musachy Barroso 9215250aad XW-640 Support multiple unknown handlers
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@727135 13f79535-47bb-0310-9956-ffa450edef68
2008-12-16 20:39:32 +00:00
Musachy Barroso 030c7e0193 XW-640 Support multiple unknown handlers
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@727100 13f79535-47bb-0310-9956-ffa450edef68
2008-12-16 17:47:24 +00:00
Musachy Barroso 7c795d7366 WW-2878 install sources by default
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@726719 13f79535-47bb-0310-9956-ffa450edef68
2008-12-15 15:45:13 +00:00
Musachy Barroso bbdbe79929 WW-2824 refactored altSyntax expression code
thanks to Gabriel Belingueres for patch.

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@726715 13f79535-47bb-0310-9956-ffa450edef68
2008-12-15 15:39:15 +00:00
Musachy Barroso f4d486dbd3 Output "onreset" properly
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@726337 13f79535-47bb-0310-9956-ffa450edef68
2008-12-14 02:23:24 +00:00
Musachy Barroso c502db56c1 WW-2796 Remove reference to deprecated velocity constructor
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@725742 13f79535-47bb-0310-9956-ffa450edef68
2008-12-11 17:16:46 +00:00
Musachy Barroso 38615eb398 WW-2913 fix layout for showcase, tested on FF 3, IE 7 and IE 6. It ain't pretty but it works.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@724847 13f79535-47bb-0310-9956-ffa450edef68
2008-12-09 19:36:00 +00:00
Nils-Helge Garli 6e1aa0784b WW-2751 Fixed containsKey for SessionMap. Patch by Ian Robinson.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@724839 13f79535-47bb-0310-9956-ffa450edef68
2008-12-09 19:19:19 +00:00
Nils-Helge Garli 9fa90cb8b4 Updated test resource to fix failing FormTagTest
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@724838 13f79535-47bb-0310-9956-ffa450edef68
2008-12-09 19:13:45 +00:00
Musachy Barroso 2291033724 WW-2752 fix resource path in the documentation
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@724514 13f79535-47bb-0310-9956-ffa450edef68
2008-12-08 22:17:52 +00:00
Musachy Barroso 0da2e1bd1b WW-2748 call "i18n" before "prepare" in default stack
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@724495 13f79535-47bb-0310-9956-ffa450edef68
2008-12-08 21:41:19 +00:00
Musachy Barroso 7b94ab8e8d WW-2730 remove redundant "return true" from the form tag's "onsubmit" attribute
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@724471 13f79535-47bb-0310-9956-ffa450edef68
2008-12-08 20:22:33 +00:00
Nils-Helge Garli 0d5093796d Forgot to commit the updated test...
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@724183 13f79535-47bb-0310-9956-ffa450edef68
2008-12-07 19:48:56 +00:00
Nils-Helge Garli 75c4c5ee25 WW-2862 Added pass through to servlet renderer when specified or not in a portlet context.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@724182 13f79535-47bb-0310-9956-ffa450edef68
2008-12-07 19:32:45 +00:00
Wesley Wannemacher b90c0c8e60 Cleanup in JakartaMultiPartRequest, using generics. Per WW-2908, thanks for the patch Mathias
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@724074 13f79535-47bb-0310-9956-ffa450edef68
2008-12-07 04:51:34 +00:00
Wesley Wannemacher f207ed6978 broken url WW-2623
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@724071 13f79535-47bb-0310-9956-ffa450edef68
2008-12-07 04:47:19 +00:00
Nils-Helge Garli 268854f353 WW-2800 Added setters for response, request and context.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@724030 13f79535-47bb-0310-9956-ffa450edef68
2008-12-06 19:32:29 +00:00
Wesley Wannemacher 6c24b2e73c ServletUrlRenderer patch to fix s:form tag when using dynamic method invocation. Per WW-2727 and WW-2768, thanks for the patch Lukasz Racon
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@723948 13f79535-47bb-0310-9956-ffa450edef68
2008-12-06 04:53:06 +00:00
Musachy Barroso d47688da3e WW-2597 Update tld version to match xsd schema
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@723018 13f79535-47bb-0310-9956-ffa450edef68
2008-12-03 19:13:28 +00:00
Musachy Barroso 08cd7213d4 WW-2905 Synchronize on HttpSession rather than session map from context
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@722961 13f79535-47bb-0310-9956-ffa450edef68
2008-12-03 16:38:57 +00:00
Musachy Barroso 7ebff0ee12 WW-2901 Set the default includeParams to "none" (is currently "get")
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@722957 13f79535-47bb-0310-9956-ffa450edef68
2008-12-03 16:24:56 +00:00
Musachy Barroso ae2f937761 WW-2580 Add filename argument to acceptFile method in FileUploadInterceptor. Unused overload of acceptFile was also removed.
Thanks to Jelmer Kuperus for the patch (applied with some modifications).

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@722956 13f79535-47bb-0310-9956-ffa450edef68
2008-12-03 16:23:43 +00:00
Musachy Barroso 2e82cb684c Update type of tag attribute "resultsLimit" for autocompleter
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@722904 13f79535-47bb-0310-9956-ffa450edef68
2008-12-03 14:34:23 +00:00
Musachy Barroso 6e131b75f3 WW-2902 Use real HttpSession in synchronized block
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@722576 13f79535-47bb-0310-9956-ffa450edef68
2008-12-02 19:13:26 +00:00
Wesley Wannemacher c8397a1188 incorporating Concurrency API. Per WW-2880, thanks for the patch Mathias Bogaert
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@722386 13f79535-47bb-0310-9956-ffa450edef68
2008-12-02 06:41:52 +00:00
Wesley Wannemacher aebc654a59 moving CSS class declaration to the UL tag to make styling more flexible. Per WW-2655
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@722375 13f79535-47bb-0310-9956-ffa450edef68
2008-12-02 05:19:57 +00:00
David Newton 4bc9f8f62d Updated URL component's default value documentation to reflect WW-2901 change; now "none".
I don't think I like this lack of cohesion in cases like this; if the default value is coming from a default configuration file then documenting it manually with @StrutsTagAttribute seems dangerous and potentially misleading.

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@722331 13f79535-47bb-0310-9956-ffa450edef68
2008-12-02 02:04:42 +00:00
David Newton 157eacdecd Includes test update; changing struts.properties requires non-intuitive test change :/
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@722328 13f79535-47bb-0310-9956-ffa450edef68
2008-12-02 01:56:24 +00:00
Musachy Barroso 768f3973c2 WW-2671 Add fieldName attribute to FieldErrorTag
Thanks to David Evans for the patch

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@722198 13f79535-47bb-0310-9956-ffa450edef68
2008-12-01 19:49:00 +00:00
Musachy Barroso 10e69d7d93 WW-255 Add escapeJavaScript attribute to propertyTag
Thanks to Jelmer Kuperus for patch.

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@722159 13f79535-47bb-0310-9956-ffa450edef68
2008-12-01 18:24:52 +00:00
Musachy Barroso 718fa71af1 WW-2625 Add allowCaching attribute to StreamResult
Thanks to Al Sutton for the patch.

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@722124 13f79535-47bb-0310-9956-ffa450edef68
2008-12-01 16:47:29 +00:00
Wesley Wannemacher fbaccd65ec changing MakeIterator to support Iterable instead of Collection
per WW-2887, thanks for the patch Mathias Bogaert

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@721947 13f79535-47bb-0310-9956-ffa450edef68
2008-12-01 02:25:47 +00:00
David Newton a3ee86862f Fix for WW-2889 Use StringBuilder instead of StringBuffer; UrlHelper:r720222 change.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@721838 13f79535-47bb-0310-9956-ffa450edef68
2008-11-30 16:04:46 +00:00
Musachy Barroso 9407fe5e30 WW-2226 resultsLimit attribute set to -1 in autocompleter tag is ignored. Set the type of resultsLimit to Integer
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@720918 13f79535-47bb-0310-9956-ffa450edef68
2008-11-26 17:06:40 +00:00
Musachy Barroso 5ecfccb0ed WW-2891 Replace deprecated operators in FreeMarker (just ?exists on this commit)
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@720258 13f79535-47bb-0310-9956-ffa450edef68
2008-11-24 19:05:16 +00:00
Musachy Barroso f6bba24d44 WW-2888 Cleanup of FileUploadInterceptor (added some generics and use XWork's text parsing)
Some unboxing also removed

Thanks to Mathias Bogaert for patch

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@720232 13f79535-47bb-0310-9956-ffa450edef68
2008-11-24 17:12:58 +00:00
Musachy Barroso 4f46d2abb2 WW-2889 Use StringBuilder instead of StringBuffer
Thanks to Mathias Bogaert for patch

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@720222 13f79535-47bb-0310-9956-ffa450edef68
2008-11-24 16:41:07 +00:00
Nils-Helge Garli 5397257cfb WW-2846 Nested params should now work properly in portlets
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@719714 13f79535-47bb-0310-9956-ffa450edef68
2008-11-21 21:09:13 +00:00
Nils-Helge Garli ad49562c48 WW-2783 Evaluate anchor. Fix suggested by Ralf Fischer.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@719704 13f79535-47bb-0310-9956-ffa450edef68
2008-11-21 20:37:49 +00:00
Musachy Barroso dbedc4fae4 WW-2882 Make fields protected
Thanks to Mathias Bogaert for patch

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@719672 13f79535-47bb-0310-9956-ffa450edef68
2008-11-21 18:57:55 +00:00
Musachy Barroso 9fb18e8c0e WW-2879 Use Concurrent API in FreemarkerTemplateEngine
thanks to Mathias Bogaert for the patch

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@719643 13f79535-47bb-0310-9956-ffa450edef68
2008-11-21 17:13:32 +00:00
Musachy Barroso e135288df6 WW-2610 dont set "style" attribute, if there are field errors and cssClass was set. Tests added.
Thanks to Gabriel Belingueres for the patch

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@719021 13f79535-47bb-0310-9956-ffa450edef68
2008-11-19 18:47:34 +00:00
Musachy Barroso 6199a40267 WW-2071 UIBean.end does not fail when an exception happens. Throw a runtime exception, instead of just logging it
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@718748 13f79535-47bb-0310-9956-ffa450edef68
2008-11-18 22:43:53 +00:00
Musachy Barroso 7ea81313d0 WW-2246 always wrap the writer passed to FreeMarker to prevent exception when using custom tags
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@718652 13f79535-47bb-0310-9956-ffa450edef68
2008-11-18 17:04:01 +00:00
Musachy Barroso f7a7d62a87 Fix for FTL use (output was empty)
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@718354 13f79535-47bb-0310-9956-ffa450edef68
2008-11-17 20:06:38 +00:00
Nils-Helge Garli 96683b99fc Reverting change
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@701674 13f79535-47bb-0310-9956-ffa450edef68
2008-10-04 17:14:20 +00:00
Nils-Helge Garli bccea9737c Trying different things to fix bamboo error
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@701671 13f79535-47bb-0310-9956-ffa450edef68
2008-10-04 17:04:36 +00:00
Nils-Helge Garli 7ba66cfd4c Touching file to trigger build
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@701661 13f79535-47bb-0310-9956-ffa450edef68
2008-10-04 16:25:01 +00:00
David Newton 2cf1f83121 Backing out premature change :(
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@692670 13f79535-47bb-0310-9956-ffa450edef68
2008-09-06 15:47:06 +00:00
David Newton f537d7b33b Changed includeParams default to "none".
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@692662 13f79535-47bb-0310-9956-ffa450edef68
2008-09-06 15:27:21 +00:00
David Newton 3ea1503324 Added check for element's existence when adding error class to field label; it was broken when an element used "simple" theme. Gotta change some client-side validation stuff.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@692578 13f79535-47bb-0310-9956-ffa450edef68
2008-09-05 23:30:16 +00:00
Nils-Helge Garli 502d7f3987 Doesn't work right now
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@691544 13f79535-47bb-0310-9956-ffa450edef68
2008-09-03 08:38:49 +00:00
Musachy Barroso 1f1c996eb1 WW-2779 Directory traversal vulnerability while serving static content
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@688095 13f79535-47bb-0310-9956-ffa450edef68
2008-08-22 15:22:56 +00:00
René Gielen 3a08768f32 Javadoc fix
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@687847 13f79535-47bb-0310-9956-ffa450edef68
2008-08-21 20:16:02 +00:00
Musachy Barroso b8c94a58b9 Add content loader test
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@687805 13f79535-47bb-0310-9956-ffa450edef68
2008-08-21 17:11:37 +00:00
Musachy Barroso b2c5190d52 Add content loader test
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@687804 13f79535-47bb-0310-9956-ffa450edef68
2008-08-21 17:11:16 +00:00
Musachy Barroso 04fcefa44b WW-2779 Directory traversal vulnerability while serving static content
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@687425 13f79535-47bb-0310-9956-ffa450edef68
2008-08-20 18:59:01 +00:00
Musachy Barroso e40a8e540b WW-2381 Destroy method of Interceptor is never called by Struts
Patch provided by Décio Heinzelmann Luckow

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@686328 13f79535-47bb-0310-9956-ffa450edef68
2008-08-15 19:19:07 +00:00
David Newton dcf5d45fde Minor JavaDoc change; the perils of ^V. Or Cmd-V for those of us with Macs.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@684566 13f79535-47bb-0310-9956-ffa450edef68
2008-08-10 18:19:28 +00:00
Musachy Barroso dea5b76acc Organize imports (bamboo failing on one of them that is not used)
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@682419 13f79535-47bb-0310-9956-ffa450edef68
2008-08-04 15:23:34 +00:00
Musachy Barroso 73df90c49f XW-641 XWork ParameterInterceptors bypass (OGNL statement execution)
Update tests

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@682411 13f79535-47bb-0310-9956-ffa450edef68
2008-08-04 14:55:30 +00:00
Musachy Barroso 9e5c40482e Fix example (and build)
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@682390 13f79535-47bb-0310-9956-ffa450edef68
2008-08-04 13:51:06 +00:00
Musachy Barroso 68d84d684d Add some integration tests
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@681928 13f79535-47bb-0310-9956-ffa450edef68
2008-08-02 02:34:11 +00:00
Donald J. Brown 18724a34cb Making the base url of the integration tests configurable
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@681695 13f79535-47bb-0310-9956-ffa450edef68
2008-08-01 13:56:28 +00:00
Musachy Barroso 4db454df70 WW-1677 <s:submit type="button" does not render the enclosed content inside properly
${parameters.body} is not only the body of the tag but also the html opening of the tag, so it cannot be escaped

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@681101 13f79535-47bb-0310-9956-ffa450edef68
2008-07-30 16:06:15 +00:00
Musachy Barroso b57ec7454a WW-1677 <s:submit type="button" does not render the enclosed content inside properly
${parameters.body} is not only the body of the tag but also the html opening of the tag, so it cannot be escaped

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@680739 13f79535-47bb-0310-9956-ffa450edef68
2008-07-29 15:39:34 +00:00
Donald J. Brown 3d0cd93746 Adding a few functional tests and test runs against multiple servers using my new maven-itblast-plugin
WW-2471


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@680707 13f79535-47bb-0310-9956-ffa450edef68
2008-07-29 14:17:17 +00:00
Donald J. Brown 32683d3acd Updating to latest struts annotations to fix invalid tld issue
WW-2740


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@680693 13f79535-47bb-0310-9956-ffa450edef68
2008-07-29 13:38:35 +00:00
Donald J. Brown 6070c4ff6d Better handle ;jsessionid in rest plugin
WW-2328


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@680686 13f79535-47bb-0310-9956-ffa450edef68
2008-07-29 12:53:18 +00:00
Musachy Barroso abef0ef66f WW-2231 autocompleter: bug in autocompleter.ftl at disabled="false"
I also checked core tags and they are good.

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@678836 13f79535-47bb-0310-9956-ffa450edef68
2008-07-22 18:00:30 +00:00
Musachy Barroso 708019a721 WW-2271 Bogus documentation of scope interceptor
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@678526 13f79535-47bb-0310-9956-ffa450edef68
2008-07-21 18:54:57 +00:00
Musachy Barroso be385243cd WW-1677 <s:submit type="button" does not render the enclosed content inside properly
Fix build problem

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@678154 13f79535-47bb-0310-9956-ffa450edef68
2008-07-19 13:14:31 +00:00
Musachy Barroso 92c1e7e8ff WW-1677 <s:submit type="button" does not render the enclosed content inside properly
Thanks to Eric Martin and Mike Bydalek for the patch.

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@678079 13f79535-47bb-0310-9956-ffa450edef68
2008-07-19 00:08:47 +00:00
Nils-Helge Garli b0666945bb WW-2622 Added missing inject
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@677903 13f79535-47bb-0310-9956-ffa450edef68
2008-07-18 13:36:37 +00:00
Musachy Barroso 568ea0598d WW-2721 Ajax Validation does not work with ModelDriven Actions
Thanks to Wolfgang Schröder for the patch

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@677429 13f79535-47bb-0310-9956-ffa450edef68
2008-07-16 21:01:56 +00:00
Musachy Barroso bead99cf95 WW-2168 Javascript validation displays error messages, cancel does not clear them
This will only take effect in the "xhtml" or "css_xhtml" when a form has validate="true"

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@676692 13f79535-47bb-0310-9956-ffa450edef68
2008-07-14 19:01:44 +00:00
Musachy Barroso 0a0c3293ed WW-1892 Two tooltips are displayed on IE 7 when using javascript tooltips
Thanks to Jose Ignacio Gil Jaldo  for the patch.

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@676628 13f79535-47bb-0310-9956-ffa450edef68
2008-07-14 15:48:17 +00:00
Donald J. Brown f2ff3a81d2 Adding test for missing xslt include
WW-2561


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@676575 13f79535-47bb-0310-9956-ffa450edef68
2008-07-14 12:50:38 +00:00
Donald J. Brown 0b8fcdf609 Adding ability to customize validation failure status code, refactoring content type handler manager into
interface and impl for easier testing
WW-2358


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@676195 13f79535-47bb-0310-9956-ffa450edef68
2008-07-12 15:55:58 +00:00
Donald J. Brown bc7ae89de3 Adding override annotations
WW-2691


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@676182 13f79535-47bb-0310-9956-ffa450edef68
2008-07-12 14:43:27 +00:00
Donald J. Brown a5ae3c599b Ensuring action context is setup by prepare dispatcher ahead of action execution
WW-2079


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@676181 13f79535-47bb-0310-9956-ffa450edef68
2008-07-12 14:40:27 +00:00
Donald J. Brown a4ee229d43 Adding test to ensure action tags are executed without the method from the URI polluting the result
WW-2290


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@676179 13f79535-47bb-0310-9956-ffa450edef68
2008-07-12 13:55:51 +00:00
Wesley Wannemacher 60eddc6f17 quick fix, broken build, ref WW-2716
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@675438 13f79535-47bb-0310-9956-ffa450edef68
2008-07-10 04:37:34 +00:00
Donald J. Brown 78e853bcb3 Repackaging new dispatchers, adding "unsupported" servlet dispatcher, fixing a spring issue where
it was needlessly tied to WebApplicationContext and a rest issue where the autowiring of returned
result objects wasn't copied into the rest plugin from xwork
WW-2193


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@674498 13f79535-47bb-0310-9956-ffa450edef68
2008-07-07 14:10:42 +00:00
Donald J. Brown b43e67584c Choosing better package name for next-generation dispatchers
WW-2193


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@674254 13f79535-47bb-0310-9956-ffa450edef68
2008-07-06 03:54:31 +00:00
Jeromy Evans 828b457ad6 WW-2706 Changed system.out to LOG.debug in codebehind's ClasspathPackageProvider
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@673304 13f79535-47bb-0310-9956-ffa450edef68
2008-07-02 07:12:50 +00:00
Jeromy Evans 0f08615c62 WW-2702 Codebehind unknown handler can now instantiate PackageConfig.defaultClassRef instead of only ActionSupport.
Rest plugin provides defaultClassImpl impl with index() method to support unknown actions.


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@673081 13f79535-47bb-0310-9956-ffa450edef68
2008-07-01 13:49:01 +00:00
Jeromy Evans 48dbfd8104 WW-2701 Improved CodebehindUnknownHandler use of classpath leading slash & path concatenation
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@672982 13f79535-47bb-0310-9956-ffa450edef68
2008-07-01 03:48:03 +00:00
Jeromy Evans f36ac2fcc0 WW-2641 Separated the request and response ContentTypeHandlers. Added x-www-form-urlencoded handler
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@672721 13f79535-47bb-0310-9956-ffa450edef68
2008-06-30 07:54:36 +00:00
Donald J. Brown 122ab67bc1 Adding new filter tests, deprecating old filter
WW-2193


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@672473 13f79535-47bb-0310-9956-ffa450edef68
2008-06-28 07:25:05 +00:00
Nils-Helge Garli 108a676ee0 WW-2619 Added unicode escape codes
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@671184 13f79535-47bb-0310-9956-ffa450edef68
2008-06-24 14:22:29 +00:00
Nils-Helge Garli 663365f156 WW-2619 Escaped unicode characters
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@671178 13f79535-47bb-0310-9956-ffa450edef68
2008-06-24 14:10:31 +00:00
Nils-Helge Garli 2fd890506d WW-2619 Fixed some weird characters...
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@671175 13f79535-47bb-0310-9956-ffa450edef68
2008-06-24 14:04:22 +00:00
Nils-Helge Garli c5a87c85b8 WW-2622,WW-2537 Remove hard coding of .action extension and added use of generics.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@671156 13f79535-47bb-0310-9956-ffa450edef68
2008-06-24 12:33:59 +00:00
Rainer Hermanns f7f3deedc8 WW-2878 portlet dispatching after action phase renders in wrong namespace
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670542 13f79535-47bb-0310-9956-ffa450edef68
2008-06-23 12:31:51 +00:00
Musachy Barroso 295150b5e9 WW-2601 Tabindex not working on autocompleter
also fixed tabindex for datepicker 

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670371 13f79535-47bb-0310-9956-ffa450edef68
2008-06-22 15:28:01 +00:00
Donald J. Brown 1fe337bb3d Changing filter to new struts filter
WW-2193


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670311 13f79535-47bb-0310-9956-ffa450edef68
2008-06-22 04:05:11 +00:00
Donald J. Brown 8d395ee27c Adding new filter to rest showcase
WW-2193


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670310 13f79535-47bb-0310-9956-ffa450edef68
2008-06-22 04:03:27 +00:00
Donald J. Brown 8ced5d0f1f Adding new filter to showcase
WW-2193


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670309 13f79535-47bb-0310-9956-ffa450edef68
2008-06-22 04:01:01 +00:00
Donald J. Brown b69f71aa2e Better error handling in new filters, added autowire respect property to default list
WW-2193


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670308 13f79535-47bb-0310-9956-ffa450edef68
2008-06-22 04:00:43 +00:00
Donald J. Brown a4b404075c Converted web.xml to use new filter, added default action
WW-2193


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670307 13f79535-47bb-0310-9956-ffa450edef68
2008-06-22 04:00:00 +00:00
Musachy Barroso 0d72932171 Sync custom build with latest changes in javascript code
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670231 13f79535-47bb-0310-9956-ffa450edef68
2008-06-21 17:14:19 +00:00
Donald J. Brown 8f5e79d987 First cut at a new filter strategy
WW-2193


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670209 13f79535-47bb-0310-9956-ffa450edef68
2008-06-21 15:13:59 +00:00
Musachy Barroso 37371b3684 WW-2669 Autocompleter options list element does not resize correctly
thanks to Aner Perez for the patch

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670200 13f79535-47bb-0310-9956-ffa450edef68
2008-06-21 14:04:10 +00:00
Musachy Barroso cc68365a5f WW-2688 Ignore parameters that start with 'struts.'
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670197 13f79535-47bb-0310-9956-ffa450edef68
2008-06-21 13:47:47 +00:00
Rainer Hermanns 3fb3be2532 WW-2240 FileUploadInterceptor causes null pointer exception
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670196 13f79535-47bb-0310-9956-ffa450edef68
2008-06-21 13:34:53 +00:00
Rainer Hermanns e839817c48 WW-2678 portlet dispatching after action phase renders in wrong namespace
o applied slightly modified patch submitted by Herbert Poul

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670193 13f79535-47bb-0310-9956-ffa450edef68
2008-06-21 13:01:53 +00:00
Donald J. Brown dad9f86de4 Fixing test that breaks in Java 6 WW-2537
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670174 13f79535-47bb-0310-9956-ffa450edef68
2008-06-21 10:16:19 +00:00
Rainer Hermanns 51ef883a72 WW-2687 Upgrade JasperReports dependancy to 3.0.0
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670173 13f79535-47bb-0310-9956-ffa450edef68
2008-06-21 10:14:50 +00:00
Rainer Hermanns d733e103ba WW-2637 add timezone support to Jasper Reports Plugin
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670172 13f79535-47bb-0310-9956-ffa450edef68
2008-06-21 10:12:56 +00:00
Rainer Hermanns 0a23cd4ec5 WW-2537 Fix generics in all codebase
Starting with Java5 enhancements in S2. 
This patch applies required changes to S2 related to the "generified xwork"

XWork Java5 enhancements 
o added generics where possible
o use parameterizes Collection classes where possible
o converted for to for-each loops
o optimized imports
o updated tests
o aligned parameter types with Struts2
o fixed some minor bugs

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670170 13f79535-47bb-0310-9956-ffa450edef68
2008-06-21 09:40:34 +00:00
Donald J. Brown 59d65a0aa7 Fixing struts-annotations to work now
WW-2132


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670137 13f79535-47bb-0310-9956-ffa450edef68
2008-06-21 04:35:43 +00:00
David Newton 2a7a22b206 Upcased "-Disposition" as per RFC-1896/Bob's suggestion.
http://www.ietf.org/rfc/rfc1806.txt


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@670109 13f79535-47bb-0310-9956-ffa450edef68
2008-06-21 00:53:24 +00:00
Donald J. Brown 561b08386a Updating to latest annotations jar
WW-2132


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@669983 13f79535-47bb-0310-9956-ffa450edef68
2008-06-20 16:40:40 +00:00
Donald J. Brown 8378fbbd22 Ensuring that the mapper sets the namespace to / when available and no other namespace is found
WW-2461


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@669895 13f79535-47bb-0310-9956-ffa450edef68
2008-06-20 13:48:18 +00:00
Donald J. Brown 886cbda5cd Adding a test to prove radio tag properly handles a map of strings
WW-2046


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@669881 13f79535-47bb-0310-9956-ffa450edef68
2008-06-20 13:01:59 +00:00
Rainer Hermanns 9cbdb09169 WW-2479 Adding new setting to force spring object factory to use configured autowire strategy
o fixing build by commenting "old" constructor in StrutsSpringObjectFactory
o adding missing param to struts-plugin.xml in portlet-plugin

NOTE: This needs to be reviewed again!


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@669193 13f79535-47bb-0310-9956-ffa450edef68
2008-06-18 14:47:55 +00:00
David Newton 6736da66a5 Cool OGNL treachery, Jan's comments.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@668673 13f79535-47bb-0310-9956-ffa450edef68
2008-06-17 13:54:54 +00:00
Donald J. Brown d24822fb69 Adding new setting to force spring object factory to use configured
autowire strategy
WW-2479


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@668645 13f79535-47bb-0310-9956-ffa450edef68
2008-06-17 13:09:09 +00:00
Donald J. Brown 7dc0031e33 Fixing action tag so it doesn't set wrong action invocation
WW-2611


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@668602 13f79535-47bb-0310-9956-ffa450edef68
2008-06-17 10:14:25 +00:00
James Holmes 5476f03918 Reverse changes made in revision 667876.
WW-2238

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@668253 13f79535-47bb-0310-9956-ffa450edef68
2008-06-16 18:08:45 +00:00
James Holmes 5d9bed1745 WW-2238 checkboxlist labels and values mixed up
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667876 13f79535-47bb-0310-9956-ffa450edef68
2008-06-14 20:44:48 +00:00
James Holmes 6a5c87319d Quick grammar fix.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667873 13f79535-47bb-0310-9956-ffa450edef68
2008-06-14 20:26:34 +00:00
James Holmes e654941b34 Quick grammar fix.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667872 13f79535-47bb-0310-9956-ffa450edef68
2008-06-14 20:23:44 +00:00
Rainer Hermanns e8a2fb1497 WW-2536 Autocompleted element don't publish topics when it changed
o applied patch by Stanislav Malishevskiy

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667794 13f79535-47bb-0310-9956-ffa450edef68
2008-06-14 12:48:21 +00:00
Rainer Hermanns 5a5f88205d WW-2520 IE bug on tabbedpanel with Enclosed ajax div on first tab
o applied patch by Stanislav Malishevskiy

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667793 13f79535-47bb-0310-9956-ffa450edef68
2008-06-14 12:44:40 +00:00
Rainer Hermanns c760241930 WW-2480 Some OGNL expressions do not work with DateTimePicker component
o applied patch by Mike Calmus

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667791 13f79535-47bb-0310-9956-ffa450edef68
2008-06-14 12:41:00 +00:00
Rainer Hermanns bc3301bb3e WW-1725 FileUploadInterceptor and localized messages problem
o implemented requested feature based on a new config parameter:
   set useActionMessageBundle config parameter to true to use action message bundles
   The default behaviour is not changed at all, so this change is fully backwards compliant.

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667779 13f79535-47bb-0310-9956-ffa450edef68
2008-06-14 12:19:07 +00:00
Rainer Hermanns 423360d377 WW-2586 Struts 1 plugin pom has dependancy on 1.3.5
o added missing method findActionConfigId(java.lang.String) in org.apache.struts.config.ModuleConfig 
o upgraded dependancy  to Struts 1.3.9


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667778 13f79535-47bb-0310-9956-ffa450edef68
2008-06-14 12:14:42 +00:00
Donald J. Brown 3b6d7cfe82 Adding tests to ensure results are overridden correctly
WW-2559


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667743 13f79535-47bb-0310-9956-ffa450edef68
2008-06-14 04:40:02 +00:00
Donald J. Brown 873d150890 Adding support for multiple parent packages to be defined at the package level, adding more
restrictions on the namespace, parentpackage, and results annotations


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667742 13f79535-47bb-0310-9956-ffa450edef68
2008-06-14 04:20:22 +00:00
Donald J. Brown 5030b89b33 Adding parameter exception handling for portlet redirects
WW-2676


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667732 13f79535-47bb-0310-9956-ffa450edef68
2008-06-14 03:19:53 +00:00
Donald J. Brown d0e828d5a5 Removing dead code, removed overriding of buildResult as it didn't seem to add anything but
duplicate code from parent
WW-2676


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667722 13f79535-47bb-0310-9956-ffa450edef68
2008-06-14 02:38:06 +00:00
Rainer Hermanns f0efd27bb7 WW-2557 FileUploadInterceptor allows forbidden files when passed with allowed files
o applied slightly modified patch submitted by Stephan Schroeder

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667656 13f79535-47bb-0310-9956-ffa450edef68
2008-06-13 21:14:44 +00:00
James Holmes 71d6d3fade WW-2631 s:submit type="button" does not render title attribute
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667629 13f79535-47bb-0310-9956-ffa450edef68
2008-06-13 19:51:24 +00:00
Rainer Hermanns 8e7df5a712 WW-2623 Struts 2.1.3 omnibus ticket
o updated tag docs

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667572 13f79535-47bb-0310-9956-ffa450edef68
2008-06-13 15:28:16 +00:00
Rainer Hermanns 492ab02d97 WW-2660 Patches for WW-2203 prevented action parameters from other places than the request parameters from being included in ParameterAware map.
o applied patches by Dale Newfield to S2 and XW
o updated xwork dep to 2.1.2-SNAPSHOT

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667420 13f79535-47bb-0310-9956-ffa450edef68
2008-06-13 08:33:23 +00:00
Donald J. Brown 54bf39cfcd Updating struts-annotations to fix tld generation errors
WW-2674


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@667334 13f79535-47bb-0310-9956-ffa450edef68
2008-06-13 04:42:46 +00:00
Rainer Hermanns 4c1cbed577 WW-2623 Struts 2.1.3 omnibus ticket
o optimzed imports

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@666762 13f79535-47bb-0310-9956-ffa450edef68
2008-06-11 18:15:01 +00:00
Rainer Hermanns 16241f95a6 WW-2623 Struts 2.1.3 omnibus ticket
o optimzed imports

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@666761 13f79535-47bb-0310-9956-ffa450edef68
2008-06-11 18:14:02 +00:00
Rainer Hermanns f54ce89923 WW-2623 Struts 2.1.3 omnibus ticket
o optimzed imports

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@666756 13f79535-47bb-0310-9956-ffa450edef68
2008-06-11 18:11:00 +00:00
Musachy Barroso 7140edf5e5 WW-2667 REST should not extend Codebehind
* Applications that use REST must include a Codebehind's jar

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@663990 13f79535-47bb-0310-9956-ffa450edef68
2008-06-06 15:53:47 +00:00
Musachy Barroso 9efd7fcfd9 WW-2667 REST should not extend Codebehind
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@663605 13f79535-47bb-0310-9956-ffa450edef68
2008-06-05 13:31:01 +00:00
Musachy Barroso 92cea867a3 WW-2667 REST should not extend Codebehind
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@663603 13f79535-47bb-0310-9956-ffa450edef68
2008-06-05 13:29:25 +00:00
Musachy Barroso 2c54264bcc WW-2587 @SkipValidation not found on superclass method
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@663335 13f79535-47bb-0310-9956-ffa450edef68
2008-06-04 18:15:36 +00:00
James Holmes 6f47a90767 WW-2664 - Update Freemarker dependency to 2.3.13.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@662421 13f79535-47bb-0310-9956-ffa450edef68
2008-06-02 13:13:51 +00:00
Musachy Barroso fa6a04576e WW-2587 @SkipValidation not found on superclass method
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@661795 13f79535-47bb-0310-9956-ffa450edef68
2008-05-30 17:30:19 +00:00
James Holmes 43d1be3774 Update hidden tag to support being disabled per WW-2566. Thanks to Jelmer Kuperus for the patch.
I added a unit test as well.

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@660539 13f79535-47bb-0310-9956-ffa450edef68
2008-05-27 14:42:46 +00:00
James Holmes 36d82cbc7f Add comments for Maven snippet plugin and remove spurious newlines per WW-2658. Thanks to Matthieu Chase Heimer for the patch.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@660522 13f79535-47bb-0310-9956-ffa450edef68
2008-05-27 14:08:00 +00:00
Musachy Barroso 2c1ffa7e73 WW-2462 Action - component: start(Writer) is called twice
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@659853 13f79535-47bb-0310-9956-ffa450edef68
2008-05-24 17:03:40 +00:00
Musachy Barroso 5a2759896f WW-2225 Check for null error and messages on templates
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@659661 13f79535-47bb-0310-9956-ffa450edef68
2008-05-23 21:11:36 +00:00
David Newton cf1150f58c Minor spelling
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@658958 13f79535-47bb-0310-9956-ffa450edef68
2008-05-22 00:39:06 +00:00
Musachy Barroso 2019385915 Remove duplicated license header
Move license header inside <script> tag

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@658887 13f79535-47bb-0310-9956-ffa450edef68
2008-05-21 21:43:25 +00:00
Musachy Barroso e07b7eb7d2 WW-2120 Dispatcher does not put request parameters of new url on the value stack.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@658883 13f79535-47bb-0310-9956-ffa450edef68
2008-05-21 21:31:04 +00:00
Musachy Barroso dae35dfd9c WW-2651 FileUploadInterceptor.java javadoc is not formatted correctly for Confluence snippets
Thanks to Matthieu Chase Heimer for the patch

git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@658683 13f79535-47bb-0310-9956-ffa450edef68
2008-05-21 13:44:40 +00:00
David Newton 9067fdc945 Minor TLD doc spelling.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@658646 13f79535-47bb-0310-9956-ffa450edef68
2008-05-21 12:16:53 +00:00
James Holmes 66b2491338 Fix styling issue that was preventing the header on all of the showcase app pages from displaying properly in IE7.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@657105 13f79535-47bb-0310-9956-ffa450edef68
2008-05-16 15:33:10 +00:00
James Holmes ac1d6b48b8 Update to take advantage of performance improvements in FreeMarker and remove use of deprecated method.
WW-2649


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@656728 13f79535-47bb-0310-9956-ffa450edef68
2008-05-15 16:44:50 +00:00
Donald J. Brown 9a22985c1f Disabling the interceptor for multiple checkboxes with the same name, changing to add an array rather than a String
WW-2526


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@655721 13f79535-47bb-0310-9956-ffa450edef68
2008-05-13 03:14:03 +00:00
David Newton 565b8f8642 Changed name to "Struts 2 REST Plugin" (was "Struts 2 Plugin").
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@655091 13f79535-47bb-0310-9956-ffa450edef68
2008-05-10 14:01:25 +00:00
Musachy Barroso 61c03b374d * Refactor static content loading out of FilterDispatcher into DefaultStaticContentLoader, and add an extension point for it.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@653472 13f79535-47bb-0310-9956-ffa450edef68
2008-05-05 13:10:05 +00:00
Musachy Barroso e05d71ba32 * Refactor static content loading out of FilterDispatcher into DefaultStaticContentLoader, and add an extension point for it.
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@653471 13f79535-47bb-0310-9956-ffa450edef68
2008-05-05 13:09:50 +00:00
Donald J. Brown bdc01ffb85 Reformatting annoying code
WW-2623


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@652768 13f79535-47bb-0310-9956-ffa450edef68
2008-05-02 05:34:09 +00:00
Donald J. Brown 06030a440c Fixing assembly pom version
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@652766 13f79535-47bb-0310-9956-ffa450edef68
2008-05-02 05:15:01 +00:00
Donald J. Brown 09b43b1838 [maven-release-plugin] prepare for next development iteration
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@652751 13f79535-47bb-0310-9956-ffa450edef68
2008-05-02 03:47:24 +00:00
Donald J. Brown 373988eb4a [maven-release-plugin] prepare release STRUTS_2_1_2
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@652749 13f79535-47bb-0310-9956-ffa450edef68
2008-05-02 03:47:03 +00:00
547 changed files with 42872 additions and 27529 deletions
+4 -4
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>2.1.2-SNAPSHOT</version>
<version>2.1.3</version>
</parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-blank</artifactId>
@@ -34,9 +34,9 @@
<name>Blank Webapp</name>
<scm>
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/apps/blank/</connection>
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/trunk/apps/blank/</developerConnection>
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/trunk/apps/blank/</url>
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/blank</connection>
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/blank</developerConnection>
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_1_3/apps/blank</url>
</scm>
<dependencies>
+12
View File
@@ -10,6 +10,18 @@
<include file="example.xml"/>
<package name="default" namespace="/" extends="struts-default">
<default-action-ref name="index" />
<action name="index">
<result type="redirectAction">
<param name="actionName">HelloWorld</param>
<param name="namespace">/example</param>
</result>
</action>
</package>
<!-- Add packages here -->
</struts>
+1 -1
View File
@@ -5,7 +5,7 @@
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
@@ -44,7 +44,7 @@ public class ConfigTest extends StrutsTestCase {
ActionSupport.INPUT.equals(result));
}
protected Map assertFieldErrors(ActionSupport action) throws Exception {
protected Map<String, List<String>> assertFieldErrors(ActionSupport action) throws Exception {
assertTrue(action.hasFieldErrors());
return action.getFieldErrors();
}
+4 -4
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>2.1.2-SNAPSHOT</version>
<version>2.1.3</version>
</parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-mailreader</artifactId>
@@ -34,9 +34,9 @@
<name>Starter Webapp</name>
<scm>
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/apps/mailreader/</connection>
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/trunk/apps/mailreader/</developerConnection>
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/trunk/apps/mailreader/</url>
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/mailreader</connection>
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/mailreader</developerConnection>
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_1_3/apps/mailreader</url>
</scm>
<dependencies>
@@ -7,7 +7,7 @@
<filter>
<filter-name>Struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
+5 -21
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>2.1.2-SNAPSHOT</version>
<version>2.1.3</version>
</parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
@@ -41,9 +41,9 @@
</modules>
<scm>
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/apps/</connection>
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/trunk/apps/</developerConnection>
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/trunk/apps/</url>
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps</connection>
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps</developerConnection>
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_1_3/apps</url>
</scm>
<distributionManagement>
@@ -169,22 +169,6 @@
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>0.3.1</version>
<configuration>
<container>
<containerId>tomcat5x</containerId>
<home>${cargo.tomcat5x.home}</home>
<log>${project.build.directory}/tomcat5x.log</log>
<output>${project.build.directory}/tomcat5x.out</output>
</container>
<configuration>
<home>${project.build.directory}/tomcat5x</home>
</configuration>
</configuration>
</plugin>
<!-- Include source code under WEB-INF/src/java -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
@@ -247,4 +231,4 @@
</dependency>
</dependencies>
</project>
</project>
+4 -4
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>2.1.2-SNAPSHOT</version>
<version>2.1.3</version>
</parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-portlet</artifactId>
@@ -34,9 +34,9 @@
<name>Portlet Webapp</name>
<scm>
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/apps/portlet/</connection>
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/trunk/apps/portlet/</developerConnection>
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/trunk/apps/portlet/</url>
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/portlet</connection>
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/portlet</developerConnection>
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_1_3/apps/portlet</url>
</scm>
<profiles>
+73 -4
View File
@@ -26,22 +26,27 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>2.1.2-SNAPSHOT</version>
<version>2.1.3</version>
</parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-rest-showcase</artifactId>
<packaging>war</packaging>
<version>2.1.2-SNAPSHOT</version>
<version>2.1.3</version>
<name>Struts 2 Rest Showcase Example</name>
<description>Struts 2 Rest Showcase Example</description>
<dependencies>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-rest-plugin</artifactId>
<version>${pom.version}</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-convention-plugin</artifactId>
<version>${pom.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
@@ -49,9 +54,36 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.jwebunit</groupId>
<artifactId>jwebunit-core</artifactId>
<version>1.4.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.jwebunit</groupId>
<artifactId>jwebunit-htmlunit-plugin</artifactId>
<version>1.4.1</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>xom</groupId>
<artifactId>xom</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<finalName>struts2-rest-showcase</finalName>
<plugins>
@@ -70,6 +102,43 @@
<scanIntervalSeconds>10</scanIntervalSeconds>
</configuration>
</plugin>
<!--
<plugin>
<groupId>org.twdata.maven</groupId>
<artifactId>maven-itblast-plugin</artifactId>
<version>0.3</version>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<containers>tomcat5x</containers>
</configuration>
</execution>
</executions>
</plugin>
-->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>it/**</exclude>
<exclude>**/*$*</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
<!--
<pluginRepositories>
<pluginRepository>
<id>twdata-m2-repository</id>
<name>twdata.org Maven Repository</name>
<url>http://twdata-m2-repository.googlecode.com/svn/</url>
</pluginRepository>
</pluginRepositories>
-->
</project>
@@ -2,18 +2,22 @@ package org.apache.struts2.rest.example;
import java.util.Collection;
import org.apache.struts2.config.Result;
import org.apache.struts2.config.Results;
import org.apache.struts2.dispatcher.ServletActionRedirectResult;
import org.apache.struts2.rest.DefaultHttpHeaders;
import org.apache.struts2.rest.HttpHeaders;
import org.apache.struts2.convention.annotation.Results;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.ParentPackage;
import org.apache.struts2.convention.annotation.Namespaces;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.InterceptorRef;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Validateable;
import com.opensymphony.xwork2.ValidationAwareSupport;
@Results({
@Result(name="success", type=ServletActionRedirectResult.class, value="orders")
@Result(name="success", type="redirectAction", params = {"actionName" , "orders"})
})
public class OrdersController extends ValidationAwareSupport implements ModelDriven<Object>, Validateable{
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!--
/*
* $Id: struts-plugin.xml 722219 2008-12-01 20:41:26Z musachy $
*
* 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.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<!-- Overwrite Convention -->
<constant name="struts.convention.action.suffix" value="Controller"/>
<constant name="struts.convention.action.mapAllMatches" value="true"/>
<constant name="struts.convention.default.parent.package" value="rest-default"/>
<constant name="struts.convention.package.locators" value="example"/>
</struts>
@@ -12,11 +12,7 @@
<!-- START SNIPPET: filter -->
<filter>
<filter-name>action2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>actionPackages</param-name>
<param-value>org.apache.struts2.rest.example</param-value>
</init-param>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<!-- END SNIPPET: filter -->
@@ -0,0 +1,32 @@
package it.org.apache.struts2.rest.example;
import net.sourceforge.jwebunit.junit.WebTestCase;
public class GetOrdersTest extends WebTestCase {
public void setUp() throws Exception {
getTestContext().setBaseUrl(ParameterUtils.getBaseUrl());
}
public void testGetOrders() {
beginAt("/orders/3");
assertTextPresent("Bob");
assertTextNotPresent("Sarah");
}
public void testGetOrdersInHtml() {
beginAt("/orders/3.xhtml");
assertTextPresent("Bob");
}
public void testGetOrdersInXml() {
beginAt("/orders/3.xml");
assertTextPresent("<clientName>Bob");
}
public void testGetOrdersInJson() {
beginAt("/orders/3.json");
assertTextPresent("\"clientName\":\"Bob\"");
}
}
@@ -0,0 +1,39 @@
package it.org.apache.struts2.rest.example;
import net.sourceforge.jwebunit.junit.WebTestCase;
public class ListOrdersTest extends WebTestCase {
public void setUp() throws Exception {
getTestContext().setBaseUrl(ParameterUtils.getBaseUrl());
}
public void testListOrders() {
beginAt("/orders");
assertTextPresent("Bob");
assertTextPresent("Sarah");
assertTextPresent("Jim");
}
public void testListOrdersInHtml() {
beginAt("/orders.xhtml");
assertTextPresent("Bob");
assertTextPresent("Sarah");
assertTextPresent("Jim");
}
public void testListOrdersInXml() {
beginAt("/orders.xml");
assertTextPresent("<clientName>Bob");
assertTextPresent("<clientName>Sarah");
assertTextPresent("<clientName>Jim");
}
public void testListOrdersInJson() {
beginAt("/orders.json");
assertTextPresent("\"clientName\":\"Bob\"");
assertTextPresent("\"clientName\":\"Sarah\"");
assertTextPresent("\"clientName\":\"Jim\"");
}
}
@@ -0,0 +1,12 @@
package it.org.apache.struts2.rest.example;
public class ParameterUtils {
public static String getBaseUrl() {
String port = System.getProperty("http.port");
if (port == null) {
port = "8080";
}
return "http://localhost:"+port+"/struts2-rest-showcase";
}
}
@@ -0,0 +1,121 @@
package it.org.apache.struts2.rest.example;
import net.sourceforge.jwebunit.junit.WebTestCase;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import java.io.IOException;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
public class PostOrderTest extends WebTestCase {
public void setUp() throws Exception {
getTestContext().setBaseUrl(ParameterUtils.getBaseUrl());
}
public void testPostOrder() {
beginAt("/orders/new");
setWorkingForm(0);
setTextField("clientName", "Test1");
setTextField("amount", "321");
submit();
assertTextPresent("Test1");
assertLinkNotPresentWithText("Back to Orders");
}
public void testPostOrderWithErrors() {
beginAt("/orders/new");
setWorkingForm(0);
setTextField("amount", "321");
try {
submit();
} catch (FailingHttpStatusCodeException ex) {
// ignore;
}
assertTextPresent("client name is empty");
assertTextFieldEquals("amount", "321");
}
public void testPostOrderInHtml() {
beginAt("/orders/new.xhtml");
setWorkingForm(0);
setTextField("clientName", "Test2");
setTextField("amount", "321");
try {
submit();
} catch (FailingHttpStatusCodeException ex) {
// ignore;
}
assertTextPresent("Test2");
assertLinkNotPresentWithText("Back to Orders");
}
public void testPostOrderInXml() throws IOException {
HttpClient client = new HttpClient();
PostMethod method = null;
try {
method = new PostMethod(ParameterUtils.getBaseUrl()+"/orders.xml");
method.setRequestEntity(new StringRequestEntity("<org.apache.struts2.rest.example.Order>\n" +
"<clientName>Test3</clientName>\n" +
"<amount>3342</amount>\n" +
"</org.apache.struts2.rest.example.Order>"));
client.executeMethod(method);
assertEquals(201, method.getStatusCode());
assertTrue(method.getResponseHeader("Location").getValue().startsWith(ParameterUtils.getBaseUrl()+"/orders/"));
} finally {
method.releaseConnection();
}
}
public void testPostOrderInXmlWithBadData() throws IOException {
HttpClient client = new HttpClient();
PostMethod method = null;
try {
method = new PostMethod(ParameterUtils.getBaseUrl()+"/orders.xml");
method.setRequestEntity(new StringRequestEntity("<org.apache.struts2.rest.example.Order>\n" +
"<amount>3342</amount>\n" +
"</org.apache.struts2.rest.example.Order>"));
client.executeMethod(method);
assertEquals(400, method.getStatusCode());
String response = method.getResponseBodyAsString();
assertTrue(response.contains("<string>The client name is empty"));
assertNull(method.getResponseHeader("Location"));
} finally {
method.releaseConnection();
}
}
public void testPostOrderInJson() throws IOException {
HttpClient client = new HttpClient();
PostMethod method = null;
try {
method = new PostMethod(ParameterUtils.getBaseUrl()+"/orders.json");
method.setRequestEntity(new StringRequestEntity("{\"amount\":33,\"clientName\":\"Test4\"}"));
client.executeMethod(method);
assertEquals(201, method.getStatusCode());
assertTrue(method.getResponseHeader("Location").getValue().startsWith(ParameterUtils.getBaseUrl()+"/orders/"));
} finally {
method.releaseConnection();
}
}
public void testPostOrderInJsonWithBadData() throws IOException {
HttpClient client = new HttpClient();
PostMethod method = null;
try {
method = new PostMethod(ParameterUtils.getBaseUrl()+"/orders.json");
method.setRequestEntity(new StringRequestEntity("{\"amount\":33}"));
client.executeMethod(method);
String response = method.getResponseBodyAsString();
assertEquals(400, method.getStatusCode());
assertEquals("{\"actionErrors\":[],\"fieldErrors\":{\"clientName\":[\"The client name is empty\"]}}", response);
assertNull(method.getResponseHeader("Location"));
} finally {
method.releaseConnection();
}
}
}
+79 -16
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-apps</artifactId>
<version>2.1.2-SNAPSHOT</version>
<version>2.1.3</version>
</parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-showcase</artifactId>
@@ -34,9 +34,9 @@
<name>Showcase Webapp</name>
<scm>
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/apps/showcase/</connection>
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/trunk/apps/showcase/</developerConnection>
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/trunk/apps/showcase/</url>
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/showcase</connection>
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/showcase</developerConnection>
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_1_3/apps/showcase</url>
</scm>
@@ -181,6 +181,32 @@
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>net.sourceforge.jwebunit</groupId>
<artifactId>jwebunit-core</artifactId>
<version>1.4.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.jwebunit</groupId>
<artifactId>jwebunit-htmlunit-plugin</artifactId>
<version>1.4.1</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>xom</groupId>
<artifactId>xom</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
@@ -211,19 +237,56 @@
</dependency>
</dependencies>
</plugin>
<!--
<plugin>
<groupId>org.twdata.maven</groupId>
<artifactId>maven-itblast-plugin</artifactId>
<version>0.3</version>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<containers>tomcat5x</containers>
</configuration>
</execution>
</executions>
</plugin>
-->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>it/**</exclude>
<exclude>**/*$*</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
<resources>
<!-- Include resources under src/main/java in WEB-INF/classes -->
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</resource>
</resources>
<resources>
<!-- Include resources under src/main/java in WEB-INF/classes -->
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.java</include>
</includes>
</resource>
</resources>
</build>
<!--
<pluginRepositories>
<pluginRepository>
<id>twdata-m2-repository</id>
<name>twdata.org Maven Repository</name>
<url>http://twdata-m2-repository.googlecode.com/svn/</url>
</pluginRepository>
</pluginRepositories>
-->
</project>
@@ -18,6 +18,7 @@
* specific language governing permissions and limitations
* under the License.
*/
// START SNIPPET: entire-file
package org.apache.struts2.showcase.fileupload;
import java.io.File;
@@ -44,7 +45,6 @@ public class MultipleFileUploadUsingArrayAction extends ActionSupport {
public String[] getUploadContentType() { return this.uploadContentTypes; }
public void setUploadContentType(String[] uploadContentType) { this.uploadContentTypes = uploadContentType; }
public String upload() throws Exception {
System.out.println("\n\n upload2");
System.out.println("files:");
@@ -62,5 +62,5 @@ public class MultipleFileUploadUsingArrayAction extends ActionSupport {
System.out.println("\n\n");
return SUCCESS;
}
}
// END SNIPPET: entire-file
@@ -18,6 +18,7 @@
* specific language governing permissions and limitations
* under the License.
*/
// START SNIPPET: entire-file
package org.apache.struts2.showcase.fileupload;
import java.io.File;
import java.util.ArrayList;
@@ -57,9 +58,6 @@ public class MultipleFileUploadUsingListAction extends ActionSupport {
this.uploadContentTypes = contentTypes;
}
public String upload() throws Exception {
System.out.println("\n\n upload1");
@@ -78,6 +76,5 @@ public class MultipleFileUploadUsingListAction extends ActionSupport {
System.out.println("\n\n");
return SUCCESS;
}
}
// END SNIPPET: entire-file
@@ -3,7 +3,7 @@
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="ui-tags" extends="struts-default" namespace="/tags/ui">
<action name="example" class="org.apache.struts2.showcase.UITagExample">
@@ -40,26 +40,30 @@
</action>
<!-- START SNIPPET: treeExampleDynamicXWorkXml -->
<action name="showDynamicTreeAction" class="org.apache.struts2.showcase.ShowDynamicTreeAction">
<result>/tags/ui/treeExampleDynamic.jsp</result>
</action>
<!-- END SNIPPET: treeExampleDynamicXWorkXml -->
<action name="showDynamicAjaxTreeAction">
<result>/tags/ui/treeExampleAjaxDynamic.jsp</result>
</action>
<action name="showComponentTagExampleCode">
<result type="plainText">/tags/ui/componentTagExample.jsp</result>
</action>
<action name="actionTagExample">
<result>/tags/ui/actionTagExampleCalled.jsp</result>
<result name="input">/tags/ui/actionTagExampleCalling.jsp</result>
</action>
</package>
<!-- START SNIPPET: treeExampleXWorkXml -->
<package name="ui-tags-ajax" namespace="/tags/ui/ajax" extends="struts-default">
<package name="ui-tags-ajax" namespace="/tags/ui/ajax" extends="struts-default">
<!-- Actions dealing with Tree Example -->
<action name="staticTreeSelectAction">
<result>/tags/ui/staticTreeSelect.jsp</result>
@@ -68,6 +72,6 @@
<result>/tags/ui/dynamicTreeSelect.jsp</result>
</action>
</package>
<!-- END SNIPPET: treeExampleXWorkXml -->
</struts>
@@ -49,43 +49,43 @@
</div><!-- end search -->
<hr/>
<div style="clear: both;"></div>
</div>
</div><!-- end header -->
<div id="content" class="clearfix">
<decorator:body/>
<div id="nav">
<div class="wrapper">
<h2 class="accessibility">Navigation</h2>
<ul class="clearfix">
<li><a href="<s:url value="/showcase.jsp"/>">Home</a></li>
<li><a href="<s:url value="/ajax/index.jsp"/>">Ajax</a></li>
<li><a href="<s:url value="/chat/index.jsp"/>">Ajax Chat</a></li>
<li><a href="<s:url action="actionChain1!input" namespace="/actionchaining" includeParams="none" />">Action Chaining</a></li>
<li><a href="<s:url action="index" namespace="/config-browser" includeParams="none" />">Config Browser</a></li>
<li><a href="<s:url value="/conversion/index.jsp"/>">Conversion</a></li>
<li><a href="<s:url value="/empmanager/index.jsp"/>">CRUD</a></li>
<li><a href="<s:url value="/wait/index.jsp"/>">Execute & Wait</a></li>
<li><a href="<s:url value="/filedownload/index.jsp"/>">File Download</a></li>
<li><a href="<s:url value="/fileupload" />">File Upload</a></li>
<li><a href="<s:url value="/freemarker/index.jsp"/>">Freemarker</a>
<li><a href="<s:url action="hangmanMenu" namespace="/hangman"/>">Hangman</a></li>
<li><a href="<s:url value="/jsf/index.jsp"/>">JavaServer Faces</a></li>
<li><a href="<s:url value="/person/index.jsp"/>">Person Manager</a></li>
<li><a href="<s:url value="/tags/index.jsp"/>">Tags</a></li>
<li><a href="<s:url value="/tiles/index.action" />">Tiles</a></li>
<li><a href="<s:url value="/token/index.jsp"/>">Token</a></li>
<li><a href="<s:url value="/validation/index.jsp"/>">Validation</a></li>
<li><a href="<s:url value="/interactive/index.jsp"/>">Interactive Demo</a></li>
<li class="last"><a href="<s:url value="/help.jsp"/>">Help</a></li>
<li><a href="<s:url value="/showcase.jsp"/>">Home</a></li>
<li><a href="<s:url value="/ajax/index.jsp"/>">Ajax</a></li>
<li><a href="<s:url value="/chat/index.jsp"/>">Ajax Chat</a></li>
<li><a href="<s:url action="actionChain1!input" namespace="/actionchaining" includeParams="none" />">Action Chaining</a></li>
<li><a href="<s:url action="index" namespace="/config-browser" includeParams="none" />">Config Browser</a></li>
<li><a href="<s:url value="/conversion/index.jsp"/>">Conversion</a></li>
<li><a href="<s:url value="/empmanager/index.jsp"/>">CRUD</a></li>
<li><a href="<s:url value="/wait/index.jsp"/>">Execute & Wait</a></li>
<li><a href="<s:url value="/filedownload/index.jsp"/>">File Download</a></li>
<li><a href="<s:url value="/fileupload/index.jsp" />">File Upload</a></li>
<li><a href="<s:url value="/freemarker/index.jsp"/>">Freemarker</a>
<li><a href="<s:url action="hangmanMenu" namespace="/hangman"/>">Hangman</a></li>
<li><a href="<s:url value="/jsf/index.jsp"/>">JavaServer Faces</a></li>
<li><a href="<s:url value="/tags/index.jsp"/>">Tags</a></li>
<li><a href="<s:url value="/tiles/index.action" />">Tiles</a></li>
<li><a href="<s:url value="/token/index.jsp"/>">Token</a></li>
<li><a href="<s:url value="/validation/index.jsp"/>">Validation</a></li>
<li><a href="<s:url value="/interactive/index.jsp"/>">Interactive Demo</a></li>
<li><a href="<s:url value="/person/index.jsp"/>">Person Manager</a></li>
<li class="last"><a href="<s:url value="/help.jsp"/>">Help</a></li>
</ul>
</div>
<hr/>
</div><!-- end nav -->
<decorator:body/>
</div><!-- end content -->
<div>
@@ -7,26 +7,26 @@
<display-name>Struts Showcase Application</display-name>
<filter>
<filter-name>struts-cleanup</filter-name>
<filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class>
</filter>
<filter>
<filter-name>struts</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<filter-name>struts-prepare</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter</filter-class>
<init-param>
<param-name>actionPackages</param-name>
<param-value>org.apache.struts2.showcase.person</param-value>
</init-param>
</filter>
<filter>
<filter-name>struts-execute</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter</filter-class>
</filter>
<filter>
<filter-name>sitemesh</filter-name>
<filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts-cleanup</filter-name>
<filter-name>struts-prepare</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
@@ -36,7 +36,7 @@
</filter-mapping>
<filter-mapping>
<filter-name>struts</filter-name>
<filter-name>struts-execute</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
@@ -7,7 +7,7 @@
position: relative;
width: 98%;
margin: 5em auto 20px auto;
margin: 5px auto 20px auto;
padding: 0;
text-align: left;
@@ -26,8 +26,6 @@
display: none;
}
div#nav {
position: absolute;
top: -15px;
left: 0;
width: 100%;
@@ -27,6 +27,7 @@
background: #818EBD;
text-align: left;
height: 70px;
}
div#branding {
float: left;
@@ -10,7 +10,6 @@
/* end hide */
}
div#nav div.wrapper {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
@@ -0,0 +1,2 @@
<%@taglib prefix="s" uri="/struts-tags" %>
This text is from the called class
@@ -0,0 +1,14 @@
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Showcase - Tags - UI Tags - Action Tag</title>
</head>
<body>
<b>Example 1:</b>
This example calls an action and includes the output on the page
<p id="example1" style="background-color:yellow;">
<s:action namespace="/tags/ui" name="actionTagExample" executeResult="true"/>
</p>
</body>
</html>
@@ -16,8 +16,8 @@
<s:form action="exampleSubmit" enctype="multipart/form-data" javascriptTooltip="true">
<s:textfield
label="Name"
<s:textfield
label="Name"
name="name"
tooltip="Enter your Name here"/>
@@ -25,13 +25,13 @@
tooltip="Select Your Birthday"
label="Birthday"
name="birthday" />
<sx:datetimepicker
tooltip="Enter the time you wake up"
label="Wake up time"
name="wakeup"
name="wakeup"
type="time"/>
<s:textarea
tooltip="Enter your Biography"
label="Biography"
@@ -76,7 +76,7 @@
name="region" list="{'North', 'South'}"
value="'South'"
doubleValue="'Florida'"
doubleList="top == 'North' ? {'Oregon', 'Washington'} : {'Texas', 'Florida'}"
doubleList="top == 'North' ? {'Oregon', 'Washington'} : {'Texas', 'Florida'}"
doubleName="state"
headerKey="-1"
headerValue="---------- Please Select ----------"
@@ -100,35 +100,35 @@
<s:file
tooltip="Upload Your Picture"
label="Picture"
label="Picture"
name="picture" />
<s:optiontransferselect
tooltip="Select Your Favourite Cartoon Characters"
label="Favourite Cartoons Characters"
name="leftSideCartoonCharacters"
name="leftSideCartoonCharacters"
leftTitle="Left Title"
rightTitle="Right Title"
list="{'Popeye', 'He-Man', 'Spiderman'}"
list="{'Popeye', 'He-Man', 'Spiderman'}"
multiple="true"
headerKey="headerKey"
headerValue="--- Please Select ---"
emptyOption="true"
doubleList="{'Superman', 'Mickey Mouse', 'Donald Duck'}"
doubleList="{'Superman', 'Mickey Mouse', 'Donald Duck'}"
doubleName="rightSideCartoonCharacters"
doubleHeaderKey="doubleHeaderKey"
doubleHeaderValue="--- Please Select ---"
doubleHeaderValue="--- Please Select ---"
doubleEmptyOption="true"
doubleMultiple="true" />
<s:textarea
label="Your Thougths"
name="thoughts"
name="thoughts"
tooltip="Enter your thoughts here" />
<s:submit onclick="alert('Custom onclick event triggered before submitting form... Press OK to continue!');" />
<s:submit />
<s:reset onclick="alert('Resetting form now... Press OK to continue!');" />
</s:form>
</body>
</html>
@@ -6,7 +6,7 @@
</head>
<body>
<h1>UI Tags</h1>
<ul>
<li><s:url var="url" namespace="/tags/ui" action="example" method="input" /><s:a href="%{url}">UI Example</s:a></li>
<li><s:url var="url" namespace="/tags/ui" action="exampleVelocity" method="input" /><s:a href="%{url}">UI Example (Velocity)</s:a></li>
@@ -16,6 +16,7 @@
<li><s:url var="url" namespace="/tags/ui" action="showDynamicTreeAction"/><s:a href="%{url}">Tree Example (dynamic)</s:a>
<li><s:url var="url" namespace="/tags/ui" action="showDynamicAjaxTreeAction"/><s:a href="%{url}">Tree Example (dynamic ajax loading)</s:a>
<li><s:url var="url" value="componentTagExample.jsp"/><s:a href="%{#url}">Component Tag Example</s:a>
<li><s:url var="url" namespace="/tags/ui" action="actionTagExample" method="input" /><s:a href="%{url}">Action Tag Example</s:a></li>
<li><a href="datepicker/index.jsp">DateTime picker tag - Pick a date</a></li>
<li><a href="timepicker/index.jsp">DateTime picker tag - Pick a time</a></li>
<%--li><s:url var="url" namespace="/tags/ui" action="populateUsingIterator" method="input" /><s:a href="%{url}">UI population using iterator tag</s:a></li--%>
@@ -0,0 +1,29 @@
/*
* $Id$
*
* 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;
public class ActionTagExampleTest extends ITBaseTest {
public void test() {
beginAt("/tags/ui/actionTagExample!input.action");
assertTextPresent("This text is from the called class");
}
}
@@ -0,0 +1,31 @@
/*
* $Id$
*
* 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;
public class ComponentTagExampleTest extends ITBaseTest {
public void test() {
beginAt("/tags/ui/componentTagExample.jsp");
assertTextPresent("Freemarker Custom Template - parameter 'paramName' - paramValue1");
assertTextPresent("Freemarker Custom Template - parameter 'paramName' - paramValue4");
assertTextPresent("JSP Custom Template - parameter 'paramName' - paramValue2");
assertTextPresent("JSP Custom Template - parameter 'paramName' - paramValue3");
}
}
@@ -0,0 +1,30 @@
/*
* $Id$
*
* 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 net.sourceforge.jwebunit.junit.WebTestCase;
public abstract class ITBaseTest extends WebTestCase {
public void setUp() throws Exception {
getTestContext().setBaseUrl(ParameterUtils.getBaseUrl());
}
}
@@ -0,0 +1,32 @@
/*
* $Id$
*
* 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;
public class ParameterUtils {
public static String getBaseUrl() {
String port = System.getProperty("http.port");
if (port == null) {
port = "8080";
}
return "http://localhost:"+port+"/struts2-showcase";
}
}
@@ -0,0 +1,55 @@
/*
* $Id$
*
* 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;
public class UITagExampleTest extends ITBaseTest {
public void testInputForm() {
setScriptingEnabled(false);
beginAt("/tags/ui/example!input.action");
assertFormPresent("exampleSubmit");
// text box
assertFormElementPresent("name");
// textarea
assertFormElementPresent("bio");
// select
assertFormElementPresent("favouriteColor");
// checkbox list
assertFormElementPresent("friends");
// checkbox
assertFormElementPresent("legalAge");
// set fields
setTextField("name", "name");
setTextField("bio", "bio");
selectOption("favouriteColor", "Red");
checkCheckbox("friends", "Patrick");
checkCheckbox("friends", "Jason");
checkCheckbox("legalAge");
submit();
assertTextInElement("name", "name");
assertTextInElement("bio", "bio");
assertTextInElement("favouriteColor", "Red");
assertTextInElement("friends", "[Patrick, Jason]");
assertTextInElement("legalAge", "true");
}
}
@@ -0,0 +1,37 @@
package it.org.apache.struts2.showcase.staticcontent;
import it.org.apache.struts2.showcase.ITBaseTest;
import java.io.IOException;
import net.sourceforge.jwebunit.exception.TestingEngineResponseException;
public class StaticContentTest extends ITBaseTest {
public void testInvalidRersources1() throws IOException {
try {
beginAt("/struts..");
fail("Previous request should have failed");
} catch (TestingEngineResponseException ex) {
// ok
}
}
public void testInvalidRersources2() throws IOException {
try {
beginAt("/struts/..%252f");
fail("Previous request should have failed");
} catch (TestingEngineResponseException ex) {
// ok
}
}
/*public void testInvalidRersources3() throws IOException {
try {
beginAt("/struts/..%252f..%252f..%252fWEB-INF/classes/org/apache/struts2/showcase/action/EmployeeAction.class/");
fail("Previous request should have failed");
} catch (TestingEngineResponseException ex) {
// ok
}
}*/
}
+176 -146
View File
@@ -1,26 +1,4 @@
<?xml version="1.0"?>
<!--
/*
* Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Id$
*/
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-assembly</artifactId>
@@ -33,16 +11,160 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>2.1.2-SNAPSHOT</version>
<version>2.1.3</version>
</parent>
<scm>
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/assembly</connection>
<developerConnection>
scm:svn:https://svn.apache.org/repos/asf/struts/struts2/trunk/assembly</developerConnection>
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/trunk/assembly</url>
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/assembly</connection>
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/assembly</developerConnection>
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_1_3/assembly</url>
</scm>
<profiles>
<profile>
<id>j4</id>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-1</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>attached</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptors>
<descriptor>src/main/assembly/all.xml</descriptor>
<descriptor>src/main/assembly/lib.xml</descriptor>
<descriptor>src/main/assembly/lib-jdk14.xml</descriptor>
<descriptor>src/main/assembly/apps.xml</descriptor>
<descriptor>src/main/assembly/src.xml</descriptor>
<descriptor>src/main/assembly/docs.xml</descriptor>
</descriptors>
<finalName>struts-${version}</finalName>
<outputDirectory>target/assembly/out</outputDirectory>
<workDirectory>target/assembly/work</workDirectory>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<!-- Backported JDK 1.4 jars -->
<dependency>
<groupId>net.sf.retrotranslator</groupId>
<artifactId>retrotranslator-runtime</artifactId>
<version>1.2.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>backport-util-concurrent</groupId>
<artifactId>backport-util-concurrent</artifactId>
<version>3.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.opensymphony</groupId>
<artifactId>xwork</artifactId>
<version>2.1.2</version>
<type>jar</type>
<classifier>jdk14</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-config-browser-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-jasperreports-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-jfreechart-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-jsf-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-pell-multipart-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plexus-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-sitegraph-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-sitemesh-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-struts1-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-tiles-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-rest-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
</dependencies>
</profile>
</profiles>
<build>
<plugins>
<plugin>
@@ -109,7 +231,7 @@
<groupId>com.opensymphony</groupId>
<artifactId>xwork</artifactId>
<classifier>javadoc</classifier>
<version>2.1.1</version>
<version>2.1.2</version>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/xwork-apidocs</outputDirectory>
@@ -125,12 +247,9 @@
<phase>process-resources</phase>
<configuration>
<tasks>
<mkdir dir="${project.build.directory}/cwiki"/>
<get src="http://struts.apache.org/2.x/docs.zip"
dest="${project.build.directory}/docs.zip"
ignoreerrors="false"/>
<unzip src="${project.build.directory}/docs.zip"
dest="${project.build.directory}/cwiki"/>
<mkdir dir="${project.build.directory}/cwiki" />
<get src="http://struts.apache.org/2.x/docs.zip" dest="${project.build.directory}/docs.zip" ignoreerrors="false" />
<unzip src="${project.build.directory}/docs.zip" dest="${project.build.directory}/cwiki" />
</tasks>
</configuration>
<goals>
@@ -142,11 +261,19 @@
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-1</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>attached</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptors>
<descriptor>src/main/assembly/all.xml</descriptor>
<descriptor>src/main/assembly/lib.xml</descriptor>
<descriptor>src/main/assembly/lib-jdk14.xml</descriptor>
<descriptor>src/main/assembly/apps.xml</descriptor>
<descriptor>src/main/assembly/src.xml</descriptor>
<descriptor>src/main/assembly/docs.xml</descriptor>
@@ -166,6 +293,18 @@
<artifactId>struts2-codebehind-plugin</artifactId>
<version>${version}</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-convention-plugin</artifactId>
<version>${version}</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-javatemplates-plugin</artifactId>
<version>${version}</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
@@ -268,115 +407,6 @@
<version>${version}</version>
</dependency>
<!-- Backported JDK 1.4 jars -->
<dependency>
<groupId>net.sf.retrotranslator</groupId>
<artifactId>retrotranslator-runtime</artifactId>
<version>1.2.1</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>backport-util-concurrent</groupId>
<artifactId>backport-util-concurrent</artifactId>
<version>3.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.opensymphony</groupId>
<artifactId>xwork</artifactId>
<version>2.1.1</version>
<type>jar</type>
<classifier>jdk14</classifier>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-config-browser-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-jasperreports-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-jfreechart-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-jsf-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-pell-multipart-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plexus-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-sitegraph-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-sitemesh-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-struts1-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-tiles-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-rest-plugin</artifactId>
<version>${version}</version>
<classifier>jdk14</classifier>
</dependency>
</dependencies>
</project>
</project>
+10 -2
View File
@@ -127,6 +127,14 @@
<directory>../plugins/codebehind/target/site</directory>
<outputDirectory>docs/struts2-plugins/struts2-codebehind-plugin</outputDirectory>
</fileSet>
<fileSet>
<directory>../plugins/codebehind/target/site</directory>
<outputDirectory>docs/struts2-plugins/struts2-javatemplates-plugin</outputDirectory>
</fileSet>
<fileSet>
<directory>../plugins/convention/target/site</directory>
<outputDirectory>docs/struts2-plugins/struts2-convention-plugin</outputDirectory>
</fileSet>
<fileSet>
<directory>../plugins/config-browser/target/site</directory>
<outputDirectory>docs/struts2-plugins/struts2-config-browser-plugin</outputDirectory>
@@ -152,7 +160,7 @@
<outputDirectory>docs/struts2-plugins/struts2-jsf-plugin</outputDirectory>
</fileSet>
<fileSet>
<directory>../plugins/jsf/target/site</directory>
<directory>../plugins/junit/target/site</directory>
<outputDirectory>docs/struts2-plugins/struts2-junit-plugin</outputDirectory>
</fileSet>
<fileSet>
@@ -188,7 +196,7 @@
<outputDirectory>docs/struts2-plugins/struts2-sitemesh-plugin</outputDirectory>
</fileSet>
<fileSet>
<directory>../plugins/tiles/target/site</directory>
<directory>../plugins/testng/target/site</directory>
<outputDirectory>docs/struts2-plugins/struts2-testng-plugin</outputDirectory>
</fileSet>
<fileSet>
+2 -2
View File
@@ -84,7 +84,7 @@
<outputDirectory>docs/struts2-plugins/struts2-jsf-plugin</outputDirectory>
</fileSet>
<fileSet>
<directory>../plugins/jsf/target/site</directory>
<directory>../plugins/junit/target/site</directory>
<outputDirectory>docs/struts2-plugins/struts2-junit-plugin</outputDirectory>
</fileSet>
<fileSet>
@@ -120,7 +120,7 @@
<outputDirectory>docs/struts2-plugins/struts2-sitemesh-plugin</outputDirectory>
</fileSet>
<fileSet>
<directory>../plugins/tiles/target/site</directory>
<directory>../plugins/testng/target/site</directory>
<outputDirectory>docs/struts2-plugins/struts2-testng-plugin</outputDirectory>
</fileSet>
<fileSet>
+7 -8
View File
@@ -26,7 +26,7 @@
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-parent</artifactId>
<version>2.1.2-SNAPSHOT</version>
<version>2.1.3</version>
</parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
@@ -34,9 +34,9 @@
<name>Struts 2 Core</name>
<scm>
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/core/</connection>
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/trunk/core/</developerConnection>
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/trunk/core/</url>
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/core</connection>
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/core</developerConnection>
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_1_3/core</url>
</scm>
<build>
@@ -56,7 +56,7 @@
<artifactItem>
<groupId>com.opensymphony</groupId>
<artifactId>xwork</artifactId>
<version>2.1.1</version>
<version>2.1.2</version>
<classifier>sources</classifier>
</artifactItem>
</artifactItems>
@@ -229,7 +229,7 @@
<dependency>
<groupId>com.opensymphony</groupId>
<artifactId>xwork</artifactId>
<version>2.1.1</version>
<version>2.1.2</version>
</dependency>
<!--<dependency>-->
@@ -241,7 +241,7 @@
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.12</version>
<version>2.3.13</version>
</dependency>
<dependency>
@@ -392,7 +392,6 @@
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts-annotations</artifactId>
<version>1.0.3</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
@@ -118,9 +118,15 @@ public final class StrutsConstants {
*/
public static final String STRUTS_MULTIPART_PARSER = "struts.multipart.parser";
/** Whether Spring should autoWire or not */
/** How Spring should autowire. Valid values are 'name', 'type', 'auto', and 'constructor' */
public static final String STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE = "struts.objectFactory.spring.autoWire";
/** Whether the autowire strategy chosen by STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE is always respected. Defaults
* to false, which is the legacy behavior that tries to determine the best strategy for the situation.
* @since 2.1.3
*/
public static final String STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE_ALWAYS_RESPECT = "struts.objectFactory.spring.autoWire.alwaysRespect";
/** Whether Spring should use its class cache or not */
public static final String STRUTS_OBJECTFACTORY_SPRING_USE_CLASS_CACHE = "struts.objectFactory.spring.useClassCache";
@@ -184,4 +190,9 @@ public final class StrutsConstants {
/** The {@link com.opensymphony.xwork2.util.PatternMatcher} implementation class */
public static final String STRUTS_PATTERNMATCHER = "struts.patternMatcher";
/** The {@link org.apache.struts2.dispatcher.StaticContentLoader} implementation class */
public static final String STRUTS_STATIC_CONTENT_LOADER = "struts.staticContentLoader";
/** The {@link com.opensymphony.xwork2.UnknownHandlerManager} implementation class */
public static final String STRUTS_UNKNOWN_HANDLER_MANAGER = "struts.unknownHandlerManager";
}
@@ -45,6 +45,7 @@ import org.apache.struts2.views.jsp.TagUtils;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionProxyFactory;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;
@@ -190,7 +191,7 @@ public class ActionComponent extends ContextBean {
Map application = ctx.getApplication();
Dispatcher du = Dispatcher.getInstance();
Map extraContext = du.createContextMap(new RequestMap(req),
Map<String, Object> extraContext = du.createContextMap(new RequestMap(req),
newParams,
session,
application,
@@ -279,6 +280,7 @@ public class ActionComponent extends ContextBean {
// get the old value stack from the request
ValueStack stack = getStack();
// execute at this point, after params have been set
ActionInvocation inv = ActionContext.getContext().getActionInvocation();
try {
proxy = actionProxyFactory.createActionProxy(namespace, actionName, methodName, createExtraContext(), executeResult, true);
@@ -292,6 +294,9 @@ public class ActionComponent extends ContextBean {
} finally {
// set the old stack back on the request
req.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
if (inv != null) {
ActionContext.getContext().setActionInvocation(inv);
}
}
if ((getVar() != null) && (proxy != null)) {
@@ -243,25 +243,84 @@ public class Component {
return null;
}
if (altSyntax()) {
// does the expression start with %{ and end with }? if so, just cut it off!
if (expr.startsWith("%{") && expr.endsWith("}")) {
expr = expr.substring(2, expr.length() - 1);
}
}
expr = stripExpressionIfAltSyntax(expr);
return getStack().findValue(expr);
}
/**
* If altsyntax (%{...}) is applied, simply strip the "%{" and "}" off.
* @param expr the expression (must be not null)
* @return the stripped expression if altSyntax is enabled. Otherwise
* the parameter expression is returned as is.
*/
protected String stripExpressionIfAltSyntax(String expr) {
return stripExpressionIfAltSyntax(stack, expr);
}
/**
* If altsyntax (%{...}) is applied, simply strip the "%{" and "}" off.
* @param stack the ValueStack where the context value is searched for.
* @param expr the expression (must be not null)
* @return the stripped expression if altSyntax is enabled. Otherwise
* the parameter expression is returned as is.
*/
public static String stripExpressionIfAltSyntax(ValueStack stack, String expr) {
if (altSyntax(stack)) {
// does the expression start with %{ and end with }? if so, just cut it off!
if (expr.startsWith("%{") && expr.endsWith("}")) {
return expr.substring(2, expr.length() - 1);
}
}
return expr;
}
/**
* Is the altSyntax enabled? [TRUE]
* <p/>
* @param stack the ValueStack where the context value is searched for.
* @return true if altSyntax is activated. False otherwise.
* See <code>struts.properties</code> where the altSyntax flag is defined.
*/
public static boolean altSyntax(ValueStack stack) {
return ContextUtil.isUseAltSyntax(stack.getContext());
}
/**
* Is the altSyntax enabled? [TRUE]
* <p/>
* See <code>struts.properties</code> where the altSyntax flag is defined.
*/
public boolean altSyntax() {
return ContextUtil.isUseAltSyntax(stack.getContext());
return altSyntax(stack);
}
/**
* Adds the sorrounding %{ } to the expression for proper processing.
* @param expr the expression.
* @return the modified expression if altSyntax is enabled, or the parameter
* expression otherwise.
*/
protected String completeExpressionIfAltSyntax(String expr) {
if (altSyntax()) {
return "%{" + expr + "}";
}
return expr;
}
/**
* This check is needed for backwards compatibility with 2.1.x
* @param expr the expression.
* @return the found string if altSyntax is enabled. The parameter
* expression otherwise.
*/
protected String findStringIfAltSyntax(String expr) {
if (altSyntax()) {
return findString(expr);
}
return expr;
}
/**
* Evaluates the OGNL stack to find an Object value.
* <p/>
@@ -309,14 +368,9 @@ public class Component {
*/
protected Object findValue(String expr, Class toType) {
if (altSyntax() && toType == String.class) {
return TextParseUtil.translateVariables('%', expr, stack);
return TextParseUtil.translateVariables('%', expr, stack);
} else {
if (altSyntax()) {
// does the expression start with %{ and end with }? if so, just cut it off!
if (expr.startsWith("%{") && expr.endsWith("}")) {
expr = expr.substring(2, expr.length() - 1);
}
}
expr = stripExpressionIfAltSyntax(expr);
return getStack().findValue(expr, toType);
}
@@ -219,7 +219,7 @@ public class Date extends ContextBean {
*/
public String formatTime(TextProvider tp, java.util.Date date) {
java.util.Date now = new java.util.Date();
StringBuffer sb = new StringBuffer();
StringBuilder sb = new StringBuilder();
List args = new ArrayList();
long secs = Math.abs((now.getTime() - date.getTime()) / 1000);
long mins = secs / 60;
@@ -143,13 +143,7 @@ public abstract class DoubleListUIBean extends ListUIBean {
}
if (doubleListValue != null) {
if (altSyntax()) {
// the same logic as with findValue(String)
// if value start with %{ and end with }, just cut it off!
if (doubleListValue.startsWith("%{") && doubleListValue.endsWith("}")) {
doubleListValue = doubleListValue.substring(2, doubleListValue.length() - 1);
}
}
doubleListValue = stripExpressionIfAltSyntax(doubleListValue);
addParameter("doubleListValue", doubleListValue);
}else if (tmpDoubleList instanceof Map) {
@@ -186,11 +180,7 @@ public abstract class DoubleListUIBean extends ListUIBean {
Form form = (Form) findAncestor(Form.class);
if (doubleId != null) {
// this check is needed for backwards compatibility with 2.1.x
if (altSyntax()) {
addParameter("doubleId", findString(doubleId));
} else {
addParameter("doubleId", doubleId);
}
addParameter("doubleId", findStringIfAltSyntax(doubleId));
} else if (form != null) {
addParameter("doubleId", form.getParameters().get("id") + "_" +escape(this.doubleName));
} else {
@@ -21,16 +21,15 @@
package org.apache.struts2.components;
import java.util.ArrayList;
import java.util.List;
import com.opensymphony.xwork2.util.ValueStack;
import org.apache.struts2.components.Param.UnnamedParametric;
import org.apache.struts2.views.annotations.StrutsTag;
import org.apache.struts2.views.annotations.StrutsTagAttribute;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.views.annotations.StrutsTag;
import org.apache.struts2.components.Param.UnnamedParametric;
import com.opensymphony.xwork2.util.ValueStack;
import java.util.ArrayList;
import java.util.List;
/**
* <!-- START SNIPPET: javadoc -->
@@ -66,6 +65,10 @@ import com.opensymphony.xwork2.util.ValueStack;
* ....
* &lt;/s:form&gt;
*
* OR
*
* &lt;s:fielderror fieldName="field1" /&gt;
*
* <!-- END SNIPPET: example -->
* </pre>
*
@@ -87,7 +90,7 @@ import com.opensymphony.xwork2.util.ValueStack;
"or partial depending on param tag nested)if they exists")
public class FieldError extends UIBean implements UnnamedParametric {
private List errorFieldNames = new ArrayList();
private List<String> errorFieldNames = new ArrayList<String>();
public FieldError(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
super(stack, request, response);
@@ -99,14 +102,27 @@ public class FieldError extends UIBean implements UnnamedParametric {
return TEMPLATE;
}
@Override
protected void evaluateExtraParams() {
super.evaluateExtraParams();
if (errorFieldNames != null)
addParameter("errorFieldNames", errorFieldNames);
}
public void addParameter(Object value) {
if (value != null) {
errorFieldNames.add(value.toString());
}
}
public List getFieldErrorFieldNames() {
public List<String> getFieldErrorFieldNames() {
return errorFieldNames;
}
@StrutsTagAttribute(description="Field name for single field attribute usage", type="String")
public void setFieldName(String fieldName) {
addParameter(fieldName);
}
}
@@ -93,6 +93,7 @@ public class Form extends ClosingUIBean {
private int sequence = 0;
protected String onsubmit;
protected String onreset;
protected String action;
protected String target;
protected String enctype;
@@ -103,7 +104,7 @@ public class Form extends ClosingUIBean {
protected String windowState;
protected String acceptcharset;
protected String focusElement;
protected Configuration configuration;
protected ObjectFactory objectFactory;
protected UrlRenderer urlRenderer;
@@ -134,12 +135,12 @@ public class Form extends ClosingUIBean {
public void setObjectFactory(ObjectFactory objectFactory) {
this.objectFactory = objectFactory;
}
@Inject
public void setUrlRenderer(UrlRenderer urlRenderer) {
this.urlRenderer = urlRenderer;
}
@Inject
public void setActionValidatorManager(ActionValidatorManager mgr) {
this.actionValidatorManager = mgr;
@@ -178,6 +179,10 @@ public class Form extends ClosingUIBean {
addParameter("onsubmit", findString(onsubmit));
}
if (onreset != null) {
addParameter("onreset", findString(onreset));
}
if (target != null) {
addParameter("target", findString(target));
}
@@ -200,7 +205,7 @@ public class Form extends ClosingUIBean {
// we have this if check so we don't do this twice (on open and close of the template)
addParameter("tagNames", new ArrayList());
}
if (focusElement != null) {
addParameter("focusElement", findString(focusElement));
}
@@ -295,6 +300,11 @@ public class Form extends ClosingUIBean {
this.onsubmit = onsubmit;
}
@StrutsTagAttribute(description="HTML onreset attribute")
public void setOnreset(String onreset) {
this.onreset = onreset;
}
@StrutsTagAttribute(description="Set action name to submit to, without .action suffix", defaultValue="current action")
public void setAction(String action) {
this.action = action;
@@ -34,7 +34,7 @@ import com.opensymphony.xwork2.inject.Inject;
/**
* FormButton.
*/
public abstract class FormButton extends UIBean {
public abstract class FormButton extends ClosingUIBean {
static final String BUTTONTYPE_INPUT = "input";
static final String BUTTONTYPE_BUTTON = "button";
@@ -111,11 +111,7 @@ public abstract class FormButton extends UIBean {
String _tmp_id = "";
if (id != null) {
// this check is needed for backwards compatibility with 2.1.x
if (altSyntax()) {
_tmp_id = findString(id);
} else {
_tmp_id = id;
}
_tmp_id = findStringIfAltSyntax(id);
}
else {
if (form != null && form.getParameters().get("id") != null) {
@@ -124,7 +124,7 @@ public class Include extends Component {
public boolean end(Writer writer, String body) {
String page = findString(value, "value", "You must specify the URL to include. Example: /foo.jsp");
StringBuffer urlBuf = new StringBuffer();
StringBuilder urlBuf = new StringBuilder();
// Add URL
urlBuf.append(page);
@@ -212,7 +212,7 @@ public class Include extends Component {
}
}
StringBuffer flatPathBuffer = new StringBuffer();
StringBuilder flatPathBuffer = new StringBuilder();
for (int i = 0; i < stack.size(); i++) {
flatPathBuffer.append("/").append(stack.elementAt(i));
@@ -34,16 +34,16 @@ import com.opensymphony.xwork2.util.ValueStack;
/**
* <!-- START SNIPPET: javadoc -->
*
* <p>Iterator will iterate over a value. An iterable value can be either of: java.util.Collection, java.util.Iterator,
* java.util.Enumeration, java.util.Map, array.</p> <p/> <!-- END SNIPPET: javadoc -->
* <p>Iterator will iterate over a value. An iterable value can be any of: java.util.Collection, java.util.Iterator,
* java.util.Enumeration, java.util.Map, or an array.</p> <p/> <!-- END SNIPPET: javadoc -->
*
* <!-- START SNIPPET: params -->
*
* <ul>
*
* <li>status (String) - if specified, an instanceof IteratorStatus will be pushed into stack upon each iteration</li>
* <li>status (String) - if specified, an instance of IteratorStatus will be pushed into stack upon each iteration</li>
*
* <li>value (Object) - the source to iterate over, must be iteratable, else an the object itself will be put into a
* <li>value (Object) - the source to iterate over, must be iteratable, else the object itself will be put into a
* newly created List (see MakeIterator#convert(Object)</li>
*
* <li>id (String) - if specified the current iteration object will be place with this id in Struts stack's context
@@ -73,7 +73,7 @@ import com.opensymphony.xwork2.util.ValueStack;
*
* <p>The following example uses a {@link Bean} tag and places it into the ActionContext. The iterator tag will retrieve
* that object from the ActionContext and then calls its getDays() method as above. The status attribute is also used to
* create a {@link IteratorStatus} object, which in this example, its odd() method is used to alternate row
* create an {@link IteratorStatus} object, which in this example, its odd() method is used to alternate row
* colours:</p>
*
* <!-- END SNIPPET: example2description -->
@@ -111,7 +111,7 @@ import com.opensymphony.xwork2.util.ValueStack;
*
* <p> The next example will further demonstrate the use of the status attribute, using a DAO obtained from the action
* class through OGNL, iterating over groups and their users (in a security context). The last() method indicates if the
* current object is the last available in the iteration, and if not, we need to seperate the users using a comma: </p>
* current object is the last available in the iteration, and if not, we need to separate the users using a comma: </p>
*
* <!-- END SNIPPET: example3description -->
*
@@ -175,13 +175,32 @@ import com.opensymphony.xwork2.util.ValueStack;
* &lt;s:property value="#stat.index" /&gt;
*
* &lt;!-- grab the top of the stack which should be the --&gt;
* &lt;!-- current iteration value (0, 1, ... 5) --&gt;
* &lt;!-- current iteration value (1, ... 5) --&gt;
* &lt;s:property value="top" /&gt;
* &lt;/s:iterator&gt;
*
* <!-- END SNIPPET: example5code -->
* </pre>
*
* <!-- START SNIPPET: example6description -->
*
* </p>Another way to create a simple loop, similar to JSTL's
* &lt;c:forEach begin="..." end="..." ...&gt; is to use some
* OGNL magic, which provides some under-the-covers magic to
* make 0-n loops trivial. This example also loops five times.
*
* <!-- END SNIPPET: example6description -->
*
* <pre>
* <!-- START SNIPPET: example6code -->
*
* &lt;s:iterator status="stat" value="(5).{ #this }" &gt;
* &lt;s:property value="#stat.count" /&gt; &lt;!-- Note that "count" is 1-based, "index" is 0-based. --&gt;
* &lt;/s:iterator&gt;
*
* <!-- END SNIPPET: example6code -->
* </pre>
*
*/
@StrutsTag(name="iterator", tldTagClass="org.apache.struts2.views.jsp.IteratorTag", description="Iterate over a iterable value")
public class IteratorComponent extends ContextBean {
@@ -88,10 +88,7 @@ public class Label extends UIBean {
String providedLabel = TextProviderHelper.getText(key, key, stack);
addParameter("nameValue", providedLabel);
} else if (name != null) {
String expr = name;
if (altSyntax()) {
expr = "%{" + expr + "}";
}
String expr = completeExpressionIfAltSyntax(name);
addParameter("nameValue", findString(expr));
}
}
@@ -43,7 +43,7 @@ import com.opensymphony.xwork2.util.ValueStack;
*
* Note that the listkey and listvalue attribute will default to "key" and "value"
* respectively only when the list attribute is evaluated to a Map or its decendant.
* Other thing else, will result in listkey and listvalue to be null and not used.
* Everything else will result in listkey and listvalue to be null and not used.
*
* <!-- END SNIPPET: javadoc -->
*
@@ -103,19 +103,14 @@ public abstract class ListUIBean extends UIBean {
}
if (listKey != null) {
listKey = stripExpressionIfAltSyntax(listKey);
addParameter("listKey", listKey);
} else if (value instanceof Map) {
addParameter("listKey", "key");
}
if (listValue != null) {
if (altSyntax()) {
// the same logic as with findValue(String)
// if value start with %{ and end with }, just cut it off!
if (listValue.startsWith("%{") && listValue.endsWith("}")) {
listValue = listValue.substring(2, listValue.length() - 1);
}
}
listValue = stripExpressionIfAltSyntax(listValue);
addParameter("listValue", listValue);
} else if (value instanceof Map) {
addParameter("listValue", "value");
@@ -99,6 +99,7 @@ public class Property extends Component {
private String defaultValue;
private String value;
private boolean escape = true;
private boolean escapeJavaScript = false;
@StrutsTagAttribute(description="The default value to be used if <u>value</u> attribute is null")
public void setDefault(String defaultValue) {
@@ -110,6 +111,11 @@ public class Property extends Component {
this.escape = escape;
}
@StrutsTagAttribute(description="Whether to escape Javascript", type="Boolean", defaultValue="false")
public void setEscapeJavaScript(boolean escapeJavaScript) {
this.escapeJavaScript = escapeJavaScript;
}
@StrutsTagAttribute(description="Value to be displayed", type="Object", defaultValue="&lt;top of stack&gt;")
public void setValue(String value) {
this.value = value;
@@ -123,12 +129,8 @@ public class Property extends Component {
if (value == null) {
value = "top";
}
else if (altSyntax()) {
// the same logic as with findValue(String)
// if value start with %{ and end with }, just cut it off!
if (value.startsWith("%{") && value.endsWith("}")) {
value = value.substring(2, value.length() - 1);
}
else {
value = stripExpressionIfAltSyntax(value);
}
// exception: don't call findString(), since we don't want the
@@ -150,10 +152,13 @@ public class Property extends Component {
}
private String prepare(String value) {
String result = value;
if (escape) {
return TextUtils.htmlEncode(value);
} else {
return value;
result = TextUtils.htmlEncode(result);
}
if (escapeJavaScript) {
result = TextUtils.escapeJavaScript(result);
}
return result;
}
}
@@ -74,6 +74,9 @@ public class Reset extends FormButton {
super(stack, request, response);
}
public String getDefaultOpenTemplate() {
return "empty";
}
protected String getDefaultTemplate() {
return Reset.TEMPLATE;
}
@@ -82,7 +82,7 @@ public class ServletUrlRenderer implements UrlRenderer {
result = UrlHelper.buildUrl(_value, urlComponent.req, urlComponent.res, urlComponent.parameters, scheme, urlComponent.includeContext, urlComponent.encode, urlComponent.forceAddSchemeHostAndPort, urlComponent.escapeAmp);
}
if ( urlComponent.anchor != null && urlComponent.anchor.length() > 0 ) {
result += '#' + urlComponent.anchor;
result += '#' + urlComponent.findString(urlComponent.anchor);
}
String var = urlComponent.getVar();
@@ -131,10 +131,10 @@ public class ServletUrlRenderer implements UrlRenderer {
String actionMethod = nameMapping.getMethod();
final ActionConfig actionConfig = formComponent.configuration.getRuntimeConfiguration().getActionConfig(
namespace, action);
namespace, actionName);
if (actionConfig != null) {
ActionMapping mapping = new ActionMapping(action, namespace, actionMethod, formComponent.parameters);
ActionMapping mapping = new ActionMapping(actionName, namespace, actionMethod, formComponent.parameters);
String result = UrlHelper.buildUrl(formComponent.actionMapper.getUriFromActionMapping(mapping),
formComponent.request, formComponent.response, null);
formComponent.addParameter("action", result);
@@ -153,14 +153,14 @@ public class ServletUrlRenderer implements UrlRenderer {
// if the name isn't specified, use the action name
if (formComponent.name == null) {
formComponent.addParameter("name", action);
formComponent.addParameter("name", actionName);
}
// if the id isn't specified, use the action name
if (formComponent.getId() == null && action!=null ) {
formComponent.addParameter("id", formComponent.escape(action));
if (formComponent.getId() == null && actionName!=null ) {
formComponent.addParameter("id", formComponent.escape(actionName));
}
} else if (action != null) {
} else if (actionName != null) {
// Since we can't find an action alias in the configuration, we just
// assume the action attribute supplied is the path to be used as
// the URI this form is submitting to.
@@ -168,10 +168,10 @@ public class ServletUrlRenderer implements UrlRenderer {
// Warn user that the specified namespace/action combo
// was not found in the configuration.
if (namespace != null) {
LOG.warn("No configuration found for the specified action: '" + action + "' in namespace: '" + namespace + "'. Form action defaulting to 'action' attribute's literal value.");
LOG.warn("No configuration found for the specified action: '" + actionName + "' in namespace: '" + namespace + "'. Form action defaulting to 'action' attribute's literal value.");
}
String result = UrlHelper.buildUrl(action, formComponent.request, formComponent.response, null);
String result = UrlHelper.buildUrl(actionName, formComponent.request, formComponent.response, null);
formComponent.addParameter("action", result);
// namespace: cut out anything between the start and the last /
@@ -52,15 +52,20 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
description="Render a submit button",
allowDynamicAttributes=true)
public class Submit extends FormButton {
private static final Logger LOG = LoggerFactory.getLogger(Submit.class);
final public static String TEMPLATE = "submit";
final public static String OPEN_TEMPLATE = "submit";
final public static String TEMPLATE = "submit-close";
protected String src;
public Submit(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
super(stack, request, response);
}
public String getDefaultOpenTemplate() {
return OPEN_TEMPLATE;
}
protected String getDefaultTemplate() {
return TEMPLATE;
}
@@ -76,10 +81,10 @@ public class Submit extends FormButton {
super.evaluateParams();
}
public void evaluateExtraParams() {
super.evaluateExtraParams();
if (src != null)
addParameter("src", findString(src));
}
@@ -92,12 +97,18 @@ public class Submit extends FormButton {
protected boolean supportsImageType() {
return true;
}
@StrutsTagAttribute(description="Supply an image src for <i>image</i> type submit button. Will have no effect for types <i>input</i> and <i>button</i>.")
public void setSrc(String src) {
this.src = src;
}
@Override
public boolean usesBody() {
return true;
}
/**
* Overrides to be able to render body in a template rather than always before the template
*/
@@ -105,7 +116,7 @@ public class Submit extends FormButton {
evaluateParams();
try {
addParameter("body", body);
mergeTemplate(writer, buildTemplateName(template, getDefaultTemplate()));
} catch (Exception e) {
LOG.error("error when rendering", e);
@@ -50,8 +50,10 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
*
* <p/>
*
* If the named message is not found, then the body of the tag will be used as default message.
* If no body is used, then the name of the message will be used.
* If the named message is not found in a property file, then the body of the
* tag will be used as default message. If no body is used, then the stack will
* be searched, and if a value is returned, it will written to the output.
* If no value is found on the stack, the key of the message will be written out.
*
* <!-- END SNIPPET: javadoc -->
*
@@ -123,6 +125,7 @@ public class Text extends ContextBean implements Param.UnnamedParametric {
protected List values = Collections.EMPTY_LIST;
protected String actualName;
protected String name;
protected String searchStack;
public Text(ValueStack stack) {
super(stack);
@@ -133,6 +136,10 @@ public class Text extends ContextBean implements Param.UnnamedParametric {
this.name = name;
}
@StrutsTagAttribute(description="Search the stack if property is not found on resources", type = "Boolean", defaultValue = "true")
public void setSearchValueStack(String searchStack) {
this.searchStack = searchStack;
}
public boolean usesBody() {
// overriding this to true such that EVAL_BODY_BUFFERED is return and
@@ -150,7 +157,8 @@ public class Text extends ContextBean implements Param.UnnamedParametric {
defaultMessage = actualName;
}
String msg = TextProviderHelper.getText(actualName, defaultMessage, values, getStack());
Boolean doSearchStack = searchStack != null ? (Boolean) findValue(searchStack, Boolean.class) : true;
String msg = TextProviderHelper.getText(actualName, defaultMessage, values, getStack(), doSearchStack == null || doSearchStack);
if (msg != null) {
try {
@@ -32,6 +32,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsException;
import org.apache.struts2.util.TextProviderHelper;
import org.apache.struts2.components.template.Template;
import org.apache.struts2.components.template.TemplateEngine;
@@ -511,7 +512,7 @@ public abstract class UIBean extends Component {
super.end(writer, body, false);
mergeTemplate(writer, buildTemplateName(template, getDefaultTemplate()));
} catch (Exception e) {
LOG.error("error when rendering", e);
throw new StrutsException(e);
}
finally {
popComponentStack();
@@ -763,10 +764,7 @@ public abstract class UIBean extends Component {
if (value != null) {
addParameter("nameValue", findValue(value, valueClazz));
} else if (name != null) {
String expr = name;
if (altSyntax()) {
expr = "%{" + expr + "}";
}
String expr = completeExpressionIfAltSyntax(name);
addParameter("nameValue", findValue(expr, valueClazz));
}
@@ -858,7 +856,7 @@ public abstract class UIBean extends Component {
evaluateExtraParams();
}
protected String escape(String name) {
protected String escape(String name) {
// escape any possible values that can make the ID painful to work with in JavaScript
if (name != null) {
return name.replaceAll("[^a-zA-Z0-9_]", "_");
@@ -965,11 +963,7 @@ public abstract class UIBean extends Component {
String tryId;
if (id != null) {
// this check is needed for backwards compatibility with 2.1.x
if (altSyntax()) {
tryId = findString(id);
} else {
tryId = id;
}
tryId = findStringIfAltSyntax(id);
} else if (form != null) {
tryId = form.getParameters().get("id") + "_"
+ escape(name != null ? findString(name) : null);
@@ -1044,12 +1038,12 @@ public abstract class UIBean extends Component {
this.disabled = disabled;
}
@StrutsTagAttribute(description="Label expression used for rendering a element specific label")
@StrutsTagAttribute(description="Label expression used for rendering an element specific label")
public void setLabel(String label) {
this.label = label;
}
@StrutsTagAttribute(description="String that will be appended to the labe", defaultValue=":")
@StrutsTagAttribute(description="String that will be appended to the label", defaultValue=":")
public void setLabelSeparator(String labelseparator) {
this.labelSeparator = labelseparator;
}
@@ -46,17 +46,17 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
* <p>This tag is used to create a URL.</p>
*
* <p>You can use the &lt;param&gt; tag inside the body to provide
* additional request parameters. If the value of a param is an Array or
* additional request parameters. If the value of a param is an Array or
* an Iterable all the values will be added to the URL.</p>
*
* <b>NOTE:</b>
* <p>By default request parameters will be separated using escaped ampersands (i.e., &amp;amp;).
* This is necessary for XHTML compliance, however, when using the URL generated by this tag
* with the &lt;s:property&gt; tag, the <b>escapeAmp</b> attribute should be used to disable
* ampersand escaping.</p>
*
* ampersand escaping.</p>
*
* <b>NOTE:</b>
* <p>When includeParams is 'all' or 'get', the parameter defined in a &lt;param&gt;
* <p>When includeParams is 'all' or 'get', the parameter defined in a &lt;param&gt;
* tag will take precedence over any params included due to the includeParams attribute. For
* example, in Example 3 below, if there is a id parameter in the url where the page this
* tag is included like http://&lt;host&gt;:&lt;port&gt;/&lt;context&gt;/editUser.action?id=3333&name=John
@@ -163,7 +163,7 @@ public class URL extends ContextBean {
public void setUrlIncludeParams(String urlIncludeParams) {
this.urlIncludeParams = urlIncludeParams;
}
@Inject
public void setUrlRenderer(UrlRenderer urlRenderer) {
this.urlRenderer = urlRenderer;
@@ -185,7 +185,7 @@ public class URL extends ContextBean {
return super.end(writer, body);
}
@StrutsTagAttribute(description="The includeParams attribute may have the value 'none', 'get' or 'all'", defaultValue="get")
@StrutsTagAttribute(description="The includeParams attribute may have the value 'none', 'get' or 'all'", defaultValue="none")
public void setIncludeParams(String includeParams) {
this.includeParams = includeParams;
}
@@ -244,7 +244,7 @@ public class URL extends ContextBean {
public void setAnchor(String anchor) {
this.anchor = anchor;
}
@StrutsTagAttribute(description="Specifies whether to escape ampersand (&amp;) to (&amp;amp;) or not", type="Boolean", defaultValue="true")
public void setEscapeAmp(boolean escapeAmp) {
this.escapeAmp = escapeAmp;
@@ -23,10 +23,9 @@ package org.apache.struts2.components.template;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
@@ -55,8 +54,8 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine {
static Class bodyContent = null;
private FreemarkerManager freemarkerManager;
private final HashMap<String, freemarker.template.Template> templates = new HashMap<String, freemarker.template.Template>();
private final HashSet<String> missingTemplates = new HashSet<String>();
private final Map<String, freemarker.template.Template> templates = new ConcurrentHashMap<String, freemarker.template.Template>();
private final Set<String> missingTemplates = new CopyOnWriteArraySet<String>();
private boolean freemarkerCaching = false;
static {
@@ -163,22 +162,20 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine {
// the BodyContent JSP writer doesn't like it when FM flushes automatically --
// so let's just not do it (it will be flushed eventually anyway)
Writer writer = templateContext.getWriter();
if (bodyContent != null && bodyContent.isAssignableFrom(writer.getClass())) {
final Writer wrapped = writer;
writer = new Writer() {
public void write(char cbuf[], int off, int len) throws IOException {
wrapped.write(cbuf, off, len);
}
final Writer wrapped = writer;
writer = new Writer() {
public void write(char cbuf[], int off, int len) throws IOException {
wrapped.write(cbuf, off, len);
}
public void flush() throws IOException {
// nothing!
}
public void flush() throws IOException {
// nothing!
}
public void close() throws IOException {
wrapped.close();
}
};
}
public void close() throws IOException {
wrapped.close();
}
};
try {
stack.push(templateContext.getTag());
@@ -193,28 +190,20 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine {
}
protected void addToMissingTemplateCache(String templateName) {
synchronized(missingTemplates) {
missingTemplates.add(templateName);
}
missingTemplates.add(templateName);
}
protected boolean isTemplateMissing(String templateName) {
synchronized(missingTemplates) {
return missingTemplates.contains(templateName);
}
return missingTemplates.contains(templateName);
}
protected void addToCache(String templateName,
freemarker.template.Template template) {
synchronized(templates) {
templates.put(templateName, template);
}
templates.put(templateName, template);
}
protected freemarker.template.Template findInCache(String templateName) {
synchronized(templates) {
return templates.get(templateName);
}
return templates.get(templateName);
}
/**
@@ -26,6 +26,8 @@ import java.util.StringTokenizer;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.components.UrlRenderer;
import org.apache.struts2.dispatcher.DefaultStaticContentLoader;
import org.apache.struts2.dispatcher.StaticContentLoader;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
import org.apache.struts2.views.freemarker.FreemarkerManager;
@@ -34,6 +36,7 @@ import org.apache.struts2.views.velocity.VelocityManager;
import com.opensymphony.xwork2.ActionProxyFactory;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.TextProvider;
import com.opensymphony.xwork2.UnknownHandlerManager;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.config.ConfigurationProvider;
@@ -44,10 +47,7 @@ import com.opensymphony.xwork2.inject.ContainerBuilder;
import com.opensymphony.xwork2.inject.Context;
import com.opensymphony.xwork2.inject.Factory;
import com.opensymphony.xwork2.inject.Scope;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import com.opensymphony.xwork2.util.PatternMatcher;
import com.opensymphony.xwork2.util.ValueStackFactory;
import com.opensymphony.xwork2.util.*;
import com.opensymphony.xwork2.util.location.LocatableProperties;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
@@ -151,6 +151,12 @@ import com.opensymphony.xwork2.validator.ActionValidatorManager;
* <td>singleton</td>
* <td>Matches patterns, such as action names, generally used in configuration (since 2.1)</td>
* </tr>
* <tr>
* <td>org.apache.struts2.views.dispatcher.DefaultStaticContentLoader</td>
* <td>struts.staticContentLoader</td>
* <td>singleton</td>
* <td>Loads static resources (since 2.1)</td>
* </tr>
* </table>
*
* <!-- END SNIPPET: extensionPoints -->
@@ -209,6 +215,8 @@ public class BeanSelectionProvider implements ConfigurationProvider {
alias(ReflectionProvider.class, StrutsConstants.STRUTS_REFLECTIONPROVIDER, builder, props);
alias(ReflectionContextFactory.class, StrutsConstants.STRUTS_REFLECTIONCONTEXTFACTORY, builder, props);
alias(PatternMatcher.class, StrutsConstants.STRUTS_PATTERNMATCHER, builder, props);
alias(StaticContentLoader.class, StrutsConstants.STRUTS_STATIC_CONTENT_LOADER, builder, props);
alias(UnknownHandlerManager.class, StrutsConstants.STRUTS_UNKNOWN_HANDLER_MANAGER, builder, props);
if ("true".equalsIgnoreCase(props.getProperty(StrutsConstants.STRUTS_DEVMODE))) {
props.setProperty(StrutsConstants.STRUTS_I18N_RELOAD, "true");
@@ -77,6 +77,7 @@ public class StrutsXmlConfigurationProvider extends XmlConfigurationProvider {
reloadKey = "configurationReload-"+filename;
Map<String,String> dtdMappings = new HashMap<String,String>(getDtdMappings());
dtdMappings.put("-//Apache Software Foundation//DTD Struts Configuration 2.0//EN", "struts-2.0.dtd");
dtdMappings.put("-//Apache Software Foundation//DTD Struts Configuration 2.1//EN", "struts-2.1.dtd");
setDtdMappings(dtdMappings);
File file = new File(filename);
if (file.getParent() != null) {
@@ -59,8 +59,13 @@ import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
* <!-- SNIPPET END: description -->
*
*
* @deprecated Since Struts 2.1.3, use {@link org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter} and
* {@link org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter} to use other Servlet filters that need access to
* the ActionContext
* @see FilterDispatcher
* @see Dispatcher
* @see org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter
* @see org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter
*
* @version $Date$ $Id$
*/
@@ -0,0 +1,356 @@
/*
* $Id$
*
* 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.dispatcher;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.StringTokenizer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.dispatcher.ng.HostConfig;
import org.apache.struts2.util.ClassLoaderUtils;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
public class DefaultStaticContentLoader implements StaticContentLoader {
/**
* Provide a logging instance.
*/
private Logger log;
/**
* Store set of path prefixes to use with static resources.
*/
protected String[] pathPrefixes;
/**
* Store state of StrutsConstants.STRUTS_SERVE_STATIC_CONTENT setting.
*/
protected boolean serveStatic;
/**
* Store state of StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE setting.
*/
protected boolean serveStaticBrowserCache;
/**
* Provide a formatted date for setting heading information when caching static content.
*/
protected final Calendar lastModifiedCal = Calendar.getInstance();
/**
* Store state of StrutsConstants.STRUTS_I18N_ENCODING setting.
*/
protected String encoding;
/**
* Modify state of StrutsConstants.STRUTS_SERVE_STATIC_CONTENT setting.
*
* @param val
* New setting
*/
@Inject(StrutsConstants.STRUTS_SERVE_STATIC_CONTENT)
public void setServeStaticContent(String val) {
serveStatic = "true".equals(val);
}
/**
* Modify state of StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE
* setting.
*
* @param val
* New setting
*/
@Inject(StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE)
public void setServeStaticBrowserCache(String val) {
serveStaticBrowserCache = "true".equals(val);
}
/**
* Modify state of StrutsConstants.STRUTS_I18N_ENCODING setting.
* @param val New setting
*/
@Inject(StrutsConstants.STRUTS_I18N_ENCODING)
public void setEncoding(String val) {
encoding = val;
}
/*
* (non-Javadoc)
*
* @see org.apache.struts2.dispatcher.StaticResourceLoader#setHostConfig(javax.servlet.FilterConfig)
*/
public void setHostConfig(HostConfig filterConfig) {
String param = filterConfig.getInitParameter("packages");
String packages = getAdditionalPackages();
if (param != null) {
packages = param + " " + packages;
}
this.pathPrefixes = parse(packages);
initLogging(filterConfig);
}
protected String getAdditionalPackages() {
return "org.apache.struts2.static template org.apache.struts2.interceptor.debugging static";
}
/**
* Create a string array from a comma-delimited list of packages.
*
* @param packages
* A comma-delimited String listing packages
* @return A string array of packages
*/
protected String[] parse(String packages) {
if (packages == null) {
return null;
}
List<String> pathPrefixes = new ArrayList<String>();
StringTokenizer st = new StringTokenizer(packages, ", \n\t");
while (st.hasMoreTokens()) {
String pathPrefix = st.nextToken().replace('.', '/');
if (!pathPrefix.endsWith("/")) {
pathPrefix += "/";
}
pathPrefixes.add(pathPrefix);
}
return pathPrefixes.toArray(new String[pathPrefixes.size()]);
}
/*
* (non-Javadoc)
*
* @see org.apache.struts2.dispatcher.StaticResourceLoader#findStaticResource(java.lang.String,
* javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
public void findStaticResource(String path, HttpServletRequest request, HttpServletResponse response)
throws IOException {
String name = cleanupPath(path);
for (String pathPrefix : pathPrefixes) {
URL resourceUrl = findResource(buildPath(name, pathPrefix));
if (resourceUrl != null) {
InputStream is = null;
try {
//check that the resource path is under the pathPrefix path
String pathEnding = buildPath(name, pathPrefix);
if (resourceUrl.getFile().endsWith(pathEnding))
is = resourceUrl.openStream();
} catch (Exception ex) {
// just ignore it
continue;
}
//not inside the try block, as this could throw IOExceptions also
if (is != null) {
process(is, path, request, response);
return;
}
}
}
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
protected void process(InputStream is, String path, HttpServletRequest request, HttpServletResponse response) throws IOException {
if (is != null) {
Calendar cal = Calendar.getInstance();
// check for if-modified-since, prior to any other headers
long ifModifiedSince = 0;
try {
ifModifiedSince = request.getDateHeader("If-Modified-Since");
} catch (Exception e) {
log.warn("Invalid If-Modified-Since header value: '"
+ request.getHeader("If-Modified-Since") + "', ignoring");
}
long lastModifiedMillis = lastModifiedCal.getTimeInMillis();
long now = cal.getTimeInMillis();
cal.add(Calendar.DAY_OF_MONTH, 1);
long expires = cal.getTimeInMillis();
if (ifModifiedSince > 0 && ifModifiedSince <= lastModifiedMillis) {
// not modified, content is not sent - only basic
// headers and status SC_NOT_MODIFIED
response.setDateHeader("Expires", expires);
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
is.close();
return;
}
// set the content-type header
String contentType = getContentType(path);
if (contentType != null) {
response.setContentType(contentType);
}
if (serveStaticBrowserCache) {
// set heading information for caching static content
response.setDateHeader("Date", now);
response.setDateHeader("Expires", expires);
response.setDateHeader("Retry-After", expires);
response.setHeader("Cache-Control", "public");
response.setDateHeader("Last-Modified", lastModifiedMillis);
} else {
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setHeader("Expires", "-1");
}
try {
copy(is, response.getOutputStream());
} finally {
is.close();
}
return;
}
}
private void initLogging(HostConfig filterConfig) {
String factoryName = filterConfig.getInitParameter("loggerFactory");
if (factoryName != null) {
try {
Class cls = ClassLoaderUtils.loadClass(factoryName, this.getClass());
LoggerFactory fac = (LoggerFactory)cls.newInstance();
LoggerFactory.setLoggerFactory(fac);
} catch (InstantiationException e) {
System.err.println("Unable to instantiate logger factory: "+factoryName+", using default");
e.printStackTrace();
} catch (IllegalAccessException e) {
System.err.println("Unable to access logger factory: "+factoryName+", using default");
e.printStackTrace();
} catch (ClassNotFoundException e) {
System.err.println("Unable to locate logger factory class: "+factoryName+", using default");
e.printStackTrace();
}
}
log = LoggerFactory.getLogger(FilterDispatcher.class);
}
/**
* Look for a static resource in the classpath.
*
* @param path The resource path
* @return The inputstream of the resource
* @throws IOException If there is a problem locating the resource
*/
protected URL findResource(String path) throws IOException {
return ClassLoaderUtil.getResource(path, getClass());
}
/**
* @param name resource name
* @param packagePrefix The package prefix to use to locate the resource
* @return full path
* @throws UnsupportedEncodingException
* @throws IOException
*/
protected String buildPath(String name, String packagePrefix) throws UnsupportedEncodingException {
String resourcePath;
if (packagePrefix.endsWith("/") && name.startsWith("/")) {
resourcePath = packagePrefix + name.substring(1);
} else {
resourcePath = packagePrefix + name;
}
return URLDecoder.decode(resourcePath, encoding);
}
/**
* Determine the content type for the resource name.
*
* @param name The resource name
* @return The mime type
*/
protected String getContentType(String name) {
// NOT using the code provided activation.jar to avoid adding yet another dependency
// this is generally OK, since these are the main files we server up
if (name.endsWith(".js")) {
return "text/javascript";
} else if (name.endsWith(".css")) {
return "text/css";
} else if (name.endsWith(".html")) {
return "text/html";
} else if (name.endsWith(".txt")) {
return "text/plain";
} else if (name.endsWith(".gif")) {
return "image/gif";
} else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) {
return "image/jpeg";
} else if (name.endsWith(".png")) {
return "image/png";
} else {
return null;
}
}
/**
* Copy bytes from the input stream to the output stream.
*
* @param input
* The input stream
* @param output
* The output stream
* @throws IOException
* If anything goes wrong
*/
protected void copy(InputStream input, OutputStream output) throws IOException {
final byte[] buffer = new byte[4096];
int n;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
output.flush();
}
public boolean canHandle(String resourcePath) {
return serveStatic && (resourcePath.startsWith("/struts") || resourcePath.startsWith("/static"));
}
/**
* @param path requested path
* @return path without leading "/struts" or "/static"
*/
protected String cleanupPath(String path) {
//path will start with "/struts" or "/static", remove them
return path.substring(7);
}
}
@@ -24,10 +24,14 @@ package org.apache.struts2.dispatcher;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
@@ -58,10 +62,14 @@ import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.config.ConfigurationManager;
import com.opensymphony.xwork2.config.ConfigurationProvider;
import com.opensymphony.xwork2.config.entities.InterceptorMapping;
import com.opensymphony.xwork2.config.entities.InterceptorStackConfig;
import com.opensymphony.xwork2.config.entities.PackageConfig;
import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
import com.opensymphony.xwork2.inject.Container;
import com.opensymphony.xwork2.inject.ContainerBuilder;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.interceptor.Interceptor;
import com.opensymphony.xwork2.util.FileManager;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import com.opensymphony.xwork2.util.ValueStack;
@@ -98,7 +106,7 @@ public class Dispatcher {
* Store list of DispatcherListeners.
*/
private static List<DispatcherListener> dispatcherListeners =
new ArrayList<DispatcherListener>();
new CopyOnWriteArrayList<DispatcherListener>();
/**
* Store ConfigurationManager instance, set on init.
@@ -162,7 +170,7 @@ public class Dispatcher {
*
* @param listener The listener to add
*/
public static synchronized void addDispatcherListener(DispatcherListener listener) {
public static void addDispatcherListener(DispatcherListener listener) {
dispatcherListeners.add(listener);
}
@@ -171,7 +179,7 @@ public class Dispatcher {
*
* @param listener The listener
*/
public static synchronized void removeDispatcherListener(DispatcherListener listener) {
public static void removeDispatcherListener(DispatcherListener listener) {
dispatcherListeners.remove(listener);
}
@@ -257,13 +265,27 @@ public class Dispatcher {
instance.set(null);
// clean up DispatcherListeners
synchronized(Dispatcher.class) {
if (dispatcherListeners.size() > 0) {
for (DispatcherListener l : dispatcherListeners) {
l.dispatcherDestroyed(this);
if (!dispatcherListeners.isEmpty()) {
for (DispatcherListener l : dispatcherListeners) {
l.dispatcherDestroyed(this);
}
}
// clean up all interceptors by calling their destroy() method
Set<Interceptor> interceptors = new HashSet<Interceptor>();
Collection<PackageConfig> packageConfigs = configurationManager.getConfiguration().getPackageConfigs().values();
for (PackageConfig packageConfig : packageConfigs) {
for (Object config : packageConfig.getAllInterceptorConfigs().values()) {
if (config instanceof InterceptorStackConfig) {
for (InterceptorMapping interceptorMapping : ((InterceptorStackConfig) config).getInterceptors()) {
interceptors.add(interceptorMapping.getInterceptor());
}
}
}
}
for (Interceptor interceptor : interceptors) {
interceptor.destroy();
}
// clean up configuration
configurationManager.destroyConfiguration();
@@ -317,39 +339,6 @@ public class Dispatcher {
}
}
private void init_MethodConfigurationProvider() {
// See https://issues.apache.org/struts/browse/WW-1522
/*
com.opensymphony.xwork2.inject.DependencyException: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyException: No mapping found for dependency [type=org.apache.struts2.dispatcher.mapper.ActionMapper, name='default'] in public static void org.apache.struts2.dispatcher.FilterDispatcher.setActionMapper(org.apache.struts2.dispatcher.mapper.ActionMapper).
at com.opensymphony.xwork2.inject.ContainerImpl.addInjectorsForMembers(ContainerImpl.java:135)
at com.opensymphony.xwork2.inject.ContainerImpl.addInjectorsForMethods(ContainerImpl.java:104)
at com.opensymphony.xwork2.inject.ContainerImpl.injectStatics(ContainerImpl.java:89)
at com.opensymphony.xwork2.inject.ContainerBuilder.create(ContainerBuilder.java:494)
at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reload(DefaultConfiguration.java:140)
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:52)
at org.apache.struts2.dispatcher.Dispatcher.init_MethodConfigurationProvider(Dispatcher.java:347)
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:421)
at org.apache.struts2.config.MethodConfigurationProviderTest.setUp(MethodConfigurationProviderTest.java:68)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:40)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)
Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyException: No mapping found for dependency [type=org.apache.struts2.dispatcher.mapper.ActionMapper, name='default'] in public static void org.apache.struts2.dispatcher.FilterDispatcher.setActionMapper(org.apache.struts2.dispatcher.mapper.ActionMapper).
at com.opensymphony.xwork2.inject.ContainerImpl.createParameterInjector(ContainerImpl.java:217)
at com.opensymphony.xwork2.inject.ContainerImpl.getParametersInjectors(ContainerImpl.java:207)
at com.opensymphony.xwork2.inject.ContainerImpl$MethodInjector.<init>(ContainerImpl.java:260)
at com.opensymphony.xwork2.inject.ContainerImpl$3.create(ContainerImpl.java:108)
at com.opensymphony.xwork2.inject.ContainerImpl$3.create(ContainerImpl.java:106)
at com.opensymphony.xwork2.inject.ContainerImpl.addInjectorsForMembers(ContainerImpl.java:132)
... 26 more
MethodConfigurationProvider provider = new MethodConfigurationProvider();
provider.init(configurationManager.getConfiguration());
provider.loadPackages();
*/
}
private void init_FilterInitParameters() {
configurationManager.addConfigurationProvider(new ConfigurationProvider() {
public void destroy() {}
@@ -392,15 +381,6 @@ Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyExcepti
paramsWorkaroundEnabled = "true".equals(container.getInstance(String.class,
StrutsConstants.STRUTS_DISPATCHER_PARAMETERSWORKAROUND));
}
synchronized(Dispatcher.class) {
if (dispatcherListeners.size() > 0) {
for (DispatcherListener l : dispatcherListeners) {
l.dispatcherInitialized(this);
}
}
}
}
/**
@@ -417,7 +397,6 @@ Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyExcepti
init_TraditionalXmlConfigurations(); // [2]
init_LegacyStrutsProperties(); // [3]
init_CustomConfigurationProviders(); // [5]
init_MethodConfigurationProvider();
init_FilterInitParameters() ; // [6]
init_AliasStandardObjects() ; // [7]
@@ -426,6 +405,11 @@ Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyExcepti
init_CheckConfigurationReloading(container);
init_CheckWebLogicWorkaround(container);
if (!dispatcherListeners.isEmpty()) {
for (DispatcherListener l : dispatcherListeners) {
l.dispatcherInitialized(this);
}
}
}
/**
@@ -452,6 +436,12 @@ Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyExcepti
// If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
if (stack == null) {
ActionContext ctx = ActionContext.getContext();
if (ctx != null) {
stack = ctx.getValueStack();
}
}
if (stack != null) {
extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
}
@@ -482,7 +472,13 @@ Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyExcepti
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
}
} catch (ConfigurationException e) {
LOG.error("Could not find action or result", e);
// WW-2874 Only log error if in devMode
if(devMode) {
LOG.error("Could not find action or result", e);
}
else {
LOG.warn("Could not find action or result", e);
}
sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
} catch (Exception e) {
sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
@@ -516,7 +512,10 @@ Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyExcepti
Map application = new ApplicationMap(context);
Map<String,Object> extraContext = createContextMap(requestMap, params, session, application, request, response, context);
extraContext.put(ServletActionContext.ACTION_MAPPING, mapping);
if (mapping != null) {
extraContext.put(ServletActionContext.ACTION_MAPPING, mapping);
}
return extraContext;
}
@@ -22,16 +22,9 @@
package org.apache.struts2.dispatcher;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
@@ -44,18 +37,16 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.RequestUtils;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.dispatcher.ng.filter.FilterHostConfig;
import org.apache.struts2.util.ClassLoaderUtils;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.config.ConfigurationProvider;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.ClassLoaderUtil;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;
import com.opensymphony.xwork2.util.logging.Logger;
@@ -65,90 +56,96 @@ import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
/**
* Master filter for Struts that handles four distinct
* responsibilities:
*
* <p/>
* <ul>
*
* <p/>
* <li>Executing actions</li>
*
* <p/>
* <li>Cleaning up the {@link ActionContext} (see note)</li>
*
* <p/>
* <li>Serving static content</li>
*
* <p/>
* <li>Kicking off XWork's interceptor chain for the request lifecycle</li>
*
* <p/>
* </ul>
*
* <p/>
* <p/> <b>IMPORTANT</b>: this filter must be mapped to all requests. Unless you know exactly what you are doing, always
* map to this URL pattern: /*
*
* <p/>
* <p/> <b>Executing actions</b>
*
* <p/>
* <p/> This filter executes actions by consulting the {@link ActionMapper} and determining if the requested URL should
* invoke an action. If the mapper indicates it should, <b>the rest of the filter chain is stopped</b> and the action is
* invoked. This is important, as it means that filters like the SiteMesh filter must be placed <b>before</b> this
* filter or they will not be able to decorate the output of actions.
*
* <p/>
* <p/> <b>Cleaning up the {@link ActionContext}</b>
*
* <p/>
* <p/> This filter will also automatically clean up the {@link ActionContext} for you, ensuring that no memory leaks
* take place. However, this can sometimes cause problems integrating with other products like SiteMesh. See {@link
* ActionContextCleanUp} for more information on how to deal with this.
*
* <p/>
* <p/> <b>Serving static content</b>
*
* <p/>
* <p/> This filter also serves common static content needed when using various parts of Struts, such as JavaScript
* files, CSS files, etc. It works by looking for requests to /struts/*, and then mapping the value after "/struts/"
* to common packages in Struts and, optionally, in your class path. By default, the following packages are
* automatically searched:
*
* <p/>
* <ul>
*
* <p/>
* <li>org.apache.struts2.static</li>
*
* <p/>
* <li>template</li>
*
* <p/>
* </ul>
*
* <p/>
* <p/> This means that you can simply request /struts/xhtml/styles.css and the XHTML UI theme's default stylesheet
* will be returned. Likewise, many of the AJAX UI components require various JavaScript files, which are found in the
* org.apache.struts2.static package. If you wish to add additional packages to be searched, you can add a comma
* separated (space, tab and new line will do as well) list in the filter init parameter named "packages". <b>Be
* careful</b>, however, to expose any packages that may have sensitive information, such as properties file with
* database access credentials.
*
* <p/>
*
* <p/>
* <p/>
* <p>
*
* <p/>
* This filter supports the following init-params:
* <!-- START SNIPPET: params -->
*
* <p/>
* <ul>
*
* <p/>
* <li><b>config</b> - a comma-delimited list of XML configuration files to load.</li>
*
* <p/>
* <li><b>actionPackages</b> - a comma-delimited list of Java packages to scan for Actions.</li>
*
* <p/>
* <li><b>configProviders</b> - a comma-delimited list of Java classes that implement the
* {@link ConfigurationProvider} interface that should be used for building the {@link Configuration}.</li>
*
* <p/>
* <li><b>loggerFactory</b> - The class name of the {@link LoggerFactory} implementation.</li>
*
* <p/>
* <li><b>*</b> - any other parameters are treated as framework constants.</li>
*
* <p/>
* </ul>
*
* <p/>
* <!-- END SNIPPET: params -->
*
* <p/>
* </p>
*
* <p/>
* To use a custom {@link Dispatcher}, the <code>createDispatcher()</code> method could be overriden by
* the subclass.
*
* @version $Date$ $Id$
* @deprecated Since Struts 2.1.3, use {@link org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter} instead or
* {@link org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter} and {@link org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter}
* if needing using the {@link ActionContextCleanUp} filter in addition to this one
*
* @see ActionMapper
* @see ActionContextCleanUp
*
* @version $Date$ $Id$
* @see org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
* @see org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter
* @see org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter
*/
public class FilterDispatcher implements StrutsStatics, Filter {
@@ -157,31 +154,6 @@ public class FilterDispatcher implements StrutsStatics, Filter {
*/
private Logger log;
/**
* Store set of path prefixes to use with static resources.
*/
private String[] pathPrefixes;
/**
* Provide a formatted date for setting heading information when caching static content.
*/
private final Calendar lastModifiedCal = Calendar.getInstance();
/**
* Store state of StrutsConstants.STRUTS_SERVE_STATIC_CONTENT setting.
*/
private boolean serveStatic;
/**
* Store state of StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE setting.
*/
private boolean serveStaticBrowserCache;
/**
* Store state of StrutsConstants.STRUTS_I18N_ENCODING setting.
*/
private String encoding;
/**
* Provide ActionMapper instance, set by injection.
*/
@@ -197,6 +169,11 @@ public class FilterDispatcher implements StrutsStatics, Filter {
*/
protected Dispatcher dispatcher;
/**
* Loads stattic resources, set by injection
*/
protected StaticContentLoader staticResourceLoader;
/**
* Initializes the filter by creating a default dispatcher
* and setting the default packages for static resources.
@@ -213,12 +190,7 @@ public class FilterDispatcher implements StrutsStatics, Filter {
dispatcher.init();
dispatcher.getContainer().inject(this);
String param = filterConfig.getInitParameter("packages");
String packages = "org.apache.struts2.static template org.apache.struts2.interceptor.debugging";
if (param != null) {
packages = param + " " + packages;
}
this.pathPrefixes = parse(packages);
staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig));
} finally {
ActionContext.setContext(null);
}
@@ -229,22 +201,22 @@ public class FilterDispatcher implements StrutsStatics, Filter {
if (factoryName != null) {
try {
Class cls = ClassLoaderUtils.loadClass(factoryName, this.getClass());
LoggerFactory fac = (LoggerFactory)cls.newInstance();
LoggerFactory fac = (LoggerFactory) cls.newInstance();
LoggerFactory.setLoggerFactory(fac);
} catch (InstantiationException e) {
System.err.println("Unable to instantiate logger factory: "+factoryName+", using default");
System.err.println("Unable to instantiate logger factory: " + factoryName + ", using default");
e.printStackTrace();
} catch (IllegalAccessException e) {
System.err.println("Unable to access logger factory: "+factoryName+", using default");
System.err.println("Unable to access logger factory: " + factoryName + ", using default");
e.printStackTrace();
} catch (ClassNotFoundException e) {
System.err.println("Unable to locate logger factory class: "+factoryName+", using default");
System.err.println("Unable to locate logger factory class: " + factoryName + ", using default");
e.printStackTrace();
}
}
log = LoggerFactory.getLogger(FilterDispatcher.class);
}
/**
@@ -273,8 +245,8 @@ public class FilterDispatcher implements StrutsStatics, Filter {
* @return Initialized Dispatcher
*/
protected Dispatcher createDispatcher(FilterConfig filterConfig) {
Map<String,String> params = new HashMap<String,String>();
for (Enumeration e = filterConfig.getInitParameterNames(); e.hasMoreElements(); ) {
Map<String, String> params = new HashMap<String, String>();
for (Enumeration e = filterConfig.getInitParameterNames(); e.hasMoreElements();) {
String name = (String) e.nextElement();
String value = filterConfig.getInitParameter(name);
params.put(name, value);
@@ -283,30 +255,12 @@ public class FilterDispatcher implements StrutsStatics, Filter {
}
/**
* Modify state of StrutsConstants.STRUTS_SERVE_STATIC_CONTENT setting.
* @param val New setting
* Modify state of StrutsConstants.STRUTS_STATIC_CONTENT_LOADER setting.
* @param staticResourceLoader val New setting
*/
@Inject(StrutsConstants.STRUTS_SERVE_STATIC_CONTENT)
public void setServeStaticContent(String val) {
serveStatic = "true".equals(val);
}
/**
* Modify state of StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE setting.
* @param val New setting
*/
@Inject(StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE)
public void setServeStaticBrowserCache(String val) {
serveStaticBrowserCache = "true".equals(val);
}
/**
* Modify state of StrutsConstants.STRUTS_I18N_ENCODING setting.
* @param val New setting
*/
@Inject(StrutsConstants.STRUTS_I18N_ENCODING)
public void setEncoding(String val) {
encoding = val;
@Inject
public void setStaticResourceLoader(StaticContentLoader staticResourceLoader) {
this.staticResourceLoader = staticResourceLoader;
}
/**
@@ -344,7 +298,7 @@ public class FilterDispatcher implements StrutsStatics, Filter {
* Wrap and return the given request, if needed, so as to to transparently
* handle multipart data as a wrapped class around the given request.
*
* @param request Our ServletRequest object
* @param request Our ServletRequest object
* @param response Our ServerResponse object
* @return Wrapped HttpServletRequest object
* @throws ServletException on any error
@@ -380,31 +334,6 @@ public class FilterDispatcher implements StrutsStatics, Filter {
return request;
}
/**
* Create a string array from a comma-delimited list of packages.
*
* @param packages A comma-delimited String listing packages
* @return A string array of packages
*/
protected String[] parse(String packages) {
if (packages == null) {
return null;
}
List<String> pathPrefixes = new ArrayList<String>();
StringTokenizer st = new StringTokenizer(packages, ", \n\t");
while (st.hasMoreTokens()) {
String pathPrefix = st.nextToken().replace('.', '/');
if (!pathPrefix.endsWith("/")) {
pathPrefix += "/";
}
pathPrefixes.add(pathPrefix);
}
return pathPrefixes.toArray(new String[pathPrefixes.size()]);
}
/**
* Process an action or handle a request a static resource.
* <p/>
@@ -428,12 +357,12 @@ public class FilterDispatcher implements StrutsStatics, Filter {
String timerKey = "FilterDispatcher_doFilter: ";
try {
// FIXME: this should be refactored better to not duplicate work with the action invocation
ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
ActionContext ctx = new ActionContext(stack.getContext());
ActionContext.setContext(ctx);
UtilTimerStack.push(timerKey);
request = prepareDispatcherAndWrapRequest(request, response);
ActionMapping mapping;
@@ -453,9 +382,8 @@ public class FilterDispatcher implements StrutsStatics, Filter {
resourcePath = request.getPathInfo();
}
if (serveStatic && resourcePath.startsWith("/struts")) {
String name = resourcePath.substring("/struts".length());
findStaticResource(name, request, response);
if (staticResourceLoader.canHandle(resourcePath)) {
staticResourceLoader.findStaticResource(resourcePath, request, response);
} else {
// this is a normal request, let it pass through
chain.doFilter(request, response);
@@ -474,137 +402,4 @@ public class FilterDispatcher implements StrutsStatics, Filter {
}
}
}
/**
* Locate a static resource and copy directly to the response,
* setting the appropriate caching headers.
*
* @param name The resource name
* @param request The request
* @param response The response
* @throws IOException If anything goes wrong
*/
protected void findStaticResource(String name, HttpServletRequest request, HttpServletResponse response) throws IOException {
if (!name.endsWith(".class")) {
for (String pathPrefix : pathPrefixes) {
InputStream is = findInputStream(name, pathPrefix);
if (is != null) {
Calendar cal = Calendar.getInstance();
// check for if-modified-since, prior to any other headers
long ifModifiedSince = 0;
try {
ifModifiedSince = request.getDateHeader("If-Modified-Since");
} catch (Exception e) {
log.warn("Invalid If-Modified-Since header value: '" + request.getHeader("If-Modified-Since") + "', ignoring");
}
long lastModifiedMillis = lastModifiedCal.getTimeInMillis();
long now = cal.getTimeInMillis();
cal.add(Calendar.DAY_OF_MONTH, 1);
long expires = cal.getTimeInMillis();
if (ifModifiedSince > 0 && ifModifiedSince <= lastModifiedMillis) {
// not modified, content is not sent - only basic headers and status SC_NOT_MODIFIED
response.setDateHeader("Expires", expires);
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
is.close();
return;
}
// set the content-type header
String contentType = getContentType(name);
if (contentType != null) {
response.setContentType(contentType);
}
if (serveStaticBrowserCache) {
// set heading information for caching static content
response.setDateHeader("Date", now);
response.setDateHeader("Expires", expires);
response.setDateHeader("Retry-After", expires);
response.setHeader("Cache-Control", "public");
response.setDateHeader("Last-Modified", lastModifiedMillis);
} else {
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setHeader("Expires", "-1");
}
try {
copy(is, response.getOutputStream());
} finally {
is.close();
}
return;
}
}
}
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
/**
* Determine the content type for the resource name.
*
* @param name The resource name
* @return The mime type
*/
protected String getContentType(String name) {
// NOT using the code provided activation.jar to avoid adding yet another dependency
// this is generally OK, since these are the main files we server up
if (name.endsWith(".js")) {
return "text/javascript";
} else if (name.endsWith(".css")) {
return "text/css";
} else if (name.endsWith(".html")) {
return "text/html";
} else if (name.endsWith(".txt")) {
return "text/plain";
} else if (name.endsWith(".gif")) {
return "image/gif";
} else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) {
return "image/jpeg";
} else if (name.endsWith(".png")) {
return "image/png";
} else {
return null;
}
}
/**
* Copy bytes from the input stream to the output stream.
*
* @param input The input stream
* @param output The output stream
* @throws IOException If anything goes wrong
*/
protected void copy(InputStream input, OutputStream output) throws IOException {
final byte[] buffer = new byte[4096];
int n;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
output.flush();
}
/**
* Look for a static resource in the classpath.
*
* @param name The resource name
* @param packagePrefix The package prefix to use to locate the resource
* @return The inputstream of the resource
* @throws IOException If there is a problem locating the resource
*/
protected InputStream findInputStream(String name, String packagePrefix) throws IOException {
String resourcePath;
if (packagePrefix.endsWith("/") && name.startsWith("/")) {
resourcePath = packagePrefix + name.substring(1);
} else {
resourcePath = packagePrefix + name;
}
resourcePath = URLDecoder.decode(resourcePath, encoding);
return ClassLoaderUtil.getResourceAsStream(resourcePath, getClass());
}
}
@@ -47,6 +47,8 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
* must "swallow" the exception. This it does by logging the
* exception as an error.
*
* @deprecated Since Struts 2.1.3 as it probably isn't used anymore
*
*/
public class FilterDispatcherCompatWeblogic61 extends FilterDispatcher {
@@ -194,7 +194,7 @@ public class ServletActionRedirectResult extends ServletRedirectResult implement
}
}
StringBuffer tmpLocation = new StringBuffer(actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null)));
StringBuilder tmpLocation = new StringBuilder(actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null)));
UrlHelper.buildParametersString(requestParameters, tmpLocation, "&");
setLocation(tmpLocation.toString());
@@ -21,12 +21,15 @@
package org.apache.struts2.dispatcher;
import java.util.Map;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.PageContext;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.views.util.UrlHelper;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.util.logging.Logger;
@@ -123,6 +126,17 @@ public class ServletDispatcherResult extends StrutsResultSupport {
HttpServletResponse response = ServletActionContext.getResponse();
RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation);
//add parameters passed on the location to #parameters
// see WW-2120
if (invocation != null && finalLocation != null && finalLocation.length() > 0
&& finalLocation.indexOf("?") > 0) {
String queryString = finalLocation.substring(finalLocation.indexOf("?") + 1);
Map parameters = (Map) invocation.getInvocationContext().getContextMap().get("parameters");
Map queryParams = UrlHelper.parseQueryString(queryString, true);
if (queryParams != null && !queryParams.isEmpty())
parameters.putAll(queryParams);
}
// if the view doesn't exist, let's do a 404
if (dispatcher == null) {
response.sendError(404, "result '" + finalLocation + "' not found");
@@ -39,12 +39,12 @@ import javax.servlet.http.HttpSession;
* Note, this will occur lazily - only when the entry set is asked for.
*
*/
public class SessionMap extends AbstractMap implements Serializable {
public class SessionMap<K, V> extends AbstractMap<K,V> implements Serializable {
private static final long serialVersionUID = 4678843241638046854L;
protected HttpSession session;
protected Set<Object> entries;
protected Set<Map.Entry<K,V>> entries;
protected HttpServletRequest request;
@@ -101,23 +101,23 @@ public class SessionMap extends AbstractMap implements Serializable {
*
* @return a Set of attributes from the http session.
*/
public Set entrySet() {
public Set<java.util.Map.Entry<K,V>> entrySet() {
if (session == null) {
return Collections.EMPTY_SET;
return Collections.emptySet();
}
synchronized (session) {
if (entries == null) {
entries = new HashSet<Object>();
entries = new HashSet<Map.Entry<K,V>>();
Enumeration enumeration = session.getAttributeNames();
Enumeration<? extends Object> enumeration = session.getAttributeNames();
while (enumeration.hasMoreElements()) {
final String key = enumeration.nextElement().toString();
final Object value = session.getAttribute(key);
entries.add(new Map.Entry() {
entries.add(new Map.Entry<K,V>() {
public boolean equals(Object obj) {
Map.Entry entry = (Map.Entry) obj;
Map.Entry<K, V> entry = (Map.Entry<K, V>) obj;
return ((key == null) ? (entry.getKey() == null) : key.equals(entry.getKey())) && ((value == null) ? (entry.getValue() == null) : value.equals(entry.getValue()));
}
@@ -126,18 +126,18 @@ public class SessionMap extends AbstractMap implements Serializable {
return ((key == null) ? 0 : key.hashCode()) ^ ((value == null) ? 0 : value.hashCode());
}
public Object getKey() {
return key;
public K getKey() {
return (K) key;
}
public Object getValue() {
return value;
public V getValue() {
return (V) value;
}
public Object setValue(Object obj) {
public V setValue(Object obj) {
session.setAttribute(key, obj);
return value;
return (V) value;
}
});
}
@@ -153,13 +153,13 @@ public class SessionMap extends AbstractMap implements Serializable {
* @param key the name of the session attribute.
* @return the session attribute or <tt>null</tt> if it doesn't exist.
*/
public Object get(Object key) {
public V get(Object key) {
if (session == null) {
return null;
}
synchronized (session) {
return session.getAttribute(key.toString());
return (V) session.getAttribute(key.toString());
}
}
@@ -170,7 +170,7 @@ public class SessionMap extends AbstractMap implements Serializable {
* @param value the value to set.
* @return the object that was just set.
*/
public Object put(Object key, Object value) {
public V put(K key, V value) {
synchronized (this) {
if (session == null) {
session = request.getSession(true);
@@ -191,7 +191,7 @@ public class SessionMap extends AbstractMap implements Serializable {
* @param key the name of the attribute to remove.
* @return the value that was removed or <tt>null</tt> if the value was not found (and hence, not removed).
*/
public Object remove(Object key) {
public V remove(Object key) {
if (session == null) {
return null;
}
@@ -199,10 +199,27 @@ public class SessionMap extends AbstractMap implements Serializable {
synchronized (session) {
entries = null;
Object value = get(key);
V value = get(key);
session.removeAttribute(key.toString());
return value;
}
}
/**
* Checks if the specified session attribute with the given key exists.
*
* @param key the name of the session attribute.
* @return <tt>true</tt> if the session attribute exits or <tt>false</tt> if it doesn't exist.
*/
public boolean containsKey(Object key) {
if (session == null) {
return false;
}
synchronized (session) {
return (session.getAttribute(key.toString()) != null);
}
}
}
@@ -0,0 +1,58 @@
/*
* $Id$
*
* 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.dispatcher;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.dispatcher.ng.HostConfig;
/**
* Interface for loading static resources, based on a path
*/
public interface StaticContentLoader {
/**
* @param path Requested resource path
* @return true if this loader is able to load this type of resource, false otherwise
*/
public boolean canHandle(String path);
/**
* @param filterConfig The filter configuration
*/
public abstract void setHostConfig(HostConfig filterConfig);
/**
* Locate a static resource and copy directly to the response, setting the
* appropriate caching headers.
*
* @param path The resource name
* @param request The request
* @param response The response
* @throws IOException If anything goes wrong
*/
public abstract void findStaticResource(String path, HttpServletRequest request, HttpServletResponse response)
throws IOException;
}
@@ -61,6 +61,8 @@ import com.opensymphony.xwork2.util.ValueStack;
* <li><b>bufferSize</b> - the size of the buffer to copy from input to output
* (default = <code>1024</code>).</li>
*
* <li><b>allowCaching</b> if set to 'false' it will set the headers 'Pragma' and 'Cache-Control'
* to 'no-cahce', and prevent client from caching the content. (default = <code>true</code>)
* </ul>
*
* <p>These parameters can also be set by exposing a similarly named getter method on your Action. For example, you can
@@ -94,6 +96,7 @@ public class StreamResult extends StrutsResultSupport {
protected String inputName = "inputStream";
protected InputStream inputStream;
protected int bufferSize = 1024;
protected boolean allowCaching = true;
public StreamResult() {
super();
@@ -103,6 +106,24 @@ public class StreamResult extends StrutsResultSupport {
this.inputStream = in;
}
/**
* @return Returns the whether or not the client should be requested to allow caching of the data stream.
*/
public boolean getAllowCaching() {
return allowCaching;
}
/**
* Set allowCaching to <tt>false</tt> to indicate that the client should be requested not to cache the data stream.
* This is set to <tt>false</tt> by default
*
* @param allowCaching Enable caching.
*/
public void setAllowCaching(boolean allowCaching) {
this.allowCaching = allowCaching;
}
/**
* @return Returns the bufferSize.
*/
@@ -219,7 +240,13 @@ public class StreamResult extends StrutsResultSupport {
// Set the content-disposition
if (contentDisposition != null) {
oResponse.addHeader("Content-disposition", conditionalParse(contentDisposition, invocation));
oResponse.addHeader("Content-Disposition", conditionalParse(contentDisposition, invocation));
}
// Set the cache control headers if neccessary
if (!allowCaching) {
oResponse.addHeader("Pragma", "no-cache");
oResponse.addHeader("Cache-Control", "no-cache");
}
// Get the outputstream
@@ -400,18 +400,26 @@ public class DefaultActionMapper implements ActionMapper {
Configuration config = configManager.getConfiguration();
String prefix = uri.substring(0, lastSlash);
namespace = "";
boolean rootAvailable = false;
// Find the longest matching namespace, defaulting to the default
for (Iterator i = config.getPackageConfigs().values().iterator(); i
.hasNext();) {
String ns = ((PackageConfig) i.next()).getNamespace();
for (Object cfg : config.getPackageConfigs().values()) {
String ns = ((PackageConfig) cfg).getNamespace();
if (ns != null && prefix.startsWith(ns) && (prefix.length() == ns.length() || prefix.charAt(ns.length()) == '/')) {
if (ns.length() > namespace.length()) {
namespace = ns;
}
}
if ("/".equals(ns)) {
rootAvailable = true;
}
}
name = uri.substring(namespace.length() + 1);
// Still none found, use root namespace if found
if (rootAvailable && "".equals(namespace)) {
namespace = "/";
}
}
if (!allowSlashesInActionNames && name != null) {
@@ -511,7 +519,7 @@ public class DefaultActionMapper implements ActionMapper {
* @see org.apache.struts2.dispatcher.mapper.ActionMapper#getUriFromActionMapping(org.apache.struts2.dispatcher.mapper.ActionMapping)
*/
public String getUriFromActionMapping(ActionMapping mapping) {
StringBuffer uri = new StringBuffer();
StringBuilder uri = new StringBuilder();
if (mapping.getNamespace() != null) {
uri.append(mapping.getNamespace());
@@ -47,18 +47,19 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
/**
* Multipart form data request adapter for Jakarta Commons Fileupload package.
*
*/
public class JakartaMultiPartRequest implements MultiPartRequest {
static final Logger LOG = LoggerFactory.getLogger(MultiPartRequest.class);
// maps parameter name -> List of FileItem objects
private Map<String,List<FileItem>> files = new HashMap<String,List<FileItem>>();
private final Map<String,List<FileItem>> files = new HashMap<String,List<FileItem>>();
// maps parameter name -> List of param values
private Map<String,List<String>> params = new HashMap<String,List<String>>();
private final Map<String,List<String>> params = new HashMap<String,List<String>>();
// any errors while processing this request
private List<String> errors = new ArrayList<String>();
private final List<String> errors = new ArrayList<String>();
private long maxSize;
@@ -151,38 +152,36 @@ public class JakartaMultiPartRequest implements MultiPartRequest {
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getContentType(java.lang.String)
*/
public String[] getContentType(String fieldName) {
List items = (List) files.get(fieldName);
List<FileItem> items = files.get(fieldName);
if (items == null) {
return null;
}
List<String> contentTypes = new ArrayList<String>(items.size());
for (int i = 0; i < items.size(); i++) {
FileItem fileItem = (FileItem) items.get(i);
for (FileItem fileItem : items) {
contentTypes.add(fileItem.getContentType());
}
return (String[]) contentTypes.toArray(new String[contentTypes.size()]);
return contentTypes.toArray(new String[contentTypes.size()]);
}
/* (non-Javadoc)
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFile(java.lang.String)
*/
public File[] getFile(String fieldName) {
List items = (List) files.get(fieldName);
List<FileItem> items = files.get(fieldName);
if (items == null) {
return null;
}
List<File> fileList = new ArrayList<File>(items.size());
for (int i = 0; i < items.size(); i++) {
DiskFileItem fileItem = (DiskFileItem) items.get(i);
fileList.add(fileItem.getStoreLocation());
for (FileItem fileItem : items) {
fileList.add(((DiskFileItem) fileItem).getStoreLocation());
}
return (File[]) fileList.toArray(new File[fileList.size()]);
return fileList.toArray(new File[fileList.size()]);
}
/* (non-Javadoc)
@@ -196,40 +195,38 @@ public class JakartaMultiPartRequest implements MultiPartRequest {
}
List<String> fileNames = new ArrayList<String>(items.size());
for (int i = 0; i < items.size(); i++) {
DiskFileItem fileItem = (DiskFileItem) items.get(i);
for (FileItem fileItem : items) {
fileNames.add(getCanonicalName(fileItem.getName()));
}
return (String[]) fileNames.toArray(new String[fileNames.size()]);
return fileNames.toArray(new String[fileNames.size()]);
}
/* (non-Javadoc)
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFilesystemName(java.lang.String)
*/
public String[] getFilesystemName(String fieldName) {
List items = (List) files.get(fieldName);
List<FileItem> items = files.get(fieldName);
if (items == null) {
return null;
}
List<String> fileNames = new ArrayList<String>(items.size());
for (int i = 0; i < items.size(); i++) {
DiskFileItem fileItem = (DiskFileItem) items.get(i);
fileNames.add(fileItem.getStoreLocation().getName());
for (FileItem fileItem : items) {
fileNames.add(((DiskFileItem) fileItem).getStoreLocation().getName());
}
return (String[]) fileNames.toArray(new String[fileNames.size()]);
return fileNames.toArray(new String[fileNames.size()]);
}
/* (non-Javadoc)
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameter(java.lang.String)
*/
public String getParameter(String name) {
List v = (List) params.get(name);
List<String> v = params.get(name);
if (v != null && v.size() > 0) {
return (String) v.get(0);
return v.get(0);
}
return null;
@@ -248,7 +245,7 @@ public class JakartaMultiPartRequest implements MultiPartRequest {
public String[] getParameterValues(String name) {
List<String> v = params.get(name);
if (v != null && v.size() > 0) {
return (String[]) v.toArray(new String[v.size()]);
return v.toArray(new String[v.size()]);
}
return null;
@@ -0,0 +1,79 @@
/*
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
*
* 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.dispatcher.ng;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.StaticContentLoader;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.RequestUtils;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Contains execution operations for filters
*/
public class ExecuteOperations {
private ServletContext servletContext;
private Dispatcher dispatcher;
public ExecuteOperations(ServletContext servletContext, Dispatcher dispatcher) {
this.dispatcher = dispatcher;
this.servletContext = servletContext;
}
/**
* Tries to execute a request for a static resource
* @return True if it was handled, false if the filter should fall through
* @throws IOException
* @throws ServletException
*/
public boolean executeStaticResourceRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
// there is no action in this request, should we look for a static resource?
String resourcePath = RequestUtils.getServletPath(request);
if ("".equals(resourcePath) && null != request.getPathInfo()) {
resourcePath = request.getPathInfo();
}
StaticContentLoader staticResourceLoader = dispatcher.getContainer().getInstance(StaticContentLoader.class);
if (staticResourceLoader.canHandle(resourcePath)) {
staticResourceLoader.findStaticResource(resourcePath, request, response);
// The framework did its job here
return true;
} else {
// this is a normal request, let it pass through
return false;
}
}
/**
* Executes an action
* @throws ServletException
*/
public void executeAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws ServletException {
dispatcher.serviceAction(request, response, servletContext, mapping);
}
}
@@ -0,0 +1,46 @@
/*
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
*
* 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.dispatcher.ng;
import javax.servlet.ServletContext;
import java.util.Iterator;
/**
* Abstraction for host configuration information such as init params or the servlet context.
*/
public interface HostConfig {
/**
* @param key The parameter key
* @return The parameter value
*/
String getInitParameter(String key);
/**
* @return A list of parameter names
*/
Iterator<String> getInitParameterNames();
/**
* @return The servlet context
*/
ServletContext getServletContext();
}
@@ -0,0 +1,110 @@
/*
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
*
* 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.dispatcher.ng;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import com.opensymphony.xwork2.ActionContext;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.StaticContentLoader;
import org.apache.struts2.util.ClassLoaderUtils;
import java.util.HashMap;
import java.util.Map;
import java.util.Iterator;
/**
* Contains initialization operations
*/
public class InitOperations {
public InitOperations() {
}
/**
* Initializes the internal Struts logging
*/
public void initLogging(HostConfig filterConfig) {
String factoryName = filterConfig.getInitParameter("loggerFactory");
if (factoryName != null) {
try {
Class cls = ClassLoaderUtils.loadClass(factoryName, this.getClass());
LoggerFactory fac = (LoggerFactory) cls.newInstance();
LoggerFactory.setLoggerFactory(fac);
} catch (InstantiationException e) {
System.err.println("Unable to instantiate logger factory: " + factoryName + ", using default");
e.printStackTrace();
} catch (IllegalAccessException e) {
System.err.println("Unable to access logger factory: " + factoryName + ", using default");
e.printStackTrace();
} catch (ClassNotFoundException e) {
System.err.println("Unable to locate logger factory class: " + factoryName + ", using default");
e.printStackTrace();
}
}
}
/**
* Creates and initializes the dispatcher
*/
public Dispatcher initDispatcher(HostConfig filterConfig) {
Dispatcher dispatcher = createDispatcher(filterConfig);
dispatcher.init();
return dispatcher;
}
/**
* Initializes the static content loader with the filter configuration
*/
public StaticContentLoader initStaticContentLoader(HostConfig filterConfig, Dispatcher dispatcher) {
StaticContentLoader loader = dispatcher.getContainer().getInstance(StaticContentLoader.class);
loader.setHostConfig(filterConfig);
return loader;
}
/**
* @return The dispatcher on the thread.
* @throws IllegalStateException If there is no dispatcher available
*/
public Dispatcher findDispatcherOnThread() {
Dispatcher dispatcher = Dispatcher.getInstance();
if (dispatcher == null) {
throw new IllegalStateException("Must have the StrutsPrepareFilter execute before this one");
}
return dispatcher;
}
/**
* Create a {@link Dispatcher}
*/
private Dispatcher createDispatcher(HostConfig filterConfig) {
Map<String, String> params = new HashMap<String, String>();
for (Iterator e = filterConfig.getInitParameterNames(); e.hasNext();) {
String name = (String) e.next();
String value = filterConfig.getInitParameter(name);
params.put(name, value);
}
return new Dispatcher(filterConfig.getServletContext(), params);
}
public void cleanup() {
ActionContext.setContext(null);
}
}
@@ -0,0 +1,171 @@
/*
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
*
* 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.dispatcher.ng;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.StrutsException;
import javax.servlet.ServletException;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.util.ValueStack;
import com.opensymphony.xwork2.util.ValueStackFactory;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import java.io.IOException;
import java.util.HashMap;
/**
* Contains preparation operations for a request before execution
*/
public class PrepareOperations {
private ServletContext servletContext;
private Dispatcher dispatcher;
private static final String STRUTS_ACTION_MAPPING_KEY = "struts.actionMapping";
public static final String CLEANUP_RECURSION_COUNTER = "__cleanup_recursion_counter";
private Logger log = LoggerFactory.getLogger(PrepareOperations.class);
public PrepareOperations(ServletContext servletContext, Dispatcher dispatcher) {
this.dispatcher = dispatcher;
this.servletContext = servletContext;
}
/**
* Creates the action context and initializes the thread local
*/
public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) {
ActionContext ctx;
Integer counter = 1;
Integer oldCounter = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER);
if (oldCounter != null) {
counter = oldCounter + 1;
}
ActionContext oldContext = ActionContext.getContext();
if (oldContext != null) {
// detected existing context, so we are probably in a forward
ctx = new ActionContext(new HashMap<String, Object>(oldContext.getContextMap()));
} else {
ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
stack.getContext().putAll(dispatcher.createContextMap(request, response, null, servletContext));
ctx = new ActionContext(stack.getContext());
}
request.setAttribute(CLEANUP_RECURSION_COUNTER, counter);
ActionContext.setContext(ctx);
return ctx;
}
/**
* Cleans up a request of thread locals
*/
public void cleanupRequest(HttpServletRequest request) {
Integer counterVal = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER);
if (counterVal != null) {
counterVal -= 1;
request.setAttribute(CLEANUP_RECURSION_COUNTER, counterVal);
if (counterVal > 0 ) {
if (log.isDebugEnabled()) {
log.debug("skipping cleanup counter="+counterVal);
}
return;
}
}
// always clean up the thread request, even if an action hasn't been executed
ActionContext.setContext(null);
Dispatcher.setInstance(null);
}
/**
* Assigns the dispatcher to the dispatcher thread local
*/
public void assignDispatcherToThread() {
Dispatcher.setInstance(dispatcher);
}
/**
* Sets the request encoding and locale on the response
*/
public void setEncodingAndLocale(HttpServletRequest request, HttpServletResponse response) {
dispatcher.prepare(request, response);
}
/**
* Wraps the request with the Struts wrapper that handles multipart requests better
* @return The new request, if there is one
* @throws ServletException
*/
public HttpServletRequest wrapRequest(HttpServletRequest oldRequest) throws ServletException {
HttpServletRequest request = oldRequest;
try {
// Wrap request first, just in case it is multipart/form-data
// parameters might not be accessible through before encoding (ww-1278)
request = dispatcher.wrapRequest(request, servletContext);
} catch (IOException e) {
String message = "Could not wrap servlet request with MultipartRequestWrapper!";
throw new ServletException(message, e);
}
return request;
}
/**
* Finds and optionally creates an {@link ActionMapping}. It first looks in the current request to see if one
* has already been found, otherwise, it creates it and stores it in the request. No mapping will be created in the
* case of static resource requests or unidentifiable requests for other servlets, for example.
*/
public ActionMapping findActionMapping(HttpServletRequest request, HttpServletResponse response) {
ActionMapping mapping = (ActionMapping) request.getAttribute(STRUTS_ACTION_MAPPING_KEY);
if (mapping == null) {
try {
mapping = dispatcher.getContainer().getInstance(ActionMapper.class).getMapping(request, dispatcher.getConfigurationManager());
if (mapping != null) {
request.setAttribute(STRUTS_ACTION_MAPPING_KEY, mapping);
}
} catch (Exception ex) {
dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
}
}
return mapping;
}
/**
* Cleans up the dispatcher instance
*/
public void cleanupDispatcher() {
if (dispatcher == null) {
throw new StrutsException("something is seriously wrong, Dispatcher is not initialized (null) ");
} else {
try {
dispatcher.cleanup();
} finally {
ActionContext.setContext(null);
}
}
}
}
@@ -0,0 +1,52 @@
/*
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
*
* 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.dispatcher.ng.filter;
import org.apache.struts2.util.MakeIterator;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import java.util.Iterator;
import org.apache.struts2.dispatcher.ng.HostConfig;
/**
* Host configuration that wraps FilterConfig
*/
public class FilterHostConfig implements HostConfig {
private FilterConfig config;
public FilterHostConfig(FilterConfig config) {
this.config = config;
}
public String getInitParameter(String key) {
return config.getInitParameter(key);
}
public Iterator<String> getInitParameterNames() {
return MakeIterator.convert(config.getInitParameterNames());
}
public ServletContext getServletContext() {
return config.getServletContext();
}
}
@@ -0,0 +1,85 @@
/*
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
*
* 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.dispatcher.ng.filter;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.ng.PrepareOperations;
import org.apache.struts2.dispatcher.ng.ExecuteOperations;
import org.apache.struts2.dispatcher.ng.InitOperations;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Executes the discovered request information. This filter requires the {@link StrutsPrepareFilter} to have already
* been executed in the current chain.
*/
public class StrutsExecuteFilter implements StrutsStatics, Filter {
private PrepareOperations prepare;
private ExecuteOperations execute;
private FilterConfig filterConfig;
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
protected synchronized void lazyInit() {
if (execute == null) {
InitOperations init = new InitOperations();
Dispatcher dispatcher = init.findDispatcherOnThread();
init.initStaticContentLoader(new FilterHostConfig(filterConfig), dispatcher);
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
}
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// This is necessary since we need the dispatcher instance, which was created by the prepare filter
lazyInit();
ActionMapping mapping = prepare.findActionMapping(request, response);
if (mapping == null) {
boolean handled = execute.executeStaticResourceRequest(request, response);
if (!handled) {
chain.doFilter(request, response);
}
} else {
execute.executeAction(request, response, mapping);
}
}
public void destroy() {
prepare = null;
execute = null;
filterConfig = null;
}
}
@@ -0,0 +1,86 @@
/*
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
*
* 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.dispatcher.ng.filter;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.ng.PrepareOperations;
import org.apache.struts2.dispatcher.ng.ExecuteOperations;
import org.apache.struts2.dispatcher.ng.InitOperations;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Handles both the preparation and execution phases of the Struts dispatching process. This filter is better to use
* when you don't have another filter that needs access to action context information, such as Sitemesh.
*/
public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter {
private PrepareOperations prepare;
private ExecuteOperations execute;
public void init(FilterConfig filterConfig) throws ServletException {
InitOperations init = new InitOperations();
try {
FilterHostConfig config = new FilterHostConfig(filterConfig);
init.initLogging(config);
Dispatcher dispatcher = init.initDispatcher(config);
init.initStaticContentLoader(config, dispatcher);
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
} finally {
init.cleanup();
}
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
prepare.createActionContext(request, response);
prepare.assignDispatcherToThread();
prepare.setEncodingAndLocale(request, response);
request = prepare.wrapRequest(request);
ActionMapping mapping = prepare.findActionMapping(request, response);
if (mapping == null) {
boolean handled = execute.executeStaticResourceRequest(request, response);
if (!handled) {
chain.doFilter(request, response);
}
} else {
execute.executeAction(request, response, mapping);
}
} finally {
prepare.cleanupRequest(request);
}
}
public void destroy() {
prepare.cleanupDispatcher();
}
}
@@ -0,0 +1,74 @@
/*
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
*
* 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.dispatcher.ng.filter;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.ng.PrepareOperations;
import org.apache.struts2.dispatcher.ng.InitOperations;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Prepares the request for execution by a later {@link org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter} filter instance.
*/
public class StrutsPrepareFilter implements StrutsStatics, Filter {
private PrepareOperations prepare;
public void init(FilterConfig filterConfig) throws ServletException {
InitOperations init = new InitOperations();
try {
FilterHostConfig config = new FilterHostConfig(filterConfig);
init.initLogging(config);
Dispatcher dispatcher = init.initDispatcher(config);
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
} finally {
init.cleanup();
}
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
prepare.createActionContext(request, response);
prepare.assignDispatcherToThread();
prepare.setEncodingAndLocale(request, response);
request = prepare.wrapRequest(request);
prepare.findActionMapping(request, response);
chain.doFilter(request, response);
} finally {
prepare.cleanupRequest(request);
}
}
public void destroy() {
prepare.cleanupDispatcher();
}
}
@@ -0,0 +1,70 @@
/*
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
*
* 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.
*/
/**
* This package contains a reimagining of the traditional Struts filter dispatchers. Each specific deployment has
* their own filters to prevent confusion. In addition, the operations have been explicitly pulled into *Operations
* objects that try to document through method naming what is happening at every step. Here are a few common use
* cases and how you would manage the Struts deployment:
*
* <h3>Simple Dispatcher</h3>
* <pre>
* &lt;filter&gt;
* &lt;filter-name&gt;struts2&lt;/filter-name&gt;
* &lt;filter-class&gt;org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter&lt;/filter-class&gt;
* &lt;/filter&gt;
*
* &lt;filter-mapping&gt;
* &lt;filter-name&gt;struts2&lt;/filter-name&gt;
* &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
* &lt;/filter-mapping&gt;
* </pre>
*
* <h3>Deployment with Sitemesh</h3>
* <pre>
* &lt;filter&gt;
* &lt;filter-name&gt;struts2-prepare&lt;/filter-name&gt;
* &lt;filter-class&gt;org.apache.struts2.dispatcher.filter.StrutsPrepareFilter&lt;/filter-class&gt;
* &lt;/filter&gt;
* &lt;filter&gt;
* &lt;filter-name&gt;sitemesh&lt;/filter-name&gt;
* &lt;filter-class&gt;com.opensymphony.module.sitemesh.filter.PageFilter&lt;/filter-class&gt;
* &lt;/filter&gt;
* &lt;filter&gt;
* &lt;filter-name&gt;struts2-execute&lt;/filter-name&gt;
* &lt;filter-class&gt;org.apache.struts2.dispatcher.filter.StrutsExecuteFilter&lt;/filter-class&gt;
* &lt;/filter&gt;
*
* &lt;filter-mapping&gt;
* &lt;filter-name&gt;struts2-prepare&lt;/filter-name&gt;
* &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
* &lt;/filter-mapping&gt;
* &lt;filter-mapping&gt;
* &lt;filter-name&gt;sitemesh&lt;/filter-name&gt;
* &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
* &lt;/filter-mapping&gt;
* &lt;filter-mapping&gt;
* &lt;filter-name&gt;struts2-execute&lt;/filter-name&gt;
* &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
* &lt;/filter-mapping&gt;
* </pre>
*
*/
package org.apache.struts2.dispatcher.ng;
@@ -0,0 +1,51 @@
/*
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
*
* 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.dispatcher.ng.servlet;
import org.apache.struts2.util.MakeIterator;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import java.util.Iterator;
import org.apache.struts2.dispatcher.ng.HostConfig;
/**
* Host configuration that wraps a ServletConfig
*/
public class ServletHostConfig implements HostConfig {
private ServletConfig config;
public ServletHostConfig(ServletConfig config) {
this.config = config;
}
public String getInitParameter(String key) {
return config.getInitParameter(key);
}
public Iterator<String> getInitParameterNames() {
return MakeIterator.convert(config.getInitParameterNames());
}
public ServletContext getServletContext() {
return config.getServletContext();
}
}
@@ -0,0 +1,87 @@
/*
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
*
* 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.dispatcher.ng.servlet;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.ng.InitOperations;
import org.apache.struts2.dispatcher.ng.PrepareOperations;
import org.apache.struts2.dispatcher.ng.ExecuteOperations;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.*;
import java.io.IOException;
/**
* Servlet dispatcher for Struts. The preferred way to use Struts is as a filter via the
* {@link org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter} and its variants. This servlet dispatcher
* is only for those that really know what they are doing as it may not support every feature of Struts, particularly
* static resource serving.
*/
public class StrutsServlet extends HttpServlet {
private PrepareOperations prepare;
private ExecuteOperations execute;
@Override
public void init(ServletConfig filterConfig) throws ServletException {
InitOperations init = new InitOperations();
try {
ServletHostConfig config = new ServletHostConfig(filterConfig);
init.initLogging(config);
Dispatcher dispatcher = init.initDispatcher(config);
init.initStaticContentLoader(config, dispatcher);
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
} finally {
init.cleanup();
}
}
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
try {
prepare.createActionContext(request, response);
prepare.assignDispatcherToThread();
prepare.setEncodingAndLocale(request, response);
request = prepare.wrapRequest(request);
ActionMapping mapping = prepare.findActionMapping(request, response);
if (mapping == null) {
boolean handled = execute.executeStaticResourceRequest(request, response);
if (!handled)
throw new ServletException("Resource loading not supported, use the StrutsPrepareAndExecuteFilter instead.");
} else {
execute.executeAction(request, response, mapping);
}
} finally {
prepare.cleanupRequest(request);
}
}
@Override
public void destroy() {
prepare.cleanupDispatcher();
}
}
@@ -85,21 +85,4 @@ public class StrutsObjectFactory extends ObjectFactory {
}
}
public Result buildResult(ResultConfig resultConfig, Map extraContext) throws Exception {
String resultClassName = resultConfig.getClassName();
if (resultClassName == null)
return null;
Object result = buildBean(resultClassName, extraContext);
reflectionProvider.setProperties(resultConfig.getParams(), result, extraContext);
if (result instanceof Result)
return (Result) result;
// This is for the new API:
// if (result instanceof org.apache.struts2.spi.Result)
// return new ResultAdapter((org.apache.struts2.spi.Result) result);
throw new ConfigurationException(result.getClass().getName() + " does not implement Result.");
}
}
@@ -26,6 +26,7 @@ import com.opensymphony.xwork2.ActionContext;
import java.util.Map;
import java.util.Collections;
import java.util.TreeMap;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
@@ -36,31 +37,31 @@ import org.apache.struts2.dispatcher.mapper.ActionMapping;
* exactly like {@link ParametersInterceptor}, only the parameters come from the {@link ActionMapping}, not the
* {@link ActionContext#getParameters()} method.
* <!-- END SNIPPET: description -->
*
* <p/>
* <p/> <u>Interceptor parameters:</u>
*
* <p/>
* <!-- START SNIPPET: parameters -->
*
* <p/>
* <ul>
*
* <p/>
* <li>ordered - set to true if you want the top-down property setter behaviour</li>
*
* <p/>
* </ul>
*
* <p/>
* <!-- END SNIPPET: parameters -->
*
* <p/>
* <p/> <u>Extending the interceptor:</u>
*
* <p/>
* <!-- START SNIPPET: extending -->
*
* <p/>
* <p/> The best way to add behavior to this interceptor is to utilize the {@link com.opensymphony.xwork2.interceptor.ParameterNameAware} interface in your
* actions. However, if you wish to apply a global rule that isn't implemented in your action, then you could extend
* this interceptor and override the {@link #acceptableName(String)} method.
*
* <p/>
* <!-- END SNIPPET: extending -->
*
* <p/>
* <p/> <u>Example code:</u>
*
* <p/>
* <pre>
* <!-- START SNIPPET: example -->
* &lt;action name="someAction" class="com.examples.SomeAction"&gt;
@@ -75,9 +76,10 @@ public class ActionMappingParametersInteceptor extends ParametersInterceptor {
/**
* @param ac The action context
* @return the parameters from the action mapping in the context. If none found, returns
* an empty map.
* an empty map.
*/
protected Map retrieveParametersFromContext(ActionContext ac) {
@Override
protected Map retrieveParameters(ActionContext ac) {
ActionMapping mapping = (ActionMapping) ac.get(ServletActionContext.ACTION_MAPPING);
if (mapping != null) {
return mapping.getParams();
@@ -85,4 +87,27 @@ public class ActionMappingParametersInteceptor extends ParametersInterceptor {
return Collections.EMPTY_MAP;
}
}
/**
* Adds the parameters into context's ParameterMap
*
* @param ac The action context
* @param newParams The parameter map to apply
* <p/>
* In this class this is a no-op, since the parameters were fetched from the same location.
* In subclasses both retrieveParameters() and addParametersToContext() should be overridden.
*/
@Override
protected void addParametersToContext(ActionContext ac, Map newParams) {
Map previousParams = ac.getParameters();
Map combinedParams = null;
if (previousParams != null) {
combinedParams = new TreeMap(previousParams);
} else {
combinedParams = new TreeMap();
}
combinedParams.putAll(newParams);
ac.setParameters(combinedParams);
}
}
@@ -22,6 +22,8 @@
package org.apache.struts2.interceptor;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import com.opensymphony.xwork2.interceptor.Interceptor;
import java.util.Map;
@@ -53,6 +55,8 @@ public class CheckboxInterceptor implements Interceptor {
private String uncheckedValue = Boolean.FALSE.toString();
private static final Logger LOG = LoggerFactory.getLogger(CheckboxInterceptor.class);
public void destroy() {
}
@@ -61,7 +65,7 @@ public class CheckboxInterceptor implements Interceptor {
public String intercept(ActionInvocation ai) throws Exception {
Map parameters = ai.getInvocationContext().getParameters();
Map<String, String> newParams = new HashMap<String, String>();
Map<String, String[]> newParams = new HashMap<String, String[]>();
Set<String> keys = parameters.keySet();
for (Iterator<String> iterator = keys.iterator(); iterator.hasNext();) {
String key = iterator.next();
@@ -69,12 +73,17 @@ public class CheckboxInterceptor implements Interceptor {
if (key.startsWith("__checkbox_")) {
String name = key.substring("__checkbox_".length());
Object values = parameters.get(key);
iterator.remove();
if (values != null && values instanceof String[] && ((String[])values).length > 1) {
LOG.debug("Bypassing automatic checkbox detection due to multiple checkboxes of the same name: #1", name);
continue;
}
// is this checkbox checked/submitted?
if (!parameters.containsKey(name)) {
// if not, let's be sure to default the value to false
newParams.put(name, uncheckedValue);
newParams.put(name, new String[]{uncheckedValue});
}
}
}
@@ -32,6 +32,9 @@ import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.util.TokenHelper;
import org.apache.struts2.ServletActionContext;
import javax.servlet.http.HttpSession;
/**
@@ -212,6 +215,7 @@ public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor {
String name = getBackgroundProcessName(proxy);
ActionContext context = actionInvocation.getInvocationContext();
Map session = context.getSession();
HttpSession httpSession = ServletActionContext.getRequest().getSession(true);
Boolean secondTime = true;
if (executeAfterValidationPass) {
@@ -225,7 +229,9 @@ public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor {
}
}
synchronized (session) {
//sync on the real HttpSession as the session from the context is a wrap that is created
//on every request
synchronized (httpSession) {
BackgroundProcess bp = (BackgroundProcess) session.get(KEY + name);
if ((!executeAfterValidationPass || secondTime) && bp == null) {
@@ -22,15 +22,7 @@
package org.apache.struts2.interceptor;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
@@ -43,133 +35,170 @@ import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import com.opensymphony.xwork2.util.TextParseUtil;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;
/**
* <!-- START SNIPPET: description -->
*
* <p/>
* Interceptor that is based off of {@link MultiPartRequestWrapper}, which is automatically applied for any request that
* includes a file. It adds the following parameters, where [File Name] is the name given to the file uploaded by the
* HTML form:
*
* <p/>
* <ul>
*
* <p/>
* <li>[File Name] : File - the actual File</li>
*
* <p/>
* <li>[File Name]ContentType : String - the content type of the file</li>
*
* <p/>
* <li>[File Name]FileName : String - the actual name of the file uploaded (not the HTML name)</li>
*
* <p/>
* </ul>
*
* <p/>
* <p/> You can get access to these files by merely providing setters in your action that correspond to any of the three
* patterns above, such as setDocument(File document), setDocumentContentType(String contentType), etc.
* <br/>See the example code section.
*
* <p/>
* <p/> This interceptor will add several field errors, assuming that the action implements {@link ValidationAware}.
* These error messages are based on several i18n values stored in struts-messages.properties, a default i18n file
* processed for all i18n requests. You can override the text of these messages by providing text for the following
* keys:
*
* <p/>
* <ul>
*
* <p/>
* <li>struts.messages.error.uploading - a general error that occurs when the file could not be uploaded</li>
*
* <p/>
* <li>struts.messages.error.file.too.large - occurs when the uploaded file is too large</li>
*
* <p/>
* <li>struts.messages.error.content.type.not.allowed - occurs when the uploaded file does not match the expected
* content types specified</li>
*
* <p/>
* <li>struts.messages.error.file.extension.not.allowed - occurs when the uploaded file does not match the expected
* file extensions specified</li>
* <p/>
* </ul>
*
* <p/>
* <!-- END SNIPPET: description -->
*
* <p/>
* <p/> <u>Interceptor parameters:</u>
*
* <p/>
* <!-- START SNIPPET: parameters -->
*
* <p/>
* <ul>
*
* <p/>
* <li>maximumSize (optional) - the maximum size (in bytes) that the interceptor will allow a file reference to be set
* on the action. Note, this is <b>not</b> related to the various properties found in struts.properties.
* Default to approximately 2MB.</li>
*
* <p/>
* <li>allowedTypes (optional) - a comma separated list of content types (ie: text/html) that the interceptor will allow
* a file reference to be set on the action. If none is specified allow all types to be uploaded.</li>
*
* </ul>
*
* <!-- END SNIPPET: parameters -->
*
* <p/> <u>Extending the interceptor:</u>
*
* <p/>
*
* <li>allowedExtensions (optional) - a comma separated list of file extensions (ie: .html) that the interceptor will allow
* a file reference to be set on the action. If none is specified allow all extensions to be uploaded.</li>
* </ul>
* <p/>
* <p/>
* <!-- END SNIPPET: parameters -->
* <p/>
* <p/> <u>Extending the interceptor:</u>
* <p/>
* <p/>
* <p/>
* <!-- START SNIPPET: extending -->
*
* You can extend this interceptor and override the {@link #acceptFile} method to provide more control over which files
* <p/>
* You can extend this interceptor and override the acceptFile method to provide more control over which files
* are supported and which are not.
*
* <p/>
* <!-- END SNIPPET: extending -->
*
* <p/>
* <p/> <u>Example code:</u>
*
* <p/>
* <pre>
* <!-- START SNIPPET: example -->
* &lt;action name="doUpload" class="com.examples.UploadAction"&gt;
* <!-- START SNIPPET: example-configuration -->
* &lt;action name="doUpload" class="com.example.UploadAction"&gt;
* &lt;interceptor-ref name="fileUpload"/&gt;
* &lt;interceptor-ref name="basicStack"/&gt;
* &lt;result name="success"&gt;good_result.ftl&lt;/result&gt;
* &lt;result name="success"&gt;good_result.jsp&lt;/result&gt;
* &lt;/action&gt;
* <!-- END SNIPPET: example-configuration -->
* </pre>
*
* And then you need to set encoding <code>multipart/form-data</code> in the form where the user selects the file to upload.
* <p/>
* <!-- START SNIPPET: multipart-note -->
* <p/>
* You must set the encoding to <code>multipart/form-data</code> in the form where the user selects the file to upload.
* <p/>
* <!-- END SNIPPET: multipart-note -->
* <p/>
* <pre>
* <!-- START SNIPPET: example-form -->
* &lt;s:form action="doUpload" method="post" enctype="multipart/form-data"&gt;
* &lt;s:file name="upload" label="File"/&gt;
* &lt;s:submit/&gt;
* &lt;/s:form&gt;
* <!-- END SNIPPET: example-form -->
* </pre>
*
* <p/>
* And then in your action code you'll have access to the File object if you provide setters according to the
* naming convention documented in the start.
*
* <p/>
* <pre>
* public com.examples.UploadAction implemements Action {
* <!-- START SNIPPET: example-action -->
* package com.example;
* <p/>
* import java.io.File;
* import com.opensymphony.xwork2.ActionSupport;
* <p/>
* public UploadAction extends ActionSupport {
* private File file;
* private String contentType;
* private String filename;
*
* <p/>
* public void setUpload(File file) {
* this.file = file;
* }
*
* <p/>
* public void setUploadContentType(String contentType) {
* this.contentType = contentType;
* }
*
* <p/>
* public void setUploadFileName(String filename) {
* this.filename = filename;
* }
*
* ...
* <p/>
* public String execute() {
* //...
* return SUCCESS;
* }
* }
* <!-- END SNIPPET: example-action -->
* </pre>
* <!-- END SNIPPET: example -->
*
*/
public class FileUploadInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = -4764627478894962478L;
protected static final Logger LOG = LoggerFactory.getLogger(FileUploadInterceptor.class);
private static final String DEFAULT_DELIMITER = ",";
private static final String DEFAULT_MESSAGE = "no.message.found";
protected boolean useActionMessageBundle;
protected Long maximumSize;
protected String allowedTypes;
protected Set allowedTypesSet = Collections.EMPTY_SET;
protected Set<String> allowedTypesSet = Collections.emptySet();
protected Set<String> allowedExtensionsSet = Collections.emptySet();
public void setUseActionMessageBundle(String value) {
this.useActionMessageBundle = Boolean.valueOf(value);
}
/**
* Sets the allowed extensions
*
* @param allowedExtensions A comma-delimited list of extensions
*/
public void setAllowedExtensions(String allowedExtensions) {
allowedExtensionsSet = TextParseUtil.commaDelimitedStringToSet(allowedExtensions);
}
/**
* Sets the allowed mimetypes
@@ -177,10 +206,7 @@ public class FileUploadInterceptor extends AbstractInterceptor {
* @param allowedTypes A comma-delimited list of types
*/
public void setAllowedTypes(String allowedTypes) {
this.allowedTypes = allowedTypes;
// set the allowedTypes as a collection for easier access later
allowedTypesSet = getDelimitedValues(allowedTypes);
allowedTypesSet = TextParseUtil.commaDelimitedStringToSet(allowedTypes);
}
/**
@@ -197,20 +223,22 @@ public class FileUploadInterceptor extends AbstractInterceptor {
*/
public String intercept(ActionInvocation invocation) throws Exception {
ActionContext ac = invocation.getInvocationContext();
HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST);
if (!(request instanceof MultiPartRequestWrapper)) {
if (LOG.isDebugEnabled()) {
ActionProxy proxy = invocation.getProxy();
LOG.debug(getTextMessage("struts.messages.bypass.request", new Object[]{proxy.getNamespace(), proxy.getActionName()}, ActionContext.getContext().getLocale()));
LOG.debug(getTextMessage("struts.messages.bypass.request", new Object[]{proxy.getNamespace(), proxy.getActionName()}, ac.getLocale()));
}
return invocation.invoke();
}
final Object action = invocation.getAction();
ValidationAware validation = null;
Object action = invocation.getAction();
if (action instanceof ValidationAware) {
validation = (ValidationAware) action;
}
@@ -218,9 +246,7 @@ public class FileUploadInterceptor extends AbstractInterceptor {
MultiPartRequestWrapper multiWrapper = (MultiPartRequestWrapper) request;
if (multiWrapper.hasErrors()) {
for (Iterator errorIter = multiWrapper.getErrors().iterator(); errorIter.hasNext();) {
String error = (String) errorIter.next();
for (String error : multiWrapper.getErrors()) {
if (validation != null) {
validation.addActionError(error);
}
@@ -229,9 +255,7 @@ public class FileUploadInterceptor extends AbstractInterceptor {
}
}
Map parameters = ac.getParameters();
// Bind allowed Files
// bind allowed Files
Enumeration fileParameterNames = multiWrapper.getFileParameterNames();
while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
// get the value of this input tag
@@ -245,23 +269,36 @@ public class FileUploadInterceptor extends AbstractInterceptor {
String[] fileName = multiWrapper.getFileNames(inputName);
if (isNonEmpty(fileName)) {
// Get a File object for the uploaded File
// get a File object for the uploaded File
File[] files = multiWrapper.getFiles(inputName);
if (files != null) {
for (int index = 0; index < files.length; index++) {
if (files != null && files.length > 0) {
List<File> acceptedFiles = new ArrayList<File>(files.length);
List<String> acceptedContentTypes = new ArrayList<String>(files.length);
List<String> acceptedFileNames = new ArrayList<String>(files.length);
String contentTypeName = inputName + "ContentType";
String fileNameName = inputName + "FileName";
if (acceptFile(files[index], contentType[index], inputName, validation, ac.getLocale())) {
parameters.put(inputName, files);
parameters.put(inputName + "ContentType", contentType);
parameters.put(inputName + "FileName", fileName);
for (int index = 0; index < files.length; index++) {
if (acceptFile(action, files[index], fileName[index], contentType[index], inputName, validation, ac.getLocale())) {
acceptedFiles.add(files[index]);
acceptedContentTypes.add(contentType[index]);
acceptedFileNames.add(fileName[index]);
}
}
if (!acceptedFiles.isEmpty()) {
Map<String, Object> params = ac.getParameters();
params.put(inputName, acceptedFiles.toArray(new File[acceptedFiles.size()]));
params.put(contentTypeName, acceptedContentTypes.toArray(new String[acceptedContentTypes.size()]));
params.put(fileNameName, acceptedFileNames.toArray(new String[acceptedFileNames.size()]));
}
}
} else {
LOG.error(getTextMessage("struts.messages.invalid.file", new Object[]{inputName}, ActionContext.getContext().getLocale()));
LOG.error(getTextMessage(action, "struts.messages.invalid.file", new Object[]{inputName}, ac.getLocale()));
}
} else {
LOG.error(getTextMessage("struts.messages.invalid.content.type", new Object[]{inputName}, ActionContext.getContext().getLocale()));
LOG.error(getTextMessage(action, "struts.messages.invalid.content.type", new Object[]{inputName}, ac.getLocale()));
}
}
@@ -272,12 +309,13 @@ public class FileUploadInterceptor extends AbstractInterceptor {
fileParameterNames = multiWrapper.getFileParameterNames();
while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
String inputValue = (String) fileParameterNames.nextElement();
File[] file = multiWrapper.getFiles(inputValue);
for (int index = 0; index < file.length; index++) {
File currentFile = file[index];
if(LOG.isInfoEnabled()) {
LOG.info(getTextMessage("struts.messages.removing.file", new Object[]{inputValue, currentFile}, ActionContext.getContext().getLocale()));
File[] files = multiWrapper.getFiles(inputValue);
for (File currentFile : files) {
if (LOG.isInfoEnabled()) {
LOG.info(getTextMessage(action, "struts.messages.removing.file", new Object[]{inputValue, currentFile}, ac.getLocale()));
}
if ((currentFile != null) && currentFile.isFile()) {
currentFile.delete();
}
@@ -290,6 +328,7 @@ public class FileUploadInterceptor extends AbstractInterceptor {
/**
* Override for added functionality. Checks if the proposed file is acceptable based on contentType and size.
*
* @param action - uploading action for message retrieval.
* @param file - proposed upload file.
* @param contentType - contentType of the file.
* @param inputName - inputName of the file.
@@ -298,26 +337,33 @@ public class FileUploadInterceptor extends AbstractInterceptor {
* @param locale
* @return true if the proposed file is acceptable by contentType and size.
*/
protected boolean acceptFile(File file, String contentType, String inputName, ValidationAware validation, Locale locale) {
protected boolean acceptFile(Object action, File file, String filename, String contentType, String inputName, ValidationAware validation, Locale locale) {
boolean fileIsAcceptable = false;
// If it's null the upload failed
if (file == null) {
String errMsg = getTextMessage("struts.messages.error.uploading", new Object[]{inputName}, locale);
String errMsg = getTextMessage(action, "struts.messages.error.uploading", new Object[]{inputName}, locale);
if (validation != null) {
validation.addFieldError(inputName, errMsg);
}
LOG.error(errMsg);
} else if (maximumSize != null && maximumSize.longValue() < file.length()) {
String errMsg = getTextMessage("struts.messages.error.file.too.large", new Object[]{inputName, file.getName(), "" + file.length()}, locale);
} else if (maximumSize != null && maximumSize < file.length()) {
String errMsg = getTextMessage(action, "struts.messages.error.file.too.large", new Object[]{inputName, filename, file.getName(), "" + file.length()}, locale);
if (validation != null) {
validation.addFieldError(inputName, errMsg);
}
LOG.error(errMsg);
} else if ((! allowedTypesSet.isEmpty()) && (!containsItem(allowedTypesSet, contentType))) {
String errMsg = getTextMessage("struts.messages.error.content.type.not.allowed", new Object[]{inputName, file.getName(), contentType}, locale);
} else if ((!allowedTypesSet.isEmpty()) && (!containsItem(allowedTypesSet, contentType))) {
String errMsg = getTextMessage(action, "struts.messages.error.content.type.not.allowed", new Object[]{inputName, filename, file.getName(), contentType}, locale);
if (validation != null) {
validation.addFieldError(inputName, errMsg);
}
LOG.error(errMsg);
} else if ((! allowedExtensionsSet.isEmpty()) && (!hasAllowedExtension(allowedExtensionsSet, filename))) {
String errMsg = getTextMessage(action, "struts.messages.error.file.extension.not.allowed", new Object[]{inputName, filename, file.getName(), contentType}, locale);
if (validation != null) {
validation.addFieldError(inputName, errMsg);
}
@@ -331,26 +377,32 @@ public class FileUploadInterceptor extends AbstractInterceptor {
}
/**
* @param itemCollection - Collection of string items (all lowercase).
* @param key - Key to search for.
* @return true if itemCollection contains the key, false otherwise.
* @param extensionCollection - Collection of extensions (all lowercase).
* @param filename - filename to check.
* @return true if the filename has an allowed extension, false otherwise.
*/
private static boolean containsItem(Collection itemCollection, String key) {
return itemCollection.contains(key.toLowerCase());
}
private static boolean hasAllowedExtension(Collection<String> extensionCollection, String filename) {
if (filename == null) {
return false;
}
private static Set getDelimitedValues(String delimitedString) {
Set<String> delimitedValues = new HashSet<String>();
if (delimitedString != null) {
StringTokenizer stringTokenizer = new StringTokenizer(delimitedString, DEFAULT_DELIMITER);
while (stringTokenizer.hasMoreTokens()) {
String nextToken = stringTokenizer.nextToken().toLowerCase().trim();
if (nextToken.length() > 0) {
delimitedValues.add(nextToken);
}
String lowercaseFilename = filename.toLowerCase();
for (String extension : extensionCollection) {
if (lowercaseFilename.endsWith(extension)) {
return true;
}
}
return delimitedValues;
return false;
}
/**
* @param itemCollection - Collection of string items (all lowercase).
* @param item - Item to search for.
* @return true if itemCollection contains the item, false otherwise.
*/
private static boolean containsItem(Collection<String> itemCollection, String item) {
return itemCollection.contains(item.toLowerCase());
}
private static boolean isNonEmpty(Object[] objArray) {
@@ -364,9 +416,19 @@ public class FileUploadInterceptor extends AbstractInterceptor {
}
private String getTextMessage(String messageKey, Object[] args, Locale locale) {
return getTextMessage(null, messageKey, args, locale);
}
private String getTextMessage(Object action, String messageKey, Object[] args, Locale locale) {
if (args == null || args.length == 0) {
return LocalizedTextUtil.findText(this.getClass(), messageKey, locale);
if ( action != null && useActionMessageBundle) {
return LocalizedTextUtil.findText(action.getClass(), messageKey, locale);
}
return LocalizedTextUtil.findText(this.getClass(), messageKey, locale);
} else {
if ( action != null && useActionMessageBundle) {
return LocalizedTextUtil.findText(action.getClass(), messageKey, locale, DEFAULT_MESSAGE, args);
}
return LocalizedTextUtil.findText(this.getClass(), messageKey, locale, DEFAULT_MESSAGE, args);
}
}
@@ -42,5 +42,5 @@ public interface ParameterAware {
*
* @param parameters a Map of parameters (name/value Strings).
*/
public void setParameters(Map<String,String[]> parameters);
public void setParameters(Map<String, String[]> parameters);
}
@@ -98,11 +98,14 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
*
* </ul>
*
* <li>sessionReset - boolean value causing all session values to be reset to action's default values or application
* scope values, note that it is similliar to type="start" and in fact it does the same, but in our team it is sometimes
* semantically preferred. We use session scope in two patterns - sometimes there are wizzard-like action sequences that
* <li>sessionReset - name of a parameter (defaults to 'session.reset') which if set, causes all session values to be reset to action's default values or application
* scope values, note that it is similar to type="start" and in fact it does the same, but in our team it is sometimes
* semantically preferred. We use session scope in two patterns - sometimes there are wizard-like action sequences that
* have start and end, and sometimes we just want simply reset current session values.</li>
*
* <li>reset - boolean, defaults to false, if set, it has the same effect as setting all session values to be reset to action's default values or application.</li>
*
* <li>autoCreateSession - boolean value, sets if the session should be automatically created.</li>
* </ul>
*
* <!-- END SNIPPET: parameters -->
@@ -135,7 +135,7 @@ public class ServletConfigInterceptor extends AbstractInterceptor implements Str
}
if (action instanceof ParameterAware) {
((ParameterAware) action).setParameters(context.getParameters());
((ParameterAware) action).setParameters((Map)context.getParameters());
}
if (action instanceof ApplicationAware) {
@@ -24,6 +24,7 @@ package org.apache.struts2.interceptor;
import java.util.Map;
import org.apache.struts2.util.TokenHelper;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
@@ -31,6 +32,8 @@ import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import com.opensymphony.xwork2.util.LocalizedTextUtil;
import javax.servlet.http.HttpSession;
/**
* <!-- START SNIPPET: description -->
*
@@ -129,7 +132,9 @@ public class TokenInterceptor extends MethodFilterInterceptor {
log.debug("Intercepting invocation to check for valid transaction token.");
}
Map session = ActionContext.getContext().getSession();
//see WW-2902: we need to use the real HttpSession here, as opposed to the map
//that wraps the session, because a new wrap is created on every request
HttpSession session = ServletActionContext.getRequest().getSession(true);
synchronized (session) {
if (!TokenHelper.validToken()) {
@@ -22,8 +22,13 @@
package org.apache.struts2.interceptor.validation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import org.apache.commons.lang.ArrayUtils;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.util.AnnotationUtils;
import com.opensymphony.xwork2.validator.ValidationInterceptor;
/**
@@ -31,24 +36,38 @@ import com.opensymphony.xwork2.validator.ValidationInterceptor;
* annotation, and if found, don't validate this action method
*/
public class AnnotationValidationInterceptor extends ValidationInterceptor {
/** Auto-generated serialization id */
private static final long serialVersionUID = 1813272797367431184L;
protected String doIntercept(ActionInvocation invocation) throws Exception {
Object action = invocation.getAction();
if (action != null) {
Method method = getActionMethod(action.getClass(), invocation.getProxy().getMethod());
SkipValidation skip = (SkipValidation) method.getAnnotation(SkipValidation.class);
if (skip != null) {
Collection<Method> annotatedMethods = AnnotationUtils.getAnnotatedMethods(action.getClass(), SkipValidation.class);
if (annotatedMethods.contains(method))
return invocation.invoke();
//check if method overwites an annotated method
Class clazz = action.getClass().getSuperclass();
while (clazz != null) {
annotatedMethods = AnnotationUtils.getAnnotatedMethods(clazz, SkipValidation.class);
if (annotatedMethods != null) {
for (Method annotatedMethod : annotatedMethods) {
if (annotatedMethod.getName().equals(method.getName())
&& Arrays.equals(annotatedMethod.getParameterTypes(), method.getParameterTypes())
&& Arrays.equals(annotatedMethod.getExceptionTypes(), method.getExceptionTypes()))
return invocation.invoke();
}
}
clazz = clazz.getSuperclass();
}
}
return super.doIntercept(invocation);
}
// FIXME: This is copied from DefaultActionInvocation but should be exposed through the interface
protected Method getActionMethod(Class actionClass, String methodName) throws NoSuchMethodException {
Method method;
@@ -34,6 +34,7 @@ import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import com.opensymphony.xwork2.util.logging.Logger;
@@ -43,7 +44,7 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
* <p>Serializes validation and action errors into JSON. This interceptor does not
* perform any validation, so it must follow the 'validation' interceptor on the stack.
* </p>
*
*
* <p>This stack (defined in struts-default.xml) shows how to use this interceptor with the
* 'validation' interceptor</p>
* <pre>
@@ -58,19 +59,19 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
* </pre>
* <p>If 'validationFailedStatus' is set it will be used as the Response status
* when validation fails.</p>
*
* <p>If the request has a parameter 'struts.validateOnly' execution will return after
*
* <p>If the request has a parameter 'struts.validateOnly' execution will return after
* validation (action won't be executed).</p>
*
*
* <p>A request parameter named 'enableJSONValidation' must be set to 'true' to
* use this interceptor</p>
*/
public class JSONValidationInterceptor extends MethodFilterInterceptor {
private static final Logger LOG = LoggerFactory.getLogger(JSONValidationInterceptor.class);
private static final String VALIDATE_ONLY_PARAM = "struts.validateOnly";
private static final String VALIDATE_JSON_PARAM = "struts.enableJSONValidation";
static char[] hex = "0123456789ABCDEF".toCharArray();
private int validationFailedStatus = -1;
@@ -90,7 +91,7 @@ public class JSONValidationInterceptor extends MethodFilterInterceptor {
Object action = invocation.getAction();
String jsonEnabled = request.getParameter(VALIDATE_JSON_PARAM);
if (jsonEnabled != null && "true".equals(jsonEnabled)) {
if (action instanceof ValidationAware) {
// generate json
@@ -130,7 +131,7 @@ public class JSONValidationInterceptor extends MethodFilterInterceptor {
//action errors
if (validationAware.hasActionErrors()) {
sb.append("\"errors\":");
sb.append(buildArray(validationAware.getActionErrors()));
sb.append(buildArray(validationAware.getActionErrors()));
}
//field errors
@@ -143,7 +144,9 @@ public class JSONValidationInterceptor extends MethodFilterInterceptor {
for (Map.Entry<String, List<String>> fieldError : fieldErrors
.entrySet()) {
sb.append("\"");
sb.append(fieldError.getKey());
//if it is model driven, remove "model." see WW-2721
sb.append(validationAware instanceof ModelDriven ? fieldError.getKey().substring(6)
: fieldError.getKey());
sb.append("\":");
sb.append(buildArray(fieldError.getValue()));
sb.append(",");

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