From 617ab8d9c4f5f477a49836f14bf92fc6a170158e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Gielen?= Date: Sun, 16 Nov 2008 18:49:35 +0000 Subject: [PATCH] WW-2870: Tag r718077 as Struts 2.0.14 git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14@718080 13f79535-47bb-0310-9956-ffa450edef68 --- STRUTS_2_0_X/apps/blank/LICENSE.txt | 174 + STRUTS_2_0_X/apps/blank/NOTICE.txt | 6 + STRUTS_2_0_X/apps/blank/README.txt | 10 + STRUTS_2_0_X/apps/blank/pom.xml | 59 + .../src/main/java/example/ExampleSupport.java | 30 + .../src/main/java/example/HelloWorld.java | 61 + .../blank/src/main/java/example/Login.java | 59 + .../blank/src/main/java/example/build.bat | 3 + .../apps/blank/src/main/resources/LICENSE.txt | 174 + .../apps/blank/src/main/resources/NOTICE.txt | 5 + .../apps/blank/src/main/resources/example.xml | 25 + .../resources/example/Login-validation.xml | 16 + .../main/resources/example/package.properties | 5 + .../resources/example/package_es.properties | 5 + .../apps/blank/src/main/resources/struts.xml | 15 + .../blank/src/main/webapp/WEB-INF/web.xml | 20 + .../src/main/webapp/example/HelloWorld.jsp | 28 + .../blank/src/main/webapp/example/Login.jsp | 15 + .../blank/src/main/webapp/example/Menu.jsp | 3 + .../blank/src/main/webapp/example/Missing.jsp | 11 + .../src/main/webapp/example/Register.jsp | 3 + .../blank/src/main/webapp/example/Welcome.jsp | 18 + .../apps/blank/src/main/webapp/index.html | 10 + .../src/test/java/example/ConfigTest.java | 97 + .../src/test/java/example/HelloWorldTest.java | 37 + .../src/test/java/example/LoginTest.java | 55 + STRUTS_2_0_X/apps/mailreader/README.txt | 18 + STRUTS_2_0_X/apps/mailreader/pom.xml | 56 + .../src/main/java/alternate.properties | 3 + .../src/main/java/alternate_ja.properties | 1 + .../src/main/java/mailreader-default.xml | 47 + .../src/main/java/mailreader-support.xml | 63 + .../java/mailreader2/ApplicationListener.java | 234 + .../AuthenticationInterceptor.java | 31 + .../src/main/java/mailreader2/Constants.java | 128 + .../java/mailreader2/Login-validation.xml | 14 + .../src/main/java/mailreader2/Login.java | 48 + .../src/main/java/mailreader2/Logout.java | 35 + .../java/mailreader2/MailreaderSupport.java | 582 + .../mailreader2/MailreaderSupport.properties | 96 + .../MailreaderSupport_ja.properties | 89 + .../MailreaderSupport_ru.properties | 89 + ...istration-Registration_save-validation.xml | 28 + .../mailreader2/Registration-validation.xml | 32 + .../main/java/mailreader2/Registration.java | 122 + ...scription-Subscription_save-validation.xml | 23 + .../mailreader2/Subscription-validation.xml | 11 + .../main/java/mailreader2/Subscription.java | 145 + .../src/main/java/mailreader2/Welcome.java | 49 + .../apps/mailreader/src/main/java/struts.xml | 16 + .../mailreader/src/main/resources/LICENSE.txt | 174 + .../mailreader/src/main/resources/NOTICE.txt | 5 + .../src/main/webapp/ChangePassword.jsp | 25 + .../apps/mailreader/src/main/webapp/Error.jsp | 40 + .../mailreader/src/main/webapp/Footer.jsp | 6 + .../apps/mailreader/src/main/webapp/Login.jsp | 33 + .../src/main/webapp/META-INF/context.xml | 3 + .../mailreader/src/main/webapp/MainMenu.jsp | 26 + .../src/main/webapp/Registration.jsp | 115 + .../src/main/webapp/Subscription.jsp | 60 + .../src/main/webapp/WEB-INF/database.xml | 13 + .../src/main/webapp/WEB-INF/web.xml | 30 + .../mailreader/src/main/webapp/Welcome.jsp | 55 + .../src/main/webapp/css/mailreader.css | 46 + .../mailreader/src/main/webapp/index.html | 10 + .../src/main/webapp/struts-power.gif | Bin 0 -> 1798 bytes .../apps/mailreader/src/main/webapp/tour.html | 2470 +++ STRUTS_2_0_X/apps/pom.xml | 170 + STRUTS_2_0_X/apps/portlet/README.txt | 17 + STRUTS_2_0_X/apps/portlet/pom.xml | 80 + .../apps/portlet/src/main/etc/exo/web.xml | 63 + .../main/etc/gridsphere/README-gridsphere.txt | 2 + .../etc/gridsphere/gridsphere-portlet.xml | 24 + .../portlet/src/main/etc/gridsphere/group.xml | 10 + .../src/main/etc/gridsphere/layout.xml | 19 + .../src/main/etc/gridsphere/struts-portlet | 0 .../portlet/src/main/etc/gridsphere/web.xml | 63 + .../src/main/etc/jbossportal2.0/jboss-app.xml | 3 + .../main/etc/jbossportal2.0/jboss-portlet.xml | 12 + .../src/main/etc/jbossportal2.0/jboss-web.xml | 3 + .../etc/jbossportal2.0/portlet-instances.xml | 11 + .../jbossportal2.0/struts-portlet-pages.xml | 18 + .../src/main/etc/jbossportal2.2/jboss-app.xml | 3 + .../main/etc/jbossportal2.2/jboss-portlet.xml | 12 + .../src/main/etc/jbossportal2.2/jboss-web.xml | 3 + .../jbossportal2.2/struts-portlet-object.xml | 25 + .../main/etc/jetspeed2/README-jetspeed2.txt | 1 + .../main/etc/jetspeed2/struts-portlet.psml | 20 + .../portlet/src/main/etc/liferay3.6.1/web.xml | 75 + .../portlet/example/ExampleAction.java | 39 + .../struts2/portlet/example/FormExample.java | 50 + .../example/FormExampleModelDriven.java | 37 + .../example/FormExampleWithValidation.java | 47 + .../portlet/example/FormResultAction.java | 49 + .../portlet/example/FormTestAction.java | 36 + .../portlet/example/SavePrefsAction.java | 62 + .../example/fileupload/FileUploadAction.java | 81 + .../struts2/portlet/example/model/Name.java | 18 + .../portlet/example/spring/SpringAction.java | 58 + .../portlet/example/spring/ThingManager.java | 38 + .../portlet/src/main/resources/LICENSE.txt | 174 + .../portlet/src/main/resources/NOTICE.txt | 5 + .../apps/portlet/src/main/resources/log4j.xml | 15 + ...le-processValidationExample-validation.xml | 13 + .../src/main/resources/struts-edit.xml | 48 + .../src/main/resources/struts-help.xml | 14 + .../src/main/resources/struts-view.xml | 130 + .../src/main/resources/struts.properties | 1 + .../portlet/src/main/resources/struts.xml | 11 + .../template/xhtml/components/checkbox.vm | 12 + .../template/xhtml/components/datefield.vm | 8 + .../template/xhtml/components/mytextfield.vm | 15 + .../portlet/src/main/resources/validators.xml | 16 + .../webapp/WEB-INF/applicationContext.xml | 18 + .../portlet/src/main/webapp/WEB-INF/dwr.xml | 21 + .../main/webapp/WEB-INF/edit/defaultEdit.jsp | 5 + .../main/webapp/WEB-INF/edit/formExample.jsp | 5 + .../webapp/WEB-INF/edit/formExampleInput.jsp | 8 + .../src/main/webapp/WEB-INF/edit/index.jsp | 11 + .../webapp/WEB-INF/edit/namespaceTest.jsp | 4 + .../main/webapp/WEB-INF/edit/prefsForm.jsp | 6 + .../main/webapp/WEB-INF/edit/prefsSaved.jsp | 5 + .../src/main/webapp/WEB-INF/edit/test.jsp | 4 + .../main/webapp/WEB-INF/help/defaultHelp.jsp | 1 + .../src/main/webapp/WEB-INF/help/index.jsp | 1 + .../src/main/webapp/WEB-INF/portlet.xml | 132 + .../src/main/webapp/WEB-INF/readme.txt | 10 + .../src/main/webapp/WEB-INF/view/ajax.jsp | 1 + .../src/main/webapp/WEB-INF/view/ajaxData.jsp | 1 + .../main/webapp/WEB-INF/view/ajaxExample.jsp | 48 + .../main/webapp/WEB-INF/view/fileUpload.jsp | 13 + .../webapp/WEB-INF/view/fileUploadSuccess.jsp | 14 + .../main/webapp/WEB-INF/view/formExample.jsp | 5 + .../webapp/WEB-INF/view/formExampleInput.jsp | 8 + .../view/formExampleInputModelDriven.jsp | 8 + .../WEB-INF/view/formExampleInputPrg.jsp | 8 + .../view/formExampleInputValidation.jsp | 8 + .../webapp/WEB-INF/view/freeMarkerExample.ftl | 3 + .../WEB-INF/view/freeMarkerExampleInput.ftl | 5 + .../main/webapp/WEB-INF/view/helloWorld.vm | 4 + .../src/main/webapp/WEB-INF/view/index.jsp | 17 + .../webapp/WEB-INF/view/notImplemented.jsp | 1 + .../webapp/WEB-INF/view/springExample.jsp | 16 + .../main/webapp/WEB-INF/view/tokenExample.jsp | 5 + .../webapp/WEB-INF/view/tokenExampleInput.jsp | 20 + .../portlet/src/main/webapp/WEB-INF/web.xml | 30 + .../portlet/src/main/webapp/styles/styles.css | 7 + STRUTS_2_0_X/apps/showcase/README.txt | 10 + STRUTS_2_0_X/apps/showcase/pom.xml | 185 + .../apache/struts2/showcase/DateAction.java | 106 + .../showcase/DynamicTreeSelectAction.java | 55 + .../LotsOfOptiontransferselectAction.java | 286 + .../showcase/LotsOfRichtexteditorAction.java | 78 + .../struts2/showcase/MoreSelectsAction.java | 135 + .../showcase/ShowDynamicTreeAction.java | 37 + .../apache/struts2/showcase/UITagExample.java | 322 + .../showcase/action/AbstractCRUDAction.java | 97 + .../showcase/action/EmployeeAction.java | 126 + .../struts2/showcase/action/SkillAction.java | 89 + .../showcase/actionchaining/ActionChain1.java | 45 + .../showcase/actionchaining/ActionChain2.java | 58 + .../showcase/actionchaining/ActionChain3.java | 68 + .../struts2/showcase/ajax/AjaxTestAction.java | 54 + .../ajax/AutocompleterExampleAction.java | 39 + .../ajax/Example4ShowPanelAction.java | 75 + .../struts2/showcase/ajax/Example5Action.java | 43 + .../struts2/showcase/ajax/tree/Category.java | 104 + .../showcase/ajax/tree/GetCategory.java | 49 + .../struts2/showcase/ajax/tree/Toggle.java | 34 + .../showcase/application/MemoryStorage.java | 142 + .../struts2/showcase/application/Storage.java | 50 + .../application/TestDataProvider.java | 118 + .../chat/ChatAuthenticationInterceptor.java | 60 + .../struts2/showcase/chat/ChatException.java | 36 + .../showcase/chat/ChatInterceptor.java | 61 + .../showcase/chat/ChatLoginAction.java | 68 + .../showcase/chat/ChatLogoutAction.java | 58 + .../struts2/showcase/chat/ChatMessage.java | 49 + .../struts2/showcase/chat/ChatService.java | 37 + .../showcase/chat/ChatServiceImpl.java | 115 + .../showcase/chat/ChatSessionListener.java | 53 + .../struts2/showcase/chat/Constants.java | 25 + .../struts2/showcase/chat/CrudRoomAction.java | 64 + .../struts2/showcase/chat/DateConverter.java | 59 + .../showcase/chat/EnterRoomAction.java | 62 + .../struts2/showcase/chat/ExitRoomAction.java | 58 + .../chat/MessagesAvailableInRoomAction.java | 59 + .../apache/struts2/showcase/chat/Room.java | 101 + .../showcase/chat/RoomsAvailableAction.java | 48 + .../chat/SendMessageToRoomAction.java | 70 + .../apache/struts2/showcase/chat/User.java | 48 + .../showcase/chat/UsersAvailableAction.java | 49 + .../chat/UsersAvailableInRoomAction.java | 61 + .../struts2/showcase/conversion/Address.java | 38 + .../showcase/conversion/AddressAction.java | 47 + .../conversion/EnumTypeConverter.java | 58 + .../showcase/conversion/OperationsEnum.java | 33 + .../conversion/OperationsEnumAction.java | 56 + .../struts2/showcase/conversion/Person.java | 37 + .../showcase/conversion/PersonAction.java | 46 + .../struts2/showcase/dao/AbstractDao.java | 77 + .../org/apache/struts2/showcase/dao/Dao.java | 53 + .../struts2/showcase/dao/EmployeeDao.java | 67 + .../apache/struts2/showcase/dao/SkillDao.java | 41 + .../showcase/exception/CreateException.java | 43 + .../showcase/exception/DeleteException.java | 44 + .../exception/DuplicateKeyException.java | 44 + .../showcase/exception/StorageException.java | 44 + .../showcase/exception/UpdateException.java | 45 + .../filedownload/FileDownloadAction.java | 50 + .../showcase/fileupload/FileUploadAction.java | 85 + .../MultipleFileUploadUsingArrayAction.java | 66 + .../MultipleFileUploadUsingListAction.java | 83 + .../freemarker/CustomFreemarkerManager.java | 58 + .../CustomFreemarkerManagerUtil.java | 42 + .../freemarker/StandardTagsAction.java | 67 + .../hangman/GetUpdatedHangmanAction.java | 59 + .../hangman/GuessCharacterAction.java | 59 + .../struts2/showcase/hangman/Hangman.java | 109 + .../showcase/hangman/HangmanConstants.java | 26 + .../showcase/hangman/HangmanException.java | 44 + .../showcase/hangman/HangmanService.java | 34 + .../hangman/PropertiesVocabSource.java | 71 + .../showcase/hangman/StartHangmanAction.java | 61 + .../struts2/showcase/hangman/Vocab.java | 86 + .../struts2/showcase/hangman/VocabSource.java | 25 + .../integration/EditGangsterAction.java | 44 + .../showcase/integration/GangsterForm.java | 108 + .../integration/SaveGangsterAction.java | 51 + .../showcase/jsf/JsfEmployeeAction.java | 122 + .../struts2/showcase/model/Employee.java | 176 + .../struts2/showcase/model/IdEntity.java | 36 + .../apache/struts2/showcase/model/Skill.java | 72 + .../showcase/modelDriven/Gangster.java | 62 + .../modelDriven/ModelDrivenAction.java | 45 + .../showcase/person/EditPersonAction.java | 84 + .../showcase/person/ListPeopleAction.java | 56 + .../showcase/person/NewPersonAction.java | 57 + .../struts2/showcase/person/Person.java | 86 + .../showcase/person/PersonManager.java | 58 + .../showcase/source/ViewSourceAction.java | 224 + .../tag/nonui/actionPrefix/SubmitAction.java | 42 + .../tag/nonui/actiontag/ActionTagDemo.java | 38 + .../iteratortag/AppendIteratorTagDemo.java | 80 + .../iteratortag/IteratorGeneratorTagDemo.java | 69 + .../iteratortag/MergeIteratorTagDemo.java | 81 + .../iteratortag/SubsetIteratorTagDemo.java | 88 + .../struts2/showcase/token/TokenAction.java | 84 + .../AbstractValidationActionSupport.java | 36 + .../FieldValidatorsExampleAction.java | 107 + .../NonFieldValidatorsExampleAction.java | 60 + .../showcase/validation/QuizAction.java | 64 + .../validation/SubmitApplication.java | 60 + .../struts2/showcase/validation/User.java | 53 + .../VisitorValidatorsExampleAction.java | 42 + .../showcase/wait/LongProcessAction.java | 50 + .../struts2/showcase/xslt/JVMAction.java | 103 + .../showcase/src/main/resources/LICENSE.txt | 174 + .../showcase/src/main/resources/NOTICE.txt | 6 + .../main/resources/globalMessages.properties | 7 + .../resources/globalMessages_de.properties | 7 + .../src/main/resources/log4j.properties | 31 + .../myTheme/myAnotherTemplate.ftl | 6 + .../struts2/showcase/DateAction.properties | 1 + ...-lotsOfRichtexteditorSubmit-validation.xml | 30 + .../UITagExample-conversion.properties | 1 + .../EmployeeAction-conversion.properties | 1 + .../action/EmployeeAction-validation.xml | 21 + .../showcase/action/EmployeeAction.properties | 9 + .../action/EmployeeAction_de.properties | 9 + .../action/SkillAction-validation.xml | 11 + .../showcase/action/SkillAction.properties | 6 + .../showcase/action/SkillAction_de.properties | 6 + .../ajax/Example5Action-validation.xml | 19 + .../ChatLoginAction-chatLogin-validation.xml | 14 + .../chat/ChatMessage-conversion.properties | 1 + .../CrudRoomAction-createRoom-validation.xml | 20 + .../showcase/chat/Room-conversion.properties | 1 + ...oomAction-sendMessageToRoom-validation.xml | 15 + .../AddressAction-conversion.properties | 6 + ...OperationsEnumAction-conversion.properties | 4 + .../PersonAction-conversion.properties | 1 + .../FileUploadAction-validation.xml | 19 + ...ploadUsingListAction-conversion.properties | 1 + .../EditPersonAction-conversion.properties | 3 + .../person/NewPersonAction-validation.xml | 8 + .../showcase/person/Person-validation.xml | 13 + .../IteratorGeneratorTagDemo-validation.xml | 22 + ...idatorsExampleAction-conversion.properties | 1 + ...ClientSideValidationExample-validation.xml | 74 + ...bmitFieldValidatorsExamples-validation.xml | 68 + .../FieldValidatorsExampleAction.properties | 1 + ...tNonFieldValidatorsExamples-validation.xml | 18 + .../validation/QuizAction-validation.xml | 23 + ...plication-submitApplication-validation.xml | 24 + .../User-userContext-validation.xml | 27 + ...itVisitorValidatorsExamples-validation.xml | 20 + .../main/resources/struts-actionchaining.xml | 21 + .../src/main/resources/struts-ajax.xml | 78 + .../src/main/resources/struts-chat.xml | 135 + .../src/main/resources/struts-conversion.xml | 75 + .../main/resources/struts-filedownload.xml | 33 + .../src/main/resources/struts-fileupload.xml | 40 + .../src/main/resources/struts-freemarker.xml | 18 + .../src/main/resources/struts-hangman.xml | 48 + .../src/main/resources/struts-integration.xml | 49 + .../src/main/resources/struts-jsf.xml | 38 + .../main/resources/struts-model-driven.xml | 20 + .../src/main/resources/struts-person.xml | 12 + .../src/main/resources/struts-tags-non-ui.xml | 126 + .../src/main/resources/struts-tags-ui.xml | 70 + .../src/main/resources/struts-tags.xml | 7 + .../src/main/resources/struts-tiles.xml | 31 + .../src/main/resources/struts-token.xml | 63 + .../src/main/resources/struts-validation.xml | 124 + .../src/main/resources/struts-wait.xml | 35 + .../src/main/resources/struts-xslt.xml | 40 + .../showcase/src/main/resources/struts.xml | 130 + .../webapp/WEB-INF/applicationContext.xml | 117 + .../src/main/webapp/WEB-INF/decorators.xml | 27 + .../main/webapp/WEB-INF/decorators/main.jsp | 120 + .../showcase/src/main/webapp/WEB-INF/dwr.xml | 25 + .../webapp/WEB-INF/sitemesh-decorator.tld | 79 + .../src/main/webapp/WEB-INF/sitemesh-page.tld | 95 + .../src/main/webapp/WEB-INF/sitemesh.xml | 54 + .../src/main/webapp/WEB-INF/tiles.xml | 48 + .../src/main/webapp/WEB-INF/validation.xml | 37 + .../showcase/src/main/webapp/WEB-INF/web.xml | 165 + .../actionchaining/actionChainingResult.jsp | 14 + .../src/main/webapp/ajax/AjaxResult.jsp | 12 + .../src/main/webapp/ajax/AjaxResult2.js | 2 + .../src/main/webapp/ajax/AjaxResult3.jsp | 12 + .../showcase/src/main/webapp/ajax/JSONList.js | 63 + .../main/webapp/ajax/autocompleter/index.jsp | 83 + .../src/main/webapp/ajax/commonInclude.jsp | 4 + .../showcase/src/main/webapp/ajax/footer.jsp | 8 + .../showcase/src/main/webapp/ajax/index.jsp | 23 + .../showcase/src/main/webapp/ajax/options.ftl | 5 + .../main/webapp/ajax/remotebutton/index.jsp | 65 + .../main/webapp/ajax/remotediv/example1.jsp | 24 + .../main/webapp/ajax/remotediv/example10.jsp | 31 + .../main/webapp/ajax/remotediv/example2.jsp | 28 + .../main/webapp/ajax/remotediv/example3.jsp | 27 + .../main/webapp/ajax/remotediv/example4.jsp | 27 + .../main/webapp/ajax/remotediv/example5.jsp | 27 + .../main/webapp/ajax/remotediv/example6.jsp | 24 + .../main/webapp/ajax/remotediv/example7.jsp | 27 + .../main/webapp/ajax/remotediv/example8.jsp | 56 + .../main/webapp/ajax/remotediv/example9.jsp | 56 + .../src/main/webapp/ajax/remotediv/index.jsp | 55 + .../main/webapp/ajax/remoteforms/index.jsp | 109 + .../main/webapp/ajax/remoteforms/test1.jsp | 18 + .../main/webapp/ajax/remoteforms/test2.jsp | 6 + .../main/webapp/ajax/remoteforms/test3.jsp | 8 + .../src/main/webapp/ajax/remotelink/index.jsp | 102 + .../main/webapp/ajax/tabbedpanel/example1.jsp | 115 + .../main/webapp/ajax/tabbedpanel/example2.jsp | 31 + .../main/webapp/ajax/tabbedpanel/example3.jsp | 59 + .../main/webapp/ajax/tabbedpanel/example4.jsp | 20 + .../main/webapp/ajax/tabbedpanel/example5.jsp | 31 + .../webapp/ajax/tabbedpanel/example5Ok.jsp | 9 + .../main/webapp/ajax/tabbedpanel/index.jsp | 27 + .../ajax/tabbedpanel/nodecorate/panel1.ftl | 3 + .../ajax/tabbedpanel/nodecorate/panel2.ftl | 7 + .../tabbedpanel/nodecorate/panel2Submit.ftl | 2 + .../ajax/tabbedpanel/nodecorate/panel3.ftl | 9 + .../tabbedpanel/nodecorate/panel3Submit.ftl | 2 + .../showcase/src/main/webapp/ajax/testjs.jsp | 14 + .../src/main/webapp/ajax/tree/getCategory.jsp | 24 + .../webapp/ajax/tree/partialChunkHeader.jsp | 6 + .../src/main/webapp/ajax/tree/toggle.jsp | 12 + .../src/main/webapp/ajax/tree/tree.jsp | 13 + .../src/main/webapp/ajax/widgets/index.jsp | 39 + .../src/main/webapp/chat/chatLogin.ftl | 16 + .../src/main/webapp/chat/createRoom.ftl | 2 + .../showcase/src/main/webapp/chat/index.jsp | 3 + .../webapp/chat/messagesAvailableInRoom.ftl | 33 + .../src/main/webapp/chat/roomSelection.ftl | 165 + .../src/main/webapp/chat/roomsAvailable.ftl | 44 + .../webapp/chat/sendMessageToRoomResult.ftl | 2 + .../src/main/webapp/chat/showRoom.ftl | 161 + .../src/main/webapp/chat/usersAvailable.ftl | 6 + .../main/webapp/chat/usersAvailableInRoom.ftl | 8 + .../main/webapp/conversion/Address.java.txt | 35 + .../webapp/conversion/AddressAction.java.txt | 44 + .../conversion/EnumTypeConverter.java.txt | 55 + .../webapp/conversion/OperationsEnum.java.txt | 30 + .../conversion/OperationsEnumAction.java.txt | 53 + .../OperationsEnumActionConversion.txt | 4 + .../main/webapp/conversion/Person.java.txt | 34 + .../webapp/conversion/PersonAction.java.txt | 43 + .../webapp/conversion/enterAddressInfo.jsp | 48 + .../webapp/conversion/enterOperations.jsp | 31 + .../webapp/conversion/enterPersonInfo.jsp | 58 + .../src/main/webapp/conversion/index.jsp | 26 + .../webapp/conversion/showAddressInfo.jsp | 15 + .../main/webapp/conversion/showOperations.jsp | 17 + .../main/webapp/conversion/showPersonInfo.jsp | 17 + .../customTheme/ftlCustomTemplate.ftl | 7 + .../customTheme/jspCustomTemplate.jsp | 8 + .../apps/showcase/src/main/webapp/date.jsp | 2 + .../main/webapp/empmanager/editEmployee.jsp | 41 + .../src/main/webapp/empmanager/editSkill.jsp | 27 + .../src/main/webapp/empmanager/index.jsp | 21 + .../main/webapp/empmanager/listEmployees.jsp | 26 + .../src/main/webapp/empmanager/listSkills.jsp | 24 + .../src/main/webapp/filedownload/index.jsp | 23 + .../src/main/webapp/fileupload/index.jsp | 25 + .../multipleUploadUsingArray-success.jsp | 37 + .../fileupload/multipleUploadUsingArray.jsp | 20 + .../multipleUploadUsingList-success.jsp | 37 + .../fileupload/multipleUploadUsingList.jsp | 20 + .../main/webapp/fileupload/upload-success.jsp | 25 + .../src/main/webapp/fileupload/upload.jsp | 23 + .../customFreemarkerManagerUsage.ftl | 26 + .../src/main/webapp/freemarker/index.jsp | 23 + .../main/webapp/freemarker/standardTags.ftl | 4 + .../src/main/webapp/hangman/blank.ftl | 0 .../src/main/webapp/hangman/hangmanAjax.ftl | 241 + .../src/main/webapp/hangman/hangmanMenu.ftl | 18 + .../main/webapp/hangman/hangmanNonAjax.ftl | 135 + .../webapp/hangman/images/Chalkboard_0.png | Bin 0 -> 1307 bytes .../webapp/hangman/images/Chalkboard_1.png | Bin 0 -> 1226 bytes .../webapp/hangman/images/Chalkboard_2.png | Bin 0 -> 1221 bytes .../webapp/hangman/images/Chalkboard_3.png | Bin 0 -> 1227 bytes .../webapp/hangman/images/Chalkboard_4.png | Bin 0 -> 1240 bytes .../webapp/hangman/images/Chalkboard_5.png | Bin 0 -> 1260 bytes .../webapp/hangman/images/Chalkboard_A.png | Bin 0 -> 1391 bytes .../webapp/hangman/images/Chalkboard_B.png | Bin 0 -> 1460 bytes .../webapp/hangman/images/Chalkboard_C.png | Bin 0 -> 1271 bytes .../webapp/hangman/images/Chalkboard_D.png | Bin 0 -> 1420 bytes .../webapp/hangman/images/Chalkboard_E.png | Bin 0 -> 1363 bytes .../webapp/hangman/images/Chalkboard_F.png | Bin 0 -> 1270 bytes .../webapp/hangman/images/Chalkboard_G.png | Bin 0 -> 1368 bytes .../webapp/hangman/images/Chalkboard_H.png | Bin 0 -> 1310 bytes .../webapp/hangman/images/Chalkboard_I.png | Bin 0 -> 1296 bytes .../webapp/hangman/images/Chalkboard_J.png | Bin 0 -> 1225 bytes .../webapp/hangman/images/Chalkboard_K.png | Bin 0 -> 1431 bytes .../webapp/hangman/images/Chalkboard_L.png | Bin 0 -> 1252 bytes .../webapp/hangman/images/Chalkboard_M.png | Bin 0 -> 1353 bytes .../webapp/hangman/images/Chalkboard_N.png | Bin 0 -> 1419 bytes .../webapp/hangman/images/Chalkboard_O.png | Bin 0 -> 1412 bytes .../webapp/hangman/images/Chalkboard_P.png | Bin 0 -> 1371 bytes .../webapp/hangman/images/Chalkboard_Q.png | Bin 0 -> 1474 bytes .../webapp/hangman/images/Chalkboard_R.png | Bin 0 -> 1446 bytes .../webapp/hangman/images/Chalkboard_S.png | Bin 0 -> 1393 bytes .../webapp/hangman/images/Chalkboard_T.png | Bin 0 -> 1284 bytes .../webapp/hangman/images/Chalkboard_U.png | Bin 0 -> 1377 bytes .../webapp/hangman/images/Chalkboard_V.png | Bin 0 -> 1322 bytes .../webapp/hangman/images/Chalkboard_W.png | Bin 0 -> 1440 bytes .../webapp/hangman/images/Chalkboard_X.png | Bin 0 -> 1397 bytes .../webapp/hangman/images/Chalkboard_Y.png | Bin 0 -> 1318 bytes .../webapp/hangman/images/Chalkboard_Z.png | Bin 0 -> 1353 bytes .../hangman/images/Chalkboard_underscroll.png | Bin 0 -> 1110 bytes .../src/main/webapp/hangman/images/choose.png | Bin 0 -> 3321 bytes .../src/main/webapp/hangman/images/guess.png | Bin 0 -> 2900 bytes .../webapp/hangman/images/guesses-left.png | Bin 0 -> 2372 bytes .../main/webapp/hangman/images/hangman.png | Bin 0 -> 3850 bytes .../webapp/hangman/images/letter-spacer.png | Bin 0 -> 926 bytes .../main/webapp/hangman/images/play-again.png | Bin 0 -> 8607 bytes .../webapp/hangman/images/scaffold_-1.png | Bin 0 -> 9806 bytes .../main/webapp/hangman/images/scaffold_0.png | Bin 0 -> 9017 bytes .../main/webapp/hangman/images/scaffold_1.png | Bin 0 -> 7999 bytes .../main/webapp/hangman/images/scaffold_2.png | Bin 0 -> 7260 bytes .../main/webapp/hangman/images/scaffold_3.png | Bin 0 -> 6715 bytes .../main/webapp/hangman/images/scaffold_4.png | Bin 0 -> 6268 bytes .../main/webapp/hangman/images/scaffold_5.png | Bin 0 -> 4267 bytes .../src/main/webapp/hangman/images/start.png | Bin 0 -> 5145 bytes .../main/webapp/hangman/images/you-lose.png | Bin 0 -> 7500 bytes .../main/webapp/hangman/images/you-win.png | Bin 0 -> 6544 bytes .../showcase/src/main/webapp/hangman/test.ftl | 21 + .../hangman/updateCharacterAvailable.ftl | 47 + .../main/webapp/hangman/updateGuessLeft.ftl | 7 + .../main/webapp/hangman/updateScaffold.ftl | 3 + .../webapp/hangman/updateVocabCharacters.ftl | 20 + .../apps/showcase/src/main/webapp/help.jsp | 31 + .../src/main/webapp/images/indicator.gif | Bin 0 -> 1553 bytes .../src/main/webapp/images/struts-gif.zip | Bin 0 -> 4765 bytes .../src/main/webapp/images/struts-power.gif | Bin 0 -> 1798 bytes .../src/main/webapp/images/struts.gif | Bin 0 -> 4720 bytes .../apps/showcase/src/main/webapp/index.jsp | 1 + .../main/webapp/integration/modelDriven.jsp | 31 + .../webapp/integration/modelDrivenResult.jsp | 24 + .../src/main/webapp/jsf/employee/edit.jsp | 106 + .../src/main/webapp/jsf/employee/list.jsp | 69 + .../showcase/src/main/webapp/jsf/index.jsp | 24 + .../main/webapp/modelDriven/modelDriven.jsp | 31 + .../webapp/modelDriven/modelDrivenResult.jsp | 24 + .../src/main/webapp/person/editPerson.jsp | 41 + .../showcase/src/main/webapp/person/index.jsp | 12 + .../src/main/webapp/person/listPeople.ftl | 28 + .../src/main/webapp/person/newPerson.ftl | 19 + .../showcase/src/main/webapp/showcase.jsp | 58 + .../showcase/src/main/webapp/styles/forms.css | 102 + .../main/webapp/styles/layout-navtop-1col.css | 33 + .../webapp/styles/layout-navtop-localleft.css | 36 + .../src/main/webapp/styles/layout.css | 136 + .../showcase/src/main/webapp/styles/main.css | 5 + .../src/main/webapp/styles/nav-horizontal.css | 80 + .../showcase/src/main/webapp/styles/tools.css | 68 + .../showcase/src/main/webapp/styles/typo.css | 195 + .../showcase/src/main/webapp/tags/index.jsp | 16 + .../tags/non-ui/actionPrefix/actionPrefix.ftl | 19 + .../actionPrefix/actionPrefixExample.ftl | 48 + .../webapp/tags/non-ui/actionPrefix/index.jsp | 13 + .../tags/non-ui/actionPrefix/methodPrefix.ftl | 19 + .../tags/non-ui/actionPrefix/normalSubmit.ftl | 17 + .../actionPrefix/redirectActionPrefix.ftl | 22 + .../tags/non-ui/actionTag/includedPage.jsp | 1 + .../tags/non-ui/actionTag/includedPage2.jsp | 2 + .../tags/non-ui/actionTag/includedPage3.jsp | 2 + .../non-ui/actionTag/showActionTagDemo.jsp | 43 + .../src/main/webapp/tags/non-ui/date.jsp | 104 + .../src/main/webapp/tags/non-ui/debug.jsp | 20 + .../main/webapp/tags/non-ui/ifTag/testIf.ftl | 611 + .../main/webapp/tags/non-ui/ifTag/testIf.jsp | 616 + .../src/main/webapp/tags/non-ui/index.jsp | 24 + .../appendIteratorTagDemoResult.jsp | 25 + .../iteratorGeneratorTagDemoResult.jsp | 19 + .../mergeIteratorTagDemoResult.jsp | 25 + .../iteratorTag/showAppendIteratorTagDemo.jsp | 19 + .../showIteratorGeneratorTagDemo.jsp | 21 + .../iteratorTag/showMergeIteratorTagDemo.jsp | 17 + .../iteratorTag/subsetIteratorTagDemo.jsp | 20 + .../subsetIteratorTagDemoResult.jsp | 21 + .../webapp/tags/ui/componentTagExample.jsp | 62 + .../main/webapp/tags/ui/datepicker/index.jsp | 23 + .../main/webapp/tags/ui/dynamicTreeSelect.jsp | 6 + .../src/main/webapp/tags/ui/example.jsp | 126 + .../src/main/webapp/tags/ui/example.vm | 32 + .../main/webapp/tags/ui/exampleSubmited.jsp | 43 + .../main/webapp/tags/ui/exampleSubmited.vm | 47 + .../webapp/tags/ui/images/backgroundImage.jpg | Bin 0 -> 13192 bytes .../main/webapp/tags/ui/images/leopard.jpg | Bin 0 -> 3850 bytes .../src/main/webapp/tags/ui/index.jsp | 23 + .../tags/ui/lotsOfOptiontransferselect.jsp | 93 + .../ui/lotsOfOptiontransferselectSubmit.jsp | 94 + .../src/main/webapp/tags/ui/moreSelects.jsp | 61 + .../main/webapp/tags/ui/moreSelectsSubmit.jsp | 53 + .../main/webapp/tags/ui/staticTreeSelect.jsp | 28 + .../main/webapp/tags/ui/timepicker/index.jsp | 20 + .../webapp/tags/ui/treeExampleDynamic.jsp | 47 + .../main/webapp/tags/ui/treeExampleStatic.jsp | 53 + .../main/webapp/template/xhtml/mytemplate.jsp | 9 + .../showcase/src/main/webapp/tiles/body.ftl | 10 + .../showcase/src/main/webapp/tiles/body.jsp | 18 + .../showcase/src/main/webapp/tiles/header.jsp | 1 + .../showcase/src/main/webapp/tiles/layout.ftl | 12 + .../showcase/src/main/webapp/tiles/layout.jsp | 17 + .../src/main/webapp/token/doublePost.jsp | 15 + .../src/main/webapp/token/example1.jsp | 24 + .../src/main/webapp/token/example2.jsp | 24 + .../src/main/webapp/token/example3.jsp | 24 + .../src/main/webapp/token/example4.ftl | 26 + .../showcase/src/main/webapp/token/index.jsp | 33 + .../src/main/webapp/token/transferDone.jsp | 25 + .../clientSideValidationExample.jsp | 55 + .../validation/fieldValidatorsExample.jsp | 55 + .../src/main/webapp/validation/footer.jsp | 9 + .../src/main/webapp/validation/index.jsp | 42 + .../validation/nonFieldValidatorsExample.jsp | 38 + .../src/main/webapp/validation/quiz-ajax.jsp | 23 + .../src/main/webapp/validation/quiz-basic.jsp | 27 + .../webapp/validation/quiz-client-css.jsp | 24 + .../main/webapp/validation/quiz-client.jsp | 24 + .../main/webapp/validation/quiz-success.jsp | 14 + .../storeErrorsAcrossRequestCancel.jsp | 21 + .../storeErrorsAcrossRequestExample.jsp | 44 + .../validation/storeErrorsAcrossRequestOk.jsp | 23 + .../successClientSideValidationExample.jsp | 53 + .../successFieldValidatorsExample.jsp | 48 + .../successNonFieldValidatorsExample.jsp | 33 + .../successVisitorValidatorsExample.jsp | 35 + .../validation/validationExamplesStyles.css | 11 + .../validation/visitorValidatorsExample.jsp | 36 + .../showcase/src/main/webapp/viewSource.jsp | 53 + .../src/main/webapp/wait/complete.jsp | 13 + .../src/main/webapp/wait/example1.jsp | 16 + .../src/main/webapp/wait/example2.jsp | 17 + .../src/main/webapp/wait/example3.jsp | 18 + .../showcase/src/main/webapp/wait/index.jsp | 19 + .../showcase/src/main/webapp/wait/wait.jsp | 16 + .../src/main/webapp/xslt/environment.xsl | 25 + .../showcase/src/main/webapp/xslt/index.jsp | 26 + STRUTS_2_0_X/assembly/pom.xml | 438 + .../assembly/src/main/assembly/all.xml | 212 + .../assembly/src/main/assembly/apps.xml | 43 + .../assembly/src/main/assembly/docs.xml | 116 + .../assembly/src/main/assembly/lib-jdk14.xml | 58 + .../assembly/src/main/assembly/lib.xml | 49 + .../assembly/src/main/assembly/src.xml | 120 + .../assembly/src/main/resources/LICENSE.txt | 174 + .../assembly/src/main/resources/NOTICE.txt | 3 + .../src/main/resources/backport/NOTICE.txt | 7 + .../backport/RETROTRANSLATOR-LICENSE.txt | 29 + .../assembly/src/main/resources/build.xml | 53 + STRUTS_2_0_X/backport/ASM-LICENSE.txt | 28 + STRUTS_2_0_X/backport/LICENSE.txt | 29 + .../backport/RETROTRANSLATOR-LICENSE.txt | 29 + STRUTS_2_0_X/backport/S2-FOR-J4-README.txt | 22 + STRUTS_2_0_X/backport/STRUTS-LICENSE.txt | 174 + STRUTS_2_0_X/backport/XWORK-LICENSE.txt | 50 + .../backport/backport-util-concurrent-3.0.jar | Bin 0 -> 327810 bytes STRUTS_2_0_X/backport/readme.html | 656 + .../retrotranslator-runtime-1.2.2.jar | Bin 0 -> 260721 bytes .../retrotranslator-transformer-1.2.2.jar | Bin 0 -> 116677 bytes STRUTS_2_0_X/backport/translate.bat | 2 + STRUTS_2_0_X/backport/translate.sh | 3 + STRUTS_2_0_X/core/pom.xml | 449 + .../core/src/main/etc/taglib-settings.xml | 5 + .../java/org/apache/struts2/RequestUtils.java | 56 + .../apache/struts2/ServletActionContext.java | 149 + .../org/apache/struts2/StrutsConstants.java | 160 + .../org/apache/struts2/StrutsException.java | 104 + .../org/apache/struts2/StrutsStatics.java | 68 + .../org/apache/struts2/StrutsTestCase.java | 57 + .../apache/struts2/TestNGStrutsTestCase.java | 58 + .../components/AbstractRemoteCallUIBean.java | 175 + .../struts2/components/ActionComponent.java | 295 + .../struts2/components/ActionError.java | 66 + .../struts2/components/ActionMessage.java | 62 + .../org/apache/struts2/components/Anchor.java | 171 + .../struts2/components/AppendIterator.java | 171 + .../struts2/components/Autocompleter.java | 305 + .../org/apache/struts2/components/Bean.java | 155 + .../apache/struts2/components/Checkbox.java | 84 + .../struts2/components/CheckboxList.java | 57 + .../struts2/components/ClosingUIBean.java | 66 + .../apache/struts2/components/ComboBox.java | 201 + .../apache/struts2/components/Component.java | 492 + .../org/apache/struts2/components/Date.java | 374 + .../struts2/components/DateTimePicker.java | 328 + .../org/apache/struts2/components/Debug.java | 96 + .../org/apache/struts2/components/Div.java | 193 + .../struts2/components/DoubleListUIBean.java | 568 + .../struts2/components/DoubleSelect.java | 65 + .../org/apache/struts2/components/Else.java | 74 + .../org/apache/struts2/components/ElseIf.java | 107 + .../apache/struts2/components/FieldError.java | 111 + .../org/apache/struts2/components/File.java | 101 + .../org/apache/struts2/components/Form.java | 494 + .../apache/struts2/components/FormButton.java | 164 + .../struts2/components/GenericUIBean.java | 128 + .../org/apache/struts2/components/Head.java | 140 + .../org/apache/struts2/components/Hidden.java | 63 + .../org/apache/struts2/components/I18n.java | 134 + .../org/apache/struts2/components/If.java | 98 + .../apache/struts2/components/Include.java | 411 + .../components/InputTransferSelect.java | 339 + .../struts2/components/IteratorComponent.java | 289 + .../org/apache/struts2/components/Label.java | 95 + .../apache/struts2/components/ListUIBean.java | 152 + .../struts2/components/MergeIterator.java | 184 + .../apache/struts2/components/OptGroup.java | 145 + .../components/OptionTransferSelect.java | 577 + .../org/apache/struts2/components/Param.java | 157 + .../apache/struts2/components/Password.java | 76 + .../apache/struts2/components/Property.java | 158 + .../org/apache/struts2/components/Push.java | 150 + .../org/apache/struts2/components/Radio.java | 63 + .../struts2/components/RemoteUICallBean.java | 54 + .../org/apache/struts2/components/Reset.java | 105 + .../org/apache/struts2/components/Select.java | 145 + .../org/apache/struts2/components/Set.java | 148 + .../org/apache/struts2/components/Submit.java | 338 + .../struts2/components/TabbedPanel.java | 151 + .../org/apache/struts2/components/Text.java | 190 + .../apache/struts2/components/TextArea.java | 103 + .../apache/struts2/components/TextField.java | 109 + .../org/apache/struts2/components/Token.java | 119 + .../org/apache/struts2/components/Tree.java | 433 + .../apache/struts2/components/TreeNode.java | 103 + .../org/apache/struts2/components/UIBean.java | 1063 + .../org/apache/struts2/components/URL.java | 425 + .../struts2/components/UpDownSelect.java | 225 + .../components/table/AbstractFilterModel.java | 104 + .../components/table/RenderFilterModel.java | 47 + .../components/table/SortFilterModel.java | 199 + .../components/table/SortableTableModel.java | 40 + .../struts2/components/table/WebTable.java | 354 + .../components/table/WebTableColumn.java | 84 + .../table/renderer/AbstractCellRenderer.java | 74 + .../table/renderer/BooleanCellRenderer.java | 65 + .../table/renderer/CellRenderer.java | 30 + .../table/renderer/DateCellRenderer.java | 64 + .../table/renderer/DefaultCellRenderer.java | 42 + .../table/renderer/FixedTextCellRenderer.java | 49 + .../table/renderer/LinkCellRenderer.java | 243 + .../table/renderer/NumericCellRenderer.java | 103 + .../components/table/renderer/package.html | 23 + .../template/BaseTemplateEngine.java | 110 + .../template/FreemarkerTemplateEngine.java | 213 + .../template/JspTemplateEngine.java | 82 + .../struts2/components/template/Template.java | 91 + .../components/template/TemplateEngine.java | 46 + .../template/TemplateEngineManager.java | 126 + .../template/TemplateRenderingContext.java | 76 + .../template/VelocityTemplateEngine.java | 108 + .../struts2/config/BeanSelectionProvider.java | 251 + .../ClasspathConfigurationProvider.java | 531 + .../config/DefaultPropertiesProvider.java | 52 + .../struts2/config/DefaultSettings.java | 118 + .../struts2/config/DelegatingSettings.java | 131 + ...LegacyPropertiesConfigurationProvider.java | 91 + .../config/MethodConfigurationProvider.java | 259 + .../org/apache/struts2/config/Namespace.java | 32 + .../org/apache/struts2/config/NullResult.java | 36 + .../apache/struts2/config/ParentPackage.java | 32 + .../struts2/config/PropertiesSettings.java | 148 + .../org/apache/struts2/config/Result.java | 37 + .../org/apache/struts2/config/Results.java | 32 + .../config/ServletContextSingleton.java | 91 + .../org/apache/struts2/config/Settings.java | 318 + .../StrutsXmlConfigurationProvider.java | 174 + .../org/apache/struts2/config/package.html | 23 + .../dispatcher/ActionContextCleanUp.java | 137 + .../struts2/dispatcher/ApplicationMap.java | 194 + .../dispatcher/DefaultActionSupport.java | 72 + .../apache/struts2/dispatcher/Dispatcher.java | 859 + .../dispatcher/DispatcherListener.java | 42 + .../struts2/dispatcher/FilterDispatcher.java | 640 + .../FilterDispatcherCompatWeblogic61.java | 105 + .../struts2/dispatcher/HttpHeaderResult.java | 160 + .../struts2/dispatcher/PlainTextResult.java | 170 + .../apache/struts2/dispatcher/RequestMap.java | 149 + .../ServletActionRedirectResult.java | 230 + .../dispatcher/ServletDispatcherResult.java | 145 + .../dispatcher/ServletRedirectResult.java | 162 + .../apache/struts2/dispatcher/SessionMap.java | 207 + .../struts2/dispatcher/StreamResult.java | 244 + .../dispatcher/StrutsRequestWrapper.java | 88 + .../dispatcher/StrutsResultSupport.java | 223 + .../struts2/dispatcher/VelocityResult.java | 237 + .../dispatcher/mapper/ActionMapper.java | 64 + .../dispatcher/mapper/ActionMapping.java | 144 + .../mapper/CompositeActionMapper.java | 160 + .../mapper/DefaultActionMapper.java | 501 + .../mapper/Restful2ActionMapper.java | 250 + .../mapper/RestfulActionMapper.java | 130 + .../multipart/JakartaMultiPartRequest.java | 306 + .../multipart/MultiPartRequest.java | 120 + .../multipart/MultiPartRequestWrapper.java | 246 + .../struts2/dispatcher/multipart/package.html | 23 + .../apache/struts2/dispatcher/package.html | 23 + .../struts2/impl/StrutsActionProxy.java | 56 + .../impl/StrutsActionProxyFactory.java | 44 + .../struts2/impl/StrutsObjectFactory.java | 106 + .../struts2/interceptor/ApplicationAware.java | 42 + .../interceptor/BackgroundProcess.java | 136 + .../interceptor/CheckboxInterceptor.java | 94 + .../interceptor/CookieInterceptor.java | 277 + .../struts2/interceptor/CookiesAware.java | 27 + .../interceptor/CreateSessionInterceptor.java | 95 + .../ExecuteAndWaitInterceptor.java | 348 + .../interceptor/FileUploadInterceptor.java | 371 + .../interceptor/MessageStoreInterceptor.java | 333 + .../struts2/interceptor/NoParameters.java | 32 + .../struts2/interceptor/ParameterAware.java | 45 + .../struts2/interceptor/PrincipalAware.java | 33 + .../struts2/interceptor/PrincipalProxy.java | 70 + .../ProfilingActivationInterceptor.java | 111 + .../struts2/interceptor/RequestAware.java | 42 + .../struts2/interceptor/RolesInterceptor.java | 154 + .../struts2/interceptor/ScopeInterceptor.java | 450 + .../interceptor/ServletConfigInterceptor.java | 172 + .../interceptor/ServletRequestAware.java | 43 + .../interceptor/ServletResponseAware.java | 43 + .../struts2/interceptor/SessionAware.java | 43 + .../StrutsConversionErrorInterceptor.java | 125 + .../struts2/interceptor/TokenInterceptor.java | 174 + .../TokenSessionStoreInterceptor.java | 163 + .../debugging/DebuggingInterceptor.java | 390 + .../debugging/PrettyPrintWriter.java | 184 + .../AnnotationValidationInterceptor.java | 68 + .../validation/SkipValidation.java | 38 + .../portlet/PortletActionConstants.java | 126 + .../portlet/PortletApplicationMap.java | 206 + .../struts2/portlet/PortletRequestMap.java | 167 + .../struts2/portlet/PortletSessionMap.java | 171 + .../portlet/context/PortletActionContext.java | 200 + .../DirectRenderFromEventAction.java | 72 + .../portlet/dispatcher/Jsr168Dispatcher.java | 595 + .../interceptor/PortletAwareInterceptor.java | 84 + .../interceptor/PortletContextAware.java | 29 + .../interceptor/PortletPreferencesAware.java | 39 + .../PortletPreferencesInterceptor.java | 104 + .../interceptor/PortletPrincipalProxy.java | 93 + .../interceptor/PortletRequestAware.java | 29 + .../interceptor/PortletResponseAware.java | 29 + .../interceptor/PortletStateInterceptor.java | 95 + .../ServletPortletPreferences.java | 95 + .../result/PortletActionRedirectResult.java | 238 + .../struts2/portlet/result/PortletResult.java | 224 + .../portlet/result/PortletVelocityResult.java | 289 + .../portlet/servlet/PortletHttpSession.java | 214 + .../portlet/servlet/PortletServletConfig.java | 81 + .../servlet/PortletServletContext.java | 235 + .../servlet/PortletServletInputStream.java | 121 + .../servlet/PortletServletOutputStream.java | 88 + .../servlet/PortletServletRequest.java | 558 + .../PortletServletRequestDispatcher.java | 70 + .../servlet/PortletServletResponse.java | 233 + .../struts2/portlet/servlet/package.html | 27 + .../portlet/util/PortletUrlHelper.java | 306 + .../interceptor/ServletPrincipalProxy.java | 90 + .../struts2/util/AppendIteratorFilter.java | 84 + .../org/apache/struts2/util/AttributeMap.java | 137 + .../apache/struts2/util/ClassLoaderUtils.java | 134 + .../org/apache/struts2/util/ContainUtil.java | 108 + .../java/org/apache/struts2/util/Counter.java | 123 + .../apache/struts2/util/DateFormatter.java | 93 + .../util/FastByteArrayOutputStream.java | 220 + .../struts2/util/InvocationSessionStore.java | 121 + .../struts2/util/IteratorFilterSupport.java | 59 + .../struts2/util/IteratorGenerator.java | 141 + .../org/apache/struts2/util/ListEntry.java | 52 + .../org/apache/struts2/util/MakeIterator.java | 109 + .../struts2/util/MergeIteratorFilter.java | 90 + .../util/ObjectFactoryDestroyable.java | 33 + .../org/apache/struts2/util/PrefixTrie.java | 66 + .../struts2/util/ServletContextAware.java | 32 + .../struts2/util/SortIteratorFilter.java | 108 + .../java/org/apache/struts2/util/Sorter.java | 152 + .../struts2/util/StrutsTestCaseHelper.java | 57 + .../struts2/util/StrutsTypeConverter.java | 92 + .../org/apache/struts2/util/StrutsUtil.java | 293 + .../struts2/util/SubsetIteratorFilter.java | 176 + .../org/apache/struts2/util/TabbedPane.java | 68 + .../java/org/apache/struts2/util/Timer.java | 51 + .../org/apache/struts2/util/TokenHelper.java | 186 + .../java/org/apache/struts2/util/URLBean.java | 100 + .../struts2/util/VelocityStrutsUtil.java | 61 + .../struts2/validators/DWRValidator.java | 142 + .../struts2/views/DefaultTagLibrary.java | 134 + .../struts2/views/JspSupportServlet.java | 40 + .../org/apache/struts2/views/TagLibrary.java | 53 + .../struts2/views/annotations/StrutsTag.java | 42 + .../views/annotations/StrutsTagAttribute.java | 46 + .../views/freemarker/FreemarkerManager.java | 353 + .../views/freemarker/FreemarkerResult.java | 299 + .../freemarker/PortletFreemarkerResult.java | 272 + .../views/freemarker/ScopesHashModel.java | 121 + .../views/freemarker/StrutsBeanWrapper.java | 103 + .../freemarker/StrutsClassTemplateLoader.java | 35 + .../freemarker/tags/ActionErrorModel.java | 42 + .../freemarker/tags/ActionMessageModel.java | 42 + .../views/freemarker/tags/ActionModel.java | 46 + .../views/freemarker/tags/AnchorModel.java | 42 + .../freemarker/tags/AutocompleterModel.java | 43 + .../views/freemarker/tags/BeanModel.java | 42 + .../views/freemarker/tags/CallbackWriter.java | 99 + .../freemarker/tags/CheckboxListModel.java | 42 + .../views/freemarker/tags/CheckboxModel.java | 42 + .../views/freemarker/tags/ComboBoxModel.java | 42 + .../views/freemarker/tags/ComponentModel.java | 42 + .../views/freemarker/tags/DateModel.java | 44 + .../freemarker/tags/DateTimePickerModel.java | 40 + .../views/freemarker/tags/DivModel.java | 42 + .../freemarker/tags/DoubleSelectModel.java | 42 + .../views/freemarker/tags/ElseIfModel.java | 44 + .../views/freemarker/tags/ElseModel.java | 45 + .../freemarker/tags/FieldErrorModel.java | 42 + .../views/freemarker/tags/FileModel.java | 42 + .../views/freemarker/tags/FormModel.java | 42 + .../views/freemarker/tags/HeadModel.java | 42 + .../views/freemarker/tags/HiddenModel.java | 42 + .../views/freemarker/tags/I18nModel.java | 42 + .../views/freemarker/tags/IfModel.java | 44 + .../views/freemarker/tags/IncludeModel.java | 42 + .../tags/InputTransferSelectModel.java | 44 + .../views/freemarker/tags/IteratorModel.java | 42 + .../views/freemarker/tags/LabelModel.java | 42 + .../views/freemarker/tags/OptGroupModel.java | 43 + .../tags/OptionTransferSelectModel.java | 44 + .../views/freemarker/tags/ParamModel.java | 42 + .../views/freemarker/tags/PasswordModel.java | 42 + .../views/freemarker/tags/PropertyModel.java | 42 + .../views/freemarker/tags/PushModel.java | 42 + .../views/freemarker/tags/RadioModel.java | 42 + .../views/freemarker/tags/ResetModel.java | 42 + .../views/freemarker/tags/SelectModel.java | 42 + .../views/freemarker/tags/SetModel.java | 42 + .../views/freemarker/tags/StrutsModels.java | 477 + .../views/freemarker/tags/SubmitModel.java | 42 + .../freemarker/tags/TabbedPanelModel.java | 42 + .../views/freemarker/tags/TagModel.java | 141 + .../views/freemarker/tags/TextAreaModel.java | 42 + .../views/freemarker/tags/TextFieldModel.java | 42 + .../views/freemarker/tags/TextModel.java | 42 + .../views/freemarker/tags/TokenModel.java | 42 + .../views/freemarker/tags/TreeModel.java | 44 + .../views/freemarker/tags/TreeNodeModel.java | 43 + .../views/freemarker/tags/URLModel.java | 42 + .../freemarker/tags/UpDownSelectModel.java | 45 + .../views/freemarker/tags/WebTableModel.java | 42 + .../apache/struts2/views/jsp/ActionTag.java | 88 + .../org/apache/struts2/views/jsp/BeanTag.java | 58 + .../views/jsp/ComponentTagSupport.java | 70 + .../org/apache/struts2/views/jsp/DateTag.java | 66 + .../apache/struts2/views/jsp/ElseIfTag.java | 51 + .../org/apache/struts2/views/jsp/ElseTag.java | 42 + .../org/apache/struts2/views/jsp/I18nTag.java | 54 + .../org/apache/struts2/views/jsp/IfTag.java | 52 + .../apache/struts2/views/jsp/IncludeTag.java | 54 + .../struts2/views/jsp/IteratorStatus.java | 77 + .../apache/struts2/views/jsp/IteratorTag.java | 84 + .../apache/struts2/views/jsp/ParamTag.java | 60 + .../apache/struts2/views/jsp/PropertyTag.java | 67 + .../org/apache/struts2/views/jsp/PushTag.java | 54 + .../org/apache/struts2/views/jsp/SetTag.java | 67 + .../views/jsp/StrutsBodyTagSupport.java | 125 + .../apache/struts2/views/jsp/TagUtils.java | 111 + .../org/apache/struts2/views/jsp/TextTag.java | 54 + .../org/apache/struts2/views/jsp/URLTag.java | 142 + .../views/jsp/iterator/AppendIteratorTag.java | 47 + .../jsp/iterator/IteratorGeneratorTag.java | 255 + .../views/jsp/iterator/MergeIteratorTag.java | 48 + .../views/jsp/iterator/SortIteratorTag.java | 153 + .../views/jsp/iterator/SubsetIteratorTag.java | 289 + .../org/apache/struts2/views/jsp/package.html | 23 + .../views/jsp/ui/AbstractClosingTag.java | 39 + .../views/jsp/ui/AbstractDoubleListTag.java | 372 + .../struts2/views/jsp/ui/AbstractListTag.java | 52 + .../views/jsp/ui/AbstractRemoteCallUITag.java | 117 + .../views/jsp/ui/AbstractRequiredListTag.java | 37 + .../struts2/views/jsp/ui/AbstractUITag.java | 235 + .../struts2/views/jsp/ui/ActionErrorTag.java | 43 + .../views/jsp/ui/ActionMessageTag.java | 42 + .../struts2/views/jsp/ui/AnchorTag.java | 66 + .../views/jsp/ui/AutocompleterTag.java | 177 + .../struts2/views/jsp/ui/CheckboxListTag.java | 42 + .../struts2/views/jsp/ui/CheckboxTag.java | 54 + .../struts2/views/jsp/ui/ComboBoxTag.java | 83 + .../struts2/views/jsp/ui/ComponentTag.java | 41 + .../views/jsp/ui/DateTimePickerTag.java | 139 + .../apache/struts2/views/jsp/ui/DebugTag.java | 39 + .../apache/struts2/views/jsp/ui/DivTag.java | 87 + .../struts2/views/jsp/ui/DoubleSelectTag.java | 53 + .../struts2/views/jsp/ui/FieldErrorTag.java | 42 + .../apache/struts2/views/jsp/ui/FileTag.java | 61 + .../apache/struts2/views/jsp/ui/FormTag.java | 111 + .../apache/struts2/views/jsp/ui/HeadTag.java | 66 + .../struts2/views/jsp/ui/HiddenTag.java | 42 + .../views/jsp/ui/InputTransferSelectTag.java | 205 + .../apache/struts2/views/jsp/ui/LabelTag.java | 54 + .../apache/struts2/views/jsp/ui/OgnlTool.java | 48 + .../struts2/views/jsp/ui/OptGroupTag.java | 79 + .../views/jsp/ui/OptionTransferSelectTag.java | 346 + .../struts2/views/jsp/ui/PasswordTag.java | 58 + .../apache/struts2/views/jsp/ui/RadioTag.java | 42 + .../apache/struts2/views/jsp/ui/ResetTag.java | 73 + .../struts2/views/jsp/ui/SelectTag.java | 80 + .../struts2/views/jsp/ui/SubmitTag.java | 184 + .../struts2/views/jsp/ui/TabbedPanelTag.java | 78 + .../struts2/views/jsp/ui/TextFieldTag.java | 73 + .../struts2/views/jsp/ui/TextareaTag.java | 74 + .../apache/struts2/views/jsp/ui/TokenTag.java | 42 + .../struts2/views/jsp/ui/TreeNodeTag.java | 56 + .../apache/struts2/views/jsp/ui/TreeTag.java | 305 + .../struts2/views/jsp/ui/UpDownSelectTag.java | 123 + .../views/jsp/ui/table/WebTableTag.java | 74 + .../struts2/views/util/ContextUtil.java | 103 + .../struts2/views/util/ResourceUtil.java | 35 + .../apache/struts2/views/util/TextUtil.java | 242 + .../apache/struts2/views/util/UrlHelper.java | 348 + .../apache/struts2/views/util/package.html | 23 + .../views/velocity/StrutsResourceLoader.java | 51 + .../views/velocity/StrutsVelocityContext.java | 115 + .../views/velocity/VelocityManager.java | 611 + .../components/AbstractDirective.java | 132 + .../velocity/components/ActionDirective.java | 42 + .../components/ActionErrorDirective.java | 42 + .../components/ActionMessageDirective.java | 42 + .../velocity/components/AnchorDirective.java | 46 + .../components/AutocompleterDirective.java | 46 + .../velocity/components/BeanDirective.java | 42 + .../components/CheckBoxDirective.java | 42 + .../components/CheckBoxListDirective.java | 42 + .../components/ComboBoxDirective.java | 42 + .../components/ComponentDirective.java | 46 + .../velocity/components/DateDirective.java | 43 + .../components/DateTimePickerDirective.java | 40 + .../velocity/components/DivDirective.java | 46 + .../components/DoubleSelectDirective.java | 42 + .../components/FieldErrorDirective.java | 42 + .../velocity/components/FileDirective.java | 42 + .../velocity/components/FormDirective.java | 46 + .../velocity/components/HeadDirective.java | 42 + .../velocity/components/HiddenDirective.java | 42 + .../velocity/components/I18nDirective.java | 42 + .../velocity/components/IncludeDirective.java | 42 + .../InputTransferSelectDirective.java | 43 + .../velocity/components/LabelDirective.java | 42 + .../components/OptGroupDirective.java | 44 + .../OptionTransferSelectDirective.java | 44 + .../velocity/components/ParamDirective.java | 42 + .../components/PasswordDirective.java | 42 + .../components/PropertyDirective.java | 41 + .../velocity/components/PushDirective.java | 42 + .../velocity/components/RadioDirective.java | 42 + .../velocity/components/ResetDirective.java | 42 + .../velocity/components/SelectDirective.java | 42 + .../velocity/components/SetDirective.java | 42 + .../velocity/components/SubmitDirective.java | 42 + .../components/TabbedPanelDirective.java | 42 + .../components/TextAreaDirective.java | 42 + .../velocity/components/TextDirective.java | 42 + .../components/TextFieldDirective.java | 42 + .../velocity/components/TokenDirective.java | 42 + .../velocity/components/TreeDirective.java | 43 + .../components/TreeNodeDirective.java | 44 + .../velocity/components/URLDirective.java | 42 + .../components/UpDownSelectDirective.java | 44 + .../components/WebTableDirective.java | 42 + .../struts2/views/velocity/package.html | 23 + .../views/xslt/AbstractAdapterElement.java | 140 + .../views/xslt/AbstractAdapterNode.java | 385 + .../struts2/views/xslt/AdapterFactory.java | 239 + .../struts2/views/xslt/AdapterNode.java | 78 + .../struts2/views/xslt/ArrayAdapter.java | 60 + .../struts2/views/xslt/BeanAdapter.java | 175 + .../struts2/views/xslt/CollectionAdapter.java | 60 + .../apache/struts2/views/xslt/MapAdapter.java | 86 + .../struts2/views/xslt/ProxyAttrAdapter.java | 85 + .../views/xslt/ProxyElementAdapter.java | 168 + .../struts2/views/xslt/ProxyNamedNodeMap.java | 81 + .../struts2/views/xslt/ProxyNodeAdapter.java | 134 + .../views/xslt/ProxyTextNodeAdapter.java | 97 + .../views/xslt/ServletURIResolver.java | 73 + .../views/xslt/SimpleAdapterDocument.java | 257 + .../struts2/views/xslt/SimpleNodeList.java | 58 + .../struts2/views/xslt/SimpleTextNode.java | 105 + .../struts2/views/xslt/StringAdapter.java | 115 + .../apache/struts2/views/xslt/XSLTResult.java | 418 + .../apache/struts2/views/xslt/package.html | 46 + .../core/src/main/resources/LICENSE.txt | 174 + .../src/main/resources/META-INF/README.txt | 3 + .../core/src/main/resources/NOTICE.txt | 6 + .../org/apache/struts2/default.properties | 186 + .../org/apache/struts2/dispatcher/error.ftl | 153 + .../struts2/interceptor/debugging/console.ftl | 36 + .../interceptor/debugging/webconsole.css | 40 + .../interceptor/debugging/webconsole.html | 43 + .../interceptor/debugging/webconsole.js | 79 + .../apache/struts2/interceptor/package.html | 23 + .../org/apache/struts2/interceptor/wait.ftl | 33 + .../resources/org/apache/struts2/package.html | 23 + .../apache/struts2/static/CommonFunctions.js | 72 + .../org/apache/struts2/static/dojo/LICENSE | 195 + .../org/apache/struts2/static/dojo/README | 176 + .../struts2/static/dojo/Storage_version6.swf | Bin 0 -> 1963 bytes .../struts2/static/dojo/Storage_version8.swf | Bin 0 -> 2594 bytes .../org/apache/struts2/static/dojo/build.txt | 86 + .../org/apache/struts2/static/dojo/dojo.js | 11190 ++++++++++ .../static/dojo/dojo.js.uncompressed.js | 17204 ++++++++++++++++ .../struts2/static/dojo/flash6_gateway.swf | Bin 0 -> 1170 bytes .../struts2/static/dojo/iframe_history.html | 54 + .../static/dojo/src/AdapterRegistry.js | 89 + .../struts2/static/dojo/src/Deferred.js | 315 + .../struts2/static/dojo/src/DeferredList.js | 88 + .../apache/struts2/static/dojo/src/a11y.js | 103 + .../struts2/static/dojo/src/animation.js | 14 + .../static/dojo/src/animation/Animation.js | 245 + .../dojo/src/animation/AnimationEvent.js | 64 + .../dojo/src/animation/AnimationSequence.js | 162 + .../static/dojo/src/animation/Timer.js | 16 + .../static/dojo/src/animation/__package__.js | 20 + .../struts2/static/dojo/src/behavior.js | 248 + .../struts2/static/dojo/src/bootstrap1.js | 343 + .../struts2/static/dojo/src/bootstrap2.js | 59 + .../struts2/static/dojo/src/browser_debug.js | 176 + .../struts2/static/dojo/src/cal/iCalendar.js | 815 + .../static/dojo/src/cal/textDirectory.js | 75 + .../struts2/static/dojo/src/charting/Axis.js | 146 + .../struts2/static/dojo/src/charting/Chart.js | 85 + .../struts2/static/dojo/src/charting/Plot.js | 103 + .../static/dojo/src/charting/PlotArea.js | 193 + .../static/dojo/src/charting/Plotters.js | 19 + .../static/dojo/src/charting/README.txt | 46 + .../static/dojo/src/charting/Series.js | 215 + .../static/dojo/src/charting/__package__.js | 11 + .../static/dojo/src/charting/svg/Axis.js | 224 + .../static/dojo/src/charting/svg/PlotArea.js | 79 + .../static/dojo/src/charting/svg/Plotters.js | 872 + .../static/dojo/src/charting/vml/Axis.js | 270 + .../static/dojo/src/charting/vml/PlotArea.js | 78 + .../static/dojo/src/charting/vml/Plotters.js | 1141 + .../static/dojo/src/collections/ArrayList.js | 146 + .../static/dojo/src/collections/BinaryTree.js | 203 + .../dojo/src/collections/Collections.js | 124 + .../static/dojo/src/collections/Dictionary.js | 129 + .../static/dojo/src/collections/Graph.js | 153 + .../static/dojo/src/collections/Queue.js | 87 + .../static/dojo/src/collections/Set.js | 94 + .../static/dojo/src/collections/SkipList.js | 149 + .../static/dojo/src/collections/SortedList.js | 211 + .../static/dojo/src/collections/Stack.js | 85 + .../static/dojo/src/collections/Store.js | 279 + .../dojo/src/collections/__package__.js | 22 + .../apache/struts2/static/dojo/src/crypto.js | 31 + .../static/dojo/src/crypto/Blowfish.js | 576 + .../struts2/static/dojo/src/crypto/LICENSE | 11 + .../struts2/static/dojo/src/crypto/MD5.js | 199 + .../static/dojo/src/crypto/Rijndael.js | 22 + .../struts2/static/dojo/src/crypto/SHA1.js | 154 + .../struts2/static/dojo/src/crypto/SHA256.js | 20 + .../static/dojo/src/crypto/__package__.js | 17 + .../apache/struts2/static/dojo/src/data.js | 15 + .../struts2/static/dojo/src/data/Read.js | 224 + .../struts2/static/dojo/src/data/Result.js | 158 + .../struts2/static/dojo/src/data/Write.js | 169 + .../static/dojo/src/data/__package__.js | 14 + .../static/dojo/src/data/csv/CsvStore.js | 220 + .../static/dojo/src/data/csv/Result.js | 81 + .../static/dojo/src/data/csv/__package__.js | 21 + .../static/dojo/src/data/old/Attribute.js | 62 + .../struts2/static/dojo/src/data/old/Item.js | 327 + .../struts2/static/dojo/src/data/old/Kind.js | 28 + .../static/dojo/src/data/old/Observable.js | 59 + .../static/dojo/src/data/old/ResultSet.js | 70 + .../struts2/static/dojo/src/data/old/Type.js | 25 + .../struts2/static/dojo/src/data/old/Value.js | 55 + .../static/dojo/src/data/old/__package__.js | 22 + .../static/dojo/src/data/old/format/Csv.js | 112 + .../static/dojo/src/data/old/format/Json.js | 103 + .../static/dojo/src/data/old/provider/Base.js | 183 + .../dojo/src/data/old/provider/Delicious.js | 85 + .../dojo/src/data/old/provider/FlatFile.js | 153 + .../dojo/src/data/old/provider/JotSpot.js | 27 + .../dojo/src/data/old/provider/MySql.js | 27 + .../static/dojo/src/data/old/to_do.txt | 45 + .../apache/struts2/static/dojo/src/date.js | 13 + .../struts2/static/dojo/src/date/common.js | 496 + .../struts2/static/dojo/src/date/format.js | 922 + .../struts2/static/dojo/src/date/serialize.js | 175 + .../static/dojo/src/date/supplemental.js | 76 + .../apache/struts2/static/dojo/src/debug.js | 91 + .../struts2/static/dojo/src/debug/Firebug.js | 62 + .../static/dojo/src/debug/arrow_hide.gif | Bin 0 -> 163 bytes .../static/dojo/src/debug/arrow_show.gif | Bin 0 -> 165 bytes .../struts2/static/dojo/src/debug/console.js | 115 + .../struts2/static/dojo/src/debug/deep.html | 362 + .../struts2/static/dojo/src/debug/spacer.gif | Bin 0 -> 820 bytes .../static/dojo/src/dnd/DragAndDrop.js | 173 + .../static/dojo/src/dnd/HtmlDragAndDrop.js | 508 + .../static/dojo/src/dnd/HtmlDragCopy.js | 85 + .../static/dojo/src/dnd/HtmlDragManager.js | 505 + .../static/dojo/src/dnd/HtmlDragMove.js | 66 + .../struts2/static/dojo/src/dnd/Sortable.js | 28 + .../static/dojo/src/dnd/TreeDragAndDrop.js | 475 + .../static/dojo/src/dnd/TreeDragAndDropV3.js | 404 + .../static/dojo/src/dnd/__package__.js | 16 + .../apache/struts2/static/dojo/src/docs.js | 1048 + .../org/apache/struts2/static/dojo/src/dom.js | 522 + .../apache/struts2/static/dojo/src/event.js | 14 + .../static/dojo/src/event/__package__.js | 16 + .../struts2/static/dojo/src/event/browser.js | 514 + .../struts2/static/dojo/src/event/common.js | 878 + .../struts2/static/dojo/src/event/topic.js | 201 + .../struts2/static/dojo/src/experimental.js | 30 + .../apache/struts2/static/dojo/src/flash.js | 1230 ++ .../src/flash/flash6/DojoExternalInterface.as | 215 + .../dojo/src/flash/flash6/flash6_gateway.fla | Bin 0 -> 40448 bytes .../src/flash/flash8/DojoExternalInterface.as | 234 + .../dojo/src/flash/flash8/ExpressInstall.as | 81 + .../struts2/static/dojo/src/fx/__package__.js | 14 + .../apache/struts2/static/dojo/src/fx/html.js | 565 + .../apache/struts2/static/dojo/src/fx/svg.js | 100 + .../struts2/static/dojo/src/gfx/Colorspace.js | 820 + .../static/dojo/src/gfx/__package__.js | 23 + .../struts2/static/dojo/src/gfx/color.js | 183 + .../struts2/static/dojo/src/gfx/color/hsl.js | 139 + .../struts2/static/dojo/src/gfx/color/hsv.js | 246 + .../struts2/static/dojo/src/gfx/common.js | 103 + .../struts2/static/dojo/src/gfx/matrix.js | 242 + .../struts2/static/dojo/src/gfx/path.js | 320 + .../struts2/static/dojo/src/gfx/shape.js | 238 + .../apache/struts2/static/dojo/src/gfx/svg.js | 553 + .../apache/struts2/static/dojo/src/gfx/vml.js | 1157 ++ .../static/dojo/src/graphics/Colorspace.js | 15 + .../static/dojo/src/graphics/__package__.js | 12 + .../struts2/static/dojo/src/graphics/color.js | 37 + .../static/dojo/src/graphics/color/hsl.js | 33 + .../static/dojo/src/graphics/color/hsv.js | 23 + .../static/dojo/src/hostenv_adobesvg.js | 571 + .../static/dojo/src/hostenv_browser.js | 528 + .../static/dojo/src/hostenv_dashboard.js | 197 + .../struts2/static/dojo/src/hostenv_jsc.js | 76 + .../struts2/static/dojo/src/hostenv_rhino.js | 246 + .../static/dojo/src/hostenv_spidermonkey.js | 79 + .../struts2/static/dojo/src/hostenv_svg.js | 223 + .../struts2/static/dojo/src/hostenv_wsh.js | 46 + .../apache/struts2/static/dojo/src/html.js | 14 + .../static/dojo/src/html/__package__.js | 15 + .../struts2/static/dojo/src/html/color.js | 35 + .../struts2/static/dojo/src/html/common.js | 230 + .../struts2/static/dojo/src/html/display.js | 196 + .../struts2/static/dojo/src/html/iframe.js | 117 + .../static/dojo/src/html/images/shadowB.png | Bin 0 -> 470 bytes .../static/dojo/src/html/images/shadowBL.png | Bin 0 -> 272 bytes .../static/dojo/src/html/images/shadowBR.png | Bin 0 -> 271 bytes .../static/dojo/src/html/images/shadowL.png | Bin 0 -> 148 bytes .../static/dojo/src/html/images/shadowR.png | Bin 0 -> 149 bytes .../static/dojo/src/html/images/shadowT.png | Bin 0 -> 152 bytes .../static/dojo/src/html/images/shadowTL.png | Bin 0 -> 271 bytes .../static/dojo/src/html/images/shadowTR.png | Bin 0 -> 287 bytes .../struts2/static/dojo/src/html/layout.js | 487 + .../struts2/static/dojo/src/html/metrics.js | 266 + .../struts2/static/dojo/src/html/selection.js | 376 + .../struts2/static/dojo/src/html/shadow.js | 16 + .../struts2/static/dojo/src/html/style.js | 577 + .../struts2/static/dojo/src/html/util.js | 484 + .../static/dojo/src/i18n/calendar/nls/README | 6 + .../src/i18n/calendar/nls/de/gregorian.js | 29 + .../src/i18n/calendar/nls/en/gregorian.js | 30 + .../src/i18n/calendar/nls/es/gregorian.js | 29 + .../src/i18n/calendar/nls/fi/gregorian.js | 32 + .../src/i18n/calendar/nls/fr/gregorian.js | 27 + .../dojo/src/i18n/calendar/nls/gregorian.js | 45 + .../src/i18n/calendar/nls/gregorianExtras.js | 14 + .../src/i18n/calendar/nls/hu/gregorian.js | 32 + .../src/i18n/calendar/nls/it/gregorian.js | 25 + .../src/i18n/calendar/nls/ja/gregorian.js | 32 + .../i18n/calendar/nls/ja/gregorianExtras.js | 14 + .../src/i18n/calendar/nls/ko/gregorian.js | 32 + .../src/i18n/calendar/nls/nl/gregorian.js | 27 + .../src/i18n/calendar/nls/pt-br/gregorian.js | 17 + .../src/i18n/calendar/nls/pt/gregorian.js | 27 + .../src/i18n/calendar/nls/sv/gregorian.js | 32 + .../src/i18n/calendar/nls/zh-cn/gregorian.js | 22 + .../src/i18n/calendar/nls/zh-hk/gregorian.js | 26 + .../src/i18n/calendar/nls/zh-tw/gregorian.js | 26 + .../src/i18n/calendar/nls/zh/gregorian.js | 23 + .../i18n/calendar/nls/zh/gregorianExtras.js | 14 + .../struts2/static/dojo/src/i18n/common.js | 68 + .../struts2/static/dojo/src/i18n/currency.js | 289 + .../static/dojo/src/i18n/currency/common.js | 289 + .../static/dojo/src/i18n/currency/nls/EUR.js | 14 + .../static/dojo/src/i18n/currency/nls/GBP.js | 14 + .../static/dojo/src/i18n/currency/nls/INR.js | 14 + .../static/dojo/src/i18n/currency/nls/ITL.js | 14 + .../static/dojo/src/i18n/currency/nls/JPY.js | 14 + .../static/dojo/src/i18n/currency/nls/README | 6 + .../static/dojo/src/i18n/currency/nls/USD.js | 14 + .../dojo/src/i18n/currency/nls/en-us/USD.js | 13 + .../dojo/src/i18n/currency/nls/en/EUR.js | 13 + .../dojo/src/i18n/currency/nls/en/GBP.js | 13 + .../dojo/src/i18n/currency/nls/en/INR.js | 13 + .../dojo/src/i18n/currency/nls/en/ITL.js | 13 + .../dojo/src/i18n/currency/nls/en/JPY.js | 13 + .../dojo/src/i18n/currency/nls/en/USD.js | 14 + .../dojo/src/i18n/currency/nls/hi/EUR.js | 13 + .../dojo/src/i18n/currency/nls/hi/GBP.js | 13 + .../dojo/src/i18n/currency/nls/hi/INR.js | 14 + .../dojo/src/i18n/currency/nls/hi/ITL.js | 13 + .../dojo/src/i18n/currency/nls/hi/JPY.js | 13 + .../dojo/src/i18n/currency/nls/hi/USD.js | 13 + .../dojo/src/i18n/currency/nls/ja/EUR.js | 13 + .../dojo/src/i18n/currency/nls/ja/GBP.js | 13 + .../dojo/src/i18n/currency/nls/ja/INR.js | 14 + .../dojo/src/i18n/currency/nls/ja/ITL.js | 13 + .../dojo/src/i18n/currency/nls/ja/JPY.js | 14 + .../dojo/src/i18n/currency/nls/ja/USD.js | 13 + .../struts2/static/dojo/src/i18n/number.js | 292 + .../struts2/static/dojo/src/iCalendar.js | 12 + .../org/apache/struts2/static/dojo/src/io.js | 14 + .../struts2/static/dojo/src/io/BrowserIO.js | 592 + .../struts2/static/dojo/src/io/IframeIO.js | 258 + .../struts2/static/dojo/src/io/RepubsubIO.js | 514 + .../struts2/static/dojo/src/io/RhinoIO.js | 147 + .../struts2/static/dojo/src/io/ScriptSrcIO.js | 458 + .../static/dojo/src/io/XhrIframeProxy.js | 211 + .../struts2/static/dojo/src/io/__package__.js | 17 + .../struts2/static/dojo/src/io/cometd.js | 929 + .../struts2/static/dojo/src/io/common.js | 513 + .../struts2/static/dojo/src/io/cookie.js | 108 + .../static/dojo/src/io/xip_client.html | 200 + .../static/dojo/src/io/xip_server.html | 337 + .../apache/struts2/static/dojo/src/json.js | 156 + .../apache/struts2/static/dojo/src/lang.js | 14 + .../static/dojo/src/lang/__package__.js | 23 + .../struts2/static/dojo/src/lang/array.js | 186 + .../struts2/static/dojo/src/lang/assert.js | 116 + .../struts2/static/dojo/src/lang/common.js | 230 + .../struts2/static/dojo/src/lang/declare.js | 161 + .../struts2/static/dojo/src/lang/extras.js | 130 + .../struts2/static/dojo/src/lang/func.js | 148 + .../struts2/static/dojo/src/lang/repr.js | 85 + .../static/dojo/src/lang/timing/Streamer.js | 99 + .../static/dojo/src/lang/timing/Timer.js | 64 + .../dojo/src/lang/timing/__package__.js | 11 + .../struts2/static/dojo/src/lang/type.js | 251 + .../struts2/static/dojo/src/lfx/Animation.js | 575 + .../static/dojo/src/lfx/__package__.js | 15 + .../struts2/static/dojo/src/lfx/extras.js | 148 + .../struts2/static/dojo/src/lfx/html.js | 734 + .../struts2/static/dojo/src/lfx/rounded.js | 512 + .../struts2/static/dojo/src/lfx/shadow.js | 86 + .../struts2/static/dojo/src/lfx/toggle.js | 54 + .../apache/struts2/static/dojo/src/loader.js | 727 + .../struts2/static/dojo/src/loader_xd.js | 437 + .../static/dojo/src/logging/ConsoleLogger.js | 108 + .../struts2/static/dojo/src/logging/Logger.js | 387 + .../static/dojo/src/logging/__package__.js | 15 + .../apache/struts2/static/dojo/src/math.js | 127 + .../static/dojo/src/math/__package__.js | 18 + .../struts2/static/dojo/src/math/curves.js | 242 + .../struts2/static/dojo/src/math/matrix.js | 377 + .../struts2/static/dojo/src/math/points.js | 54 + .../static/dojo/src/namespaces/dojo.js | 153 + .../org/apache/struts2/static/dojo/src/ns.js | 142 + .../apache/struts2/static/dojo/src/profile.js | 146 + .../apache/struts2/static/dojo/src/regexp.js | 576 + .../struts2/static/dojo/src/rpc/Deferred.js | 16 + .../struts2/static/dojo/src/rpc/JotService.js | 43 + .../static/dojo/src/rpc/JsonService.js | 119 + .../struts2/static/dojo/src/rpc/RpcService.js | 122 + .../static/dojo/src/rpc/YahooService.js | 59 + .../static/dojo/src/rpc/__package__.js | 14 + .../struts2/static/dojo/src/rpc/yahoo.smd | 263 + .../static/dojo/src/selection/Selection.js | 425 + .../apache/struts2/static/dojo/src/storage.js | 364 + .../static/dojo/src/storage/Storage.as | 146 + .../static/dojo/src/storage/__package__.js | 17 + .../static/dojo/src/storage/browser.js | 195 + .../static/dojo/src/storage/dashboard.js | 52 + .../dojo/src/storage/storage_dialog.fla | Bin 0 -> 344064 bytes .../apache/struts2/static/dojo/src/string.js | 12 + .../struts2/static/dojo/src/string/Builder.js | 128 + .../static/dojo/src/string/__package__.js | 19 + .../struts2/static/dojo/src/string/common.js | 78 + .../struts2/static/dojo/src/string/extras.js | 261 + .../apache/struts2/static/dojo/src/style.js | 15 + .../org/apache/struts2/static/dojo/src/svg.js | 320 + .../static/dojo/src/text/__package__.js | 18 + .../static/dojo/src/text/textDirectory.js | 12 + .../struts2/static/dojo/src/undo/Manager.js | 200 + .../static/dojo/src/undo/__package__.js | 12 + .../struts2/static/dojo/src/undo/browser.js | 309 + .../apache/struts2/static/dojo/src/uri/Uri.js | 110 + .../static/dojo/src/uri/__package__.js | 14 + .../dojo/src/uuid/LightweightGenerator.js | 73 + .../dojo/src/uuid/NameBasedGenerator.js | 38 + .../static/dojo/src/uuid/NilGenerator.js | 32 + .../static/dojo/src/uuid/RandomGenerator.js | 39 + .../dojo/src/uuid/TimeBasedGenerator.js | 355 + .../struts2/static/dojo/src/uuid/Uuid.js | 379 + .../static/dojo/src/uuid/__package__.js | 22 + .../struts2/static/dojo/src/validate.js | 12 + .../static/dojo/src/validate/__package__.js | 21 + .../struts2/static/dojo/src/validate/check.js | 263 + .../static/dojo/src/validate/common.js | 248 + .../static/dojo/src/validate/creditCard.js | 90 + .../static/dojo/src/validate/datetime.js | 172 + .../struts2/static/dojo/src/validate/de.js | 26 + .../struts2/static/dojo/src/validate/jp.js | 23 + .../struts2/static/dojo/src/validate/us.js | 84 + .../struts2/static/dojo/src/validate/web.js | 95 + .../dojo/src/widget/AccordionContainer.js | 279 + .../static/dojo/src/widget/AnimatedPng.js | 98 + .../struts2/static/dojo/src/widget/Button.js | 432 + .../struts2/static/dojo/src/widget/Chart.js | 257 + .../static/dojo/src/widget/Checkbox.js | 182 + .../struts2/static/dojo/src/widget/Clock.js | 211 + .../static/dojo/src/widget/ColorPalette.js | 123 + .../static/dojo/src/widget/ComboBox.js | 840 + .../static/dojo/src/widget/ContentPane.js | 706 + .../static/dojo/src/widget/CurrencyTextbox.js | 63 + .../static/dojo/src/widget/DatePicker.js | 496 + .../static/dojo/src/widget/DateTextbox.js | 98 + .../static/dojo/src/widget/DebugConsole.js | 26 + .../struts2/static/dojo/src/widget/Dialog.js | 346 + .../struts2/static/dojo/src/widget/DocPane.js | 382 + .../static/dojo/src/widget/DomWidget.js | 902 + .../dojo/src/widget/DropdownContainer.js | 90 + .../dojo/src/widget/DropdownDatePicker.js | 228 + .../dojo/src/widget/DropdownTimePicker.js | 116 + .../struts2/static/dojo/src/widget/Editor.js | 534 + .../struts2/static/dojo/src/widget/Editor2.js | 666 + .../widget/Editor2Plugin/AlwaysShowToolbar.js | 132 + .../src/widget/Editor2Plugin/ContextMenu.js | 246 + .../widget/Editor2Plugin/CreateLinkDialog.js | 78 + .../src/widget/Editor2Plugin/FindReplace.js | 74 + .../widget/Editor2Plugin/FindReplaceDialog.js | 49 + .../widget/Editor2Plugin/InsertImageDialog.js | 64 + .../widget/Editor2Plugin/InsertTableDialog.js | 147 + .../Editor2Plugin/SimpleSignalCommands.js | 72 + .../widget/Editor2Plugin/TableOperation.js | 147 + .../widget/Editor2Plugin/ToolbarDndSupport.js | 68 + .../src/widget/Editor2Plugin/__package__.js | 15 + .../static/dojo/src/widget/Editor2Toolbar.js | 600 + .../static/dojo/src/widget/FilteringTable.js | 961 + .../static/dojo/src/widget/FisheyeList.js | 742 + .../static/dojo/src/widget/FloatingPane.js | 441 + .../struts2/static/dojo/src/widget/Form.js | 257 + .../static/dojo/src/widget/GoogleMap.js | 229 + .../static/dojo/src/widget/HtmlWidget.js | 170 + .../static/dojo/src/widget/InlineEditBox.js | 212 + .../static/dojo/src/widget/IntegerTextbox.js | 66 + .../static/dojo/src/widget/InternetTextbox.js | 168 + .../static/dojo/src/widget/LayoutContainer.js | 97 + .../static/dojo/src/widget/LinkPane.js | 42 + .../struts2/static/dojo/src/widget/Manager.js | 363 + .../struts2/static/dojo/src/widget/Menu2.js | 765 + .../static/dojo/src/widget/MonthlyCalendar.js | 188 + .../static/dojo/src/widget/PageContainer.js | 387 + .../struts2/static/dojo/src/widget/Parse.js | 346 + .../static/dojo/src/widget/PopupContainer.js | 452 + .../static/dojo/src/widget/ProgressBar.js | 289 + .../static/dojo/src/widget/RadioGroup.js | 204 + .../dojo/src/widget/RealNumberTextbox.js | 73 + .../static/dojo/src/widget/RegexpTextbox.js | 48 + .../dojo/src/widget/RemoteTabController.js | 50 + .../static/dojo/src/widget/Repeater.js | 140 + .../dojo/src/widget/ResizableTextarea.js | 102 + .../static/dojo/src/widget/ResizeHandle.js | 103 + .../static/dojo/src/widget/RichText.js | 1692 ++ .../struts2/static/dojo/src/widget/Rounded.js | 713 + .../struts2/static/dojo/src/widget/Select.js | 76 + .../struts2/static/dojo/src/widget/Show.js | 254 + .../static/dojo/src/widget/ShowAction.js | 24 + .../static/dojo/src/widget/ShowSlide.js | 229 + .../static/dojo/src/widget/SlideShow.js | 141 + .../struts2/static/dojo/src/widget/Slider.js | 888 + .../static/dojo/src/widget/SortableTable.js | 615 + .../struts2/static/dojo/src/widget/Spinner.js | 622 + .../static/dojo/src/widget/SplitContainer.js | 527 + .../static/dojo/src/widget/SplitPane.js | 514 + .../static/dojo/src/widget/SvgButton.js | 141 + .../static/dojo/src/widget/SvgWidget.js | 89 + .../static/dojo/src/widget/SwtWidget.js | 64 + .../static/dojo/src/widget/TabContainer.js | 215 + .../struts2/static/dojo/src/widget/TaskBar.js | 93 + .../struts2/static/dojo/src/widget/Textbox.js | 94 + .../static/dojo/src/widget/TimePicker.js | 342 + .../static/dojo/src/widget/TitlePane.js | 61 + .../struts2/static/dojo/src/widget/Toaster.js | 245 + .../struts2/static/dojo/src/widget/Toggler.js | 34 + .../struts2/static/dojo/src/widget/Toolbar.js | 946 + .../struts2/static/dojo/src/widget/Tooltip.js | 165 + .../struts2/static/dojo/src/widget/Tree.js | 563 + .../dojo/src/widget/TreeBasicController.js | 284 + .../dojo/src/widget/TreeBasicControllerV3.js | 825 + .../static/dojo/src/widget/TreeCommon.js | 150 + .../static/dojo/src/widget/TreeContextMenu.js | 181 + .../dojo/src/widget/TreeContextMenuV3.js | 132 + .../src/widget/TreeControllerExtension.js | 94 + .../static/dojo/src/widget/TreeDemo.js | 130 + .../src/widget/TreeDeselectOnDblselect.js | 36 + .../src/widget/TreeDisableWrapExtension.js | 55 + .../dojo/src/widget/TreeDndControllerV3.js | 137 + .../dojo/src/widget/TreeDocIconExtension.js | 117 + .../static/dojo/src/widget/TreeEditor.js | 115 + .../dojo/src/widget/TreeEmphaseOnSelect.js | 43 + .../dojo/src/widget/TreeExpandOnSelect.js | 43 + .../static/dojo/src/widget/TreeExtension.js | 24 + .../dojo/src/widget/TreeLinkExtension.js | 73 + .../dojo/src/widget/TreeLoadingController.js | 205 + .../src/widget/TreeLoadingControllerV3.js | 496 + .../static/dojo/src/widget/TreeNode.js | 523 + .../static/dojo/src/widget/TreeNodeV3.js | 740 + .../dojo/src/widget/TreeRPCController.js | 162 + .../dojo/src/widget/TreeRpcControllerV3.js | 424 + .../static/dojo/src/widget/TreeSelector.js | 179 + .../static/dojo/src/widget/TreeSelectorV3.js | 264 + .../dojo/src/widget/TreeTimeoutIterator.js | 169 + .../struts2/static/dojo/src/widget/TreeV3.js | 347 + .../static/dojo/src/widget/TreeWithNode.js | 277 + .../static/dojo/src/widget/UsTextbox.js | 88 + .../dojo/src/widget/ValidationTextbox.js | 195 + .../struts2/static/dojo/src/widget/Widget.js | 848 + .../struts2/static/dojo/src/widget/Wizard.js | 197 + .../static/dojo/src/widget/YahooMap.js | 181 + .../static/dojo/src/widget/__package__.js | 23 + .../src/widget/demoEngine/DemoContainer.js | 107 + .../dojo/src/widget/demoEngine/DemoItem.js | 71 + .../src/widget/demoEngine/DemoNavigator.js | 188 + .../dojo/src/widget/demoEngine/DemoPane.js | 44 + .../dojo/src/widget/demoEngine/SourcePane.js | 52 + .../dojo/src/widget/demoEngine/__package__.js | 20 + .../demoEngine/templates/DemoContainer.css | 39 + .../demoEngine/templates/DemoContainer.html | 25 + .../widget/demoEngine/templates/DemoItem.css | 58 + .../widget/demoEngine/templates/DemoItem.html | 21 + .../demoEngine/templates/DemoNavigator.css | 28 + .../demoEngine/templates/DemoNavigator.html | 24 + .../widget/demoEngine/templates/DemoPane.css | 18 + .../widget/demoEngine/templates/DemoPane.html | 3 + .../demoEngine/templates/SourcePane.css | 20 + .../demoEngine/templates/SourcePane.html | 3 + .../widget/demoEngine/templates/general.css | 73 + .../templates/images/test_thumb.gif | Bin 0 -> 3198 bytes .../demoEngine/templates/images/viewDemo.png | Bin 0 -> 859 bytes .../static/dojo/src/widget/html/layout.js | 121 + .../static/dojo/src/widget/html/loader.js | 843 + .../static/dojo/src/widget/html/stabile.js | 213 + .../dojo/src/widget/nls/DropdownDatePicker.js | 13 + .../dojo/src/widget/nls/DropdownTimePicker.js | 13 + .../static/dojo/src/widget/nls/TimePicker.js | 13 + .../static/dojo/src/widget/nls/fr/validate.js | 15 + .../static/dojo/src/widget/nls/ja/validate.js | 16 + .../static/dojo/src/widget/nls/validate.js | 15 + .../dojo/src/widget/nls/zh-cn/validate.js | 15 + .../static/dojo/src/widget/svg/Chart.js | 586 + .../src/widget/templates/AccordionPane.css | 22 + .../src/widget/templates/AccordionPane.html | 4 + .../src/widget/templates/ButtonTemplate.css | 59 + .../src/widget/templates/ButtonTemplate.html | 6 + .../dojo/src/widget/templates/Checkbox.css | 26 + .../dojo/src/widget/templates/Checkbox.html | 5 + .../src/widget/templates/CheckboxA11y.html | 4 + .../widget/templates/CiviCrmDatePicker.html | 12 + .../dojo/src/widget/templates/ComboBox.css | 68 + .../dojo/src/widget/templates/ComboBox.html | 16 + .../widget/templates/ComboButtonTemplate.html | 18 + .../dojo/src/widget/templates/DatePicker.css | 167 + .../dojo/src/widget/templates/DatePicker.html | 96 + .../dojo/src/widget/templates/DemoEngine.html | 24 + .../dojo/src/widget/templates/Dialog.html | 7 + .../dojo/src/widget/templates/DocPane.css | 49 + .../dojo/src/widget/templates/DocPane.html | 79 + .../templates/DropDownButtonTemplate.html | 9 + .../templates/Editor2/Dialog/createlink.html | 15 + .../widget/templates/Editor2/Dialog/find.html | 15 + .../templates/Editor2/Dialog/insertimage.html | 114 + .../templates/Editor2/Dialog/inserttable.html | 91 + .../templates/Editor2/Dialog/replace.html | 15 + .../templates/Editor2/EditorDialog.html | 18 + .../Editor2/EditorToolbar_FontName.html | 20 + .../Editor2/EditorToolbar_FontSize.html | 31 + .../Editor2/EditorToolbar_FormatBlock.html | 52 + .../Editor2/showtableborder_gecko.css | 19 + .../templates/Editor2/showtableborder_ie.css | 4 + .../src/widget/templates/EditorToolbar.css | 152 + .../src/widget/templates/EditorToolbar.html | 153 + .../widget/templates/EditorToolbarLight.html | 46 + .../templates/EditorToolbarOneline.html | 208 + .../dojo/src/widget/templates/FisheyeList.css | 27 + .../src/widget/templates/FloatingPane.css | 118 + .../src/widget/templates/FloatingPane.html | 18 + .../src/widget/templates/InlineEditBox.css | 29 + .../src/widget/templates/InlineEditBox.html | 6 + .../static/dojo/src/widget/templates/Menu.css | 60 + .../dojo/src/widget/templates/Menu2.css | 125 + .../src/widget/templates/MonthlyCalendar.css | 91 + .../src/widget/templates/MonthlyCalendar.html | 110 + .../dojo/src/widget/templates/PopUpButton.css | 35 + .../dojo/src/widget/templates/ProgressBar.css | 23 + .../src/widget/templates/ProgressBar.html | 5 + .../src/widget/templates/RemoteTabControl.css | 61 + .../widget/templates/ResizableTextarea.css | 15 + .../widget/templates/ResizableTextarea.html | 14 + .../src/widget/templates/ResizeHandle.css | 12 + .../static/dojo/src/widget/templates/Show.css | 59 + .../dojo/src/widget/templates/Show.html | 11 + .../dojo/src/widget/templates/ShowSlide.css | 12 + .../dojo/src/widget/templates/ShowSlide.html | 6 + .../dojo/src/widget/templates/SlideShow.css | 9 + .../dojo/src/widget/templates/SlideShow.html | 15 + .../dojo/src/widget/templates/Slider.css | 61 + .../dojo/src/widget/templates/Slider.html | 56 + .../widget/templates/SliderHorizontal.html | 3 + .../src/widget/templates/SliderVertical.html | 3 + .../dojo/src/widget/templates/Spinner.css | 34 + .../dojo/src/widget/templates/Spinner.html | 25 + .../src/widget/templates/SplitContainer.css | 39 + .../src/widget/templates/TabContainer.css | 162 + .../src/widget/templates/TabContainer.html | 4 + .../src/widget/templates/TabContainerA11y.css | 175 + .../dojo/src/widget/templates/TaskBar.css | 29 + .../widget/templates/TaskBarItemTemplate.html | 2 + .../dojo/src/widget/templates/Textbox.html | 5 + .../dojo/src/widget/templates/TimePicker.css | 179 + .../dojo/src/widget/templates/TimePicker.html | 98 + .../dojo/src/widget/templates/TitlePane.html | 4 + .../dojo/src/widget/templates/Toaster.css | 42 + .../dojo/src/widget/templates/Toolbar.css | 54 + .../src/widget/templates/TooltipTemplate.css | 10 + .../static/dojo/src/widget/templates/Tree.css | 29 + .../src/widget/templates/TreeDisableWrap.css | 9 + .../dojo/src/widget/templates/TreeDocIcon.css | 55 + .../dojo/src/widget/templates/TreeV3.css | 91 + .../dojo/src/widget/templates/Validate.css | 12 + .../widget/templates/ValidationTextbox.html | 8 + .../dojo/src/widget/templates/Wizard.css | 72 + .../dojo/src/widget/templates/Wizard.html | 10 + .../widget/templates/buttons/aggregate.gif | Bin 0 -> 4360 bytes .../widget/templates/buttons/backcolor.gif | Bin 0 -> 585 bytes .../src/widget/templates/buttons/bg-fade.png | Bin 0 -> 177 bytes .../src/widget/templates/buttons/bold.gif | Bin 0 -> 346 bytes .../src/widget/templates/buttons/cancel.gif | Bin 0 -> 375 bytes .../src/widget/templates/buttons/copy.gif | Bin 0 -> 210 bytes .../widget/templates/buttons/createlink.gif | Bin 0 -> 1081 bytes .../dojo/src/widget/templates/buttons/cut.gif | Bin 0 -> 112 bytes .../src/widget/templates/buttons/delete.gif | Bin 0 -> 81 bytes .../widget/templates/buttons/forecolor.gif | Bin 0 -> 574 bytes .../widget/templates/buttons/hilitecolor.gif | Bin 0 -> 585 bytes .../src/widget/templates/buttons/indent.gif | Bin 0 -> 83 bytes .../buttons/inserthorizontalrule.gif | Bin 0 -> 117 bytes .../widget/templates/buttons/insertimage.gif | Bin 0 -> 595 bytes .../templates/buttons/insertorderedlist.gif | Bin 0 -> 85 bytes .../widget/templates/buttons/inserttable.gif | Bin 0 -> 233 bytes .../templates/buttons/insertunorderedlist.gif | Bin 0 -> 98 bytes .../src/widget/templates/buttons/italic.gif | Bin 0 -> 309 bytes .../templates/buttons/justifycenter.gif | Bin 0 -> 132 bytes .../widget/templates/buttons/justifyfull.gif | Bin 0 -> 294 bytes .../widget/templates/buttons/justifyleft.gif | Bin 0 -> 194 bytes .../widget/templates/buttons/justifyright.gif | Bin 0 -> 190 bytes .../templates/buttons/left_to_right.gif | Bin 0 -> 138 bytes .../templates/buttons/list_bullet_indent.gif | Bin 0 -> 98 bytes .../templates/buttons/list_bullet_outdent.gif | Bin 0 -> 99 bytes .../templates/buttons/list_num_indent.gif | Bin 0 -> 85 bytes .../templates/buttons/list_num_outdent.gif | Bin 0 -> 85 bytes .../src/widget/templates/buttons/outdent.gif | Bin 0 -> 84 bytes .../src/widget/templates/buttons/paste.gif | Bin 0 -> 241 bytes .../src/widget/templates/buttons/redo.gif | Bin 0 -> 543 bytes .../widget/templates/buttons/removeformat.gif | Bin 0 -> 101 bytes .../templates/buttons/right_to_left.gif | Bin 0 -> 142 bytes .../src/widget/templates/buttons/save.gif | Bin 0 -> 243 bytes .../dojo/src/widget/templates/buttons/sep.gif | Bin 0 -> 58 bytes .../src/widget/templates/buttons/space.gif | Bin 0 -> 43 bytes .../templates/buttons/strikethrough.gif | Bin 0 -> 329 bytes .../widget/templates/buttons/subscript.gif | Bin 0 -> 76 bytes .../widget/templates/buttons/superscript.gif | Bin 0 -> 77 bytes .../widget/templates/buttons/underline.gif | Bin 0 -> 344 bytes .../src/widget/templates/buttons/undo.gif | Bin 0 -> 541 bytes .../src/widget/templates/buttons/wikiword.gif | Bin 0 -> 386 bytes .../dojo/src/widget/templates/check.gif | Bin 0 -> 2024 bytes .../src/widget/templates/decrementMonth.gif | Bin 0 -> 166 bytes .../src/widget/templates/decrementWeek.gif | Bin 0 -> 160 bytes .../dojo/src/widget/templates/grabCorner.gif | Bin 0 -> 77 bytes .../src/widget/templates/images/Tree/Tree.css | 36 + .../widget/templates/images/Tree/blank.gif | Bin 0 -> 55 bytes .../widget/templates/images/Tree/closed.gif | Bin 0 -> 1078 bytes .../widget/templates/images/Tree/document.gif | Bin 0 -> 240 bytes .../widget/templates/images/Tree/minus.gif | Bin 0 -> 545 bytes .../src/widget/templates/images/Tree/plus.gif | Bin 0 -> 539 bytes .../templates/images/Tree/transparent.gif | Bin 0 -> 870 bytes .../templates/images/Tree/treenode_blank.gif | Bin 0 -> 834 bytes .../templates/images/Tree/treenode_child.gif | Bin 0 -> 73 bytes .../images/Tree/treenode_expand_minus.gif | Bin 0 -> 547 bytes .../images/Tree/treenode_expand_plus.gif | Bin 0 -> 542 bytes .../templates/images/Tree/treenode_grid_c.gif | Bin 0 -> 60 bytes .../templates/images/Tree/treenode_grid_l.gif | Bin 0 -> 68 bytes .../templates/images/Tree/treenode_grid_p.gif | Bin 0 -> 63 bytes .../templates/images/Tree/treenode_grid_t.gif | Bin 0 -> 74 bytes .../templates/images/Tree/treenode_grid_v.gif | Bin 0 -> 71 bytes .../templates/images/Tree/treenode_grid_x.gif | Bin 0 -> 60 bytes .../templates/images/Tree/treenode_grid_y.gif | Bin 0 -> 67 bytes .../templates/images/Tree/treenode_grid_z.gif | Bin 0 -> 60 bytes .../images/Tree/treenode_loading.gif | Bin 0 -> 1089 bytes .../images/Tree/treenode_loading.jpg | Bin 0 -> 1390 bytes .../widget/templates/images/TreeV3/closed.gif | Bin 0 -> 162 bytes .../templates/images/TreeV3/document.gif | Bin 0 -> 342 bytes .../templates/images/TreeV3/expand_leaf.gif | Bin 0 -> 68 bytes .../images/TreeV3/expand_loading.gif | Bin 0 -> 1081 bytes .../templates/images/TreeV3/expand_minus.gif | Bin 0 -> 552 bytes .../templates/images/TreeV3/expand_plus.gif | Bin 0 -> 552 bytes .../src/widget/templates/images/TreeV3/i.gif | Bin 0 -> 71 bytes .../templates/images/TreeV3/i_bhalf.gif | Bin 0 -> 60 bytes .../widget/templates/images/TreeV3/i_half.gif | Bin 0 -> 65 bytes .../widget/templates/images/TreeV3/i_long.gif | Bin 0 -> 2113 bytes .../src/widget/templates/images/TreeV3/l.gif | Bin 0 -> 74 bytes .../widget/templates/images/TreeV3/minus.gif | Bin 0 -> 539 bytes .../widget/templates/images/TreeV3/open.gif | Bin 0 -> 139 bytes .../widget/templates/images/TreeV3/plus.gif | Bin 0 -> 539 bytes .../src/widget/templates/images/TreeV3/t.gif | Bin 0 -> 80 bytes .../src/widget/templates/images/TreeV3/x.gif | Bin 0 -> 68 bytes .../dojo/src/widget/templates/images/bar.gif | Bin 0 -> 2458 bytes .../widget/templates/images/bdYearBg.1.gif | 0 .../src/widget/templates/images/bdYearBg.gif | Bin 0 -> 74 bytes .../src/widget/templates/images/blank.gif | Bin 0 -> 43 bytes .../src/widget/templates/images/clock.png | Bin 0 -> 9422 bytes .../templates/images/combo_box_arrow.png | Bin 0 -> 336 bytes .../src/widget/templates/images/dateIcon.gif | Bin 0 -> 392 bytes .../templates/images/decrementMonth.gif | Bin 0 -> 167 bytes .../templates/images/decrementMonth.png | Bin 0 -> 194 bytes .../dojo/src/widget/templates/images/dpBg.gif | Bin 0 -> 522 bytes .../src/widget/templates/images/dpCurveBL.png | Bin 0 -> 280 bytes .../src/widget/templates/images/dpCurveBR.png | Bin 0 -> 275 bytes .../src/widget/templates/images/dpCurveTL.png | Bin 0 -> 305 bytes .../src/widget/templates/images/dpCurveTR.png | Bin 0 -> 295 bytes .../widget/templates/images/dpHorizLine.gif | Bin 0 -> 43 bytes .../templates/images/dpHorizLineFoot.gif | Bin 0 -> 43 bytes .../src/widget/templates/images/dpMonthBg.gif | Bin 0 -> 107 bytes .../src/widget/templates/images/dpMonthBg.png | Bin 0 -> 169 bytes .../widget/templates/images/dpMonthBg2.png | Bin 0 -> 169 bytes .../widget/templates/images/dpVertLine.gif | Bin 0 -> 43 bytes .../src/widget/templates/images/dpYearBg.gif | Bin 0 -> 74 bytes .../src/widget/templates/images/dpYearBg.png | Bin 0 -> 142 bytes .../images/dropdownButtonsArrow-disabled.gif | Bin 0 -> 816 bytes .../templates/images/dropdownButtonsArrow.gif | Bin 0 -> 46 bytes .../templates/images/floatingPaneClose.gif | Bin 0 -> 752 bytes .../templates/images/floatingPaneMaximize.gif | Bin 0 -> 704 bytes .../templates/images/floatingPaneMinimize.gif | Bin 0 -> 692 bytes .../templates/images/floatingPaneRestore.gif | Bin 0 -> 701 bytes .../src/widget/templates/images/h-bar.gif | Bin 0 -> 2668 bytes .../templates/images/incrementMonth.gif | Bin 0 -> 168 bytes .../templates/images/incrementMonth.png | Bin 0 -> 205 bytes .../dojo/src/widget/templates/images/no.gif | Bin 0 -> 179 bytes .../dojo/src/widget/templates/images/no.svg | 11 + .../widget/templates/images/scBackground.gif | Bin 0 -> 715 bytes .../images/slider-bg-progress-vert.gif | Bin 0 -> 1899 bytes .../templates/images/slider-bg-vert.gif | Bin 0 -> 1899 bytes .../src/widget/templates/images/slider-bg.gif | Bin 0 -> 1102 bytes .../templates/images/slider-button-horz.png | Bin 0 -> 439 bytes .../templates/images/slider-button-vert.png | Bin 0 -> 432 bytes .../widget/templates/images/slider-button.png | Bin 0 -> 381 bytes .../src/widget/templates/images/slider.gif | Bin 0 -> 865 bytes .../templates/images/slider_down_arrow.png | Bin 0 -> 382 bytes .../templates/images/slider_left_arrow.png | Bin 0 -> 343 bytes .../templates/images/slider_right_arrow.png | Bin 0 -> 366 bytes .../templates/images/slider_up_arrow.png | Bin 0 -> 378 bytes .../templates/images/soriaAccordionOff.gif | Bin 0 -> 94 bytes .../images/soriaAccordionSelected.gif | Bin 0 -> 94 bytes .../widget/templates/images/soriaActive-c.gif | Bin 0 -> 1420 bytes .../widget/templates/images/soriaActive-l.gif | Bin 0 -> 1585 bytes .../widget/templates/images/soriaActive-r.gif | Bin 0 -> 1587 bytes .../widget/templates/images/soriaBarBg.gif | Bin 0 -> 155 bytes .../widget/templates/images/soriaButton-c.gif | Bin 0 -> 848 bytes .../widget/templates/images/soriaButton-l.gif | Bin 0 -> 1001 bytes .../widget/templates/images/soriaButton-r.gif | Bin 0 -> 1001 bytes .../templates/images/soriaDisabled-c.gif | Bin 0 -> 743 bytes .../templates/images/soriaDisabled-l.gif | Bin 0 -> 894 bytes .../templates/images/soriaDisabled-r.gif | Bin 0 -> 895 bytes .../widget/templates/images/soriaMenuBg.gif | Bin 0 -> 820 bytes .../templates/images/soriaPressed-c.gif | Bin 0 -> 1446 bytes .../templates/images/soriaPressed-l.gif | Bin 0 -> 1613 bytes .../templates/images/soriaPressed-r.gif | Bin 0 -> 1614 bytes .../templates/images/spinnerDecrement.gif | Bin 0 -> 120 bytes .../templates/images/spinnerIncrement.gif | Bin 0 -> 119 bytes .../templates/images/submenu_disabled.gif | Bin 0 -> 53 bytes .../widget/templates/images/submenu_off.gif | Bin 0 -> 828 bytes .../widget/templates/images/submenu_on.gif | Bin 0 -> 828 bytes .../widget/templates/images/tab_bot_left.gif | Bin 0 -> 296 bytes .../templates/images/tab_bot_left_curr.gif | Bin 0 -> 429 bytes .../widget/templates/images/tab_bot_right.gif | Bin 0 -> 974 bytes .../templates/images/tab_bot_right_curr.gif | Bin 0 -> 1310 bytes .../src/widget/templates/images/tab_close.gif | Bin 0 -> 312 bytes .../widget/templates/images/tab_close_h.gif | Bin 0 -> 313 bytes .../src/widget/templates/images/tab_left.gif | Bin 0 -> 635 bytes .../widget/templates/images/tab_left_r.gif | Bin 0 -> 296 bytes .../templates/images/tab_left_r_curr.gif | Bin 0 -> 429 bytes .../src/widget/templates/images/tab_right.gif | Bin 0 -> 2386 bytes .../widget/templates/images/tab_right_r.gif | Bin 0 -> 974 bytes .../templates/images/tab_right_r_curr.gif | Bin 0 -> 1310 bytes .../widget/templates/images/tab_top_left.gif | Bin 0 -> 2384 bytes .../widget/templates/images/tab_top_right.gif | Bin 0 -> 2386 bytes .../src/widget/templates/images/timeIcon.gif | Bin 0 -> 211 bytes .../widget/templates/images/toolbar-bg.gif | Bin 0 -> 180 bytes .../widget/templates/images/transparent.gif | Bin 0 -> 870 bytes .../templates/images/treenode_blank.gif | Bin 0 -> 834 bytes .../templates/images/treenode_child.gif | Bin 0 -> 73 bytes .../images/treenode_expand_minus.gif | Bin 0 -> 547 bytes .../templates/images/treenode_expand_plus.gif | Bin 0 -> 542 bytes .../templates/images/treenode_grid_c.gif | Bin 0 -> 60 bytes .../templates/images/treenode_grid_l.gif | Bin 0 -> 68 bytes .../templates/images/treenode_grid_p.gif | Bin 0 -> 63 bytes .../templates/images/treenode_grid_t.gif | Bin 0 -> 74 bytes .../templates/images/treenode_grid_v.gif | Bin 0 -> 71 bytes .../templates/images/treenode_grid_x.gif | Bin 0 -> 60 bytes .../templates/images/treenode_grid_y.gif | Bin 0 -> 67 bytes .../templates/images/treenode_grid_z.gif | Bin 0 -> 60 bytes .../widget/templates/images/treenode_node.gif | Bin 0 -> 195 bytes .../widget/templates/images/verticalbar.gif | Bin 0 -> 158 bytes .../templates/images/whiteDownArrow.gif | Bin 0 -> 46 bytes .../src/widget/templates/incrementMonth.gif | Bin 0 -> 168 bytes .../src/widget/templates/incrementWeek.gif | Bin 0 -> 159 bytes .../src/widget/templates/richtextframe.html | 24 + .../static/dojo/src/widget/validate.js | 14 + .../static/dojo/src/widget/vml/Chart.js | 639 + .../struts2/static/dojo/src/xml/Parse.js | 235 + .../static/dojo/src/xml/XslTransform.js | 188 + .../static/dojo/src/xml/__package__.js | 18 + .../struts2/static/dojo/src/xml/svgUtil.js | 32 + .../struts2/static/dojo/storage_dialog.swf | Bin 0 -> 26921 bytes .../struts2/static/dojo/struts/ComboBox.css | 89 + .../apache/struts2/static/dojo/struts/Util.js | 71 + .../struts2/static/dojo/struts/tooltip.gif | Bin 0 -> 324 bytes .../struts2/static/dojo/struts/widget/Bind.js | 308 + .../static/dojo/struts/widget/BindAnchor.js | 42 + .../static/dojo/struts/widget/BindDiv.js | 392 + .../static/dojo/struts/widget/ComboBox.js | 447 + .../dojo/struts/widget/StrutsTimePicker.js | 56 + .../static/dojo/struts/widget/__package__.js | 29 + .../static/dojo/struts/widgets/dateIcon.gif | Bin 0 -> 392 bytes .../dojo/struts/widgets/dropdowncontainer.css | 21 + .../static/dojo/struts/widgets/timeIcon.gif | Bin 0 -> 392 bytes .../struts2/static/inputtransferselect.js | 129 + .../struts2/static/niftycorners/layout.js | 13 + .../struts2/static/niftycorners/nifty.js | 174 + .../static/niftycorners/niftyCorners.css | 21 + .../static/niftycorners/niftyPrint.css | 2 + .../static/niftycorners/niftylayout.css | 57 + .../struts2/static/optiontransferselect.js | 184 + .../org/apache/struts2/static/tabs.css | 100 + .../org/apache/struts2/static/tree.css | 50 + .../apache/struts2/static/validationClient.js | 58 + .../apache/struts2/struts-messages.properties | 32 + .../struts2/struts-messages_da.properties | 32 + .../struts2/struts-messages_de.properties | 32 + .../struts2/struts-messages_pl.properties | 32 + .../struts2/struts-messages_pt.properties | 32 + .../org/apache/struts2/util/package.html | 23 + .../struts2/views/freemarker/package.html | 23 + .../struts2/views/jsp/iterator/package.html | 23 + .../apache/struts2/views/jsp/ui/package.html | 23 + .../struts2/views/jsp/ui/table/package.html | 23 + .../core/src/main/resources/overview.html | 28 + .../core/src/main/resources/struts-2.0.dtd | 141 + .../src/main/resources/struts-default.xml | 268 + .../main/resources/struts-portlet-default.xml | 70 + .../core/src/main/resources/struts.vm | 37 + .../src/main/resources/template/ajax/a.ftl | 26 + .../resources/template/ajax/ajax-common.ftl | 88 + .../resources/template/ajax/autocompleter.ftl | 121 + .../resources/template/ajax/controlheader.ftl | 33 + .../resources/template/ajax/div-close.ftl | 23 + .../src/main/resources/template/ajax/div.ftl | 47 + .../resources/template/ajax/dojoRequire.js | 35 + .../resources/template/ajax/form-close.ftl | 111 + .../src/main/resources/template/ajax/form.ftl | 69 + .../src/main/resources/template/ajax/head.ftl | 28 + .../main/resources/template/ajax/submit.ftl | 63 + .../resources/template/ajax/tab-close.ftl | 23 + .../src/main/resources/template/ajax/tab.ftl | 45 + .../main/resources/template/ajax/textarea.ftl | 67 + .../resources/template/ajax/theme.properties | 20 + .../resources/template/ajax/tree-close.ftl | 23 + .../src/main/resources/template/ajax/tree.ftl | 108 + .../template/ajax/treenode-close.ftl | 23 + .../template/ajax/treenode-include.ftl | 29 + .../main/resources/template/ajax/treenode.ftl | 28 + .../resources/template/ajax/validation.js | 47 + .../template/archive/ajax/a-close.vm | 21 + .../main/resources/template/archive/ajax/a.vm | 33 + .../template/archive/ajax/div-close.vm | 21 + .../resources/template/archive/ajax/div.vm | 35 + .../template/archive/ajax/form-close.vm | 22 + .../resources/template/archive/ajax/form.vm | 39 + .../resources/template/archive/ajax/submit.vm | 33 + .../template/archive/ajax/tab-close.vm | 27 + .../resources/template/archive/ajax/tab.vm | 37 + .../template/archive/simple/checkbox.vm | 30 + .../template/archive/simple/checkboxlist.vm | 45 + .../template/archive/simple/combobox.vm | 43 + .../template/archive/simple/debug.vm | 85 + .../template/archive/simple/doubleselect.vm | 108 + .../template/archive/simple/empty.vm | 20 + .../resources/template/archive/simple/file.vm | 32 + .../template/archive/simple/form-close.vm | 21 + .../resources/template/archive/simple/form.vm | 32 + .../template/archive/simple/hidden.vm | 28 + .../template/archive/simple/label.vm | 26 + .../template/archive/simple/password.vm | 34 + .../template/archive/simple/radiomap.vm | 55 + .../archive/simple/scripting-events.vm | 34 + .../template/archive/simple/select.vm | 63 + .../template/archive/simple/submit.vm | 27 + .../template/archive/simple/table.vm | 101 + .../resources/template/archive/simple/text.vm | 34 + .../template/archive/simple/textarea.vm | 33 + .../template/archive/simple/token.vm | 22 + .../template/archive/xhtml/checkbox.vm | 39 + .../template/archive/xhtml/checkboxlist.vm | 23 + .../template/archive/xhtml/combobox.vm | 21 + .../template/archive/xhtml/controlfooter.vm | 22 + .../template/archive/xhtml/controlheader.vm | 47 + .../resources/template/archive/xhtml/debug.vm | 21 + .../template/archive/xhtml/doubleselect.vm | 21 + .../resources/template/archive/xhtml/empty.vm | 20 + .../resources/template/archive/xhtml/file.vm | 21 + .../template/archive/xhtml/form-close.vm | 22 + .../resources/template/archive/xhtml/form.vm | 28 + .../template/archive/xhtml/hidden.vm | 21 + .../resources/template/archive/xhtml/label.vm | 21 + .../template/archive/xhtml/password.vm | 21 + .../template/archive/xhtml/radiomap.vm | 21 + .../template/archive/xhtml/select.vm | 21 + .../template/archive/xhtml/submit.vm | 23 + .../resources/template/archive/xhtml/table.vm | 21 + .../resources/template/archive/xhtml/text.vm | 21 + .../template/archive/xhtml/textarea.vm | 22 + .../resources/template/archive/xhtml/token.vm | 21 + .../resources/template/css_xhtml/checkbox.ftl | 104 + .../template/css_xhtml/checkboxlist.ftl | 26 + .../resources/template/css_xhtml/combobox.ftl | 26 + .../template/css_xhtml/control-close.ftl | 22 + .../resources/template/css_xhtml/control.ftl | 22 + .../template/css_xhtml/controlfooter.ftl | 30 + .../template/css_xhtml/controlheader-core.ftl | 72 + .../template/css_xhtml/controlheader.ftl | 30 + .../template/css_xhtml/datetimepicker.ftl | 26 + .../resources/template/css_xhtml/debug.ftl | 23 + .../template/css_xhtml/doubleselect.ftl | 26 + .../resources/template/css_xhtml/file.ftl | 26 + .../template/css_xhtml/form-close.ftl | 25 + .../template/css_xhtml/form-validate.ftl | 30 + .../resources/template/css_xhtml/form.ftl | 25 + .../resources/template/css_xhtml/head.ftl | 24 + .../css_xhtml/inputtransferselect.ftl | 26 + .../resources/template/css_xhtml/label.ftl | 47 + .../css_xhtml/optiontransferselect.ftl | 26 + .../resources/template/css_xhtml/password.ftl | 26 + .../resources/template/css_xhtml/radiomap.ftl | 27 + .../resources/template/css_xhtml/reset.ftl | 41 + .../resources/template/css_xhtml/select.ftl | 26 + .../resources/template/css_xhtml/styles.css | 32 + .../resources/template/css_xhtml/submit.ftl | 40 + .../resources/template/css_xhtml/text.ftl | 26 + .../resources/template/css_xhtml/textarea.ftl | 26 + .../template/css_xhtml/theme.properties | 20 + .../template/css_xhtml/updownselect.ftl | 26 + .../template/css_xhtml/validation.js | 90 + .../resources/template/simple/a-close.ftl | 23 + .../src/main/resources/template/simple/a.ftl | 44 + .../resources/template/simple/actionerror.ftl | 38 + .../template/simple/actionmessage.ftl | 38 + .../template/simple/autocompleter.ftl | 131 + .../resources/template/simple/checkbox.ftl | 51 + .../template/simple/checkboxlist.ftl | 55 + .../resources/template/simple/combobox.ftl | 72 + .../template/simple/common-attributes.ftl | 25 + .../template/simple/controlfooter.ftl | 22 + .../template/simple/controlheader.ftl | 22 + .../template/simple/datetimepicker.ftl | 95 + .../main/resources/template/simple/debug.ftl | 81 + .../resources/template/simple/div-close.ftl | 23 + .../main/resources/template/simple/div.ftl | 32 + .../resources/template/simple/dojoRequire.js | 22 + .../template/simple/doubleselect.ftl | 133 + .../main/resources/template/simple/empty.ftl | 22 + .../resources/template/simple/fielderror.ftl | 79 + .../main/resources/template/simple/file.ftl | 54 + .../resources/template/simple/form-close.ftl | 112 + .../main/resources/template/simple/form.ftl | 69 + .../main/resources/template/simple/head.ftl | 35 + .../main/resources/template/simple/hidden.ftl | 37 + .../template/simple/inputtransferselect.ftl | 124 + .../main/resources/template/simple/label.ftl | 44 + .../resources/template/simple/optgroup.ftl | 50 + .../template/simple/optiontransferselect.ftl | 291 + .../resources/template/simple/password.ftl | 57 + .../resources/template/simple/radiomap.ftl | 67 + .../main/resources/template/simple/reset.ftl | 60 + .../template/simple/scripting-events.ftl | 64 + .../main/resources/template/simple/select.ftl | 94 + .../main/resources/template/simple/submit.ftl | 89 + .../resources/template/simple/tab-close.ftl | 23 + .../main/resources/template/simple/tab.ftl | 42 + .../template/simple/tabbedpanel-close.ftl | 23 + .../resources/template/simple/tabbedpanel.ftl | 75 + .../main/resources/template/simple/table.ftl | 76 + .../main/resources/template/simple/text.ftl | 57 + .../resources/template/simple/textarea.ftl | 57 + .../main/resources/template/simple/token.ftl | 24 + .../template/simple/updownselect.ftl | 57 + .../template/xhtml/autocompleter.ftl | 25 + .../resources/template/xhtml/checkbox.ftl | 124 + .../resources/template/xhtml/checkboxlist.ftl | 26 + .../resources/template/xhtml/combobox.ftl | 26 + .../template/xhtml/control-close.ftl | 23 + .../main/resources/template/xhtml/control.ftl | 26 + .../template/xhtml/controlfooter.ftl | 25 + .../template/xhtml/controlheader-core.ftl | 78 + .../template/xhtml/controlheader.ftl | 28 + .../resources/template/xhtml/datepicker.ftl | 26 + .../template/xhtml/datetimepicker.ftl | 26 + .../main/resources/template/xhtml/debug.ftl | 23 + .../resources/template/xhtml/doubleselect.ftl | 26 + .../main/resources/template/xhtml/file.ftl | 25 + .../template/xhtml/form-close-validate.ftl | 121 + .../resources/template/xhtml/form-close.ftl | 25 + .../template/xhtml/form-validate.ftl | 30 + .../main/resources/template/xhtml/form.ftl | 25 + .../main/resources/template/xhtml/head.ftl | 24 + .../template/xhtml/inputtransferselect.ftl | 25 + .../main/resources/template/xhtml/label.ftl | 25 + .../template/xhtml/optiontransferselect.ftl | 25 + .../resources/template/xhtml/password.ftl | 25 + .../resources/template/xhtml/radiomap.ftl | 26 + .../main/resources/template/xhtml/reset.ftl | 31 + .../main/resources/template/xhtml/select.ftl | 25 + .../main/resources/template/xhtml/styles.css | 29 + .../main/resources/template/xhtml/submit.ftl | 31 + .../main/resources/template/xhtml/text.ftl | 25 + .../resources/template/xhtml/textarea.ftl | 25 + .../resources/template/xhtml/theme.properties | 20 + .../resources/template/xhtml/timepicker.ftl | 26 + .../main/resources/template/xhtml/tooltip.ftl | 46 + .../resources/template/xhtml/updownselect.ftl | 25 + .../resources/template/xhtml/validation.js | 103 + .../core/src/site/resources/tags/a.html | 426 + .../core/src/site/resources/tags/action.html | 82 + .../src/site/resources/tags/actionerror.html | 298 + .../site/resources/tags/actionmessage.html | 298 + .../core/src/site/resources/tags/append.html | 42 + .../site/resources/tags/autocompleter.html | 538 + .../core/src/site/resources/tags/bean.html | 50 + .../src/site/resources/tags/checkbox.html | 306 + .../src/site/resources/tags/checkboxlist.html | 322 + .../src/site/resources/tags/combobox.html | 378 + .../src/site/resources/tags/component.html | 298 + .../core/src/site/resources/tags/date.html | 66 + .../src/site/resources/tags/datepicker.html | 362 + .../site/resources/tags/datetimepicker.html | 418 + .../core/src/site/resources/tags/debug.html | 298 + .../core/src/site/resources/tags/div.html | 466 + .../src/site/resources/tags/doubleselect.html | 602 + .../tags/dropdowndatetimepicker.html | 410 + .../core/src/site/resources/tags/else.html | 42 + .../core/src/site/resources/tags/elseif.html | 50 + .../src/site/resources/tags/fielderror.html | 298 + .../core/src/site/resources/tags/file.html | 314 + .../core/src/site/resources/tags/form.html | 386 + .../src/site/resources/tags/generator.html | 74 + .../core/src/site/resources/tags/head.html | 314 + .../core/src/site/resources/tags/hidden.html | 298 + .../core/src/site/resources/tags/i18n.html | 50 + .../core/src/site/resources/tags/if.html | 50 + .../core/src/site/resources/tags/include.html | 50 + .../resources/tags/inputtransferselect.html | 442 + .../src/site/resources/tags/iterator.html | 58 + .../core/src/site/resources/tags/label.html | 306 + .../core/src/site/resources/tags/merge.html | 42 + .../src/site/resources/tags/optgroup.html | 82 + .../resources/tags/optiontransferselect.html | 818 + .../core/src/site/resources/tags/param.html | 58 + .../src/site/resources/tags/password.html | 338 + .../src/site/resources/tags/property.html | 66 + .../core/src/site/resources/tags/push.html | 50 + .../core/src/site/resources/tags/radio.html | 322 + .../core/src/site/resources/tags/reset.html | 330 + .../core/src/site/resources/tags/select.html | 362 + .../core/src/site/resources/tags/set.html | 66 + .../core/src/site/resources/tags/sort.html | 58 + .../core/src/site/resources/tags/submit.html | 458 + .../core/src/site/resources/tags/subset.html | 74 + .../src/site/resources/tags/tabbedPanel.html | 346 + .../core/src/site/resources/tags/table.html | 322 + .../core/src/site/resources/tags/text.html | 50 + .../src/site/resources/tags/textarea.html | 330 + .../src/site/resources/tags/textfield.html | 330 + .../src/site/resources/tags/timepicker.html | 354 + .../core/src/site/resources/tags/token.html | 298 + .../core/src/site/resources/tags/tree.html | 490 + .../src/site/resources/tags/treenode.html | 306 + .../src/site/resources/tags/updownselect.html | 410 + .../core/src/site/resources/tags/url.html | 154 + .../struts2/ExecutionCountTestAction.java | 53 + .../org/apache/struts2/RequestUtilsTest.java | 84 + .../struts2/ServletActionContextTest.java | 76 + .../java/org/apache/struts2/SomeEnum.java | 40 + .../java/org/apache/struts2/TestAction.java | 165 + .../apache/struts2/TestActionTagResult.java | 43 + .../struts2/TestConfigurationProvider.java | 175 + .../struts2/TestNGStrutsTestCaseTest.java | 65 + .../java/org/apache/struts2/TestResult.java | 100 + .../struts2/components/ComponentTest.java | 510 + .../struts2/components/FormButtonTest.java | 124 + .../apache/struts2/components/FormTest.java | 44 + .../struts2/components/PropertyTest.java | 146 + .../apache/struts2/components/UIBeanTest.java | 83 + .../struts2/components/UIComponentTest.java | 544 + .../apache/struts2/components/URLTest.java | 77 + .../template/BaseTemplateEngineTest.java | 86 + .../config/BeanSelectionProviderTest.java | 50 + .../ClasspathConfigurationProviderTest.java | 102 + .../struts2/config/CustomNamespaceAction.java | 26 + .../config/CustomParentPackageAction.java | 26 + .../MethodConfigurationProviderTest.java | 241 + .../apache/struts2/config/SettingsTest.java | 78 + .../apache/struts2/config/TestSettings.java | 53 + .../struts2/config/cltest/ActionImpl.java | 31 + .../config/cltest/OneResultAction.java | 28 + .../config/cltest/TwoResultAction.java | 34 + .../dispatcher/ActionContextCleanUpTest.java | 185 + .../struts2/dispatcher/DispatcherTest.java | 149 + .../dispatcher/FilterDispatcherTest.java | 298 + .../apache/struts2/dispatcher/FilterTest.java | 353 + .../dispatcher/HttpHeaderResultTest.java | 111 + .../struts2/dispatcher/NullActionMapper.java | 51 + .../dispatcher/PlainTextResultTest.java | 157 + .../ServletActionRedirectResultTest.java | 163 + ...ervletDispatchedTestAssertInterceptor.java | 58 + .../ServletDispatcherResultTest.java | 106 + .../dispatcher/ServletRedirectResultTest.java | 137 + .../struts2/dispatcher/SessionMapTest.java | 192 + .../struts2/dispatcher/StreamResultTest.java | 222 + .../dispatcher/StrutsResultSupportTest.java | 123 + .../dispatcher/VelocityResultTest.java | 147 + .../mapper/CompositeActionMapperTest.java | 126 + .../mapper/DefaultActionMapperTest.java | 525 + .../mapper/Restful2ActionMapperTest.java | 198 + .../mapper/RestfulActionMapperTest.java | 118 + .../interceptor/CookieInterceptorTest.java | 345 + .../CreateSessionInterceptorTest.java | 51 + .../ExecuteAndWaitDelayAction.java | 36 + .../ExecuteAndWaitInterceptorTest.java | 239 + .../FileUploadInterceptorTest.java | 258 + .../MessageStoreInterceptorTest.java | 247 + .../interceptor/RolesInterceptorTest.java | 86 + .../ServletConfigInterceptorTest.java | 231 + .../StrutsConversionErrorInterceptorTest.java | 98 + .../interceptor/TokenInterceptorTest.java | 138 + .../TokenSessionStoreInterceptorTest.java | 50 + .../AnnotationValidationInterceptorTest.java | 73 + .../portlet/PortletApplicationMapTest.java | 169 + .../portlet/PortletRequestMapTest.java | 140 + .../portlet/PortletSessionMapTest.java | 157 + .../context/PortletActionContextTest.java | 183 + .../dispatcher/Jsr168DispatcherTest.java | 272 + .../PortletAwareInterceptorTest.java | 67 + .../portlet/result/PortletResultTest.java | 243 + .../portlet/util/PortletUrlHelperTest.java | 159 + .../struts2/portlet/util/StrutsUtilTest.java | 243 + .../apache/struts2/util/ContainUtilTest.java | 121 + .../org/apache/struts2/util/CounterTest.java | 54 + .../util/InvocationSessionStoreTest.java | 91 + .../apache/struts2/util/PrefixTrieTest.java | 41 + .../struts2/util/StrutsTypeConverterTest.java | 110 + .../apache/struts2/util/TokenHelperTest.java | 74 + .../views/TemplateEngineManagerTest.java | 92 + .../freemarker/FreemarkerManagerTest.java | 40 + .../views/freemarker/FreemarkerTest.java | 93 + .../struts2/views/freemarker/TestAction.java | 57 + .../struts2/views/freemarker/TestBean.java | 60 + .../views/freemarker/tags/TagModelTest.java | 426 + .../struts2/views/jsp/AbstractTagTest.java | 138 + .../struts2/views/jsp/AbstractUITagTest.java | 361 + .../struts2/views/jsp/ActionTagTest.java | 260 + .../struts2/views/jsp/AnchorTagTest.java | 132 + .../views/jsp/AppendIteratorTagTest.java | 181 + .../apache/struts2/views/jsp/BeanTagTest.java | 52 + .../struts2/views/jsp/ElseIfTagTest.java | 119 + .../apache/struts2/views/jsp/ElseTagTest.java | 127 + .../apache/struts2/views/jsp/IfTagTest.java | 355 + .../struts2/views/jsp/IncludeTagTest.java | 121 + .../views/jsp/IteratorGeneratorTagTest.java | 218 + .../struts2/views/jsp/IteratorTagTest.java | 426 + .../views/jsp/MergeIteratorTagTest.java | 183 + .../struts2/views/jsp/PortletUrlTagTest.java | 363 + .../struts2/views/jsp/PropertyTagTest.java | 302 + .../apache/struts2/views/jsp/PushTagTest.java | 49 + .../apache/struts2/views/jsp/SetTagTest.java | 123 + .../views/jsp/SortIteratorTagTest.java | 217 + .../views/jsp/StrutsMockBodyContent.java | 162 + .../jsp/StrutsMockHttpServletRequest.java | 209 + .../jsp/StrutsMockHttpServletResponse.java | 98 + .../views/jsp/StrutsMockHttpSession.java | 69 + .../views/jsp/StrutsMockJspWriter.java | 170 + .../views/jsp/StrutsMockPageContext.java | 82 + .../views/jsp/StrutsMockServletContext.java | 170 + .../views/jsp/SubsetIteratorTagTest.java | 294 + .../apache/struts2/views/jsp/TextTagTest.java | 281 + .../apache/struts2/views/jsp/URLTagTest.java | 502 + .../views/jsp/ui/ActionErrorTagTest.java | 96 + .../views/jsp/ui/ActionMessageTagTest.java | 97 + .../struts2/views/jsp/ui/AnchorTest.java | 73 + .../views/jsp/ui/AutocompleterTest.java | 84 + .../apache/struts2/views/jsp/ui/Category.java | 105 + .../views/jsp/ui/CheckboxListTest.java | 186 + .../struts2/views/jsp/ui/CheckboxTest.java | 161 + .../struts2/views/jsp/ui/ComboBoxTest.java | 165 + .../struts2/views/jsp/ui/ComponentTest.java | 116 + .../struts2/views/jsp/ui/DateTagTest.java | 252 + .../views/jsp/ui/DateTimePickerTagTest.java | 69 + .../apache/struts2/views/jsp/ui/DivTest.java | 78 + .../views/jsp/ui/DoubleSelectTest.java | 324 + .../views/jsp/ui/FieldErrorTagTest.java | 245 + .../apache/struts2/views/jsp/ui/FileTest.java | 86 + .../struts2/views/jsp/ui/FormTagTest.java | 590 + .../struts2/views/jsp/ui/HeadTagTest.java | 105 + .../struts2/views/jsp/ui/HiddenTest.java | 83 + .../jsp/ui/InputTransferSelectTagTest.java | 54 + .../struts2/views/jsp/ui/JspTemplateTest.java | 53 + .../struts2/views/jsp/ui/LabelTest.java | 117 + .../apache/struts2/views/jsp/ui/MockTag.java | 128 + .../struts2/views/jsp/ui/OptGroupTest.java | 161 + .../jsp/ui/OptionTransferSelectTagTest.java | 528 + .../struts2/views/jsp/ui/PasswordTest.java | 62 + .../struts2/views/jsp/ui/RadioTest.java | 154 + .../struts2/views/jsp/ui/ResetTest.java | 135 + .../struts2/views/jsp/ui/SelectTest.java | 562 + .../views/jsp/ui/StrutsBodyContent.java | 173 + .../struts2/views/jsp/ui/SubmitAjaxTest.java | 122 + .../struts2/views/jsp/ui/SubmitTest.java | 273 + .../views/jsp/ui/TabbedPanelTagTest.java | 68 + .../struts2/views/jsp/ui/TestAction1.java | 32 + .../struts2/views/jsp/ui/TextareaTest.java | 91 + .../struts2/views/jsp/ui/TextfieldTest.java | 137 + .../struts2/views/jsp/ui/TokenTagTest.java | 98 + .../struts2/views/jsp/ui/TooltipTest.java | 252 + .../apache/struts2/views/jsp/ui/TreeTest.java | 136 + .../views/jsp/ui/UpDownSelectTagTest.java | 275 + .../org/apache/struts2/views/jsp/ui/User.java | 42 + .../struts2/views/util/ContextUtilTest.java | 107 + .../struts2/views/util/ResourceUtilTest.java | 57 + .../struts2/views/util/TextUtilTest.java | 71 + .../struts2/views/util/UrlHelperTest.java | 393 + .../struts2/views/xslt/XSLTResultTest.java | 216 + .../src/test/resources/XSLTResultTest.xsl | 31 + .../src/test/resources/XSLTResultTest2.xsl | 35 + .../src/test/resources/XSLTResultTest3.xsl | 41 + .../src/test/resources/XSLTResultTest4.xsl | 31 + .../core/src/test/resources/log4j.properties | 26 + .../apache/struts2/TestAction-validation.xml | 36 + .../org/apache/struts2/TestAction.properties | 24 + .../components/template/dummy.properties | 19 + .../theme1/themeThroughClassPath.properties | 20 + .../theme1/themeThroughFileSystem.properties | 20 + .../struts2/components/tempo.properties | 19 + .../apache/struts2/dispatcher/someJspFile.jsp | 35 + .../FileUploadInterceptor.properties | 22 + .../org/apache/struts2/othertest.properties | 20 + .../struts2/views/jsp/ui/Autocompleter-1.txt | 21 + .../struts2/views/jsp/ui/Autocompleter-2.txt | 19 + .../struts2/views/jsp/ui/Checkbox-1.txt | 9 + .../struts2/views/jsp/ui/Checkbox-2.txt | 9 + .../struts2/views/jsp/ui/Checkbox-3.txt | 16 + .../struts2/views/jsp/ui/Checkbox-4.txt | 11 + .../struts2/views/jsp/ui/Checkbox-5.txt | 9 + .../struts2/views/jsp/ui/CheckboxList-1.txt | 11 + .../struts2/views/jsp/ui/CheckboxList-2.txt | 11 + .../struts2/views/jsp/ui/CheckboxList-3.txt | 11 + .../struts2/views/jsp/ui/CheckboxList-4.txt | 9 + .../struts2/views/jsp/ui/ComboBox-1.txt | 16 + .../struts2/views/jsp/ui/ComboBox-2.txt | 25 + .../struts2/views/jsp/ui/ComboBox-3.txt | 25 + .../struts2/views/jsp/ui/ComboBox-4.txt | 14 + .../struts2/views/jsp/ui/Component-1.txt | 0 .../struts2/views/jsp/ui/Component-2.txt | 8 + .../struts2/views/jsp/ui/Component-3.txt | 8 + .../struts2/views/jsp/ui/Component-param.txt | 8 + .../views/jsp/ui/DateTimePickerTagTest-1.txt | 23 + .../struts2/views/jsp/ui/DoubleSelect-1.txt | 41 + .../struts2/views/jsp/ui/DoubleSelect-2.txt | 45 + .../struts2/views/jsp/ui/DoubleSelect-3.txt | 41 + .../apache/struts2/views/jsp/ui/File-1.txt | 4 + .../apache/struts2/views/jsp/ui/Formtag-1.txt | 4 + .../struts2/views/jsp/ui/Formtag-10.txt | 4 + .../struts2/views/jsp/ui/Formtag-11.txt | 30 + .../apache/struts2/views/jsp/ui/Formtag-2.txt | 40 + .../apache/struts2/views/jsp/ui/Formtag-3.txt | 4 + .../apache/struts2/views/jsp/ui/Formtag-4.txt | 4 + .../apache/struts2/views/jsp/ui/Formtag-5.txt | 4 + .../apache/struts2/views/jsp/ui/Formtag-6.txt | 29 + .../apache/struts2/views/jsp/ui/Formtag-7.txt | 4 + .../apache/struts2/views/jsp/ui/Formtag-8.txt | 4 + .../apache/struts2/views/jsp/ui/Formtag-9.txt | 4 + .../struts2/views/jsp/ui/HeadTagTest-1.txt | 17 + .../struts2/views/jsp/ui/HeadTagTest-2.txt | 18 + .../struts2/views/jsp/ui/HeadTagTest-3.txt | 18 + .../struts2/views/jsp/ui/HeadTagTest-4.txt | 17 + .../apache/struts2/views/jsp/ui/Hidden-1.txt | 1 + .../apache/struts2/views/jsp/ui/Label-1.txt | 4 + .../apache/struts2/views/jsp/ui/Label-2.txt | 4 + .../apache/struts2/views/jsp/ui/Label-3.txt | 6 + .../struts2/views/jsp/ui/OptGroup-1.txt | 40 + .../struts2/views/jsp/ui/OptGroup-2.txt | 41 + .../struts2/views/jsp/ui/OptGroup-3.txt | 42 + .../struts2/views/jsp/ui/OptGroup-4.txt | 40 + .../struts2/views/jsp/ui/Password-1.txt | 4 + .../apache/struts2/views/jsp/ui/Radio-1.txt | 7 + .../apache/struts2/views/jsp/ui/Radio-2.txt | 7 + .../apache/struts2/views/jsp/ui/Radio-3.txt | 7 + .../apache/struts2/views/jsp/ui/Radio-4.txt | 8 + .../apache/struts2/views/jsp/ui/Reset-1.txt | 3 + .../apache/struts2/views/jsp/ui/Reset-2.txt | 3 + .../apache/struts2/views/jsp/ui/Reset-3.txt | 3 + .../apache/struts2/views/jsp/ui/Reset-4.txt | 3 + .../apache/struts2/views/jsp/ui/Select-1.txt | 9 + .../apache/struts2/views/jsp/ui/Select-10.txt | 7 + .../apache/struts2/views/jsp/ui/Select-11.txt | 9 + .../apache/struts2/views/jsp/ui/Select-12.txt | 8 + .../apache/struts2/views/jsp/ui/Select-13.txt | 7 + .../apache/struts2/views/jsp/ui/Select-2.txt | 8 + .../apache/struts2/views/jsp/ui/Select-3.txt | 8 + .../apache/struts2/views/jsp/ui/Select-4.txt | 5 + .../apache/struts2/views/jsp/ui/Select-5.txt | 8 + .../apache/struts2/views/jsp/ui/Select-6.txt | 8 + .../apache/struts2/views/jsp/ui/Select-7.txt | 9 + .../apache/struts2/views/jsp/ui/Select-8.txt | 10 + .../apache/struts2/views/jsp/ui/Select-9.txt | 9 + .../apache/struts2/views/jsp/ui/Submit-1.txt | 3 + .../apache/struts2/views/jsp/ui/Submit-2.txt | 3 + .../apache/struts2/views/jsp/ui/Submit-3.txt | 3 + .../apache/struts2/views/jsp/ui/Submit-4.txt | 3 + .../apache/struts2/views/jsp/ui/Submit-5.txt | 3 + .../apache/struts2/views/jsp/ui/Submit-6.txt | 3 + .../apache/struts2/views/jsp/ui/Submit-7.txt | 3 + .../struts2/views/jsp/ui/TabbedPanel-1.txt | 9 + .../struts2/views/jsp/ui/TabbedPanel-2.txt | 19 + .../struts2/views/jsp/ui/TabbedPanel-3.txt | 15 + .../struts2/views/jsp/ui/TabbedPanel-4.txt | 10 + .../views/jsp/ui/TestAction1.properties | 1 + .../views/jsp/ui/TestAction1_de.properties | 1 + .../views/jsp/ui/TestAction1_fr.properties | 1 + .../struts2/views/jsp/ui/Textarea-1.txt | 4 + .../struts2/views/jsp/ui/Textfield-1.txt | 4 + .../struts2/views/jsp/ui/Textfield-2.txt | 7 + .../struts2/views/jsp/ui/Textfield-3.txt | 4 + .../struts2/views/jsp/ui/TimePicker-1.txt | 12 + .../struts2/views/jsp/ui/User-validation.xml | 8 + .../struts2/views/jsp/ui/User.properties | 1 + .../struts2/views/jsp/ui/actionerror-1.txt | 0 .../struts2/views/jsp/ui/actionerror-2.txt | 5 + .../struts2/views/jsp/ui/actionmessage-1.txt | 0 .../struts2/views/jsp/ui/actionmessage-2.txt | 5 + .../org/apache/struts2/views/jsp/ui/div-1.txt | 21 + .../struts2/views/jsp/ui/fielderror-1.txt | 5 + .../struts2/views/jsp/ui/fielderror-2.txt | 0 .../struts2/views/jsp/ui/fielderror-3.txt | 4 + .../struts2/views/jsp/ui/fielderror-4.txt | 4 + .../struts2/views/jsp/ui/fielderror-5.txt | 3 + .../apache/struts2/views/jsp/ui/href-1.txt | 16 + .../apache/struts2/views/jsp/ui/href-2.txt | 4 + .../views/jsp/ui/inputtransferselect-1.txt | 23 + .../views/jsp/ui/optiontransferselect-1.txt | 51 + .../views/jsp/ui/optiontransferselect-2.txt | 50 + .../views/jsp/ui/optiontransferselect-3.txt | 49 + .../views/jsp/ui/optiontransferselect-4.txt | 51 + .../views/jsp/ui/optiontransferselect-5.txt | 49 + .../views/jsp/ui/optiontransferselect-6.txt | 50 + .../views/jsp/ui/optiontransferselect-7.txt | 45 + .../struts2/views/jsp/ui/submit-ajax-1.txt | 23 + .../struts2/views/jsp/ui/submit-ajax-2.txt | 22 + .../struts2/views/jsp/ui/submit-ajax-3.txt | 24 + .../apache/struts2/views/jsp/ui/tooltip-1.txt | 22 + .../apache/struts2/views/jsp/ui/tooltip-2.txt | 19 + .../apache/struts2/views/jsp/ui/tooltip-3.txt | 20 + .../apache/struts2/views/jsp/ui/tree-1.txt | 42 + .../apache/struts2/views/jsp/ui/tree-2.txt | 64 + .../views/jsp/ui/updownselecttag-1.txt | 18 + .../views/jsp/ui/updownselecttag-10.txt | 18 + .../views/jsp/ui/updownselecttag-11.txt | 18 + .../views/jsp/ui/updownselecttag-2.txt | 17 + .../views/jsp/ui/updownselecttag-3.txt | 19 + .../views/jsp/ui/updownselecttag-4.txt | 18 + .../views/jsp/ui/updownselecttag-5.txt | 18 + .../views/jsp/ui/updownselecttag-6.txt | 17 + .../views/jsp/ui/updownselecttag-7.txt | 17 + .../views/jsp/ui/updownselecttag-8.txt | 17 + .../views/jsp/ui/updownselecttag-9.txt | 18 + .../core/src/test/resources/struts.properties | 37 + .../core/src/test/resources/struts.xml | 58 + .../resources/template/test/Component.ftl | 31 + .../test/resources/template/test/checkbox.jsp | 34 + .../core/src/test/resources/test.properties | 20 + .../test/resources/testmessages.properties | 21 + .../test/resources/testmessages2.properties | 20 + .../core/src/test/resources/validators.xml | 40 + STRUTS_2_0_X/plugins/codebehind/pom.xml | 86 + .../codebehind/CodebehindUnknownHandler.java | 213 + .../codebehind/src/main/resources/LICENSE.txt | 174 + .../codebehind/src/main/resources/NOTICE.txt | 5 + .../src/main/resources/struts-plugin.xml | 38 + .../CodebehindUnknownHandlerTest.java | 88 + STRUTS_2_0_X/plugins/config-browser/pom.xml | 49 + .../config_browser/ActionNamesAction.java | 90 + .../config_browser/ConfigurationHelper.java | 68 + .../config_browser/ListValidatorsAction.java | 92 + .../config_browser/ShowConfigAction.java | 112 + .../config_browser/ShowValidatorAction.java | 180 + .../src/main/resources/LICENSE.txt | 174 + .../src/main/resources/NOTICE.txt | 5 + .../resources/config-browser/actionNames.ftl | 44 + .../config-browser/config-styles.css | 813 + .../main/resources/config-browser/error.ftl | 28 + .../resources/config-browser/page-footer.ftl | 38 + .../resources/config-browser/page-header.ftl | 66 + .../resources/config-browser/showConfig.ftl | 138 + .../config-browser/showValidators.ftl | 39 + .../resources/config-browser/simple-error.ftl | 24 + .../config-browser/tigris-macros.ftl | 130 + .../config-browser/validatorDetails.ftl | 41 + .../src/main/resources/struts-plugin.xml | 65 + STRUTS_2_0_X/plugins/jasperreports/pom.xml | 50 + .../views/jasperreports/CompileReport.java | 50 + .../jasperreports/JasperReportConstants.java | 59 + .../jasperreports/JasperReportsResult.java | 365 + .../jasperreports/ValueStackDataSource.java | 137 + .../jasperreports/ValueStackShadowMap.java | 93 + .../src/main/resources/LICENSE.txt | 174 + .../src/main/resources/NOTICE.txt | 5 + .../struts2/views/jasperreports/package.html | 23 + .../src/main/resources/struts-plugin.xml | 37 + STRUTS_2_0_X/plugins/jfreechart/pom.xml | 142 + .../struts2/dispatcher/ChartResult.java | 113 + .../jfreechart/src/main/resources/LICENSE.txt | 174 + .../jfreechart/src/main/resources/NOTICE.txt | 5 + .../src/main/resources/struts-plugin.xml | 40 + .../struts2/dispatcher/ChartResultTest.java | 117 + STRUTS_2_0_X/plugins/jsf/pom.xml | 64 + .../jsf/ApplyRequestValuesInterceptor.java | 78 + .../apache/struts2/jsf/FacesInterceptor.java | 109 + .../org/apache/struts2/jsf/FacesRender.java | 79 + .../org/apache/struts2/jsf/FacesResult.java | 83 + .../struts2/jsf/FacesSetupInterceptor.java | 590 + .../org/apache/struts2/jsf/FacesSupport.java | 173 + .../jsf/InvokeApplicationInterceptor.java | 78 + .../jsf/ProcessValidationsInterceptor.java | 77 + .../struts2/jsf/RestoreViewInterceptor.java | 228 + .../struts2/jsf/StrutsNavigationHandler.java | 86 + .../struts2/jsf/StrutsVariableResolver.java | 82 + .../jsf/UpdateModelValuesInterceptor.java | 78 + .../jsf/src/main/resources/LICENSE.txt | 174 + .../plugins/jsf/src/main/resources/NOTICE.txt | 5 + .../org/apache/struts2/jsf/package.html | 31 + .../jsf/src/main/resources/struts-plugin.xml | 60 + STRUTS_2_0_X/plugins/pell-multipart/pom.xml | 50 + .../multipart/PellMultiPartRequest.java | 153 + .../src/main/resources/LICENSE.txt | 174 + .../src/main/resources/NOTICE.txt | 5 + .../src/main/resources/struts-plugin.xml | 31 + STRUTS_2_0_X/plugins/plexus/pom.xml | 49 + .../apache/struts2/plexus/PlexusFilter.java | 115 + .../plexus/PlexusLifecycleListener.java | 115 + .../struts2/plexus/PlexusObjectFactory.java | 303 + .../struts2/plexus/PlexusThreadLocal.java | 44 + .../apache/struts2/plexus/PlexusUtils.java | 53 + .../plexus/src/main/resources/LICENSE.txt | 174 + .../plexus/src/main/resources/NOTICE.txt | 5 + .../src/main/resources/struts-plugin.xml | 34 + STRUTS_2_0_X/plugins/pom.xml | 102 + STRUTS_2_0_X/plugins/sitegraph/pom.xml | 184 + .../main/java/org/apache/struts2/Main.java | 234 + .../apache/struts2/sitegraph/SiteGraph.java | 142 + .../sitegraph/StrutsConfigRetriever.java | 203 + .../sitegraph/entities/FileBasedView.java | 113 + .../sitegraph/entities/FreeMarkerView.java | 40 + .../struts2/sitegraph/entities/JspView.java | 40 + .../struts2/sitegraph/entities/Target.java | 61 + .../sitegraph/entities/VelocityView.java | 40 + .../struts2/sitegraph/entities/View.java | 46 + .../struts2/sitegraph/model/ActionNode.java | 33 + .../apache/struts2/sitegraph/model/Graph.java | 91 + .../struts2/sitegraph/model/IndentWriter.java | 62 + .../apache/struts2/sitegraph/model/Link.java | 94 + .../struts2/sitegraph/model/Render.java | 29 + .../sitegraph/model/SiteGraphNode.java | 67 + .../struts2/sitegraph/model/SubGraph.java | 132 + .../struts2/sitegraph/model/ViewNode.java | 33 + .../sitegraph/renderers/DOTRenderer.java | 260 + .../sitegraph/src/main/resources/LICENSE.txt | 174 + .../sitegraph/src/main/resources/NOTICE.txt | 5 + .../struts2/sitegraph/sitegraph-usage.txt | 7 + .../struts2/sitegraph/SiteGraphTest.java | 62 + .../org/apache/struts2/sitegraph/hello.jsp | 23 + .../org/apache/struts2/sitegraph/out.txt | 32 + .../org/apache/struts2/sitegraph/struts.xml | 60 + .../tutorial/sitegraph/guess-error.ftl | 23 + .../tutorial/sitegraph/guess-input.ftl | 34 + .../tutorial/sitegraph/guess-success.jsp | 23 + STRUTS_2_0_X/plugins/sitemesh/pom.xml | 65 + .../sitemesh/FreeMarkerPageFilter.java | 183 + .../struts2/sitemesh/NoneDecoratorMapper.java | 41 + .../struts2/sitemesh/TemplatePageFilter.java | 186 + .../struts2/sitemesh/VelocityPageFilter.java | 109 + .../sitemesh/src/main/resources/LICENSE.txt | 174 + .../sitemesh/src/main/resources/NOTICE.txt | 5 + .../src/main/resources/struts-plugin.xml | 32 + STRUTS_2_0_X/plugins/spring/pom.xml | 83 + .../spring/StrutsSpringObjectFactory.java | 89 + .../spring/src/main/resources/LICENSE.txt | 174 + .../spring/src/main/resources/NOTICE.txt | 5 + .../src/main/resources/struts-plugin.xml | 41 + .../spring/StrutsSpringObjectFactoryTest.java | 61 + ...ngObjectFactoryTest-applicationContext.xml | 28 + STRUTS_2_0_X/plugins/struts1/pom.xml | 56 + .../s1/ActionFormResetInterceptor.java | 53 + .../s1/ActionFormValidationInterceptor.java | 225 + .../struts2/s1/DynaBeanPropertyAccessor.java | 55 + .../org/apache/struts2/s1/Struts1Action.java | 138 + .../org/apache/struts2/s1/Struts1Factory.java | 149 + .../struts2/s1/WrapperActionForward.java | 56 + .../struts2/s1/WrapperActionMapping.java | 282 + .../struts2/s1/WrapperExceptionConfig.java | 63 + .../struts2/s1/WrapperMessageResources.java | 44 + .../struts2/s1/WrapperModuleConfig.java | 244 + .../struts1/src/main/resources/LICENSE.txt | 174 + .../struts1/src/main/resources/NOTICE.txt | 5 + .../src/main/resources/struts-plugin.xml | 52 + .../s1/DynaBeanPropertyAccessorTest.java | 154 + .../apache/struts2/s1/Struts1FactoryTest.java | 255 + .../apache/struts2/s1/test-struts-factory.xml | 68 + STRUTS_2_0_X/plugins/tiles/pom.xml | 56 + .../tiles/ConfiguredServletContext.java | 185 + .../tiles/StrutsTilesContainerFactory.java | 92 + .../struts2/tiles/StrutsTilesListener.java | 73 + .../tiles/StrutsTilesRequestContext.java | 128 + .../struts2/views/tiles/TilesResult.java | 106 + .../tiles/src/main/resources/LICENSE.txt | 174 + .../tiles/src/main/resources/NOTICE.txt | 5 + .../src/main/resources/struts-plugin.xml | 35 + STRUTS_2_0_X/pom.xml | 435 + STRUTS_2_0_X/src/main/idea/project.xml | 36 + STRUTS_2_0_X/src/main/idea/workspace.xml | 101 + .../src/site/resources/images/download.gif | Bin 0 -> 3782 bytes .../src/site/resources/images/help.gif | Bin 0 -> 4678 bytes .../src/site/resources/images/plugins.gif | Bin 0 -> 3265 bytes .../site/resources/images/struts2-arch.png | Bin 0 -> 19723 bytes .../site/resources/images/struts2-merger.png | Bin 0 -> 37645 bytes .../site/resources/images/struts2-merger2.png | Bin 0 -> 37958 bytes .../src/site/resources/images/struts2.png | Bin 0 -> 10133 bytes STRUTS_2_0_X/src/site/site.xml | 163 + STRUTS_2_0_X/src/site/xdoc/index.xml | 234 + STRUTS_2_0_X/src/site/xdoc/jxr.xml | 38 + 2508 files changed, 269321 insertions(+) create mode 100644 STRUTS_2_0_X/apps/blank/LICENSE.txt create mode 100644 STRUTS_2_0_X/apps/blank/NOTICE.txt create mode 100644 STRUTS_2_0_X/apps/blank/README.txt create mode 100644 STRUTS_2_0_X/apps/blank/pom.xml create mode 100644 STRUTS_2_0_X/apps/blank/src/main/java/example/ExampleSupport.java create mode 100644 STRUTS_2_0_X/apps/blank/src/main/java/example/HelloWorld.java create mode 100644 STRUTS_2_0_X/apps/blank/src/main/java/example/Login.java create mode 100644 STRUTS_2_0_X/apps/blank/src/main/java/example/build.bat create mode 100644 STRUTS_2_0_X/apps/blank/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/apps/blank/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/apps/blank/src/main/resources/example.xml create mode 100644 STRUTS_2_0_X/apps/blank/src/main/resources/example/Login-validation.xml create mode 100644 STRUTS_2_0_X/apps/blank/src/main/resources/example/package.properties create mode 100644 STRUTS_2_0_X/apps/blank/src/main/resources/example/package_es.properties create mode 100644 STRUTS_2_0_X/apps/blank/src/main/resources/struts.xml create mode 100644 STRUTS_2_0_X/apps/blank/src/main/webapp/WEB-INF/web.xml create mode 100644 STRUTS_2_0_X/apps/blank/src/main/webapp/example/HelloWorld.jsp create mode 100644 STRUTS_2_0_X/apps/blank/src/main/webapp/example/Login.jsp create mode 100644 STRUTS_2_0_X/apps/blank/src/main/webapp/example/Menu.jsp create mode 100644 STRUTS_2_0_X/apps/blank/src/main/webapp/example/Missing.jsp create mode 100644 STRUTS_2_0_X/apps/blank/src/main/webapp/example/Register.jsp create mode 100644 STRUTS_2_0_X/apps/blank/src/main/webapp/example/Welcome.jsp create mode 100644 STRUTS_2_0_X/apps/blank/src/main/webapp/index.html create mode 100644 STRUTS_2_0_X/apps/blank/src/test/java/example/ConfigTest.java create mode 100644 STRUTS_2_0_X/apps/blank/src/test/java/example/HelloWorldTest.java create mode 100644 STRUTS_2_0_X/apps/blank/src/test/java/example/LoginTest.java create mode 100644 STRUTS_2_0_X/apps/mailreader/README.txt create mode 100644 STRUTS_2_0_X/apps/mailreader/pom.xml create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/alternate.properties create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/alternate_ja.properties create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader-default.xml create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader-support.xml create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/ApplicationListener.java create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/AuthenticationInterceptor.java create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Constants.java create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Login-validation.xml create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Login.java create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Logout.java create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.java create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.properties create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport_ja.properties create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport_ru.properties create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration-Registration_save-validation.xml create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration-validation.xml create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration.java create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription-Subscription_save-validation.xml create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription-validation.xml create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription.java create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Welcome.java create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/java/struts.xml create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/webapp/ChangePassword.jsp create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/webapp/Error.jsp create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/webapp/Footer.jsp create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/webapp/Login.jsp create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/webapp/META-INF/context.xml create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/webapp/MainMenu.jsp create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/webapp/Registration.jsp create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/webapp/Subscription.jsp create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/webapp/WEB-INF/database.xml create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/webapp/WEB-INF/web.xml create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/webapp/Welcome.jsp create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/webapp/css/mailreader.css create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/webapp/index.html create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/webapp/struts-power.gif create mode 100644 STRUTS_2_0_X/apps/mailreader/src/main/webapp/tour.html create mode 100644 STRUTS_2_0_X/apps/pom.xml create mode 100644 STRUTS_2_0_X/apps/portlet/README.txt create mode 100644 STRUTS_2_0_X/apps/portlet/pom.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/exo/web.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/README-gridsphere.txt create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/gridsphere-portlet.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/group.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/layout.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/struts-portlet create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/web.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-app.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-portlet.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-web.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/portlet-instances.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/struts-portlet-pages.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-app.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-portlet.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-web.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/struts-portlet-object.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/jetspeed2/README-jetspeed2.txt create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/jetspeed2/struts-portlet.psml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/etc/liferay3.6.1/web.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/ExampleAction.java create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExample.java create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExampleModelDriven.java create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExampleWithValidation.java create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormResultAction.java create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormTestAction.java create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/SavePrefsAction.java create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/fileupload/FileUploadAction.java create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/model/Name.java create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/spring/SpringAction.java create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/spring/ThingManager.java create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/resources/log4j.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/resources/org/apache/struts2/portlet/example/FormExample-processValidationExample-validation.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/resources/struts-edit.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/resources/struts-help.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/resources/struts-view.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/resources/struts.properties create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/resources/struts.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/resources/template/xhtml/components/checkbox.vm create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/resources/template/xhtml/components/datefield.vm create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/resources/template/xhtml/components/mytextfield.vm create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/resources/validators.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/applicationContext.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/dwr.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/defaultEdit.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/formExample.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/formExampleInput.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/index.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/namespaceTest.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/prefsForm.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/prefsSaved.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/test.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/help/defaultHelp.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/help/index.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/portlet.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/readme.txt create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajax.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajaxData.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajaxExample.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/fileUpload.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/fileUploadSuccess.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExample.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInput.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInputModelDriven.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInputPrg.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInputValidation.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/freeMarkerExample.ftl create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/freeMarkerExampleInput.ftl create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/helloWorld.vm create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/index.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/notImplemented.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/springExample.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/tokenExample.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/tokenExampleInput.jsp create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/web.xml create mode 100644 STRUTS_2_0_X/apps/portlet/src/main/webapp/styles/styles.css create mode 100644 STRUTS_2_0_X/apps/showcase/README.txt create mode 100644 STRUTS_2_0_X/apps/showcase/pom.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/DateAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/DynamicTreeSelectAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfOptiontransferselectAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfRichtexteditorAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/MoreSelectsAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ShowDynamicTreeAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/UITagExample.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/AbstractCRUDAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/EmployeeAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/SkillAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain1.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain2.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain3.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AjaxTestAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AutocompleterExampleAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example4ShowPanelAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example5Action.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Category.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/GetCategory.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Toggle.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/MemoryStorage.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/Storage.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/TestDataProvider.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatAuthenticationInterceptor.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatException.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatInterceptor.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLoginAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLogoutAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatMessage.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatService.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatServiceImpl.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatSessionListener.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/Constants.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/CrudRoomAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/DateConverter.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/EnterRoomAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ExitRoomAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/MessagesAvailableInRoomAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/Room.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/RoomsAvailableAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/SendMessageToRoomAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/User.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableInRoomAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/Address.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/AddressAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/EnumTypeConverter.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnum.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnumAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/Person.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/PersonAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/AbstractDao.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/Dao.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/EmployeeDao.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/SkillDao.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/CreateException.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/DeleteException.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/DuplicateKeyException.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/StorageException.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/UpdateException.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/filedownload/FileDownloadAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/FileUploadAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingArrayAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManager.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManagerUtil.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/StandardTagsAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GetUpdatedHangmanAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GuessCharacterAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Hangman.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanConstants.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanException.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanService.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/PropertiesVocabSource.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/StartHangmanAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Vocab.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/VocabSource.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/EditGangsterAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/GangsterForm.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/SaveGangsterAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/jsf/JsfEmployeeAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Employee.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/IdEntity.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Skill.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/Gangster.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/ModelDrivenAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/Person.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/PersonManager.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/source/ViewSourceAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actionPrefix/SubmitAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actiontag/ActionTagDemo.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/AppendIteratorTagDemo.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/MergeIteratorTagDemo.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/SubsetIteratorTagDemo.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/token/TokenAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AbstractValidationActionSupport.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/QuizAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/SubmitApplication.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/User.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/LongProcessAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/xslt/JVMAction.java create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/globalMessages.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/globalMessages_de.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/log4j.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/myTemplateDir/myTheme/myAnotherTemplate.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/DateAction.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/LotsOfRichtexteditorAction-lotsOfRichtexteditorSubmit-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/UITagExample-conversion.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-conversion.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction_de.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction_de.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/ajax/Example5Action-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/ChatLoginAction-chatLogin-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/ChatMessage-conversion.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/CrudRoomAction-createRoom-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/Room-conversion.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/SendMessageToRoomAction-sendMessageToRoom-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/AddressAction-conversion.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/OperationsEnumAction-conversion.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/PersonAction-conversion.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/FileUploadAction-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction-conversion.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/EditPersonAction-conversion.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/Person-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-conversion.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitClientSideValidationExample-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitFieldValidatorsExamples-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.properties create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction-submitNonFieldValidatorsExamples-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/QuizAction-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/SubmitApplication-submitApplication-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/User-userContext-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction-submitVisitorValidatorsExamples-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-actionchaining.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-ajax.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-chat.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-conversion.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-filedownload.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-fileupload.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-freemarker.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-hangman.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-integration.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-jsf.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-model-driven.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-person.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tags-non-ui.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tags-ui.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tags.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tiles.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-token.xml create mode 100755 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-wait.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts-xslt.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/resources/struts.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/applicationContext.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/decorators.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/dwr.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/sitemesh-decorator.tld create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/sitemesh-page.tld create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/sitemesh.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/tiles.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/validation.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/web.xml create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/actionchaining/actionChainingResult.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/AjaxResult.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/AjaxResult2.js create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/AjaxResult3.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/JSONList.js create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/autocompleter/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/commonInclude.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/footer.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/options.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotebutton/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example1.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example10.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example2.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example3.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example4.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example5.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example6.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example7.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example8.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example9.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/test1.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/test2.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/test3.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotelink/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example1.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example2.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example3.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example4.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example5.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example5Ok.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel1.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel2.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel2Submit.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel3.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel3Submit.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/testjs.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/getCategory.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/partialChunkHeader.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/toggle.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/tree.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/widgets/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/chatLogin.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/createRoom.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/messagesAvailableInRoom.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/roomSelection.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/roomsAvailable.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/sendMessageToRoomResult.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/showRoom.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/usersAvailable.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/usersAvailableInRoom.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/Address.java.txt create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/AddressAction.java.txt create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/EnumTypeConverter.java.txt create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnum.java.txt create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnumAction.java.txt create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnumActionConversion.txt create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/Person.java.txt create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/PersonAction.java.txt create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterAddressInfo.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterOperations.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterPersonInfo.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showAddressInfo.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showOperations.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showPersonInfo.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/customTemplateDir/customTheme/ftlCustomTemplate.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/customTemplateDir/customTheme/jspCustomTemplate.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/date.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/editEmployee.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/editSkill.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/listEmployees.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/listSkills.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/filedownload/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingArray-success.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingArray.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingList-success.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingList.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/upload-success.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/upload.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/customFreemarkerManagerUsage.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/standardTags.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/blank.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/hangmanAjax.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/hangmanMenu.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/hangmanNonAjax.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_0.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_1.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_2.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_3.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_4.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_5.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_A.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_B.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_C.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_D.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_E.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_F.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_G.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_H.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_I.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_J.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_K.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_L.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_M.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_N.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_O.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_P.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_Q.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_R.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_S.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_T.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_U.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_V.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_W.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_X.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_Y.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_Z.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_underscroll.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/choose.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/guess.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/guesses-left.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/hangman.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/letter-spacer.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/play-again.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/scaffold_-1.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/scaffold_0.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/scaffold_1.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/scaffold_2.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/scaffold_3.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/scaffold_4.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/scaffold_5.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/start.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/you-lose.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/you-win.png create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/test.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateCharacterAvailable.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateGuessLeft.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateScaffold.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateVocabCharacters.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/help.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/images/indicator.gif create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/images/struts-gif.zip create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/images/struts-power.gif create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/images/struts.gif create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/integration/modelDriven.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/integration/modelDrivenResult.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/jsf/employee/edit.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/jsf/employee/list.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/jsf/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/modelDriven/modelDriven.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/modelDriven/modelDrivenResult.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/person/editPerson.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/person/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/person/listPeople.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/person/newPerson.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/showcase.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/forms.css create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/layout-navtop-1col.css create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/layout-navtop-localleft.css create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/layout.css create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/main.css create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/nav-horizontal.css create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/tools.css create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/typo.css create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/actionPrefix.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/actionPrefixExample.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/methodPrefix.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/normalSubmit.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/redirectActionPrefix.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/includedPage.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/includedPage2.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/includedPage3.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/showActionTagDemo.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/date.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/debug.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/ifTag/testIf.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/ifTag/testIf.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/appendIteratorTagDemoResult.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/iteratorGeneratorTagDemoResult.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/mergeIteratorTagDemoResult.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/showAppendIteratorTagDemo.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/showIteratorGeneratorTagDemo.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/showMergeIteratorTagDemo.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/subsetIteratorTagDemo.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/subsetIteratorTagDemoResult.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/componentTagExample.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/datepicker/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/dynamicTreeSelect.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/example.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/example.vm create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/exampleSubmited.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/exampleSubmited.vm create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/images/backgroundImage.jpg create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/images/leopard.jpg create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselect.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselectSubmit.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/moreSelects.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/moreSelectsSubmit.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/staticTreeSelect.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/timepicker/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/treeExampleDynamic.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/treeExampleStatic.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/template/xhtml/mytemplate.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/body.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/body.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/header.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/layout.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/layout.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/token/doublePost.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example1.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example2.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example3.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example4.ftl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/token/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/token/transferDone.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/clientSideValidationExample.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/fieldValidatorsExample.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/footer.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/nonFieldValidatorsExample.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-ajax.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-basic.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-client-css.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-client.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-success.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/storeErrorsAcrossRequestCancel.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/storeErrorsAcrossRequestExample.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/storeErrorsAcrossRequestOk.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successClientSideValidationExample.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successFieldValidatorsExample.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successNonFieldValidatorsExample.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successVisitorValidatorsExample.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/validationExamplesStyles.css create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/visitorValidatorsExample.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/viewSource.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/complete.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/example1.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/example2.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/example3.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/index.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/wait.jsp create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/xslt/environment.xsl create mode 100644 STRUTS_2_0_X/apps/showcase/src/main/webapp/xslt/index.jsp create mode 100644 STRUTS_2_0_X/assembly/pom.xml create mode 100644 STRUTS_2_0_X/assembly/src/main/assembly/all.xml create mode 100644 STRUTS_2_0_X/assembly/src/main/assembly/apps.xml create mode 100644 STRUTS_2_0_X/assembly/src/main/assembly/docs.xml create mode 100644 STRUTS_2_0_X/assembly/src/main/assembly/lib-jdk14.xml create mode 100644 STRUTS_2_0_X/assembly/src/main/assembly/lib.xml create mode 100644 STRUTS_2_0_X/assembly/src/main/assembly/src.xml create mode 100644 STRUTS_2_0_X/assembly/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/assembly/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/assembly/src/main/resources/backport/NOTICE.txt create mode 100644 STRUTS_2_0_X/assembly/src/main/resources/backport/RETROTRANSLATOR-LICENSE.txt create mode 100644 STRUTS_2_0_X/assembly/src/main/resources/build.xml create mode 100755 STRUTS_2_0_X/backport/ASM-LICENSE.txt create mode 100644 STRUTS_2_0_X/backport/LICENSE.txt create mode 100755 STRUTS_2_0_X/backport/RETROTRANSLATOR-LICENSE.txt create mode 100755 STRUTS_2_0_X/backport/S2-FOR-J4-README.txt create mode 100755 STRUTS_2_0_X/backport/STRUTS-LICENSE.txt create mode 100755 STRUTS_2_0_X/backport/XWORK-LICENSE.txt create mode 100755 STRUTS_2_0_X/backport/backport-util-concurrent-3.0.jar create mode 100644 STRUTS_2_0_X/backport/readme.html create mode 100644 STRUTS_2_0_X/backport/retrotranslator-runtime-1.2.2.jar create mode 100644 STRUTS_2_0_X/backport/retrotranslator-transformer-1.2.2.jar create mode 100644 STRUTS_2_0_X/backport/translate.bat create mode 100755 STRUTS_2_0_X/backport/translate.sh create mode 100644 STRUTS_2_0_X/core/pom.xml create mode 100644 STRUTS_2_0_X/core/src/main/etc/taglib-settings.xml create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/RequestUtils.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/ServletActionContext.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsConstants.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsException.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsStatics.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsTestCase.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/TestNGStrutsTestCase.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/AbstractRemoteCallUIBean.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ActionComponent.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ActionError.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ActionMessage.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Anchor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/AppendIterator.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Autocompleter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Bean.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Checkbox.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/CheckboxList.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ClosingUIBean.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ComboBox.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Component.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Date.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/DateTimePicker.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Debug.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Div.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/DoubleListUIBean.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/DoubleSelect.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Else.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ElseIf.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/FieldError.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/File.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Form.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/FormButton.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/GenericUIBean.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Head.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Hidden.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/I18n.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/If.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Include.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/InputTransferSelect.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/IteratorComponent.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Label.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ListUIBean.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/MergeIterator.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/OptGroup.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/OptionTransferSelect.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Param.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Password.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Property.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Push.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Radio.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/RemoteUICallBean.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Reset.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Select.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Set.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Submit.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TabbedPanel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Text.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TextArea.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TextField.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Token.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Tree.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TreeNode.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/UIBean.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/URL.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/UpDownSelect.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/AbstractFilterModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/RenderFilterModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/SortFilterModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/SortableTableModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/WebTable.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/WebTableColumn.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/AbstractCellRenderer.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/BooleanCellRenderer.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/CellRenderer.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/DateCellRenderer.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/DefaultCellRenderer.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/FixedTextCellRenderer.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/LinkCellRenderer.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/NumericCellRenderer.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/package.html create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/template/BaseTemplateEngine.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/template/JspTemplateEngine.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/template/Template.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/template/TemplateEngine.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/template/TemplateEngineManager.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/template/TemplateRenderingContext.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/template/VelocityTemplateEngine.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/BeanSelectionProvider.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/ClasspathConfigurationProvider.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/DefaultPropertiesProvider.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/DefaultSettings.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/DelegatingSettings.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/LegacyPropertiesConfigurationProvider.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/MethodConfigurationProvider.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/Namespace.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/NullResult.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/ParentPackage.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/PropertiesSettings.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/Result.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/Results.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/ServletContextSingleton.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/Settings.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/StrutsXmlConfigurationProvider.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/config/package.html create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/ActionContextCleanUp.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/ApplicationMap.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/DefaultActionSupport.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/DispatcherListener.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcher.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/FilterDispatcherCompatWeblogic61.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/HttpHeaderResult.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/PlainTextResult.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/RequestMap.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/ServletActionRedirectResult.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/ServletDispatcherResult.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/ServletRedirectResult.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/SessionMap.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/StreamResult.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/StrutsRequestWrapper.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/StrutsResultSupport.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/VelocityResult.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/mapper/ActionMapper.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/mapper/ActionMapping.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/mapper/CompositeActionMapper.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapper.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/mapper/Restful2ActionMapper.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/mapper/RestfulActionMapper.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/multipart/JakartaMultiPartRequest.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/multipart/MultiPartRequest.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/multipart/MultiPartRequestWrapper.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/multipart/package.html create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/dispatcher/package.html create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/impl/StrutsActionProxy.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/impl/StrutsActionProxyFactory.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/impl/StrutsObjectFactory.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/ApplicationAware.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/BackgroundProcess.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/CheckboxInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/CookieInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/CookiesAware.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/CreateSessionInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/ExecuteAndWaitInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/FileUploadInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/MessageStoreInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/NoParameters.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/ParameterAware.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/PrincipalAware.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/PrincipalProxy.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/ProfilingActivationInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/RequestAware.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/RolesInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/ScopeInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/ServletConfigInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/ServletRequestAware.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/ServletResponseAware.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/SessionAware.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/StrutsConversionErrorInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/TokenInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/TokenSessionStoreInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/debugging/DebuggingInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/debugging/PrettyPrintWriter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/validation/AnnotationValidationInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/interceptor/validation/SkipValidation.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/PortletActionConstants.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/PortletApplicationMap.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/PortletRequestMap.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/PortletSessionMap.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/context/PortletActionContext.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/dispatcher/DirectRenderFromEventAction.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/dispatcher/Jsr168Dispatcher.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/interceptor/PortletAwareInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/interceptor/PortletContextAware.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/interceptor/PortletPreferencesAware.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/interceptor/PortletPreferencesInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/interceptor/PortletPrincipalProxy.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/interceptor/PortletRequestAware.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/interceptor/PortletResponseAware.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/interceptor/PortletStateInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/interceptor/ServletPortletPreferences.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/result/PortletActionRedirectResult.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/result/PortletResult.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/result/PortletVelocityResult.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/servlet/PortletHttpSession.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/servlet/PortletServletConfig.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/servlet/PortletServletContext.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/servlet/PortletServletInputStream.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/servlet/PortletServletOutputStream.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/servlet/PortletServletRequest.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/servlet/PortletServletRequestDispatcher.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/servlet/PortletServletResponse.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/servlet/package.html create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/portlet/util/PortletUrlHelper.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/servlet/interceptor/ServletPrincipalProxy.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/AppendIteratorFilter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/AttributeMap.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/ClassLoaderUtils.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/ContainUtil.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/Counter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/DateFormatter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/FastByteArrayOutputStream.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/InvocationSessionStore.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/IteratorFilterSupport.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/IteratorGenerator.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/ListEntry.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/MakeIterator.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/MergeIteratorFilter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/ObjectFactoryDestroyable.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/PrefixTrie.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/ServletContextAware.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/SortIteratorFilter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/Sorter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/StrutsTestCaseHelper.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/StrutsTypeConverter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/StrutsUtil.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/SubsetIteratorFilter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/TabbedPane.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/Timer.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/TokenHelper.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/URLBean.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/util/VelocityStrutsUtil.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/validators/DWRValidator.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/DefaultTagLibrary.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/JspSupportServlet.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/TagLibrary.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/annotations/StrutsTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/annotations/StrutsTagAttribute.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerManager.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/FreemarkerResult.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/PortletFreemarkerResult.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/ScopesHashModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/StrutsBeanWrapper.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/StrutsClassTemplateLoader.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/ActionErrorModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/ActionMessageModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/ActionModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/AnchorModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/AutocompleterModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/BeanModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/CallbackWriter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/CheckboxListModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/CheckboxModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/ComboBoxModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/ComponentModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/DateModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/DateTimePickerModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/DivModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/DoubleSelectModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/ElseIfModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/ElseModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/FieldErrorModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/FileModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/FormModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/HeadModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/HiddenModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/I18nModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/IfModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/IncludeModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/InputTransferSelectModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/IteratorModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/LabelModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/OptGroupModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/OptionTransferSelectModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/ParamModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/PasswordModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/PropertyModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/PushModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/RadioModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/ResetModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/SelectModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/SetModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/StrutsModels.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/SubmitModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/TabbedPanelModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/TagModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/TextAreaModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/TextFieldModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/TextModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/TokenModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/TreeModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/TreeNodeModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/URLModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/UpDownSelectModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/freemarker/tags/WebTableModel.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ActionTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/BeanTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ComponentTagSupport.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/DateTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ElseIfTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ElseTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/I18nTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/IfTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/IncludeTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/IteratorStatus.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/IteratorTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ParamTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/PropertyTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/PushTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/SetTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/StrutsBodyTagSupport.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/TagUtils.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/TextTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/URLTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/iterator/AppendIteratorTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/iterator/IteratorGeneratorTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/iterator/MergeIteratorTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/iterator/SortIteratorTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/iterator/SubsetIteratorTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/package.html create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractClosingTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractDoubleListTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractListTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractRemoteCallUITag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractRequiredListTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/AbstractUITag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/ActionErrorTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/ActionMessageTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/AnchorTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/AutocompleterTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/CheckboxListTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/CheckboxTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/ComboBoxTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/ComponentTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/DateTimePickerTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/DebugTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/DivTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/DoubleSelectTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/FieldErrorTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/FileTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/FormTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/HeadTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/HiddenTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/LabelTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/OgnlTool.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/OptGroupTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/PasswordTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/RadioTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/ResetTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/SelectTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/SubmitTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/TabbedPanelTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/TextFieldTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/TextareaTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/TokenTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/TreeNodeTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/TreeTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/UpDownSelectTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/jsp/ui/table/WebTableTag.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/util/ContextUtil.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/util/ResourceUtil.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/util/TextUtil.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/util/UrlHelper.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/util/package.html create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/StrutsResourceLoader.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/StrutsVelocityContext.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/VelocityManager.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/AbstractDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/ActionDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/ActionErrorDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/ActionMessageDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/AnchorDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/AutocompleterDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/BeanDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/CheckBoxDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/CheckBoxListDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/ComboBoxDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/ComponentDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/DateDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/DateTimePickerDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/DivDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/DoubleSelectDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/FieldErrorDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/FileDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/FormDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/HeadDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/HiddenDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/I18nDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/IncludeDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/InputTransferSelectDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/LabelDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/OptGroupDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/OptionTransferSelectDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/ParamDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/PasswordDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/PropertyDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/PushDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/RadioDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/ResetDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/SelectDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/SetDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/SubmitDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/TabbedPanelDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/TextAreaDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/TextDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/TextFieldDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/TokenDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/TreeDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/TreeNodeDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/URLDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/UpDownSelectDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/components/WebTableDirective.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/velocity/package.html create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/AbstractAdapterElement.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/AbstractAdapterNode.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/AdapterFactory.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/AdapterNode.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/ArrayAdapter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/BeanAdapter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/CollectionAdapter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/MapAdapter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/ProxyAttrAdapter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/ProxyElementAdapter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/ProxyNamedNodeMap.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/ProxyNodeAdapter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/ProxyTextNodeAdapter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/ServletURIResolver.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/SimpleAdapterDocument.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/SimpleNodeList.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/SimpleTextNode.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/StringAdapter.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/XSLTResult.java create mode 100644 STRUTS_2_0_X/core/src/main/java/org/apache/struts2/views/xslt/package.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/core/src/main/resources/META-INF/README.txt create mode 100644 STRUTS_2_0_X/core/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/default.properties create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/dispatcher/error.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/interceptor/debugging/console.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/interceptor/debugging/webconsole.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/interceptor/debugging/webconsole.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/interceptor/debugging/webconsole.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/interceptor/package.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/interceptor/wait.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/package.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/CommonFunctions.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/LICENSE create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/README create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/Storage_version6.swf create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/Storage_version8.swf create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/build.txt create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/dojo.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/dojo.js.uncompressed.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/flash6_gateway.swf create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/iframe_history.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/AdapterRegistry.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/Deferred.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/DeferredList.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/a11y.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/animation.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/animation/Animation.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/animation/AnimationEvent.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/animation/AnimationSequence.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/animation/Timer.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/animation/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/behavior.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/bootstrap1.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/bootstrap2.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/browser_debug.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/cal/iCalendar.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/cal/textDirectory.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/charting/Axis.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/charting/Chart.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/charting/Plot.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/charting/PlotArea.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/charting/Plotters.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/charting/README.txt create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/charting/Series.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/charting/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/charting/svg/Axis.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/charting/svg/PlotArea.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/charting/svg/Plotters.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/charting/vml/Axis.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/charting/vml/PlotArea.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/charting/vml/Plotters.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/collections/ArrayList.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/collections/BinaryTree.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/collections/Collections.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/collections/Dictionary.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/collections/Graph.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/collections/Queue.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/collections/Set.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/collections/SkipList.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/collections/SortedList.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/collections/Stack.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/collections/Store.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/collections/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/crypto.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/crypto/Blowfish.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/crypto/LICENSE create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/crypto/MD5.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/crypto/Rijndael.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/crypto/SHA1.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/crypto/SHA256.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/crypto/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/Read.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/Result.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/Write.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/csv/CsvStore.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/csv/Result.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/csv/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/Attribute.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/Item.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/Kind.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/Observable.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/ResultSet.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/Type.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/Value.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/format/Csv.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/format/Json.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/provider/Base.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/provider/Delicious.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/provider/FlatFile.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/provider/JotSpot.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/provider/MySql.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/data/old/to_do.txt create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/date.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/date/common.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/date/format.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/date/serialize.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/date/supplemental.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/debug.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/debug/Firebug.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/debug/arrow_hide.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/debug/arrow_show.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/debug/console.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/debug/deep.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/debug/spacer.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/dnd/DragAndDrop.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/dnd/HtmlDragAndDrop.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/dnd/HtmlDragCopy.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/dnd/HtmlDragManager.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/dnd/HtmlDragMove.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/dnd/Sortable.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/dnd/TreeDragAndDrop.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/dnd/TreeDragAndDropV3.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/dnd/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/docs.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/dom.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/event.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/event/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/event/browser.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/event/common.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/event/topic.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/experimental.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/flash.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/flash/flash6/DojoExternalInterface.as create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/flash/flash6/flash6_gateway.fla create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/flash/flash8/DojoExternalInterface.as create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/flash/flash8/ExpressInstall.as create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/fx/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/fx/html.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/fx/svg.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/gfx/Colorspace.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/gfx/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/gfx/color.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/gfx/color/hsl.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/gfx/color/hsv.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/gfx/common.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/gfx/matrix.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/gfx/path.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/gfx/shape.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/gfx/svg.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/gfx/vml.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/graphics/Colorspace.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/graphics/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/graphics/color.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/graphics/color/hsl.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/graphics/color/hsv.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/hostenv_adobesvg.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/hostenv_browser.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/hostenv_dashboard.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/hostenv_jsc.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/hostenv_rhino.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/hostenv_spidermonkey.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/hostenv_svg.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/hostenv_wsh.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/color.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/common.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/display.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/iframe.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/images/shadowB.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/images/shadowBL.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/images/shadowBR.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/images/shadowL.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/images/shadowR.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/images/shadowT.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/images/shadowTL.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/images/shadowTR.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/layout.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/metrics.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/selection.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/shadow.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/style.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/html/util.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/README create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/de/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/en/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/es/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/fi/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/fr/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/gregorianExtras.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/hu/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/it/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/ja/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/ja/gregorianExtras.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/ko/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/nl/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/pt-br/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/pt/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/sv/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/zh-cn/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/zh-hk/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/zh-tw/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/zh/gregorian.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/calendar/nls/zh/gregorianExtras.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/common.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/common.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/EUR.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/GBP.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/INR.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/ITL.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/JPY.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/README create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/USD.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/en-us/USD.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/en/EUR.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/en/GBP.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/en/INR.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/en/ITL.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/en/JPY.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/en/USD.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/hi/EUR.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/hi/GBP.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/hi/INR.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/hi/ITL.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/hi/JPY.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/hi/USD.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/ja/EUR.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/ja/GBP.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/ja/INR.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/ja/ITL.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/ja/JPY.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/currency/nls/ja/USD.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/i18n/number.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/iCalendar.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/io.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/io/BrowserIO.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/io/IframeIO.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/io/RepubsubIO.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/io/RhinoIO.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/io/ScriptSrcIO.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/io/XhrIframeProxy.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/io/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/io/cometd.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/io/common.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/io/cookie.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/io/xip_client.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/io/xip_server.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/json.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lang.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lang/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lang/array.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lang/assert.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lang/common.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lang/declare.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lang/extras.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lang/func.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lang/repr.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lang/timing/Streamer.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lang/timing/Timer.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lang/timing/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lang/type.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lfx/Animation.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lfx/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lfx/extras.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lfx/html.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lfx/rounded.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lfx/shadow.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/lfx/toggle.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/loader.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/loader_xd.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/logging/ConsoleLogger.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/logging/Logger.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/logging/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/math.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/math/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/math/curves.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/math/matrix.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/math/points.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/namespaces/dojo.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/ns.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/profile.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/regexp.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/rpc/Deferred.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/rpc/JotService.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/rpc/JsonService.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/rpc/RpcService.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/rpc/YahooService.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/rpc/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/rpc/yahoo.smd create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/selection/Selection.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/storage.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/storage/Storage.as create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/storage/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/storage/browser.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/storage/dashboard.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/storage/storage_dialog.fla create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/string.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/string/Builder.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/string/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/string/common.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/string/extras.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/style.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/svg.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/text/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/text/textDirectory.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/undo/Manager.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/undo/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/undo/browser.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/uri/Uri.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/uri/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/uuid/LightweightGenerator.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/uuid/NameBasedGenerator.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/uuid/NilGenerator.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/uuid/RandomGenerator.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/uuid/TimeBasedGenerator.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/uuid/Uuid.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/uuid/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/validate.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/validate/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/validate/check.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/validate/common.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/validate/creditCard.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/validate/datetime.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/validate/de.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/validate/jp.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/validate/us.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/validate/web.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/AccordionContainer.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/AnimatedPng.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Button.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Chart.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Checkbox.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Clock.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ColorPalette.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ComboBox.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ContentPane.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/CurrencyTextbox.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DatePicker.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DateTextbox.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DebugConsole.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Dialog.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DocPane.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DomWidget.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownContainer.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownDatePicker.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/DropdownTimePicker.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor2.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor2Plugin/AlwaysShowToolbar.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor2Plugin/ContextMenu.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor2Plugin/CreateLinkDialog.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor2Plugin/FindReplace.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor2Plugin/FindReplaceDialog.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor2Plugin/InsertImageDialog.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor2Plugin/InsertTableDialog.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor2Plugin/SimpleSignalCommands.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor2Plugin/TableOperation.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor2Plugin/ToolbarDndSupport.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor2Plugin/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Editor2Toolbar.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/FilteringTable.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/FisheyeList.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/FloatingPane.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Form.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/GoogleMap.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/HtmlWidget.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/InlineEditBox.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/IntegerTextbox.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/InternetTextbox.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/LayoutContainer.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/LinkPane.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Manager.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Menu2.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/MonthlyCalendar.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/PageContainer.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Parse.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/PopupContainer.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ProgressBar.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/RadioGroup.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/RealNumberTextbox.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/RegexpTextbox.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/RemoteTabController.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Repeater.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ResizableTextarea.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ResizeHandle.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/RichText.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Rounded.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Select.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Show.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ShowAction.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ShowSlide.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/SlideShow.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Slider.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/SortableTable.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Spinner.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/SplitContainer.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/SplitPane.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/SvgButton.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/SvgWidget.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/SwtWidget.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TabContainer.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TaskBar.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Textbox.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TimePicker.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TitlePane.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Toaster.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Toggler.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Toolbar.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Tooltip.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Tree.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeBasicController.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeBasicControllerV3.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeCommon.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeContextMenu.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeContextMenuV3.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeControllerExtension.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeDemo.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeDeselectOnDblselect.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeDisableWrapExtension.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeDndControllerV3.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeDocIconExtension.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeEditor.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeEmphaseOnSelect.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeExpandOnSelect.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeExtension.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeLinkExtension.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeLoadingController.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeLoadingControllerV3.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeNode.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeNodeV3.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeRPCController.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeRpcControllerV3.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeSelector.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeSelectorV3.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeTimeoutIterator.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeV3.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/TreeWithNode.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/UsTextbox.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/ValidationTextbox.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Widget.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/Wizard.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/YahooMap.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoContainer.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoItem.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoNavigator.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/DemoPane.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/SourcePane.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoContainer.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoContainer.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoItem.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoItem.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoNavigator.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoNavigator.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoPane.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/DemoPane.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/SourcePane.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/SourcePane.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/general.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/images/test_thumb.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/demoEngine/templates/images/viewDemo.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/html/layout.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/html/loader.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/html/stabile.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/nls/DropdownDatePicker.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/nls/DropdownTimePicker.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/nls/TimePicker.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/nls/fr/validate.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/nls/ja/validate.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/nls/validate.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/nls/zh-cn/validate.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/svg/Chart.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/AccordionPane.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/AccordionPane.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/ButtonTemplate.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/ButtonTemplate.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Checkbox.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Checkbox.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/CheckboxA11y.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/CiviCrmDatePicker.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/ComboBox.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/ComboBox.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/ComboButtonTemplate.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/DatePicker.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/DatePicker.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/DemoEngine.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Dialog.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/DocPane.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/DocPane.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/DropDownButtonTemplate.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Editor2/Dialog/createlink.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Editor2/Dialog/find.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Editor2/Dialog/insertimage.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Editor2/Dialog/inserttable.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Editor2/Dialog/replace.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Editor2/EditorDialog.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Editor2/EditorToolbar_FontName.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Editor2/EditorToolbar_FontSize.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Editor2/EditorToolbar_FormatBlock.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Editor2/showtableborder_gecko.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Editor2/showtableborder_ie.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/EditorToolbar.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/EditorToolbar.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/EditorToolbarLight.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/EditorToolbarOneline.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/FisheyeList.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/FloatingPane.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/FloatingPane.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/InlineEditBox.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/InlineEditBox.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Menu.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Menu2.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/MonthlyCalendar.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/MonthlyCalendar.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/PopUpButton.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/ProgressBar.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/ProgressBar.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/RemoteTabControl.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/ResizableTextarea.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/ResizableTextarea.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/ResizeHandle.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Show.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Show.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/ShowSlide.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/ShowSlide.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/SlideShow.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/SlideShow.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Slider.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Slider.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/SliderHorizontal.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/SliderVertical.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Spinner.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Spinner.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/SplitContainer.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/TabContainer.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/TabContainer.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/TabContainerA11y.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/TaskBar.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/TaskBarItemTemplate.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Textbox.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/TimePicker.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/TimePicker.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/TitlePane.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Toaster.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Toolbar.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/TooltipTemplate.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Tree.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/TreeDisableWrap.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/TreeDocIcon.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/TreeV3.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Validate.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/ValidationTextbox.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Wizard.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/Wizard.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/aggregate.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/backcolor.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/bg-fade.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/bold.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/cancel.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/copy.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/createlink.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/cut.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/delete.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/forecolor.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/hilitecolor.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/indent.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/inserthorizontalrule.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/insertimage.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/insertorderedlist.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/inserttable.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/insertunorderedlist.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/italic.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/justifycenter.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/justifyfull.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/justifyleft.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/justifyright.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/left_to_right.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/list_bullet_indent.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/list_bullet_outdent.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/list_num_indent.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/list_num_outdent.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/outdent.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/paste.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/redo.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/removeformat.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/right_to_left.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/save.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/sep.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/space.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/strikethrough.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/subscript.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/superscript.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/underline.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/undo.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/buttons/wikiword.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/check.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/decrementMonth.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/decrementWeek.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/grabCorner.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/Tree.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/blank.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/closed.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/document.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/minus.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/plus.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/transparent.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/treenode_blank.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/treenode_child.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/treenode_expand_minus.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/treenode_expand_plus.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/treenode_grid_c.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/treenode_grid_l.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/treenode_grid_p.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/treenode_grid_t.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/treenode_grid_v.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/treenode_grid_x.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/treenode_grid_y.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/treenode_grid_z.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/treenode_loading.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/Tree/treenode_loading.jpg create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/closed.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/document.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/expand_leaf.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/expand_loading.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/expand_minus.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/expand_plus.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/i.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/i_bhalf.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/i_half.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/i_long.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/l.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/minus.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/open.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/plus.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/t.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/TreeV3/x.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/bar.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/bdYearBg.1.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/bdYearBg.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/blank.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/clock.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/combo_box_arrow.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dateIcon.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/decrementMonth.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/decrementMonth.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dpBg.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dpCurveBL.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dpCurveBR.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dpCurveTL.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dpCurveTR.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dpHorizLine.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dpHorizLineFoot.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dpMonthBg.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dpMonthBg.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dpMonthBg2.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dpVertLine.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dpYearBg.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dpYearBg.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dropdownButtonsArrow-disabled.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/dropdownButtonsArrow.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/floatingPaneClose.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/floatingPaneMaximize.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/floatingPaneMinimize.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/floatingPaneRestore.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/h-bar.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/incrementMonth.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/incrementMonth.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/no.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/no.svg create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/scBackground.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/slider-bg-progress-vert.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/slider-bg-vert.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/slider-bg.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/slider-button-horz.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/slider-button-vert.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/slider-button.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/slider.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/slider_down_arrow.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/slider_left_arrow.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/slider_right_arrow.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/slider_up_arrow.png create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaAccordionOff.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaAccordionSelected.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaActive-c.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaActive-l.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaActive-r.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaBarBg.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaButton-c.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaButton-l.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaButton-r.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaDisabled-c.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaDisabled-l.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaDisabled-r.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaMenuBg.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaPressed-c.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaPressed-l.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/soriaPressed-r.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/spinnerDecrement.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/spinnerIncrement.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/submenu_disabled.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/submenu_off.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/submenu_on.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/tab_bot_left.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/tab_bot_left_curr.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/tab_bot_right.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/tab_bot_right_curr.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/tab_close.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/tab_close_h.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/tab_left.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/tab_left_r.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/tab_left_r_curr.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/tab_right.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/tab_right_r.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/tab_right_r_curr.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/tab_top_left.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/tab_top_right.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/timeIcon.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/toolbar-bg.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/transparent.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/treenode_blank.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/treenode_child.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/treenode_expand_minus.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/treenode_expand_plus.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/treenode_grid_c.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/treenode_grid_l.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/treenode_grid_p.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/treenode_grid_t.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/treenode_grid_v.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/treenode_grid_x.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/treenode_grid_y.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/treenode_grid_z.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/treenode_node.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/verticalbar.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/images/whiteDownArrow.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/incrementMonth.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/incrementWeek.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/templates/richtextframe.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/validate.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/widget/vml/Chart.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/xml/Parse.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/xml/XslTransform.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/xml/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/src/xml/svgUtil.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/storage_dialog.swf create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/struts/ComboBox.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/struts/Util.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/struts/tooltip.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/struts/widget/Bind.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/struts/widget/BindAnchor.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/struts/widget/BindDiv.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/struts/widget/ComboBox.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/struts/widget/StrutsTimePicker.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/struts/widget/__package__.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/struts/widgets/dateIcon.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/struts/widgets/dropdowncontainer.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/dojo/struts/widgets/timeIcon.gif create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/inputtransferselect.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/niftycorners/layout.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/niftycorners/nifty.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/niftycorners/niftyCorners.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/niftycorners/niftyPrint.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/niftycorners/niftylayout.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/optiontransferselect.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/tabs.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/tree.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/static/validationClient.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/struts-messages.properties create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/struts-messages_da.properties create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/struts-messages_de.properties create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/struts-messages_pl.properties create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/struts-messages_pt.properties create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/util/package.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/views/freemarker/package.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/views/jsp/iterator/package.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/views/jsp/ui/package.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/org/apache/struts2/views/jsp/ui/table/package.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/overview.html create mode 100644 STRUTS_2_0_X/core/src/main/resources/struts-2.0.dtd create mode 100644 STRUTS_2_0_X/core/src/main/resources/struts-default.xml create mode 100644 STRUTS_2_0_X/core/src/main/resources/struts-portlet-default.xml create mode 100644 STRUTS_2_0_X/core/src/main/resources/struts.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/a.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/ajax-common.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/autocompleter.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/controlheader.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/div-close.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/div.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/dojoRequire.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/form-close.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/form.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/head.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/submit.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/tab-close.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/tab.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/textarea.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/theme.properties create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/tree-close.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/tree.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/treenode-close.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/treenode-include.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/treenode.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/ajax/validation.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/ajax/a-close.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/ajax/a.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/ajax/div-close.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/ajax/div.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/ajax/form-close.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/ajax/form.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/ajax/submit.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/ajax/tab-close.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/ajax/tab.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/checkbox.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/checkboxlist.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/combobox.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/debug.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/doubleselect.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/empty.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/file.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/form-close.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/form.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/hidden.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/label.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/password.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/radiomap.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/scripting-events.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/select.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/submit.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/table.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/text.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/textarea.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/simple/token.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/checkbox.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/checkboxlist.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/combobox.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/controlfooter.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/controlheader.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/debug.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/doubleselect.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/empty.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/file.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/form-close.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/form.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/hidden.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/label.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/password.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/radiomap.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/select.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/submit.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/table.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/text.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/textarea.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/archive/xhtml/token.vm create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/checkbox.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/checkboxlist.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/combobox.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/control-close.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/control.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/controlfooter.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/controlheader-core.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/controlheader.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/datetimepicker.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/debug.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/doubleselect.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/file.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/form-close.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/form-validate.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/form.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/head.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/inputtransferselect.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/label.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/optiontransferselect.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/password.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/radiomap.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/reset.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/select.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/styles.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/submit.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/text.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/textarea.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/theme.properties create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/updownselect.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/css_xhtml/validation.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/a-close.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/a.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/actionerror.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/actionmessage.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/autocompleter.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/checkbox.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/checkboxlist.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/combobox.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/common-attributes.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/controlfooter.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/controlheader.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/datetimepicker.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/debug.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/div-close.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/div.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/dojoRequire.js create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/doubleselect.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/empty.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/fielderror.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/file.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/form-close.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/form.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/head.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/hidden.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/inputtransferselect.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/label.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/optgroup.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/optiontransferselect.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/password.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/radiomap.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/reset.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/scripting-events.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/select.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/submit.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/tab-close.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/tab.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/tabbedpanel-close.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/tabbedpanel.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/table.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/text.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/textarea.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/token.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/simple/updownselect.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/autocompleter.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/checkbox.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/checkboxlist.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/combobox.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/control-close.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/control.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/controlfooter.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/controlheader-core.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/controlheader.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/datepicker.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/datetimepicker.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/debug.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/doubleselect.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/file.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/form-close-validate.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/form-close.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/form-validate.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/form.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/head.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/inputtransferselect.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/label.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/optiontransferselect.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/password.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/radiomap.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/reset.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/select.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/styles.css create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/submit.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/text.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/textarea.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/theme.properties create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/timepicker.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/tooltip.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/updownselect.ftl create mode 100644 STRUTS_2_0_X/core/src/main/resources/template/xhtml/validation.js create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/a.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/action.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/actionerror.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/actionmessage.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/append.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/autocompleter.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/bean.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/checkbox.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/checkboxlist.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/combobox.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/component.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/date.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/datepicker.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/datetimepicker.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/debug.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/div.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/doubleselect.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/dropdowndatetimepicker.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/else.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/elseif.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/fielderror.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/file.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/form.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/generator.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/head.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/hidden.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/i18n.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/if.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/include.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/inputtransferselect.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/iterator.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/label.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/merge.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/optgroup.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/optiontransferselect.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/param.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/password.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/property.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/push.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/radio.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/reset.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/select.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/set.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/sort.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/submit.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/subset.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/tabbedPanel.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/table.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/text.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/textarea.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/textfield.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/timepicker.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/token.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/tree.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/treenode.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/updownselect.html create mode 100644 STRUTS_2_0_X/core/src/site/resources/tags/url.html create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/ExecutionCountTestAction.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/RequestUtilsTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/ServletActionContextTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/SomeEnum.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/TestAction.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/TestActionTagResult.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/TestConfigurationProvider.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/TestNGStrutsTestCaseTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/TestResult.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/components/ComponentTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/components/FormButtonTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/components/FormTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/components/PropertyTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/components/UIBeanTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/components/UIComponentTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/components/URLTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/components/template/BaseTemplateEngineTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/config/BeanSelectionProviderTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/config/ClasspathConfigurationProviderTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/config/CustomNamespaceAction.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/config/CustomParentPackageAction.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/config/MethodConfigurationProviderTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/config/SettingsTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/config/TestSettings.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/config/cltest/ActionImpl.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/config/cltest/OneResultAction.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/config/cltest/TwoResultAction.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/ActionContextCleanUpTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/DispatcherTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/FilterDispatcherTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/FilterTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/HttpHeaderResultTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/NullActionMapper.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/PlainTextResultTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/ServletActionRedirectResultTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/ServletDispatchedTestAssertInterceptor.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/ServletDispatcherResultTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/ServletRedirectResultTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/SessionMapTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/StreamResultTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/StrutsResultSupportTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/VelocityResultTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/mapper/CompositeActionMapperTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/mapper/DefaultActionMapperTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/mapper/Restful2ActionMapperTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/dispatcher/mapper/RestfulActionMapperTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/interceptor/CookieInterceptorTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/interceptor/CreateSessionInterceptorTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/interceptor/ExecuteAndWaitDelayAction.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/interceptor/ExecuteAndWaitInterceptorTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/interceptor/FileUploadInterceptorTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/interceptor/MessageStoreInterceptorTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/interceptor/RolesInterceptorTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/interceptor/ServletConfigInterceptorTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/interceptor/StrutsConversionErrorInterceptorTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/interceptor/TokenInterceptorTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/interceptor/TokenSessionStoreInterceptorTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/interceptor/validation/AnnotationValidationInterceptorTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/portlet/PortletApplicationMapTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/portlet/PortletRequestMapTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/portlet/PortletSessionMapTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/portlet/context/PortletActionContextTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/portlet/dispatcher/Jsr168DispatcherTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/portlet/interceptor/PortletAwareInterceptorTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/portlet/result/PortletResultTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/portlet/util/PortletUrlHelperTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/portlet/util/StrutsUtilTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/util/ContainUtilTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/util/CounterTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/util/InvocationSessionStoreTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/util/PrefixTrieTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/util/StrutsTypeConverterTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/util/TokenHelperTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/TemplateEngineManagerTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/freemarker/FreemarkerManagerTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/freemarker/FreemarkerTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/freemarker/TestAction.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/freemarker/TestBean.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/freemarker/tags/TagModelTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/AbstractTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/AbstractUITagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ActionTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/AnchorTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/AppendIteratorTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/BeanTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ElseIfTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ElseTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/IfTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/IncludeTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/IteratorGeneratorTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/IteratorTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/MergeIteratorTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/PortletUrlTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/PropertyTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/PushTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/SetTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/SortIteratorTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/StrutsMockBodyContent.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/StrutsMockHttpServletRequest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/StrutsMockHttpServletResponse.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/StrutsMockHttpSession.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/StrutsMockJspWriter.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/StrutsMockPageContext.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/StrutsMockServletContext.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/SubsetIteratorTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/TextTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/URLTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/ActionErrorTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/ActionMessageTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/AnchorTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/AutocompleterTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/Category.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxListTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/ComponentTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/DateTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/DateTimePickerTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/DivTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/DoubleSelectTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/FieldErrorTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/FileTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/FormTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/HeadTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/HiddenTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/InputTransferSelectTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/JspTemplateTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/LabelTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/MockTag.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/OptGroupTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/OptionTransferSelectTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/PasswordTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/RadioTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/ResetTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/SelectTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/StrutsBodyContent.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/SubmitAjaxTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/SubmitTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/TabbedPanelTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/TestAction1.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/TextareaTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/TextfieldTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/TokenTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/TooltipTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/TreeTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/UpDownSelectTagTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/jsp/ui/User.java create mode 100755 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/util/ContextUtilTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/util/ResourceUtilTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/util/TextUtilTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/util/UrlHelperTest.java create mode 100644 STRUTS_2_0_X/core/src/test/java/org/apache/struts2/views/xslt/XSLTResultTest.java create mode 100644 STRUTS_2_0_X/core/src/test/resources/XSLTResultTest.xsl create mode 100644 STRUTS_2_0_X/core/src/test/resources/XSLTResultTest2.xsl create mode 100644 STRUTS_2_0_X/core/src/test/resources/XSLTResultTest3.xsl create mode 100644 STRUTS_2_0_X/core/src/test/resources/XSLTResultTest4.xsl create mode 100644 STRUTS_2_0_X/core/src/test/resources/log4j.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/TestAction-validation.xml create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/TestAction.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/components/template/dummy.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/components/template/theme1/themeThroughClassPath.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/components/template/theme1/themeThroughFileSystem.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/components/tempo.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/dispatcher/someJspFile.jsp create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/interceptor/FileUploadInterceptor.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/othertest.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Autocompleter-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Autocompleter-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Checkbox-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Checkbox-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Checkbox-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Checkbox-4.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Checkbox-5.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/CheckboxList-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/CheckboxList-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/CheckboxList-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/CheckboxList-4.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/ComboBox-4.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Component-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Component-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Component-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Component-param.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/DateTimePickerTagTest-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/DoubleSelect-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/DoubleSelect-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/DoubleSelect-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/File-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Formtag-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Formtag-10.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Formtag-11.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Formtag-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Formtag-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Formtag-4.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Formtag-5.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Formtag-6.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Formtag-7.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Formtag-8.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Formtag-9.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/HeadTagTest-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/HeadTagTest-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/HeadTagTest-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/HeadTagTest-4.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Hidden-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Label-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Label-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Label-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/OptGroup-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/OptGroup-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/OptGroup-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/OptGroup-4.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Password-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Radio-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Radio-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Radio-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Radio-4.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Reset-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Reset-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Reset-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Reset-4.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Select-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Select-10.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Select-11.txt create mode 100755 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Select-12.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Select-13.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Select-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Select-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Select-4.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Select-5.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Select-6.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Select-7.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Select-8.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Select-9.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-4.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-5.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-6.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Submit-7.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/TabbedPanel-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/TabbedPanel-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/TabbedPanel-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/TabbedPanel-4.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/TestAction1.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/TestAction1_de.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/TestAction1_fr.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Textarea-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Textfield-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Textfield-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/Textfield-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/TimePicker-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/User-validation.xml create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/User.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/actionerror-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/actionerror-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/actionmessage-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/actionmessage-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/div-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/fielderror-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/fielderror-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/fielderror-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/fielderror-4.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/fielderror-5.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/href-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/href-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/inputtransferselect-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/optiontransferselect-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/optiontransferselect-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/optiontransferselect-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/optiontransferselect-4.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/optiontransferselect-5.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/optiontransferselect-6.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/optiontransferselect-7.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/submit-ajax-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/submit-ajax-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/submit-ajax-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/tooltip-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/tooltip-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/tooltip-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/tree-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/tree-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-1.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-10.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-11.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-2.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-3.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-4.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-5.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-6.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-7.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-8.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/org/apache/struts2/views/jsp/ui/updownselecttag-9.txt create mode 100644 STRUTS_2_0_X/core/src/test/resources/struts.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/struts.xml create mode 100644 STRUTS_2_0_X/core/src/test/resources/template/test/Component.ftl create mode 100644 STRUTS_2_0_X/core/src/test/resources/template/test/checkbox.jsp create mode 100644 STRUTS_2_0_X/core/src/test/resources/test.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/testmessages.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/testmessages2.properties create mode 100644 STRUTS_2_0_X/core/src/test/resources/validators.xml create mode 100644 STRUTS_2_0_X/plugins/codebehind/pom.xml create mode 100644 STRUTS_2_0_X/plugins/codebehind/src/main/java/org/apache/struts2/codebehind/CodebehindUnknownHandler.java create mode 100644 STRUTS_2_0_X/plugins/codebehind/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/plugins/codebehind/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/plugins/codebehind/src/main/resources/struts-plugin.xml create mode 100644 STRUTS_2_0_X/plugins/codebehind/src/test/java/org/apache/struts2/codebehind/CodebehindUnknownHandlerTest.java create mode 100644 STRUTS_2_0_X/plugins/config-browser/pom.xml create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/java/org/apache/struts2/config_browser/ActionNamesAction.java create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/java/org/apache/struts2/config_browser/ConfigurationHelper.java create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/java/org/apache/struts2/config_browser/ListValidatorsAction.java create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/java/org/apache/struts2/config_browser/ShowConfigAction.java create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/java/org/apache/struts2/config_browser/ShowValidatorAction.java create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/resources/config-browser/actionNames.ftl create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/resources/config-browser/config-styles.css create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/resources/config-browser/error.ftl create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/resources/config-browser/page-footer.ftl create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/resources/config-browser/page-header.ftl create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/resources/config-browser/showConfig.ftl create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/resources/config-browser/showValidators.ftl create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/resources/config-browser/simple-error.ftl create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/resources/config-browser/tigris-macros.ftl create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/resources/config-browser/validatorDetails.ftl create mode 100644 STRUTS_2_0_X/plugins/config-browser/src/main/resources/struts-plugin.xml create mode 100644 STRUTS_2_0_X/plugins/jasperreports/pom.xml create mode 100644 STRUTS_2_0_X/plugins/jasperreports/src/main/java/org/apache/struts2/views/jasperreports/CompileReport.java create mode 100644 STRUTS_2_0_X/plugins/jasperreports/src/main/java/org/apache/struts2/views/jasperreports/JasperReportConstants.java create mode 100644 STRUTS_2_0_X/plugins/jasperreports/src/main/java/org/apache/struts2/views/jasperreports/JasperReportsResult.java create mode 100644 STRUTS_2_0_X/plugins/jasperreports/src/main/java/org/apache/struts2/views/jasperreports/ValueStackDataSource.java create mode 100644 STRUTS_2_0_X/plugins/jasperreports/src/main/java/org/apache/struts2/views/jasperreports/ValueStackShadowMap.java create mode 100644 STRUTS_2_0_X/plugins/jasperreports/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/plugins/jasperreports/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/plugins/jasperreports/src/main/resources/org/apache/struts2/views/jasperreports/package.html create mode 100644 STRUTS_2_0_X/plugins/jasperreports/src/main/resources/struts-plugin.xml create mode 100644 STRUTS_2_0_X/plugins/jfreechart/pom.xml create mode 100644 STRUTS_2_0_X/plugins/jfreechart/src/main/java/org/apache/struts2/dispatcher/ChartResult.java create mode 100644 STRUTS_2_0_X/plugins/jfreechart/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/plugins/jfreechart/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/plugins/jfreechart/src/main/resources/struts-plugin.xml create mode 100644 STRUTS_2_0_X/plugins/jfreechart/src/test/java/org/apache/struts2/dispatcher/ChartResultTest.java create mode 100644 STRUTS_2_0_X/plugins/jsf/pom.xml create mode 100644 STRUTS_2_0_X/plugins/jsf/src/main/java/org/apache/struts2/jsf/ApplyRequestValuesInterceptor.java create mode 100644 STRUTS_2_0_X/plugins/jsf/src/main/java/org/apache/struts2/jsf/FacesInterceptor.java create mode 100755 STRUTS_2_0_X/plugins/jsf/src/main/java/org/apache/struts2/jsf/FacesRender.java create mode 100644 STRUTS_2_0_X/plugins/jsf/src/main/java/org/apache/struts2/jsf/FacesResult.java create mode 100644 STRUTS_2_0_X/plugins/jsf/src/main/java/org/apache/struts2/jsf/FacesSetupInterceptor.java create mode 100644 STRUTS_2_0_X/plugins/jsf/src/main/java/org/apache/struts2/jsf/FacesSupport.java create mode 100644 STRUTS_2_0_X/plugins/jsf/src/main/java/org/apache/struts2/jsf/InvokeApplicationInterceptor.java create mode 100644 STRUTS_2_0_X/plugins/jsf/src/main/java/org/apache/struts2/jsf/ProcessValidationsInterceptor.java create mode 100644 STRUTS_2_0_X/plugins/jsf/src/main/java/org/apache/struts2/jsf/RestoreViewInterceptor.java create mode 100644 STRUTS_2_0_X/plugins/jsf/src/main/java/org/apache/struts2/jsf/StrutsNavigationHandler.java create mode 100644 STRUTS_2_0_X/plugins/jsf/src/main/java/org/apache/struts2/jsf/StrutsVariableResolver.java create mode 100644 STRUTS_2_0_X/plugins/jsf/src/main/java/org/apache/struts2/jsf/UpdateModelValuesInterceptor.java create mode 100644 STRUTS_2_0_X/plugins/jsf/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/plugins/jsf/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/plugins/jsf/src/main/resources/org/apache/struts2/jsf/package.html create mode 100644 STRUTS_2_0_X/plugins/jsf/src/main/resources/struts-plugin.xml create mode 100644 STRUTS_2_0_X/plugins/pell-multipart/pom.xml create mode 100644 STRUTS_2_0_X/plugins/pell-multipart/src/main/java/org/apache/struts2/dispatcher/multipart/PellMultiPartRequest.java create mode 100644 STRUTS_2_0_X/plugins/pell-multipart/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/plugins/pell-multipart/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/plugins/pell-multipart/src/main/resources/struts-plugin.xml create mode 100644 STRUTS_2_0_X/plugins/plexus/pom.xml create mode 100644 STRUTS_2_0_X/plugins/plexus/src/main/java/org/apache/struts2/plexus/PlexusFilter.java create mode 100644 STRUTS_2_0_X/plugins/plexus/src/main/java/org/apache/struts2/plexus/PlexusLifecycleListener.java create mode 100644 STRUTS_2_0_X/plugins/plexus/src/main/java/org/apache/struts2/plexus/PlexusObjectFactory.java create mode 100644 STRUTS_2_0_X/plugins/plexus/src/main/java/org/apache/struts2/plexus/PlexusThreadLocal.java create mode 100644 STRUTS_2_0_X/plugins/plexus/src/main/java/org/apache/struts2/plexus/PlexusUtils.java create mode 100644 STRUTS_2_0_X/plugins/plexus/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/plugins/plexus/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/plugins/plexus/src/main/resources/struts-plugin.xml create mode 100644 STRUTS_2_0_X/plugins/pom.xml create mode 100644 STRUTS_2_0_X/plugins/sitegraph/pom.xml create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/Main.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/SiteGraph.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/StrutsConfigRetriever.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/entities/FileBasedView.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/entities/FreeMarkerView.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/entities/JspView.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/entities/Target.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/entities/VelocityView.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/entities/View.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/model/ActionNode.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/model/Graph.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/model/IndentWriter.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/model/Link.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/model/Render.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/model/SiteGraphNode.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/model/SubGraph.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/model/ViewNode.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/java/org/apache/struts2/sitegraph/renderers/DOTRenderer.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/main/resources/org/apache/struts2/sitegraph/sitegraph-usage.txt create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/test/java/org/apache/struts2/sitegraph/SiteGraphTest.java create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/test/resources/org/apache/struts2/sitegraph/hello.jsp create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/test/resources/org/apache/struts2/sitegraph/out.txt create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/test/resources/org/apache/struts2/sitegraph/struts.xml create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/test/resources/org/apache/struts2/sitegraph/tutorial/sitegraph/guess-error.ftl create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/test/resources/org/apache/struts2/sitegraph/tutorial/sitegraph/guess-input.ftl create mode 100644 STRUTS_2_0_X/plugins/sitegraph/src/test/resources/org/apache/struts2/sitegraph/tutorial/sitegraph/guess-success.jsp create mode 100644 STRUTS_2_0_X/plugins/sitemesh/pom.xml create mode 100644 STRUTS_2_0_X/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/FreeMarkerPageFilter.java create mode 100644 STRUTS_2_0_X/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/NoneDecoratorMapper.java create mode 100644 STRUTS_2_0_X/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/TemplatePageFilter.java create mode 100644 STRUTS_2_0_X/plugins/sitemesh/src/main/java/org/apache/struts2/sitemesh/VelocityPageFilter.java create mode 100644 STRUTS_2_0_X/plugins/sitemesh/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/plugins/sitemesh/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/plugins/sitemesh/src/main/resources/struts-plugin.xml create mode 100644 STRUTS_2_0_X/plugins/spring/pom.xml create mode 100644 STRUTS_2_0_X/plugins/spring/src/main/java/org/apache/struts2/spring/StrutsSpringObjectFactory.java create mode 100644 STRUTS_2_0_X/plugins/spring/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/plugins/spring/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/plugins/spring/src/main/resources/struts-plugin.xml create mode 100644 STRUTS_2_0_X/plugins/spring/src/test/java/org/apache/struts2/spring/StrutsSpringObjectFactoryTest.java create mode 100644 STRUTS_2_0_X/plugins/spring/src/test/resources/org/apache/struts2/spring/StrutsSpringObjectFactoryTest-applicationContext.xml create mode 100644 STRUTS_2_0_X/plugins/struts1/pom.xml create mode 100644 STRUTS_2_0_X/plugins/struts1/src/main/java/org/apache/struts2/s1/ActionFormResetInterceptor.java create mode 100644 STRUTS_2_0_X/plugins/struts1/src/main/java/org/apache/struts2/s1/ActionFormValidationInterceptor.java create mode 100644 STRUTS_2_0_X/plugins/struts1/src/main/java/org/apache/struts2/s1/DynaBeanPropertyAccessor.java create mode 100644 STRUTS_2_0_X/plugins/struts1/src/main/java/org/apache/struts2/s1/Struts1Action.java create mode 100644 STRUTS_2_0_X/plugins/struts1/src/main/java/org/apache/struts2/s1/Struts1Factory.java create mode 100644 STRUTS_2_0_X/plugins/struts1/src/main/java/org/apache/struts2/s1/WrapperActionForward.java create mode 100644 STRUTS_2_0_X/plugins/struts1/src/main/java/org/apache/struts2/s1/WrapperActionMapping.java create mode 100644 STRUTS_2_0_X/plugins/struts1/src/main/java/org/apache/struts2/s1/WrapperExceptionConfig.java create mode 100644 STRUTS_2_0_X/plugins/struts1/src/main/java/org/apache/struts2/s1/WrapperMessageResources.java create mode 100644 STRUTS_2_0_X/plugins/struts1/src/main/java/org/apache/struts2/s1/WrapperModuleConfig.java create mode 100644 STRUTS_2_0_X/plugins/struts1/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/plugins/struts1/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/plugins/struts1/src/main/resources/struts-plugin.xml create mode 100644 STRUTS_2_0_X/plugins/struts1/src/test/java/org/apache/struts2/s1/DynaBeanPropertyAccessorTest.java create mode 100644 STRUTS_2_0_X/plugins/struts1/src/test/java/org/apache/struts2/s1/Struts1FactoryTest.java create mode 100644 STRUTS_2_0_X/plugins/struts1/src/test/resources/org/apache/struts2/s1/test-struts-factory.xml create mode 100644 STRUTS_2_0_X/plugins/tiles/pom.xml create mode 100644 STRUTS_2_0_X/plugins/tiles/src/main/java/org/apache/struts2/tiles/ConfiguredServletContext.java create mode 100644 STRUTS_2_0_X/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesContainerFactory.java create mode 100644 STRUTS_2_0_X/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesListener.java create mode 100644 STRUTS_2_0_X/plugins/tiles/src/main/java/org/apache/struts2/tiles/StrutsTilesRequestContext.java create mode 100644 STRUTS_2_0_X/plugins/tiles/src/main/java/org/apache/struts2/views/tiles/TilesResult.java create mode 100644 STRUTS_2_0_X/plugins/tiles/src/main/resources/LICENSE.txt create mode 100644 STRUTS_2_0_X/plugins/tiles/src/main/resources/NOTICE.txt create mode 100644 STRUTS_2_0_X/plugins/tiles/src/main/resources/struts-plugin.xml create mode 100644 STRUTS_2_0_X/pom.xml create mode 100644 STRUTS_2_0_X/src/main/idea/project.xml create mode 100644 STRUTS_2_0_X/src/main/idea/workspace.xml create mode 100644 STRUTS_2_0_X/src/site/resources/images/download.gif create mode 100644 STRUTS_2_0_X/src/site/resources/images/help.gif create mode 100644 STRUTS_2_0_X/src/site/resources/images/plugins.gif create mode 100644 STRUTS_2_0_X/src/site/resources/images/struts2-arch.png create mode 100644 STRUTS_2_0_X/src/site/resources/images/struts2-merger.png create mode 100644 STRUTS_2_0_X/src/site/resources/images/struts2-merger2.png create mode 100644 STRUTS_2_0_X/src/site/resources/images/struts2.png create mode 100644 STRUTS_2_0_X/src/site/site.xml create mode 100644 STRUTS_2_0_X/src/site/xdoc/index.xml create mode 100755 STRUTS_2_0_X/src/site/xdoc/jxr.xml diff --git a/STRUTS_2_0_X/apps/blank/LICENSE.txt b/STRUTS_2_0_X/apps/blank/LICENSE.txt new file mode 100644 index 000000000..c6055ec8f --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/LICENSE.txt @@ -0,0 +1,174 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/STRUTS_2_0_X/apps/blank/NOTICE.txt b/STRUTS_2_0_X/apps/blank/NOTICE.txt new file mode 100644 index 000000000..5c3c04fc8 --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/NOTICE.txt @@ -0,0 +1,6 @@ +Apache Struts + +Copyright 2006 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/ diff --git a/STRUTS_2_0_X/apps/blank/README.txt b/STRUTS_2_0_X/apps/blank/README.txt new file mode 100644 index 000000000..db14cea57 --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/README.txt @@ -0,0 +1,10 @@ +README.txt - blank + +This is an "empty" application that you can deploy as the basis of your own +application. + +For more on getting started with Struts, see + +* http://cwiki.apache.org/WW/home.html + +---------------------------------------------------------------------------- \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/blank/pom.xml b/STRUTS_2_0_X/apps/blank/pom.xml new file mode 100644 index 000000000..cfc421886 --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + org.apache.struts + struts2-apps + 2.0.14 + + org.apache.struts + struts2-blank + war + Blank Webapp + + + scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps/blank + scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps/blank + http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_0_14/apps/blank + + + + + + javax.servlet + servlet-api + 2.4 + provided + + + + javax.servlet + jsp-api + 2.0 + provided + + + + org.springframework + spring-core + 2.0.1 + test + + + + + + + + org.mortbay.jetty + maven-jetty-plugin + 6.0.1 + + 10 + + + + + + + diff --git a/STRUTS_2_0_X/apps/blank/src/main/java/example/ExampleSupport.java b/STRUTS_2_0_X/apps/blank/src/main/java/example/ExampleSupport.java new file mode 100644 index 000000000..554509a0e --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/java/example/ExampleSupport.java @@ -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 example; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * Base Action class for the Tutorial package. + */ +public class ExampleSupport extends ActionSupport { +} diff --git a/STRUTS_2_0_X/apps/blank/src/main/java/example/HelloWorld.java b/STRUTS_2_0_X/apps/blank/src/main/java/example/HelloWorld.java new file mode 100644 index 000000000..d5268ca45 --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/java/example/HelloWorld.java @@ -0,0 +1,61 @@ +/* + * $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 example; + +/** + * Set welcome message. + */ +public class HelloWorld extends ExampleSupport { + + public String execute() throws Exception { + setMessage(getText(MESSAGE)); + return SUCCESS; + } + + /** + * Provide default valuie for Message property. + */ + public static final String MESSAGE = "HelloWorld.message"; + + /** + * Field for Message property. + */ + private String message; + + /** + * Return Message property. + * + * @return Message property + */ + public String getMessage() { + return message; + } + + /** + * Set Message property. + * + * @param message Text to display on HelloWorld page. + */ + public void setMessage(String message) { + this.message = message; + } +} diff --git a/STRUTS_2_0_X/apps/blank/src/main/java/example/Login.java b/STRUTS_2_0_X/apps/blank/src/main/java/example/Login.java new file mode 100644 index 000000000..d425488b9 --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/java/example/Login.java @@ -0,0 +1,59 @@ +/* + * $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 example; + +public class Login extends ExampleSupport { + + public String execute() throws Exception { + + if (isInvalid(getUsername())) return INPUT; + + if (isInvalid(getPassword())) return INPUT; + + return SUCCESS; + } + + private boolean isInvalid(String value) { + return (value == null || value.length() == 0); + } + + private String username; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + private String password; + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + +} \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/blank/src/main/java/example/build.bat b/STRUTS_2_0_X/apps/blank/src/main/java/example/build.bat new file mode 100644 index 000000000..a3f4edd01 --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/java/example/build.bat @@ -0,0 +1,3 @@ +@echo off +set CLASSPATH=..\..\..\lib\xwork-2.0-beta-1.jar +javac *.java -d ..\..\..\classes diff --git a/STRUTS_2_0_X/apps/blank/src/main/resources/LICENSE.txt b/STRUTS_2_0_X/apps/blank/src/main/resources/LICENSE.txt new file mode 100644 index 000000000..dd5b3a58a --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/resources/LICENSE.txt @@ -0,0 +1,174 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/STRUTS_2_0_X/apps/blank/src/main/resources/NOTICE.txt b/STRUTS_2_0_X/apps/blank/src/main/resources/NOTICE.txt new file mode 100644 index 000000000..cd13ec449 --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/resources/NOTICE.txt @@ -0,0 +1,5 @@ +Apache Struts +Copyright 2000-2007 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/blank/src/main/resources/example.xml b/STRUTS_2_0_X/apps/blank/src/main/resources/example.xml new file mode 100644 index 000000000..2e3b57cfc --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/resources/example.xml @@ -0,0 +1,25 @@ + + + + + + + + + /example/HelloWorld.jsp + + + + /example/Login.jsp + Menu + + + + /example/{1}.jsp + + + + + diff --git a/STRUTS_2_0_X/apps/blank/src/main/resources/example/Login-validation.xml b/STRUTS_2_0_X/apps/blank/src/main/resources/example/Login-validation.xml new file mode 100644 index 000000000..d703ee7a3 --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/resources/example/Login-validation.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/blank/src/main/resources/example/package.properties b/STRUTS_2_0_X/apps/blank/src/main/resources/example/package.properties new file mode 100644 index 000000000..c1f4b330d --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/resources/example/package.properties @@ -0,0 +1,5 @@ +HelloWorld.message= Struts is up and running ... +requiredstring = ${getText(fieldName)} is required. +password = Password +username = User Name +Missing.message = This feature is under construction. Please try again in the next interation. diff --git a/STRUTS_2_0_X/apps/blank/src/main/resources/example/package_es.properties b/STRUTS_2_0_X/apps/blank/src/main/resources/example/package_es.properties new file mode 100644 index 000000000..a967fc67d --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/resources/example/package_es.properties @@ -0,0 +1,5 @@ +HelloWorld.message= ¡Struts está bien! ... +requiredstring = ${getText(fieldName)} se requiere. +password = Contraseña +username = Nombre de Usuario +Missing.message = ¡en obras! ¡seguir intentando! diff --git a/STRUTS_2_0_X/apps/blank/src/main/resources/struts.xml b/STRUTS_2_0_X/apps/blank/src/main/resources/struts.xml new file mode 100644 index 000000000..03f4f9b9c --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/resources/struts.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/blank/src/main/webapp/WEB-INF/web.xml b/STRUTS_2_0_X/apps/blank/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..9dd719269 --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,20 @@ + + + + Struts Blank + + + struts2 + org.apache.struts2.dispatcher.FilterDispatcher + + + + struts2 + /* + + + + index.html + + + diff --git a/STRUTS_2_0_X/apps/blank/src/main/webapp/example/HelloWorld.jsp b/STRUTS_2_0_X/apps/blank/src/main/webapp/example/HelloWorld.jsp new file mode 100644 index 000000000..938c76132 --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/webapp/example/HelloWorld.jsp @@ -0,0 +1,28 @@ +<%@ page contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + <s:text name="HelloWorld.message"/> + + + +

+ +

Languages

+ + + + diff --git a/STRUTS_2_0_X/apps/blank/src/main/webapp/example/Login.jsp b/STRUTS_2_0_X/apps/blank/src/main/webapp/example/Login.jsp new file mode 100644 index 000000000..6438080a3 --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/webapp/example/Login.jsp @@ -0,0 +1,15 @@ +<%@ page contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Sign On + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/blank/src/main/webapp/example/Menu.jsp b/STRUTS_2_0_X/apps/blank/src/main/webapp/example/Menu.jsp new file mode 100644 index 000000000..a74bd2c76 --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/webapp/example/Menu.jsp @@ -0,0 +1,3 @@ +<%@ page contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/blank/src/main/webapp/example/Missing.jsp b/STRUTS_2_0_X/apps/blank/src/main/webapp/example/Missing.jsp new file mode 100644 index 000000000..7c01ac9be --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/webapp/example/Missing.jsp @@ -0,0 +1,11 @@ +<%@ page contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + +Missing Feature + + +

+ +

+ + diff --git a/STRUTS_2_0_X/apps/blank/src/main/webapp/example/Register.jsp b/STRUTS_2_0_X/apps/blank/src/main/webapp/example/Register.jsp new file mode 100644 index 000000000..a74bd2c76 --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/webapp/example/Register.jsp @@ -0,0 +1,3 @@ +<%@ page contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/blank/src/main/webapp/example/Welcome.jsp b/STRUTS_2_0_X/apps/blank/src/main/webapp/example/Welcome.jsp new file mode 100644 index 000000000..64ffe9b10 --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/webapp/example/Welcome.jsp @@ -0,0 +1,18 @@ +<%@ page contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Welcome + " rel="stylesheet" + type="text/css"/> + + + +

Commands

+ + + + diff --git a/STRUTS_2_0_X/apps/blank/src/main/webapp/index.html b/STRUTS_2_0_X/apps/blank/src/main/webapp/index.html new file mode 100644 index 000000000..dc2bbd023 --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/main/webapp/index.html @@ -0,0 +1,10 @@ + + + + + + + +

Loading ...

+ + diff --git a/STRUTS_2_0_X/apps/blank/src/test/java/example/ConfigTest.java b/STRUTS_2_0_X/apps/blank/src/test/java/example/ConfigTest.java new file mode 100644 index 000000000..d70aa4e7d --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/test/java/example/ConfigTest.java @@ -0,0 +1,97 @@ +/* + * $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 example; + +import com.opensymphony.xwork2.ActionSupport; +import com.opensymphony.xwork2.config.RuntimeConfiguration; +import com.opensymphony.xwork2.config.entities.ActionConfig; +import com.opensymphony.xwork2.config.entities.ResultConfig; +import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider; + +import java.util.Map; +import java.util.List; + +import org.apache.struts2.StrutsTestCase; + +public class ConfigTest extends StrutsTestCase { + + protected void assertSuccess(String result) throws Exception { + assertTrue("Expected a success result!", + ActionSupport.SUCCESS.equals(result)); + } + + protected void assertInput(String result) throws Exception { + assertTrue("Expected an input result!", + ActionSupport.INPUT.equals(result)); + } + + protected Map assertFieldErrors(ActionSupport action) throws Exception { + assertTrue(action.hasFieldErrors()); + return action.getFieldErrors(); + } + + protected void assertFieldError(Map field_errors, String field_name, String error_message) { + + List errors = (List) field_errors.get(field_name); + assertNotNull("Expected errors for " + field_name, errors); + assertTrue("Expected errors for " + field_name, errors.size()>0); + // TODO: Should be a loop + assertEquals(error_message,errors.get(0)); + + } + + protected void setUp() throws Exception { + super.setUp(); + XmlConfigurationProvider c = new XmlConfigurationProvider("struts.xml"); + configurationManager.addConfigurationProvider(c); + configurationManager.reload(); + } + + protected ActionConfig assertClass(String namespace, String action_name, String class_name) { + RuntimeConfiguration configuration = configurationManager.getConfiguration().getRuntimeConfiguration(); + ActionConfig config = configuration.getActionConfig(namespace, action_name); + assertNotNull("Mssing action", config); + assertTrue("Wrong class name: [" + config.getClassName() + "]", + class_name.equals(config.getClassName())); + return config; + } + + protected ActionConfig assertClass(String action_name, String class_name) { + return assertClass("", action_name, class_name); + } + + protected void assertResult(ActionConfig config, String result_name, String result_value) { + Map results = config.getResults(); + ResultConfig result = (ResultConfig) results.get(result_name); + Map params = result.getParams(); + String value = (String) params.get("actionName"); + if (value == null) + value = (String) params.get("location"); + assertTrue("Wrong result value: [" + value + "]", + result_value.equals(value)); + } + + public void testConfig() throws Exception { + assertNotNull(configurationManager); + } + +} diff --git a/STRUTS_2_0_X/apps/blank/src/test/java/example/HelloWorldTest.java b/STRUTS_2_0_X/apps/blank/src/test/java/example/HelloWorldTest.java new file mode 100644 index 000000000..9239a706e --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/test/java/example/HelloWorldTest.java @@ -0,0 +1,37 @@ +/* + * $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 example; + +import com.opensymphony.xwork2.ActionSupport; +import junit.framework.TestCase; + +public class HelloWorldTest extends TestCase { + + public void testHelloWorld() throws Exception { + HelloWorld hello_world = new HelloWorld(); + String result = hello_world.execute(); + assertTrue("Expected a success result!", + ActionSupport.SUCCESS.equals(result)); + assertTrue("Expected the default message!", + hello_world.getText(HelloWorld.MESSAGE).equals(hello_world.getMessage())); + } +} diff --git a/STRUTS_2_0_X/apps/blank/src/test/java/example/LoginTest.java b/STRUTS_2_0_X/apps/blank/src/test/java/example/LoginTest.java new file mode 100644 index 000000000..72b761dac --- /dev/null +++ b/STRUTS_2_0_X/apps/blank/src/test/java/example/LoginTest.java @@ -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 example; + +import com.opensymphony.xwork2.ActionSupport; +import com.opensymphony.xwork2.config.entities.ActionConfig; + +import java.util.Map; + +public class LoginTest extends ConfigTest { + + public void FIXME_testLoginConfig() throws Exception { + ActionConfig config = assertClass("example", "Login_input", "example.Login"); + assertResult(config, ActionSupport.SUCCESS, "Menu"); + assertResult(config, ActionSupport.INPUT, "/example/Login.jsp"); + } + + public void testLoginSubmit() throws Exception { + Login login = new Login(); + login.setUsername("username"); + login.setPassword("password"); + String result = login.execute(); + assertSuccess(result); + } + + // Needs access to an envinronment that includes validators + public void FIXME_testLoginSubmitInput() throws Exception { + Login login = new Login(); + String result = login.execute(); + assertInput(result); + Map errors = assertFieldErrors(login); + assertFieldError(errors,"username","Username is required."); + assertFieldError(errors,"password","Password is required."); + } + +} diff --git a/STRUTS_2_0_X/apps/mailreader/README.txt b/STRUTS_2_0_X/apps/mailreader/README.txt new file mode 100644 index 000000000..802aea4d4 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/README.txt @@ -0,0 +1,18 @@ +README.txt - mailreader + +The MailReader demonstrates a localized application with a master/child +CRUD workflow. + +This rendition also demonstrates using wildcards to "normalize" an +application. + +See the Sandbox for other MailReader examples using other architectures. + +* http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2/apps/ + +For more about the MailReader applicaton genneraly, visit Struts University. + +* http://www.StrutsUniversity.org/ + + +---------------------------------------------------------------------------- \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/mailreader/pom.xml b/STRUTS_2_0_X/apps/mailreader/pom.xml new file mode 100644 index 000000000..cc13cdd8d --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + + org.apache.struts + struts2-apps + 2.0.14 + + org.apache.struts + struts2-mailreader + war + Starter Webapp + + + scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps/mailreader + scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps/mailreader + http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_0_14/apps/mailreader + + + + + + javax.servlet + servlet-api + 2.4 + provided + + + ${pom.groupId} + struts-mailreader-dao + 1.3.5 + + + + + + + src/main/java + + **/*.xml + **/*.properties + + + + + + org.mortbay.jetty + maven-jetty-plugin + 6.0.1 + + 10 + + + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/alternate.properties b/STRUTS_2_0_X/apps/mailreader/src/main/java/alternate.properties new file mode 100644 index 000000000..03dbf277b --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/alternate.properties @@ -0,0 +1,3 @@ +password=Enter your Password here ==> +struts.logo.path=struts-power.gif +struts.logo.alt=Powered by Struts diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/alternate_ja.properties b/STRUTS_2_0_X/apps/mailreader/src/main/java/alternate_ja.properties new file mode 100644 index 000000000..981adc82c --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/alternate_ja.properties @@ -0,0 +1 @@ +.password=\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b==> diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader-default.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader-default.xml new file mode 100644 index 000000000..0e7ed9669 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader-default.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + /pages/Error.jsp + /pages/Error.jsp + Login_input + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader-support.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader-support.xml new file mode 100644 index 000000000..b1b1859f5 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader-support.xml @@ -0,0 +1,63 @@ + + + + + + + + /tour.html + + + + + /Welcome.jsp + + + + + Welcome + + + + /Login.jsp + Welcome + MainMenu + ChangePassword + + + + + + /Registration.jsp + MainMenu + + + + + + + + /Subscription.jsp + Registration_input + + + + + + + + + + + + + + /{1}.jsp + + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/ApplicationListener.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/ApplicationListener.java new file mode 100644 index 000000000..fabd98d6e --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/ApplicationListener.java @@ -0,0 +1,234 @@ +/* + * $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 mailreader2; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUserDatabase; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import java.io.*; + +/** + *

ServletContextListener that initializes and finalizes the + * persistent storage of User and Subscription information for the Struts + * Demonstration Application, using an in-memory database backed by an XML + * file.

+ *

+ *

IMPLEMENTATION WARNING - If this web application is run + * from a WAR file, or in another environment where reading and writing of the + * web application resource is impossible, the initial contents will be copied + * to a file in the web application temporary directory provided by the + * container. This is for demonstration purposes only - you should + * NOT assume that files written here will survive a restart + * of your servlet container.

+ *

+ *

This class was borrowed from the Shale Mailreader. Changes were:

+ *

+ *

    + *

    + *

  • Path to database.xml (under classes here).
  • + *

    + *

  • Class to store protocol list (an array here).
  • + *

    + *

+ *

+ * DEVELOPMENT NOTE - Another approach would be to instantiate the database via Spring. + *

+ */ + +public final class ApplicationListener implements ServletContextListener { + + // ------------------------------------------------------ Manifest Constants + + + /** + *

Appication scope attribute key under which the in-memory version of + * our database is stored.

+ */ + public static final String DATABASE_KEY = "database"; + + + /** + *

Application scope attribute key under which the valid selection + * items for the protocol property is stored.

+ */ + public static final String PROTOCOLS_KEY = "protocols"; + + // ------------------------------------------------------ Instance Variables + + + /** + *

The ServletContext for this web application.

+ */ + private ServletContext context = null; + + + /** + * The {@link MemoryUserDatabase} object we construct and make available. + */ + private MemoryUserDatabase database = null; + + + /** + *

Logging output for this plug in instance.

+ */ + private Log log = LogFactory.getLog(this.getClass()); + + // ------------------------------------------------------------- Properties + + + /** + *

The web application resource path of our persistent database storage + * file.

+ */ + private String pathname = "/WEB-INF/database.xml"; + + /** + *

Return the application resource path to the database.

+ * + * @return application resource path path to the database + */ + public String getPathname() { + return (this.pathname); + } + + /** + *

Set the application resource path to the database.

+ * + * @param pathname to the database + */ + public void setPathname(String pathname) { + this.pathname = pathname; + } + + // ------------------------------------------ ServletContextListener Methods + + + /** + *

Gracefully shut down this database, releasing any resources that + * were allocated at initialization.

+ * + * @param event ServletContextEvent to process + */ + public void contextDestroyed(ServletContextEvent event) { + + log.info("Finalizing memory database plug in"); + + if (database != null) { + try { + database.close(); + } catch (Exception e) { + log.error("Closing memory database", e); + } + } + + context.removeAttribute(DATABASE_KEY); + context.removeAttribute(PROTOCOLS_KEY); + database = null; + context = null; + + } + + + /** + *

Initialize and load our initial database from persistent + * storage.

+ * + * @param event The context initialization event + */ + public void contextInitialized(ServletContextEvent event) { + + log.info("Initializing memory database plug in from '" + + pathname + "'"); + + // Remember our associated ServletContext + this.context = event.getServletContext(); + + // Construct a new database and make it available + database = new MemoryUserDatabase(); + try { + String path = calculatePath(); + if (log.isDebugEnabled()) { + log.debug(" Loading database from '" + path + "'"); + } + database.setPathname(path); + database.open(); + } catch (Exception e) { + log.error("Opening memory database", e); + throw new IllegalStateException("Cannot load database from '" + + pathname + "': " + e); + } + context.setAttribute(DATABASE_KEY, database); + + } + + // -------------------------------------------------------- Private Methods + + + /** + *

Calculate and return an absolute pathname to the XML file to contain + * our persistent storage information.

+ * + * @throws Exception if an input/output error occurs + */ + private String calculatePath() throws Exception { + + // Can we access the database via file I/O? + String path = context.getRealPath(pathname); + if (path != null) { + return (path); + } + + // Does a copy of this file already exist in our temporary directory + File dir = (File) + context.getAttribute("javax.servlet.context.tempdir"); + File file = new File(dir, "struts-example-database.xml"); + if (file.exists()) { + return (file.getAbsolutePath()); + } + + // Copy the static resource to a temporary file and return its path + InputStream is = + context.getResourceAsStream(pathname); + BufferedInputStream bis = new BufferedInputStream(is, 1024); + FileOutputStream os = + new FileOutputStream(file); + BufferedOutputStream bos = new BufferedOutputStream(os, 1024); + byte buffer[] = new byte[1024]; + while (true) { + int n = bis.read(buffer); + if (n <= 0) { + break; + } + bos.write(buffer, 0, n); + } + bos.close(); + bis.close(); + return (file.getAbsolutePath()); + + } + + +} diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/AuthenticationInterceptor.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/AuthenticationInterceptor.java new file mode 100644 index 000000000..10cc36823 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/AuthenticationInterceptor.java @@ -0,0 +1,31 @@ +package mailreader2; + +import com.opensymphony.xwork2.interceptor.Interceptor; +import com.opensymphony.xwork2.ActionInvocation; +import com.opensymphony.xwork2.Action; +import java.util.Map; +import org.apache.struts.apps.mailreader.dao.User; + +public class AuthenticationInterceptor implements Interceptor { + + public void destroy () {} + + public void init() {} + + public String intercept(ActionInvocation actionInvocation) throws Exception { + + Map session = actionInvocation.getInvocationContext().getSession(); + + User user = (User) session.get(Constants.USER_KEY); + + boolean isAuthenticated = (null!=user) && (null!=user.getDatabase()); + + if (!isAuthenticated) { + return Action.LOGIN; + } + else { + return actionInvocation.invoke(); + } + + } +} diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Constants.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Constants.java new file mode 100644 index 000000000..f33b771dd --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Constants.java @@ -0,0 +1,128 @@ +/* + * $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 mailreader2; + +/** + *

Manifest constants for the MailReader application.

+ */ +public final class Constants { + + // --- Tokens ---- + + /** + *

The token representing a "cancel" request.

+ */ + public static final String CANCEL = "cancel"; + + /** + *

The token representing a "create" task.

+ */ + public static final String CREATE = "Create"; + + /** + *

The application scope attribute under which our user database is + * stored.

+ */ + public static final String DATABASE_KEY = "database"; + + /** + *

The token representing a "edit" task.

+ */ + public static final String DELETE = "Delete"; + + /** + *

The token representing a "edit" task.

+ */ + public static final String EDIT = "Edit"; + + /** + *

The package name for this application.

+ */ + public static final String PACKAGE = "org.apache.struts.apps.mailreader"; + + /** + *

The session scope attribute under which the Subscription object + * currently selected by our logged-in User is stored.

+ */ + public static final String SUBSCRIPTION_KEY = "subscription"; + + /** + *

The session scope attribute under which the User object for the + * currently logged in user is stored.

+ */ + public static final String USER_KEY = "user"; + + /** + *

The token representing the "Host" property. + */ + public static final String HOST = "host"; + + + // ---- Error Messages ---- + + /** + *

+ * A static message in case message resource is not loaded. + *

+ */ + public static final String ERROR_MESSAGES_NOT_LOADED = + "ERROR: Message resources not loaded -- check servlet container logs for error messages."; + + /** + *

+ * A static message in case database resource is not loaded. + *

+ */ + public static final String ERROR_DATABASE_NOT_LOADED = + "ERROR: User database not loaded -- check servlet container logs for error messages."; + + /** + *

+ * A standard key from the message resources file, to test if it is available. + *

+ */ + public static final String ERROR_DATABASE_MISSING = "error.database.missing"; + + /** + *

+ * A "magic" username to trigger an ExpiredPasswordException for testing. + *

+ */ + public static final String EXPIRED_PASSWORD_EXCEPTION = "ExpiredPasswordException"; + + /** + *

+ * Name of field to associate with authentification errors. + *

+ */ + public static final String PASSWORD_MISMATCH_FIELD = "password"; + + // ---- Log Messages ---- + + /** + *

Message to log if saving a user fails.

+ */ + public static final String LOG_DATABASE_SAVE_ERROR = + " Unexpected error when saving User: "; + + +} diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Login-validation.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Login-validation.xml new file mode 100644 index 000000000..4a04c7629 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Login-validation.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Login.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Login.java new file mode 100644 index 000000000..0efa19b10 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Login.java @@ -0,0 +1,48 @@ +/* + * $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 mailreader2; + +import org.apache.struts.apps.mailreader.dao.User; +import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException; + +/** + *

Validate a user login.

+ */ +public final class Login extends MailreaderSupport { + + public String execute() throws ExpiredPasswordException { + + User user = findUser(getUsername(), getPassword()); + + if (user != null) { + setUser(user); + } + + if (hasErrors()) { + return INPUT; + } + + return SUCCESS; + + } + +} diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Logout.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Logout.java new file mode 100644 index 000000000..20732966a --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Logout.java @@ -0,0 +1,35 @@ +/* + * $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 mailreader2; + +/** + *

Log user out of the current session.

+ */ +public class Logout extends MailreaderSupport { + + public String execute() { + + setUser(null); + + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.java new file mode 100644 index 000000000..50ca23a5c --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.java @@ -0,0 +1,582 @@ +/* + * $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 mailreader2; + +import org.apache.struts2.interceptor.ApplicationAware; +import org.apache.struts2.interceptor.SessionAware; +import com.opensymphony.xwork2.ActionSupport; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts.apps.mailreader.dao.ExpiredPasswordException; +import org.apache.struts.apps.mailreader.dao.Subscription; +import org.apache.struts.apps.mailreader.dao.User; +import org.apache.struts.apps.mailreader.dao.UserDatabase; +import org.apache.struts.apps.mailreader.dao.impl.memory.MemorySubscription; +import org.apache.struts.apps.mailreader.dao.impl.memory.MemoryUser; +import java.util.Map; + +/** + *

Base Action for MailreaderSupport application.

+ *

+ *

Note that this class does NOT implement model driven because of the way + * the pre-existing model is designed. The MailReader DAO includes immutable + * fields that can only be set on construction, and some objects do not have a + * default construction. One approach would be to mirror all the DAO + * properties on the Actions. As an alternative, this implementations uses the + * DAO properties where possible, and uses local Action properties only as + * needed. To create new objects, a blank temporary object is constructed, and + * the page uses a mix of local Action properties and DAO properties. When the + * new object is to be saved, the local Action properties are used to create + * the object using the DAO factory methods, the input values are copied from + * the temporary object, and the new object is saved. It's kludge, but it + * avoids creating unnecessary local properties. Pick your poison.

+ */ +public class MailreaderSupport extends ActionSupport + implements SessionAware, ApplicationAware { + + /** + * Return CANCEL so apropriate result can be selected. + * @return "cancel" so apropriate result can be selected. + */ + public String cancel() { + return Constants.CANCEL; + } + + /** + * Convenience method to copy User properties. + **/ + protected void copyUser(User source, User target) { + if ((source==null) || (target==null)) return; + target.setFromAddress(source.getFromAddress()); + target.setFullName(source.getFullName()); + target.setPassword(source.getPassword()); + target.setReplyToAddress(source.getReplyToAddress()); + } + + /** + * Convenience method to copy Subscription properties. + **/ + protected void copySubscription(Subscription source, Subscription target) { + if ((source==null) || (target==null)) return; + target.setAutoConnect(source.getAutoConnect()); + target.setPassword(source.getPassword()); + target.setType(source.getType()); + target.setUsername(source.getUsername()); + } + + + // ---- ApplicationAware ---- + + /** + *

Field to store application context or its proxy.

+ *

+ *

The application context lasts for the life of the application. A + * reference to the database is stored in the application context at + * startup.

+ */ + private Map application; + + /** + *

Store a new application context.

+ * + * @param value A Map representing application state + */ + public void setApplication(Map value) { + application = value; + } + + /** + *

Provide application context.

+ */ + public Map getApplication() { + return application; + } + + // ---- SessionAware ---- + + /** + *

Field to store session context, or its proxy.

+ */ + private Map session; + + /** + *

Store a new session context.

+ * + * @param value A Map representing session state + */ + public void setSession(Map value) { + session = value; + } + + /** + *

Provide session context.

+ * + * @return session context + */ + public Map getSession() { + return session; + } + + // ---- Task property (utilized by UI) ---- + + /** + *

Field to store workflow task.

+ *

+ *

The Task is used to track the state of the CRUD workflows. It can be + * set to Constant.CREATE, Constant.EDIT, or Constant.DELETE as + * needed.

+ */ + private String task = null; + + + /** + *

Provide worklow task.

+ * + * @return Returns the task. + */ + public String getTask() { + return task; + } + + /** + *

Store new workflow task.

+ * + * @param value The task to set. + */ + public void setTask(String value) { + task = value; + } + + // ---- Token property (utilized by UI) ---- + + /** + *

Field to store double-submit guard.

+ */ + private String token = null; + + + /** + *

Provide Token.

+ * + * @return Returns the token. + */ + public String getToken() { + return token; + } + + /** + *

Store new Token.

+ * + * @param value The token to set. + */ + public void setToken(String value) { + token = value; + } + + + // ---- Host property ---- + + /** + *

Field to store Subscription host.

+ *

+ *

The host is an immutable property of the Subscrtion DAP object, so + * we need to store it locally until we are ready to create the + * Subscription.

+ */ + private String host; + + /** + *

Provide tSubscription host.

+ * + * @return host property + */ + public String getHost() { + return host; + } + + /** + *

Store new Subscription host.

+ * + * @param value + */ + public void setHost(String value) { + host = value; + } + + // ---- Password property ---- + + /** + *

Field to store User password property.

+ *

+ *

The User DAO object password proerty is immutable, so we store it + * locally until we are ready to create the object.

+ */ + private String password = null; + + + /** + *

Provide User password

+ * + * @return Returns the password. + */ + public String getPassword() { + return password; + } + + /** + *

Store new User Password

+ * + * @param value The password to set. + */ + public void setPassword(String value) { + password = value; + } + + // ---- Password2 property (confirmation) ---- + + /** + *

Field to store the User password confirmation.

+ *

+ *

When a User object is created, we ask the client to enter the + * password twice, to help ensure the password is being typed + * correctly.

+ */ + private String password2 = null; + + + /** + *

Provide the User password confirmation.

+ * + * @return Returns the confirmationpassword. + */ + public String getPassword2() { + return password2; + } + + /** + *

Store a new User password confirmation.

+ * + * @param value The confirmation password to set. + */ + public void setPassword2(String value) { + password2 = value; + } + + // ---- Username property ---- + + /** + *

Field to store User username.

+ *

+ *

The User DAO object password proerty is immutable, so we store it + * locally until we are ready to create the object.

+ */ + private String username = null; + + + /** + *

Provide User username.

+ * + * @return Returns the User username. + */ + public String getUsername() { + return username; + } + + /** + *

Store new User username

+ * + * @param value The username to set. + */ + public void setUsername(String value) { + username = value; + } + + // ---- Database property ---- + + /** + *

Provide reference to UserDatabase, or null if the database is not + * available.

+ * + * @return a reference to the UserDatabase or null if the database is not + * available + */ + public UserDatabase getDatabase() { + Object db = getApplication().get(Constants.DATABASE_KEY); + if (db == null) { + this.addActionError(getText("error.database.missing")); + } + return (UserDatabase) db; + } + + /** + *

Store a new reference to UserDatabase

+ * + * @param database + */ + public void setDatabase(UserDatabase database) { + getApplication().put(Constants.DATABASE_KEY, database); + } + + // ---- User property ---- + + /** + *

Provide reference to User object for authenticated user.

+ * + * @return User object for authenticated user. + */ + public User getUser() { + return (User) getSession().get(Constants.USER_KEY); + } + + /** + *

Store new reference to User Object.

+ * + * @param user User object for authenticated user + */ + public void setUser(User user) { + getSession().put(Constants.USER_KEY, user); + } + + /** + *

Obtain User object from database, or return null if the credentials + * are not found or invalid.

+ * + * @param username User username + * @param password User password + * @return User object or null if not found + * @throws ExpiredPasswordException + */ + public User findUser(String username, String password) + throws ExpiredPasswordException { + // FIXME: Stupid testing hack to compensate for inadequate DAO layer + if (Constants.EXPIRED_PASSWORD_EXCEPTION.equals(username)) { + throw new ExpiredPasswordException(Constants.EXPIRED_PASSWORD_EXCEPTION); + } + + User user = getDatabase().findUser(username); + if ((user != null) && !user.getPassword().equals(password)) { + user = null; + } + if (user == null) { + this.addFieldError(Constants.PASSWORD_MISMATCH_FIELD, + getText("error.password.mismatch")); + } + return user; + } + + /** + *

Log instance for this application.

+ */ + protected Log log = LogFactory.getLog(Constants.PACKAGE); + + /** + *

Persist the User object, including subscriptions, to the database. + *

+ * + * @throws java.lang.Exception on database error + */ + public void saveUser() throws Exception { + try { + getDatabase().save(); + } catch (Exception e) { + String message = Constants.LOG_DATABASE_SAVE_ERROR + getUser() + .getUsername(); + log.error(message, e); + throw new Exception(message, e); + } + } + + public void createInputUser() { + User user = new MemoryUser(null, null); + setUser(user); + } + + /** + *

Verify input for creating a new user, create the user, and process + * the login.

+ * + * @return A new User and empty Errors if create succeeds, or null and + * Errors if create fails + */ + public User createUser(String username, String password) { + + UserDatabase database = getDatabase(); + User user; + + try { + user = database.findUser(username); + } + + catch (ExpiredPasswordException e) { + user = getUser(); // Just so that it is not null + } + + if (user != null) { + this.addFieldError("username", "error.username.unique"); + return null; + } + + return database.createUser(username); + } + + // Since user.username is immutable, we have to use some local properties + + /** + *

Use the current User object to create a new User object, and make + * the new User object the authenticated user.

+ *

+ *

The "current" User object is usually a temporary object being used + * to capture input.

+ * + * @param _username User username + * @param _password User password + */ + public void copyUser(String _username, String _password) { + User input = getUser(); + input.setPassword(_password); + User user = createUser(_username, _password); + if (null != user) { + copyUser(input,user); + setUser(user); + } + } + + // ---- Subscription property ---- + + /** + *

Obtain the cached Subscription object, if any.

+ * + * @return Cached Subscription object or null + */ + public Subscription getSubscription() { + return (Subscription) getSession().get(Constants.SUBSCRIPTION_KEY); + } + + /** + *

Store new User Subscription.

+ * + * @param subscription + */ + public void setSubscription(Subscription subscription) { + getSession().put(Constants.SUBSCRIPTION_KEY, subscription); + } + + /** + *

Obtain User Subscription object for the given host, or return null + * if not found.

+ * + *

It would be possible for this code to throw a NullPointerException, + * but the ExceptionHandler in the xwork.xml will catch that for us.

+ * + * @return The matching Subscription or null + */ + public Subscription findSubscription(String host) { + Subscription subscription; + subscription = getUser().findSubscription(host); + return subscription; + } + + /** + *

Obtain uSER Subscription for the local Host property.

+ *

+ *

Usually, the host property will be set from the client request, + * because it was embedded in a link to the Subcription action. + * + * @return Subscription or null if not found + */ + public Subscription findSubscription() { + return findSubscription(getHost()); + } + + /** + *

Provide a "temporary" User Subscription object that can be used to + * capture input values.

+ */ + public void createInputSubscription() { + Subscription sub = new MemorySubscription(getUser(), null); + setSubscription(sub); + setHost(sub.getHost()); + } + + /** + *

Provide new User Subscription object for the given host, or null if + * the host is not unique.

+ * + * @param host + * @return New User Subscription object or null + */ + public Subscription createSubscription(String host) { + + Subscription sub; + + sub = findSubscription(host); + + if (null != sub) { + // FIXME - localization - "error.host.unique") + addFieldError(Constants.HOST,"That hostname is already defined"); + return null; + } + + return getUser().createSubscription(host); + } + + /** + *

Create a new Subscription from the current Subscription object, + * making the new Subscription the current Subscription.

+ *

+ *

Usually, the "current" Subscription is a temporary object being used + * to capture input values.

+ * + * @param host + */ + public void copySubscription(String host) { + Subscription input = getSubscription(); + Subscription sub = createSubscription(host); + if (null != sub) { + copySubscription(input, sub); + setSubscription(sub); + setHost(sub.getHost()); + } + } + + /** + *

Delete the current Subscription object from the database.

+ */ + public void removeSubscription() { + getUser().removeSubscription(getSubscription()); + getSession().remove(Constants.SUBSCRIPTION_KEY); + } + + /** + *

Provide MailServer Host for current User Subscription.

+ * + * @return MailServer Host for current User Subscription + */ + public String getSubscriptionHost() { + Subscription sub = getSubscription(); + if (null == sub) { + return null; + } + return sub.getHost(); + } + +} diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.properties b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.properties new file mode 100644 index 000000000..6a0f3a547 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport.properties @@ -0,0 +1,96 @@ +button.cancel=Cancel +button.confirm=Confirm +button.doSubmit=DO_SUBMIT +button.doReset=DO_RESULT +button.doCancel=org.apache.struts.taglib.html.CANCEL +button.reset=Reset +button.save=Save +change.message=Your password has expired. Please ask the system administrator to change it. +change.try=Try Again +change.title=Password Has Expired +database.load=Cannot load database from {0} +error.database.missing=User database is missing, cannot validate login credentials +error.fromAddress.format=Invalid format for From Address +error.fromAddress.required=From Address is required +error.fullName.required=Full Name is required +error.host.required=Mail Server is required +error.noSubscription=No Subscription bean in user session +error.password.expired=Your password has expired for username {0} +error.password.required=Password is required +error.password2.required=Confirmation password is required +error.password.match=Password and confirmation password must match +error.password.mismatch=Invalid username and/or password, please try again +error.replyToAddress.format=Invalid format for Reply To Address +struts.messages.invalid.token=Cannot submit this form out of order +error.type.invalid=Server Type must be 'imap' or 'pop3' +error.type.required=Server Type is required +error.username.required=Username is required +error.username.unique=That username is already in use - please select another +errors.footer=
+errors.header=

Validation Error

You must correct the following error(s) before proceeding:

    +errors.prefix=
  • +errors.suffix=
  • +errors.ioException=I/O exception rendering error messages: {0} +expired.password=User Password has expired for {0} +heading.autoConnect=Auto +heading.subscriptions=Current Subscriptions +heading.host=Host Name +heading.user=User Name +heading.type=Server Type +heading.action=Action +index.heading=MailReader Demonstration Application Options +index.login=Log on to the MailReader Demonstration Application +index.registration=Register with the MailReader Demonstration Application +index.title=MailReader Demonstration Application +index.tour=A Walking Tour of the MailReader Demonstration Application +linkSubscription.io=I/O Error: {0} +linkSubscription.noSubscription=No subscription under attribute {0} +linkUser.io=I/O Error: {0} +linkUser.noUser=No user under attribute {0} +login.title=MailReader Demonstration Application - Login +mainMenu.heading=Main Menu Options for +mainMenu.logout=Log off MailReader Demonstration Application +mainMenu.registration=Edit your user registration profile +mainMenu.title=MailReader Demonstration Application - Main Menu +option.imap=IMAP Protocol +option.pop3=POP3 Protocol +# prompt. +host=Mail Server +password=Password +password2=(Repeat) Password +username=Username + +registration.addSubscription=Add +registration.deleteSubscription=Delete +registration.editSubscription=Edit +registration.title.create=Register for the MailReader Demonstration Application +registration.title.edit=Edit Registration for the MailReader Demonstration Application + +subscription.autoConnect=Auto Connect +subscription.password=Mail Password +subscription.type=Server Type +subscription.username=Mail Username +subscription.title.create=Create New Mail Subscription +subscription.title.delete=Delete Existing Mail Subscription +subscription.title.edit=Edit Existing Mail Subscription + +user.fromAddress=From Address +user.fullName=Full Name +user.replyToAddress=Reply To Address + +# Standard error messages for validator framework checks +errors.required=${getText(fieldName)} is required. +errors.minlength=${getText(fieldName)} cannot be less than {1} characters. +errors.maxlength=${getText(fieldName)} cannot be greater than {1} characters. +errors.invalid=${getText(fieldName)} is invalid. +errors.byte=${getText(fieldName)} must be an byte. +errors.short=${getText(fieldName)} must be an short. +errors.integer=${getText(fieldName)} must be an integer. +errors.long=${getText(fieldName)} must be an long. +errors.float=${getText(fieldName)} must be an float. +errors.double=${getText(fieldName)} must be an double. +errors.date=${getText(fieldName)} is not a date. +errors.range=${getText(fieldName)} is not in the range ${minLength} through ${maxLength}. +errors.creditcard=${getText(fieldName)} is not a valid credit card number. +errors.email=${getText(fieldName)} is an invalid e-mail address. +errors.literal=${getText(fieldName)} diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport_ja.properties b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport_ja.properties new file mode 100644 index 000000000..2b9d2e4b6 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport_ja.properties @@ -0,0 +1,89 @@ +button.cancel=\u30ad\u30e3\u30f3\u30bb\u30eb +button.confirm=\u78ba\u8a8d +button.reset=\u30ea\u30bb\u30c3\u30c8 +button.save=\u4fdd\u5b58 +change.message=\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F\u3002\u30B7\u30B9\u30C6\u30E0\u7BA1\u7406\u8005\u306B\u304A\u554F\u3044\u5408\u308F\u305B\u4E0B\u3055\u3044 +change.try=\u518D\u8A66\u884C +change.title=\u30d1\u30b9\u30ef\u30fc\u30c9\u671f\u9650\u5207\u308c +database.load= {0} \u304B\u3089\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u30ED\u30FC\u30C9\u3067\u304D\u307E\u305B\u3093 +error.database.missing=\u30E6\u30FC\u30B6\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30ED\u30B0\u30AA\u30F3\u306E\u8A8D\u8A3C\u304C\u51FA\u6765\u307E\u305B\u3093 +error.fromAddress.format=From\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093 +error.fromAddress.required=From\u30A2\u30C9\u30EC\u30B9\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044 +error.fullName.required=\u30D5\u30EB\u30CD\u30FC\u30E0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044 +error.host.required=\u30E1\u30FC\u30EB\u30B5\u30FC\u30D0\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044 +error.noSubscription=Subscription bean \u304c\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u4e2d\u306b\u3042\u308a\u307e\u305b\u3093 +error.password.expired=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F +error.password.required=\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u5FC5\u8981\u3067\u3059 +error.password2.required=\u30D1\u30B9\u30EF\u30FC\u30C9(\u78BA\u8A8D\u7528)\u304C\u5FC5\u8981\u3067\u3059 +error.password.match=\u30D1\u30B9\u30EF\u30FC\u30C9\u3068\u78BA\u8A8D\u7528\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E00\u81F4\u3057\u3066\u3044\u307E\u305B\u3093 +error.password.mismatch=\u30E6\u30FC\u30B6\u540D\u307E\u305F\u306F\u30D1\u30B9\u30EF\u30FC\u30C9\u304C\u4E0D\u6B63\u3067\u3059\u3002\u518D\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044 +error.replyToAddress.format=\u8FD4\u4FE1\u30A2\u30C9\u30EC\u30B9\u306E\u66F8\u5F0F\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093 +struts.messages.invalid.token=\u3053\u306E\u30D5\u30A9\u30FC\u30E0\u306E\u5185\u5BB9\u304C\u6B63\u3057\u304F\u306A\u3044\u305F\u3081\u9001\u4FE1\u3059\u308B\u3053\u3068\u304C\u51FA\u6765\u307E\u305B\u3093 +error.type.invalid=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u306F 'imap' \u304B 'pop3'\u306E\u3069\u3061\u3089\u304B\u3067\u306A\u3051\u308C\u3070\u306A\u308A\u307E\u305B\u3093 +error.type.required=\u30B5\u30FC\u30D0\u30BF\u30A4\u30D7\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044 +error.username.required=\u30E6\u30FC\u30B6\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044 +error.username.unique=\u305D\u306E\u30E6\u30FC\u30B6\u540D\u306F\u65E2\u306B\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u3002 \u5225\u306E\u30E6\u30FC\u30B6\u540D\u3092\u9078\u629E\u3057\u3066\u304F\u3060\u3055\u3044 +errors.footer=

+errors.header=

\u5165\u529b\u30c1\u30a7\u30c3\u30af\u30a8\u30e9\u30fc

\u4ee5\u4e0b\u306e\u30a8\u30e9\u30fc\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044:

    +errors.prefix=
  • +errors.suffix=
  • +errors.ioException=I/O\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f: {0} +expired.password=\u30E6\u30FC\u30B6 {0} \u306E\u30D1\u30B9\u30EF\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u304C\u904E\u304E\u307E\u3057\u305F +heading.autoConnect=\u81ea\u52d5\u63a5\u7d9a +heading.subscriptions=\u73fe\u5728\u306e\u8cfc\u8aad\u60c5\u5831 +heading.host=\u30db\u30b9\u30c8\u540d +heading.user=\u30e6\u30fc\u30b6\u540d +heading.type=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7 +heading.action=\u64cd\u4f5c +index.heading=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 \u30aa\u30d7\u30b7\u30e7\u30f3 +index.login=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3 +index.registration=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332 +index.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3(Struts 1.1-dev) +index.tour=\u30b5\u30f3\u30d7\u30eb\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u6563\u7b56\u3059\u308b +linkSubscription.io=I/O\u30a8\u30e9\u30fc: {0} +linkSubscription.noSubscription=\u5c5e\u6027 {0} \u306b\u8cfc\u8aad\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093 +linkUser.io=I/O\u30a8\u30e9\u30fc: {0} +linkUser.noUser=\u5c5e\u6027 {0} \u306b\u30e6\u30fc\u30b6\u60c5\u5831\u304c\u5b58\u5728\u3057\u307e\u305b\u3093 +login.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30ed\u30b0\u30aa\u30f3 +mainMenu.heading=\u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc +mainMenu.logout=MailReader \u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u30ed\u30b0\u30aa\u30d5 +mainMenu.registration=\u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u306e\u7de8\u96c6 +mainMenu.title=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e1\u30a4\u30f3\u30e1\u30cb\u30e5\u30fc +option.imap=IMAP \u30d7\u30ed\u30c8\u30b3\u30eb +option.pop3=POP3 \u30d7\u30ed\u30c8\u30b3\u30eb +# prompt. +autoConnect=\u81ea\u52d5\u63a5\u7d9a +fromAddress=From\u30a2\u30c9\u30ec\u30b9 +fullName=\u30d5\u30eb\u30cd\u30fc\u30e0 +mailHostname=\u30e1\u30fc\u30eb\u30b5\u30fc\u30d0 +mailPassword=\u30e1\u30fc\u30eb\u30d1\u30b9\u30ef\u30fc\u30c9 +mailServerType=\u30b5\u30fc\u30d0\u30bf\u30a4\u30d7 +mailUsername=\u30e1\u30fc\u30eb\u30e6\u30fc\u30b6\u540d +.password=\u30d1\u30b9\u30ef\u30fc\u30c9 +password2=\u30d1\u30b9\u30ef\u30fc\u30c9(\u78ba\u8a8d\u7528) +replyToAddress=\u8fd4\u4fe1\u30a2\u30c9\u30ec\u30b9 +username=\u30e6\u30fc\u30b6\u540d +registration.addSubscription=\u65b0\u898f\u4f5c\u6210 +registration.deleteSubscription=\u524a\u9664 +registration.editSubscription=\u7de8\u96c6 +registration.title.create=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30e6\u30fc\u30b6\u767b\u9332 +registration.title.edit=MailReader\u30c7\u30e2\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3 - \u30d7\u30ed\u30d5\u30a1\u30a4\u30eb\u7de8\u96c6 +subscription.title.create=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u65b0\u898f\u4f5c\u6210 +subscription.title.delete=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u524a\u9664 +subscription.title.edit=\u30e1\u30fc\u30eb\u8cfc\u8aad\u60c5\u5831\u306e\u7de8\u96c6 + +# Standard error messages for validator framework checks +errors.required=${getText(fieldName)} \u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044\u3002 +errors.minlength=${getText(fieldName)} \u306f {1} \u6587\u5b57\u4ee5\u4e0a\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002 +errors.maxlength=${getText(fieldName)} \u306f {2} \u6587\u5b57\u4ee5\u4e0b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002 +errors.invalid=${getText(fieldName)} \u306f\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002 +errors.byte=${getText(fieldName)} \u306fbyte\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002 +errors.short=${getText(fieldName)} \u306fshort\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002 +errors.integer=${getText(fieldName)} \u306finteger\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002 +errors.long=${getText(fieldName)} \u306flong\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002 +errors.float=${getText(fieldName)} \u306ffloat\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002 +errors.double=${getText(fieldName)} \u306fdouble\u578b\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002 +errors.date=${getText(fieldName)} \u306f\u65e5\u4ed8\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +errors.range=${getText(fieldName)} \u306f {1} \u304b\u3089 {2} \u306e\u9593\u3067\u306a\u3051\u308c\u3070\u306a\u308a\u307e\u305b\u3093\u3002 +errors.creditcard=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30af\u30ec\u30b8\u30c3\u30c8\u30ab\u30fc\u30c9\u756a\u53f7\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 +errors.email=${getText(fieldName)} \u306f\u6b63\u3057\u3044\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u3067\u306f\u3042\u308a\u307e\u305b\u3093\u3002 diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport_ru.properties b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport_ru.properties new file mode 100644 index 000000000..6c7a88ba2 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/MailreaderSupport_ru.properties @@ -0,0 +1,89 @@ +button.cancel=\u041e\u0442\u043c\u0435\u043d\u0438\u0442\u044c +button.confirm=\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044c +button.reset=\u0421\u0431\u0440\u043e\u0441\u0438\u0442\u044c +button.save=\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c +change.message=Your password has expired. Please ask the system administrator to change it. +change.try=Try Again +change.title=Password Has Expired +database.load=\u0411\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430 \u0438\u0437 {0} +error.database.missing=\u041d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f - \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0441\u0442\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e. +error.fromAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435. +error.fromAddress.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0430\u0434\u0440\u0435\u0441 \u0432 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442:'. +error.fullName.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f. +error.host.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440. +error.noSubscription=\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u0430 \u0432 \u0441\u0435\u0441\u0441\u0438\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f +error.password.expired=Your password has expired for username {0} +error.password.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0430\u0440\u043e\u043b\u044c. +error.password2.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f. +error.password.match=\u041f\u0430\u0440\u043e\u043b\u044c \u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u044f \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442. +error.password.mismatch=\u041d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u044f \u0438/\u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c - \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0441\u043d\u043e\u0432\u0430. +error.replyToAddress.format=\u0412 \u043f\u043e\u043b\u0435 '\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430:' \u0443\u043a\u0430\u0437\u0430\u043d \u0430\u0434\u0440\u0435\u0441 \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u0444\u043e\u0440\u043c\u0430\u0442\u0435. +struts.messages.invalid.token=\u042d\u0442\u0430 \u0444\u043e\u0440\u043c\u0430 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u0430 - \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445. +error.type.invalid=\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0442\u0438\u043f\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043b\u0438\u0448\u044c 'imap' \u0438\u043b\u0438 'pop3' +error.type.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 +error.username.required=\u0422\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f +error.username.unique=\u0423\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u0438\u043c\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0443\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f - \u0432\u044b\u0431\u0435\u0440\u0438\u0442\u0435, \u043f\u043e\u0436\u0430\u043b\u0443\u0439\u0441\u0442\u0430, \u0434\u0440\u0443\u0433\u043e\u0435 \u0438\u043c\u044f. +errors.footer=

+errors.header=

\u041e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438 \u0437\u0430\u043d\u0435\u0441\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445

\u0412\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u043d\u0438\u0436\u0435 \u043e\u0448\u0438\u0431\u043a\u0438:

    +errors.prefix=
  • +errors.suffix=
  • +errors.ioException=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0430\u0445: {0} +expired.password=User Password has expired for {0} +heading.autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 +heading.subscriptions=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 +heading.host=\u0421\u0435\u0440\u0432\u0435\u0440 +heading.user=\u0418\u043c\u044f +heading.type=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 +heading.action=\u0414\u0435\u0439\u0441\u0442\u0432\u0438\u0435 +index.heading=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' +index.login=\u0412\u043e\u0439\u0442\u0438 \u043a\u0430\u043a \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c +index.registration=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f +index.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' (Struts 1.1-dev) +index.tour=\u041e\u0431\u0437\u043e\u0440 \u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' +linkSubscription.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438): {0} +linkSubscription.noSubscription=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442. +linkUser.io=\u041e\u0448\u0438\u0431\u043a\u0430 \u0432\u0432\u043e\u0434\u0430/\u0432\u044b\u0432\u043e\u0434\u0430 (\u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f): {0} +linkUser.noUser=\u0410\u0442\u0440\u0438\u0431\u0443\u0442 {0} \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435 \u0438\u043b\u0438 \u043d\u0435 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442. +login.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b - \u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0438\u043c\u0435\u043d\u0438 \u0438 \u043f\u0430\u0440\u043e\u043b\u044f. +mainMenu.heading=\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0433\u043b\u0430\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u043d\u044e \u0434\u043b\u044f +mainMenu.logout=\u0412\u044b\u0439\u0442\u0438 +mainMenu.registration=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 +mainMenu.title=\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 '\u0427\u0442\u0435\u043d\u0438\u0435 \u043f\u043e\u0447\u0442\u044b' - \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043c\u0435\u043d\u044e +option.imap=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b IMAP +option.pop3=\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b POP3 +# prompt. +autoConnect=\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435: +fromAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442: +fullName=\u041f\u043e\u043b\u043d\u043e\u0435 \u0438\u043c\u044f: +mailHostname=\u041f\u043e\u0447\u0442\u043e\u0432\u044b\u0439 \u0441\u0435\u0440\u0432\u0435\u0440: +mailPassword=\u041f\u0430\u0440\u043e\u043b\u044c \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430: +mailServerType=\u0422\u0438\u043f \u0441\u0435\u0440\u0432\u0435\u0440\u0430: +mailUsername=\u0418\u043c\u044f \u0434\u043b\u044f \u043f\u043e\u0447\u0442\u043e\u0432\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430: +password=\u041f\u0430\u0440\u043e\u043b\u044c: +password2=(\u041f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435) \u041f\u0430\u0440\u043e\u043b\u044c: +replyToAddress=\u0410\u0434\u0440\u0435\u0441 \u041e\u0442\u0432\u0435\u0442\u0438\u0442\u044c \u043d\u0430: +username=\u0418\u043c\u044f: +registration.addSubscription=\u0414\u043e\u0431\u0430\u0432\u0438\u0442\u044c +registration.deleteSubscription=\u0423\u0434\u0430\u043b\u0438\u0442\u044c +registration.editSubscription=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c +registration.title.create=\u0417\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f +registration.title.edit=\u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0441\u0432\u043e\u0435\u0439 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 +subscription.title.create=\u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 +subscription.title.delete=\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 +subscription.title.edit=\u0420\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 + +# Standard error messages for validator framework checks +errors.required=${getText(fieldName)} is required. +errors.minlength=${getText(fieldName)} cannot be less than {1} characters. +errors.maxlength=${getText(fieldName)} cannot be greater than {2} characters. +errors.invalid=${getText(fieldName)} is invalid. +errors.byte=${getText(fieldName)} must be an byte. +errors.short=${getText(fieldName)} must be an short. +errors.integer=${getText(fieldName)} must be an integer. +errors.long=${getText(fieldName)} must be an long. +errors.float=${getText(fieldName)} must be an float. +errors.double=${getText(fieldName)} must be an double. +errors.date=${getText(fieldName)} is not a date. +errors.range=${getText(fieldName)} is not in the range {1} through {2}. +errors.creditcard=${getText(fieldName)} is not a valid credit card number. +errors.email=${getText(fieldName)} is an invalid e-mail address. diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration-Registration_save-validation.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration-Registration_save-validation.xml new file mode 100644 index 000000000..689640742 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration-Registration_save-validation.xml @@ -0,0 +1,28 @@ + + + + + + + + + + true + 4 + 10 + + + + + + + + + + + + password eq password2 + + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration-validation.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration-validation.xml new file mode 100644 index 000000000..44d66bc19 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration-validation.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration.java new file mode 100644 index 000000000..635fc0d59 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Registration.java @@ -0,0 +1,122 @@ +/* + * $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 mailreader2; + +import org.apache.struts.apps.mailreader.dao.User; + + +/** + *

    Insert or update a User object to the persistent store.

    + */ +public class Registration extends MailreaderSupport { + + /** + *

    Double check that there is not a valid User login.

    + * + * @return True if there is not a valid User login + */ + private boolean isCreating() { + User user = getUser(); + return (null == user) || (null == user.getDatabase()); + } + + /** + *

    Retrieve User object to edit or null if User does not exist.

    + * + * @return The "Success" result for this mapping + * @throws Exception on any error + */ + public String input() throws Exception { + + if (isCreating()) { + createInputUser(); + setTask(Constants.CREATE); + } else { + setTask(Constants.EDIT); + setUsername(getUser().getUsername()); + setPassword(getUser().getPassword()); + setPassword2(getUser().getPassword()); + } + + return INPUT; + } + + /** + *

    Insert or update a Registration.

    + * + * @return The "outcome" result code + * @throws Exception on any error + */ + public String save() throws Exception { + return execute(); + } + + /** + *

    Insert or update a User object to the persistent store.

    + *

    + *

    If a User is not logged in, then a new User is created and + * automatically logged in. Otherwise, the existing User is updated.

    + * + * @return The "outcome" result code + * @throws Exception on any error + */ + public String execute() + throws Exception { + + boolean creating = Constants.CREATE.equals(getTask()); + creating = creating && isCreating(); // trust but verify + + if (creating) { + + User user = findUser(getUsername(), getPassword()); + boolean haveUser = (user != null); + + if (haveUser) { + addActionError(getText("error.username.unique")); + return INPUT; + } + + copyUser(getUsername(), getPassword()); + + } else { + + // FIXME: Any way to call the RegisrationSave validators from here? + String newPassword = getPassword(); + if (newPassword != null) { + String confirmPassword = getPassword2(); + boolean matches = ((null != confirmPassword) + && (confirmPassword.equals(newPassword))); + if (matches) { + getUser().setPassword(newPassword); + } else { + addActionError(getText("error.password.match")); + return INPUT; + } + } + } + + saveUser(); + + return SUCCESS; + } + +} diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription-Subscription_save-validation.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription-Subscription_save-validation.xml new file mode 100644 index 000000000..9f2f6d793 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription-Subscription_save-validation.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription-validation.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription-validation.xml new file mode 100644 index 000000000..df903c25b --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription-validation.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription.java new file mode 100644 index 000000000..a495986bc --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Subscription.java @@ -0,0 +1,145 @@ +/* + * $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 mailreader2; + +import com.opensymphony.xwork2.Preparable; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + *

    Provide an Edit method for retrieving an existing subscription, and a + * Save method for updating or inserting a subscription.

    + */ +public class Subscription extends MailreaderSupport + implements Preparable { + + /** + *

    Field to store list of MailServer types

    + */ + private Map types = null; + + /** + *

    Provide the list of MailServer types.

    + * + * @return List of MailServer types + */ + public Map getTypes() { + return types; + } + + /** + *

    Setup the MailerServer types and set the local Host property from + * the User Subscription (if any).

    + */ + public void prepare() { + + Map m = new LinkedHashMap(); + m.put("imap", "IMAP Protocol"); + m.put("pop3", "POP3 Protocol"); + types = m; + + setHost(getSubscriptionHost()); + } + + /** + *

    Setup a temporary User Subscription object to capture input + * values.

    + * + * @return INPUT + */ + public String input() { + createInputSubscription(); + setTask(Constants.CREATE); + return INPUT; + } + + /** + *

    Load User Subscription for the local Host property.

    + *

    + *

    Usually, the Host is being set from the request by a link to an Edit + * or Delete task.

    + * + * @return INPUT or Error, if Subscription is not found + */ + public String find() { + + org.apache.struts.apps.mailreader.dao.Subscription + sub = findSubscription(); + + if (sub == null) { + return ERROR; + } + + setSubscription(sub); + + return INPUT; + + } + + /** + *

    Prepare to present a confirmation page before removing + * Subscription.

    + * + * @return INPUT or Error, if Subscription is not found + */ + public String delete() { + + setTask(Constants.DELETE); + return find(); + } + + /** + *

    Prepare to edit User Subscription.

    + * + * @return INPUT or Error, if Subscription is not found + */ + public String edit() { + + setTask(Constants.EDIT); + return find(); + } + + /** + *

    Examine the Task property and DELETE, CREATE, or save the User + * Subscription, as appropriate.

    + * + * @return SUCCESS + * @throws Exception on a database error + */ + public String save() throws Exception { + + if (Constants.DELETE.equals(getTask())) { + removeSubscription(); + } + + if (Constants.CREATE.equals(getTask())) { + copySubscription(getHost()); + } + + if (hasErrors()) return INPUT; + + saveUser(); + return SUCCESS; + } + +} diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Welcome.java b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Welcome.java new file mode 100644 index 000000000..e43d6c463 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/mailreader2/Welcome.java @@ -0,0 +1,49 @@ +/* + * $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 mailreader2; + +/** + * Verify that essential resources are available. + */ +public class Welcome extends MailreaderSupport { + + public String execute() { + + // Confirm message resources loaded + String message = getText(Constants.ERROR_DATABASE_MISSING); + if (Constants.ERROR_DATABASE_MISSING.equals(message)) { + addActionError(Constants.ERROR_MESSAGES_NOT_LOADED); + } + + // Confirm database loaded + if (null==getDatabase()) { + addActionError(Constants.ERROR_DATABASE_NOT_LOADED); + } + + if (hasErrors()) { + return ERROR; + } + else { + return SUCCESS; + } + } +} diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/java/struts.xml b/STRUTS_2_0_X/apps/mailreader/src/main/java/struts.xml new file mode 100644 index 000000000..e0cbeb590 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/java/struts.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/resources/LICENSE.txt b/STRUTS_2_0_X/apps/mailreader/src/main/resources/LICENSE.txt new file mode 100644 index 000000000..dd5b3a58a --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/resources/LICENSE.txt @@ -0,0 +1,174 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/resources/NOTICE.txt b/STRUTS_2_0_X/apps/mailreader/src/main/resources/NOTICE.txt new file mode 100644 index 000000000..cd13ec449 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/resources/NOTICE.txt @@ -0,0 +1,5 @@ +Apache Struts +Copyright 2000-2007 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/ChangePassword.jsp b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/ChangePassword.jsp new file mode 100644 index 000000000..ce543d79b --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/ChangePassword.jsp @@ -0,0 +1,25 @@ +<%@ page contentType="text/html; charset=UTF-8" %> +<%@ taglib uri="/struts-tags" prefix="s" %> + + + + <s:text name="change.title"/> + " rel="stylesheet" + type="text/css"/> + + + + +

    + +

    + +

    + "> + + +

    + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Error.jsp b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Error.jsp new file mode 100644 index 000000000..05ab5e083 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Error.jsp @@ -0,0 +1,40 @@ +<%@ page contentType="text/html; charset=UTF-8" %> +<%@ taglib uri="/struts-tags" prefix="s" %> + + + + Unexpected Error + + + +

    An unexpected error has occured

    + +

    + Please report this error to your system administrator + or appropriate technical support personnel. + Thank you for your cooperation. +

    + +
    + +

    Error Message

    + + + +

    + +

    + +
    + +

    Technical Details

    + +

    + +

    + + + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Footer.jsp b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Footer.jsp new file mode 100644 index 000000000..56d80bbc0 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Footer.jsp @@ -0,0 +1,6 @@ +<%@ taglib uri="/struts-tags" prefix="s" %> +
    + +

    + "> +

    diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Login.jsp b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Login.jsp new file mode 100644 index 000000000..86db095ff --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Login.jsp @@ -0,0 +1,33 @@ +<%@ page contentType="text/html; charset=UTF-8" %> +<%@ taglib uri="/struts-tags" prefix="s" %> + + + + <s:text name="login.title"/> + " rel="stylesheet" + type="text/css"/> + + + + + + + + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/META-INF/context.xml b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/META-INF/context.xml new file mode 100644 index 000000000..9b0b5d00f --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/META-INF/context.xml @@ -0,0 +1,3 @@ + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/MainMenu.jsp b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/MainMenu.jsp new file mode 100644 index 000000000..b5321401c --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/MainMenu.jsp @@ -0,0 +1,26 @@ +<%@ page contentType="text/html; charset=UTF-8" %> +<%@ taglib uri="/struts-tags" prefix="s" %> + + + + <s:text name="mainMenu.title"/> + " rel="stylesheet" + type="text/css"/> + + + +

    + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Registration.jsp b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Registration.jsp new file mode 100644 index 000000000..884012405 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Registration.jsp @@ -0,0 +1,115 @@ +<%@ page contentType="text/html; charset=UTF-8" %> +<%@ taglib uri="/struts-tags" prefix="s" %> + + + + + <s:text name="registration.title.create"/> + + + <s:text name="registration.title.edit"/> + + " rel="stylesheet" + type="text/css"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    +
    + + + + + + + + + + + + + + + + + + + + + +
    + + + + + + + + + +
    + + + + + + + + + + "> + + +   + "> + + + +
    + + "> + +
    + + + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Subscription.jsp b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Subscription.jsp new file mode 100644 index 000000000..67323ccf6 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Subscription.jsp @@ -0,0 +1,60 @@ +<%@ page contentType="text/html; charset=UTF-8" %> +<%@ taglib uri="/struts-tags" prefix="s" %> + + + + + <s:text name="subscription.title.create"/> + + + <s:text name="subscription.title.edit"/> + + + <s:text name="subscription.title.delete"/> + + " rel="stylesheet" + type="text/css"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/WEB-INF/database.xml b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/WEB-INF/database.xml new file mode 100644 index 000000000..5710477aa --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/WEB-INF/database.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/WEB-INF/web.xml b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..0772ab2fe --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,30 @@ + + + + + Struts 2 Mailreader + + + Struts2 + + org.apache.struts2.dispatcher.FilterDispatcher + + + + + Struts2 + *.do + + + + + + mailreader2.ApplicationListener + + + + + index.html + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Welcome.jsp b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Welcome.jsp new file mode 100644 index 000000000..0ce3e5460 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/Welcome.jsp @@ -0,0 +1,55 @@ +<%@ page contentType="text/html; charset=UTF-8" %> +<%@ taglib uri="/struts-tags" prefix="s" %> + + + + + <s:text name="index.title"/> + " rel="stylesheet" + type="text/css"/> + + + +

    + + + +

    Language Options

    +
      +
    • + + en + + English +
    • +
    • + + ja + + Japanese +
    • +
    • + + ru + + Russian +
    • +
    + +
    + +

    + " + alt="" border="0px"/> + +

    + + + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/css/mailreader.css b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/css/mailreader.css new file mode 100644 index 000000000..bfc76487e --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/css/mailreader.css @@ -0,0 +1,46 @@ +/** +* Mailreader stylesheet +*/ + +body { + background-color: #FFFFFF; + color: #000000; + link: 000066; + visited: #660066; + active: #33CCCC; +} + +A:hover { + color: #FF0000; +} + +h1 { + font-family: Arial, Helvetica, sans-serif; +} + +h2 { + font-family: Arial, Helvetica, sans-serif; +} + +h3 { + font-family: Arial, Helvetica, sans-serif; +} + +h4 { + font-family: Arial, Helvetica, sans-serif; +} + +h5 { + font-family: Arial, Helvetica, sans-serif; +} + +h6 { + font-family: Arial, Helvetica, sans-serif; +} + +font.hint { + font-style: italic; + font-size: 80%; + font-family: Arial, Helvetica, sans-serif; + text-align: left; +} \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/index.html b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/index.html new file mode 100644 index 000000000..1b01b3fb3 --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/index.html @@ -0,0 +1,10 @@ + + + + + + + +

    Loading ...

    + + diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/struts-power.gif b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/struts-power.gif new file mode 100644 index 0000000000000000000000000000000000000000..5f4e9d426757b4416401ea4f7083e08480fac11b GIT binary patch literal 1798 zcmchW`BPI@6vuDEPL)O!su3_ifI?i*TU(Yv*&$dosV0ITNWm*{K~O750YL!=rW9F1 zy$m9yfJ(H`DQ*NUqA()Q1qM`?yA}(SWmZ2;|SO&8U;*ykMDP<{PDP}3+Y6-&<$`Zm7%o4=4 zVur<(#e~I}#R!yG#IT66h_DE=2m;UsY0!dZs7Blz?ooyz41*a4abqE(l%a&7n4yTH zfFz*|Aq>F`K^zp+V#;8`V9a0yjL^y;${@lZ%pjNw)F1}XKnYlogTbH;(x3&+h+Bw@ z;SowPrHI=P#zI60C72S#tqT;8#Dro@F@o&@3Ti1L6k&>BJ@5lCp&RUg{Q&|t1Zofi zXrP2r;DEuP4bq^6IOn)D#PBd7h%*xQgRu}{OfUjpVO^krBte)U@DZE_1Aq(4!D!eP ztOP#*6S~0;V1k8VL!bsRfQC-M0uC4q+8~X%6LHm$h8P}#i-D1_AB=?vBktqieAVBZ zOX^R^*{r_`SF1Ogb6xKp*Q&RJJA!^gPDu~V-9*p93G1cdbAT&>d9agyl>STn-+%0< zEyCjxHj7eKdlE$<(r_7C2sDWMcOcVg#51)CZLYa|&~&z2^tI-nuN)FMI%Mz@J1<+M zH-<(})R~7ATLvU$1ivo0tPu00r~C`WCo42x7glwTOS=!c2Hejevjoyg-`Pt0c?Kic z$3A{&NY$5JU2)5ef1=hzASzNI`y1(2?dHeiQq#Jr=LL4v{I@k?C%h=EbaN5^dfD~? z(U6hj9*uOA+i`_A_*L-p?-DP`2aMT;+>RsEG9rRu~ zCg-8&zGH2gh~I?jv#RsSis@Zns+N5*HM){lw|LZZbbNBldY(u{dv4t;g zHuBZOF@7yajeWC>a-6Jpy>J~V%Ru*(gP7+VGAAcH^U%8F*flV%?p z{B3wB`qAu`b_KjjW{g5zBumCwu!70~QQ;igSHRC+p2^ zlNtqP^?g?(^F7Z_#iUO+ILz4~`-wleb&I@1D9Jy0)6lNLX2lgdSvz_*QnZIJ6 zppH;O_2Ge%&Uay(l!g3S)%Us=DuL>c1Lx+iD&W_29ClWuxR$RCZyZW|SSUGMH__@9 zd%iAh{??0s=0yeV$$RYkZ=a=(>9P*UX&t&+4!9W~iE%T27Aj+(KT0u#X)*OSEl~64}

    a1+>C+=E}g~yqGRj0%yfM+92a`l?u zqbXi)U8Nb6FPI!3YO2>=lMS}+-6$Ij{4~(RFJAlkS2?yW&r+Ku+B+KE>iwCr;rs_j z-|Li(&8dC#k=|&#H-S!7tONL zLSqMdj~hCC)L0cSu-)nEJmLM^*Esvwt7{})7(H&%K4$wEWnJ%4T$)^@Nl@)$g}osj i->jUKVkC}vXd1Hcsk_Ov^jjj=nWP5!`xzM`@BaX)9*BDY literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/mailreader/src/main/webapp/tour.html b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/tour.html new file mode 100644 index 000000000..8da35136d --- /dev/null +++ b/STRUTS_2_0_X/apps/mailreader/src/main/webapp/tour.html @@ -0,0 +1,2470 @@ + + + + + + + + A Walking Tour of the Struts 2 MailReader Application + + + +

    +

    A Walking Tour of the Struts 2 MailReader Application

    + +

    + + This article is meant to introduce a new user to Apache Struts 2 by + "walking through" a simple, but functional, application. + The article includes code snippets, but for the best result, you might + want to install the MailReader application on your own development + workstation and follow along. + Of course, the full source code to the MailReader is included in the + distribution. + +

    + +

    + + The tour assumes the reader has a basic understanding of the Java + language, JavaBeans, web applications, and JavaServer Pages. For + background on these technologies, see the + + Key Technologies Primer. + +

    + +
    + + + + + + + + + + +
    + +

    + The premise of the MailReader is that it is the first iteration of a + portal application. + This version allows users to register and maintain a set of + accounts with various mail servers. + If completed, the application would let users read mail from their + accounts. +

    + +

    + The MailReader application demonstrates registering with an application, + logging into an application, maintaining a master record, and maintaining + child records. + This article overviews the constructs needed to do these things, + including the server pages, Java classes, and configuration elements. +

    + +

    + For more about the MailReader, including alternate implementations and a + set of formal Use Cases, + please visit the + Struts University MailReader site. +

    + +
    +
    +

    + JAAS - + Note that for compatibility and ease of deployment, the MailReader + uses "application-based" authorization. + However, use of the standard Java Authentication and Authorization + Service (JAAS) is recommended for most applications. + (See the + Key Technologies Primer for more about + authentication technologies.) +

    +
    +
    + +

    + The tour starts with how the initial welcome page is displayed, and + then steps through logging into the application and editing a subscription. + Please note that this not a quick peek at a "Hello World" application. + The tour is a rich trek into a realistic, best practices application. + You may need to adjust your chair and get a fresh cup of coffee. + Printed, the article is 29 pages long (US). +

    + +

    Welcome Page

    + +

    + A web application, like any other web site, can specify a list of welcome pages. + When you open a web application without specifying a particular page, a + default "welcome page" is served as the response. +

    + +

    web.xml

    + +

    + When a web application loads, + the container reads and parses the "Web Application Deployment + Descriptor", or "web.xml" file. + The framework plugs into a web application via a servlet filter. + Like any filter, the "struts2" filter is deployed via the "web.xml". +

    + +
    +
    web.xml - The Web Application Deployment Descriptor
    +
    <?xml version="1.0" encoding="ISO-8859-1"?>
    +<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    +  "http://java.sun.com/dtd/web-app_2_3.dtd">
    +<web-app>
    +
    +  <display-name>Struts 2 MailReader</display-name>
    +
    +  <filter>
    +    <filter-name>struts2</filter-name>
    +    <filter-class>
    +      org.apache.struts2.dispatcher.FilterDispatcher
    +    </filter-class>
    +   </filter>
    +
    +  <filter-mapping>
    +    <filter-name>struts2</filter-name>
    +    <url-pattern>/*</url-pattern>
    +  </filter-mapping>
    +
    +  <listener>
    +    <listener-class>
    +      org.springframework.web.context.ContextLoaderListener
    +    </listener-class>
    +  </listener>
    +
    +  <!-- Application Listener for MailReader database -->
    +  <listener>
    +    <listener-class>
    +      mailreader2.ApplicationListener
    +    </listener-class>
    +  </listener>
    +
    +  <welcome-file-list>
    +    <welcome-file>index.html</welcome-file>
    +  </welcome-file-list>
    +
    +  </web-app>
    +
    + +

    + You might note that the web.xml configuration does not specify which file extension + to use with actions. + The default extension for Struts 2 is ".action", + but the extension can be changed in the struts.properties file. + For compatability with prior releases, the MailReader uses a .do extension for actions. +

    + +
    +
    struts.properties
    +
    struts.action.extension = do
    +
    + +

    + The web.xml does specify a "Welcome File List" for the application. + When a web address refers to a directory rather than an individual file, + the container consults the Welcome File List for the name of a page to + open by default. +

    + +

    + However, most Struts applications do not refer to physical pages, + but to "virtual resources" called actions. + Actions specify code that we want to be run before a page + or other resource renders the response. + An accepted practice is to never link directly to server pages, + but only to logical action mappings. + By linking to actions, developers can often "rewire" an application + without editing the server pages. +

    + +
    +
    Best Practice:
    +
    +

    "Link actions not pages."

    +
    +
    + +

    + The actions are listed in one or more XML configuration files, + the default configuration file being named "struts.xml". + When the application loads, the struts.xml, and any other files + it includes, are parsed, and the framework creates a set of + configuration objects. + Among other things, the configuration maps a request for a certain + page to a certain action mapping. +

    + + +

    + Sites can list zero or more "Welcome" pages in the web.xml. + + Unless you are using Java 1.5, + actions cannot be specified as a Welcome page. + So, in the case of a Welcome page, + how do we follow the best practice of navigating through actions + rather than pages? +

    + +

    + One solution is to use a page to "bootstrap" one of our actions. + We can register the usual "index.html" as the Welcome page and have it + redirect to a "Welcome" action. +

    + +
    +
    MailReader's index.html
    +
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    +<html><head>
    +  <META HTTP-EQUIV="Refresh" CONTENT="0;URL=Welcome.do">
    +  </head>
    +  <body>
    +    <p>Loading ...</p>
    +</body></html>
    +
    + +

    + As an alternative, + we could also have used a JSP page that issued the redirect with a Struts tag, + but a plain HTML solution works as well. +

    + +

    Welcome.do

    + +

    + When the client requests "Welcome.do", the request is passed to the "struts2" + FilterDispatcher (that we registered in the web.xml file). + The FilterDispatcher retrieves the appropriate action mapping from the + configuration. + If we just wanted to forward to the Welcome page, we could use a simple + configuration element. +

    +
    +
    A simple "forward thru" action element
    +
    <action name="Welcome">
    +  <result>/pages/Welcome.jsp</result>
    +</action>
    +
    + +

    + If a client asks for the Welcome action ("Welcome.do"), the "/page/Welcome.jsp" + page would be returned in response. + The client does not know, or need to know, that the physical resource is located at + "/pages/Welcome.jsp". + All the client knows is that it requested the resource "Welcome.do". +

    + +

    + But if we peek at the configuration file for the MailReader, + we find a slightly more complicated XML element for the Welcome action. +

    + +
    +
    The Welcome action element
    +
    <action name="Welcome" class="mailreader2.Welcome">
    +    <result>/pages/Welcome.jsp</result>
    +    <interceptor-ref name="guest"/>
    +    </action>
    +
    + +

    + Here, the Welcome Java class executes whenever + someone asks for the Welcome action. + As it completes, the Action class can select which "result" is displayed. + The default result name is "success". + Another available result, defined at a global scope, is "error". +

    + +
    +
    Key concept:
    +
    +

    + The Action class doesn't need to know what result type is needed + for "success" or "error". + The Action can just return the logical name for a result, + without knowing how the result is implemented. +

    +
    +
    + +

    + The net effect is that all of the result details, + including the paths to server pages, + all can be declared once in the configuration. + Tightly coupled implementation details are not scattered all over + the application. +

    + +
    +
    Key concept:
    +
    +

    + The Struts configuration lets us separate concerns and "say it once". + The configuration helps us "normalize" an application, + in much the same way we normalize a database schema. +

    +
    +
    + + +

    + OK ... but why would a Welcome Action want to choose between "success" and + "error"? +

    + +

    Welcome Action

    + +

    + The MailReader application retains a list of users along with their email + accounts. + The application stores this information in a database. + If the application can't connect to the database, the application can't do + its job. + So before displaying the Welcome page, the Welcome + class checks to see if the database is available. +

    + +

    + The MailReader is also an internationalized application. + So, the Welcome Action class checks to see if the message resources are + available too. + If both resources are available, the class passes back the "success" token. + Otherwise, the class passes back the "error" token, + so that the appropriate messages can be displayed. +

    + +
    +
    The Welcome Action class
    +
    package mailreader2;
    +public class Welcome extends MailreaderSupport {
    +
    +  public String execute() {
    +
    +    // Confirm message resources loaded
    +    String message = getText(Constants.ERROR_DATABASE_MISSING);
    +    if (Constants.ERROR_DATABASE_MISSING.equals(message)) {
    +      addActionError(Constants.ERROR_MESSAGES_NOT_LOADED);
    +    }
    +
    +    // Confirm database loaded
    +    if (null==getDatabase()) {
    +      addActionError(Constants.ERROR_DATABASE_NOT_LOADED);
    +    }
    +
    +    if (hasErrors()) {
    +      return ERROR;
    +    }
    +    else {
    +      return SUCCESS;
    +    }
    +  }
    +}
    +
    + +

    + Several common result names are predefined, + including ERROR, SUCCESS, LOGIN, NONE, and INPUT, + so that these tokens can be used consistently across Struts 2 applications. +

    + + +

    Global Results

    + +

    + As mentioned, "error" is defined in a global scope. + Other actions may have trouble connecting to the database later, + or other unexpected errors may occur. + The MailReader defines the "error" result as a Global Result, + so that any action can use it. +

    + +
    +
    MailReader's global-result element
    +
     <global-results>
    +  <result name="error">/pages/Error.jsp</result>
    +  <result name="invalid.token">/pages/Error.jsp</result>
    +  <result name="login" type="redirect-action">Login_input</result>
    +</global-results>
    +
    + +

    + Of course, if an individual action mapping defines its own "error" result type, + the local result would be used instead. +

    + +

    ApplicationListener.java +

    + +

    + The database is exposed as an object stored in application scope. + The database object is based on an interface. + Different implementations of the database could be loaded without changing + the rest of the application. + But how is the database object loaded in the first place? +

    + +

    + The database is created by a custom Listener that we configured in the "web.xml". +

    + +
    +
    mailreader2.ApplicationListener
    +
     <listener>
    +  <listener-class>
    +    mailreader2.ApplicationListener
    +  </listener-class>
    +</listener>
    +
    + +

    + By default, our ApplicationListener loads a MemoryDatabase + implementation of the UserDatabase. + MemoryDatabase stores the database content as a XML document, + which is parsed and loaded as a set of nested hashtables. + The outer table is the list of user objects, each of which has its own + inner hashtable of subscriptions. + When you register, a user object is stored in this hashtable. + When you login, the user object is stored within the session context. +

    + +

    + The database comes seeded with a sample user. + If you check the "database.xml" file under "/src/main/resources", + you'll see the sample user described in XML. +

    + +
    +
    The "seed" user element from the MailReader database.xml
    +
    <user username="user" fromAddress="John.User@somewhere.com"
    +  fullName="John Q. User" password="pass">
    +    <subscription host="mail.hotmail.com" autoConnect="false"
    +      password="bar" type="pop3" username="user1234">
    +    </subscription>
    +    <subscription host="mail.yahoo.com" autoConnect="false" password="foo"
    +      type="imap" username="jquser">
    +    </subscription>
    +</user>
    +
    + +

    + The "seed" user element creates a registration record for "John Q. User", + with the subscription detail for his hotmail and yahoo accounts. +

    + +

    Message Resources +

    + +

    + As mentioned, MailReader is an internationalized application. + In Struts 2, message resources are associated with the Action class being processed. + If we check the source, we find a language resource bundle named + MailreaderSupport. + MailreaderSupport is our base class for all the MailReader Actions. + Since all of our Actions extend MailreaderSupport, + all of our Actions can use the same resource bundle. +

    + +
    +
    Message Resource entries used by the Welcome page
    +
    index.heading=MailReader Application Options
    +index.login=Log on to the MailReader Application
    +index.registration=Register with the MailReader Application
    +index.title=MailReader Demonstration Application
    +index.tour=A Walking Tour of the MailReader Demonstration Application
    +
    + +

    + If you change a message in the resource, and then rebuild and reload the + application, the change will appear throughout the application. + If you provide message resources for additional locales, you can + localize your application. + The MailReader provides resources for English, Russian, and Japanese. +

    + +

    Welcome Page

    + +

    + After confirming that the necessary resources exist, the Welcome action + forwards to the Welcome page. +

    +
    +
    Welcome.jsp
    +
    <%@ page contentType="text/html; charset=UTF-8" %>
    +<%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
    +  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    +    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    +  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    +    <head>
    +      <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    +      <title><s:text name="index.title"/></title>
    +      <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
    +      type="text/css"/>
    +    </head>
    +
    +    <body>
    +      <h3><s:text name="index.heading"/></h3>
    +
    +      <ul>
    +        <li><a href="<s:url action="Registration_input"/>"><s:text
    +          name="index.registration"/></a></li>
    +        <li><a href="<s:url action="Login_input"/>"><s:text
    +          name="index.login"/></a></li>
    +      </ul>
    +
    +      <h3>Language Options</h3>
    +      <ul>
    +          <li>
    +              <s:url id="en" action="Welcome">
    +                  <s:param name="request_locale">en</s:param>
    +              </s:url>
    +               <s:a href="%{en}">English</s:a>
    +           </li>
    +          <li>
    +              <s:url id="ja" action="Welcome">
    +                <s:param name="request_locale">ja</s:param>
    +              </s:url>
    +              <s:a href="%{ja}">Japanese</s:a>
    +          </li>
    +          <li>
    +              <s:url id="ru" action="Welcome">
    +              <s:param name="request_locale">ru</s:param>
    +              </s:url>
    +              <s:a href="%{ru}">Russian</s:a>
    +          </li>
    +      </ul>
    +
    +    <hr />
    +
    +    <p><s:i18n name="alternate">
    +    <img src="<s:text name="struts.logo.path"/>"
    +      alt="<s:text name="struts.logo.alt"/>"/>
    +    </s:i18n></p>
    +
    +    <p><a href="<s:url action="Tour" />"><s:text name="index.tour"/></a></p>
    +
    +  </body>
    +</html>
    +
    + +

    + At the top of the Welcome page, there are several directives that load the + Struts 2 tag libraries. + These are just the usual red tape that goes with any JSP file. + The rest of the page utilizes three Struts JSP tags: + "text", "url", and "i18n". +

    + +

    + (We use the tag prefix "s:" in the Struts 2 MailReader application, + but you can use whatever prefix you like in your applications.) +

    + +

    + The text tag inserts a message from an + application's default resource bundle. + If the framework's locale setting is changed for a user, + the text tag will render messages from the new locale's resource + bundle instead. +

    + +

    + The url tag can render a reference to an + action or any other web resource, + applying "URL encoding" to the hyperlinks as needed. + Java's URL encoding feature lets your application maintain client state + without requiring cookies. +

    + +
    +
    Tip:
    +
    +

    + Cookies - + If you turn cookies off in your browser, and then reload your browser + and this page, + you will see the links with the Java session id information attached. + (If you are using Internet Explorer and try this, + be sure you reset cookies for the appropriate security zone, + and that you disallow "per-session" cookies.) +

    +
    +
    + +

    + The i18n tag provides access to multiple resource bundles. + The MailReader application uses a second set of message resources for + non-text elements. + When these are needed, we use the "i18n" tag to specify a different bundle. +

    + +

    + The alternate bundle is stored in the {{/src/main/resources}} folder, + so that it ends up under "classes", which is on the application's class path. +

    + +

    + In the span of a single request for the Welcome page, the framework has done + quite a bit already: +

    + +
      +
    • + Confirmed that required resources were loaded during initialization. +
    • + +
    • + Written all the page headings and labels from internationalized + message resources. +
    • + +
    • + Automatically URL-encoded paths as needed. +
    • +
    + +

    + When rendered, the Welcome page lists two menu options: + one to register with the application and one to log on (if you have + already registered). + Let's follow the Login link first. +

    + +

    Login

    + +

    + If you choose the Login link, and all goes well, the Login action forwards + control to the Login page. +

    + +

    Login Page

    + +

    + The Login page displays a form that accepts a username and password. + You can use the default username and password to login + (user and pass), if + you like. Try omitting or misspelling the username and password in + various combinations to see how the application reacts. + Note that both the username and password are case sensitive. +

    + +
    +
    Login.jsp
    +
    <%@ page contentType="text/html; charset=UTF-8" %>
    +  <%@ taglib prefix="s" uri="http://struts.apache.org/tags"  %>
    +  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    +    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    +  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    +  <head>
    +    <title><s:text name="login.title"/></title>
    +      <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
    +        type="text/css"/>
    +  </head>
    +  <body onLoad="self.focus();document.Login.username.focus()">
    +    <s:actionerror/>
    +    <s:form action="Login" validate="true">
    +      <s:textfield key="username"/>
    +      <s:password key="password"/>
    +      <s:submit key="button.save"/>
    +      <s:reset key="button.reset"/>
    +      <s:submit action="Login_cancel" onclick="form.onsubmit=null"
    +        key="button.cancel"/>
    +    </s:form>
    +    <jsp:include page="Footer.jsp"/>
    +  </body>
    +</html>
    +
    + +

    + We already saw some of the tags used by the Login page on the Welcome page. + Let's focus on the new tags. +

    + +

    + The first new tag on the Login page is actionerrors. + Most of the possible validation errors are related to a single field. + If you don't enter a username, + the framework can place an error message near the tag prompting you to + enter a username. + But some messages are not related to a single field. + For example, the database might be down. + If the action returns an "Action Error", as opposed to a "Field Error", + the messages are rendered in place of the "actionerror" tag. + The text for the validation errors, whether they are Action Errors or + Field Errors, can be specified in the resource bundle, + making the messages easy to manage and localize. +

    + +

    + The second new tag is form. + This tag renders a HTML form tag. + The "validate=true" setting enables client-side validation, + so that the form can be validated with JavaScript before being sent + back to the server. + The framework will still validate the form again, just to be sure, but the + client-side validation can save a few round-trips to the server. +

    + +

    + Within the form tag, + we see four more new tags: "textfield", "password", "submit", + and "reset". We also see a second usage of "submit" that utilizes an + "action" attribute. +

    + +

    + When we place a control on a form, we usually need to code a set of + HTML tags to do everything we want to do. + Most often, we do not just want a plain "input type=text" tag. + We want the input field to have a label too, and maybe even + a tooltip. And, of course, a place to print a message + should invalid data be entered. +

    + +

    + The Struts Tags support templates and themes so that a set of HTML tags can be + rendered from a single Struts Tag. For example, the single tag +

    + +
    
    +    <s:textfield key="username"/>
    +
    + +

    + generates a wad of HTML markup. +

    + +
    +
    <tr>
    +  <td class="tdLabel">
    +    <label for="Login_username" class="label">Username:</label>
    +  </td>
    +  <td>
    +    <input type="text" name="username" value="" id="Login_username"/>
    +  </td>
    +</tr>
    +
    + +

    + If for some reason you don't like the markup generated by a Struts Tag, + it's each to change. + Each tag is driven by a template that can be updated on a tag-by-tag basis. + For example, + here is the default template that generates the markup for the ActionErrors tag: +

    + +
    +
    <#if (actionErrors?exists && actionErrors?size > 0)>
    +  <ul>
    +    <#list actionErrors as error>
    +      <li><span class="errorMessage">${error}</span></li>
    +    </#list>
    +  </ul>
    +</#if>
    +
    + +

    + If you wanted ActionErrors displayed in a table instead of a list, + you could edit a copy of this file, save it as a file named + "template/simple/actionerror.ftl", + and place this one file at the base of your application's classpath. +

    + +
    +
    <#if (actionErrors?exists && actionErrors?size > 0)>
    +  <table>
    +    <#list actionErrors as error>
    +      <tr><td><span class="errorMessage">${error}</span></td></tr>
    +    </#list>
    +  </table>
    +</#if>
    +
    + +

    + Under the covers, the framework uses + Freemarker + for its standard templating language. + FreeMarker is similar to + Velocity, + but it offers better error reporting and some additional features. + If you prefer, Velocity and JSP templates can also be used to create your own tags. +

    + +

    + The password tag renders a "input type=password" + tag, along with the usual template/theme markup. + By default, the password tag will not retain input if the submit fails. + If the username is wrong, + the client will have to enter the password again too. + (If you did want to retain the password when validation fails, + you can set the tag's "showPassword" property to true.) +

    + +

    + Unsurprisingly, the submit and reset tags + render buttons of the corresponding types. +

    + +

    + The second submit button is more interesting. +

    + +
      <s:submit action="Login_cancel" onclick="form.onsubmit=null"
    +    key="button.cancel"/>
    +
    + +

    + Here we are creating the Cancel button for the form. + The button's attribute action="Login_cancel" + tells the framework to submit to the Login's "cancel" method + instead of the usual "execute" method. + The onclick="form.onsubmit=null" script defeats client-side validation. + On the server side, "cancel" is on a special list of methods that bypass validation, + so the request will go directly to the Action's cancel method. + Another entry on the special-case list is the "input" method. +

    + +
    +
    Tip:
    +
    +

    + The Struts Tags have options and capabilities beyond what we have shown here. + For more see, the + Struts Tag documentation. +

    +
    +
    + +

    + OK, but how do the tags know that both of these fields are required? + How do they know what message to display when the fields are empty? +

    + +

    + For the answers, we need to look at another flavor of configuration file: + the "validation" file. +

    + +

    Login-validation.xml +

    + +

    + While it is not hard to code data-entry validation into an Action class, + the framework provides an even easier way to validate input. +

    + +

    + The validation framework is configured through another XML document, the + Login-validation.xml. +

    + +
    +
    Validation file for Login Action
    +
    <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
    +  "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
    +<validators>
    +  <field name="username">
    +    <field-validator type="requiredstring">
    +    <message key="error.username.required"/>
    +  </field-validator>
    +  </field>
    +  <field name="password">
    +    <field-validator type="requiredstring">
    +    <message key="error.password.required"/>
    +    </field-validator>
    +  </field>
    +</validators>
    +
    +
    + +

    + You may note that the DTD refers to "XWork". + + Open Symphony XWork + is a generic command-pattern framework that can be used outside of a + web environment. Essentially, Struts 2 is a web-based extension of the + XWork framework. +

    + +

    + The field elements correspond to the ActionForm properties. + The username and password field elements + say that each field depends on the "requiredstring" validator. + If the username is blank or absent, validation will fail and an error + message is generated. + The messages would be based on the "error.username.required" or + "error.password.required" message templates from the resource bundle. +

    + + + +

    Login Action

    + +

    + If validation passes, the framework invokes the "execute" method of the Login Action. + The actual Login Action is brief, since most of the functionality derives + from the base class, MailreaderSupport. +

    + +
    +
    Login.java
    +
    package mailreader2;
    +import org.apache.struts.apps.mailreader.dao.User;
    +public final class Login extends MailreaderSupport {
    +public String execute() throws ExpiredPasswordException {
    +  User user = findUser(getUsername(), getPassword());
    +  if (user != null) {
    +    setUser(user);
    +  }
    +  if (hasErrors()) {
    +    return INPUT;
    +  }
    +    return SUCCESS;
    +  }
    +}
    +
    + +

    + Login lays out what we do to authenticate a user. + We try to find the user using the credentials provided. + If the user is found, we cache a reference. + If the user is not found, we return "input" so the client can try again. + Otherwise, we return "success", so that the client can access the rest of the application. +

    + +

    MailreaderSupport.java

    + +

    + Let's look at the relevant properties and methods from MailreaderSupport + and another base class, ActionSupport, namely + "getUsername", "getPassword", "findUser", "setUser", and "hasErrors". +

    + +

    + The framework lets you define + JavaBean properties + directly on the Action. + Any JavaBean property can be used, including rich objects. + When a request comes in, + any public properties on the Action class are matched with the request parameters. + When the names match, the request parameter value is set to the JavaBean property. + The framework will make its best effort to convert the data, + and, if necessary, it will report any conversion errors. +

    + +

    + The Username and Password properties are nothing fancy, + just standard JavaBean properties. +

    + +
    +
    MailreaderSupport.getUsername() and getPassword()
    +
    private String username = null;
    +public String getUsername() {
    +  return this.username;
    +}
    +public void setUsername(String username) {
    +  this.username = username;
    +}
    +
    +private String password = null;
    +public String getPassword() {
    +  return this.password;
    +}
    +public void setPassword(String password) {
    +  this.password = password;
    +}
    +
    + +

    + We use these properties to capture the client's credentials, + and pass them to the more interesting findUser method. +

    + +
    +
    MailreaderSupport.findUser
    +
    public User findUser(String username, String password)
    +  throws ExpiredPasswordException {
    +  User user = getDatabase().findUser(username);
    +  if ((user != null) && !user.getPassword().equals(password)) {
    +    user = null;
    +  }
    +  if (user == null) {
    +    this.addFieldError("password", getText("error.password.mismatch"));
    +  }
    +  return user;
    +}
    +
    + +

    + The "findUser" method dips into the MailReader Data Access Object layer, + which is represented by the Database property. + The code for the DAO layer is maintained as a separate component. + The MailReader application imports the DAO JAR, + but it is not responsible for maintaining any of the DAO source. + Keeping the data access layer at "arms-length" is a very good habit. + It encourages a style of development where the data access layer + can be tested and developed independently of a specific end-user application. + In fact, there are several renditions of the MailReader application, + all which share the same MailReader DAO JAR! +

    + +
    +
    Best Practice:
    +
    +

    + "Strongly separate data access and business logic from the rest of + the application." +

    +
    +
    + +

    + When "findUser" returns, + the Login Action looks to see if a valid (non-null) User object is returned. + A valid User is passed to the User property. + Although it is still a JavaBean property, + the User property is not implemented in quite the same way as Username and Password. +

    + +
    +
    MailreaderSupport.setUser
    +
    public User getUser() {
    +  return (User) getSession().get(Constants.USER_KEY);
    +}
    +public void setUser(User user) {
    +  getSession().put(Constants.USER_KEY, user);
    +}
    +
    + +

    + Instead of using a field to store the property value, + "setUser" passes it to a Session property. +

    + +
    +
    MailreaderSupport.getSession() and setSession()
    +
    private Map session;
    +public Map getSession() {
    +  return session;
    +
    +public void setSession(Map value) {
    +  session = value;
    +}
    +
    + +

    + To look at the MailreaderSupport class, + you would think the Session property is a plain-old Map. + In fact, + the Session property is an adapter that is backed by the servlet session object at runtime. + The MailreaderSupport class doesn't need to know that though. + It can treat Session like any other Map. + We can also test the MailreaderSupport class by passing it some other implementation of + Map, running the test, + and then looking to see what changes MailreaderSupport made to our "mock" Session object. +

    + +

    + But, when MailreaderSupport is running inside a web application, + how does it acquire a reference to the servlet session? +

    + +

    + Good question. If you were to look at just the MailreaderSupport class, + you would not see a single line of code that sets the session property. + But, yet, when we run the class, the session property is not null. + Hmmm. +

    + +

    + The magic that provides the Session property a runtime value is called + "dependency injection". + The MailreaderSupport class implements a interface called SessionAware. + SessionAware is bundled with the framework, + and it defines a setter for the Session property. +

    + +

    + public void setSession(Map session); +

    + +

    + Also bundled with the framework is an object called the + ServletConfigInterceptor. + If the ServletConfigInterceptor sees that an Action implements the SessionAware interface, + it automatically set the session property. +

    + +
    if (action instanceof SessionAware) {
    +  ((SessionAware) action).setSession(context.getSession());
    +}
    + +

    + The framework uses these "Interceptor" classes to create a front controller + for each action an application defines. + Each Interceptor can peek at the request before an Action class is invoked, + and then again after the Action class is invoked. + (If you have worked with Servlet + Filters, + you will recognize this pattern. + But, unlike Filters, Interceptors are not tied to HTTP. + Interceptors can be tested and developed outside of a web application.) +

    + +

    + You can use the same set of Interceptors for all your actions, + or define a special set of Interceptors for any given action, + or define different sets of Interceptors to use with different types of actions. + The framework comes with a default set of Interceptors, + that it will use when another set is not specified, + but you can designate your own default Interceptor set (or "stack") + in the Struts configuration. +

    + +

    + Many Interceptors provide a utility or helper functions, + like setting the session property. + Others, like the ValidationInterceptor, + can change the workflow of an action. + Interceptors are key feature of the framework, + and we will see a few more on the tour. +

    + +

    + If a valid User is not found, or the password doesn't match, + the "findUser" method invokes the addFieldError method to note the + problem. + When "findUser" returns, the Login Action checks for errors, + and then it returns either INPUT or SUCCESS. +

    + +

    + The "addFieldError" method is provided by the ActionSupport class, + which is bundled with the framework. + The constants for INPUT and SUCCESS are also provided by ActionSupport. + While the ActionSupport class provides many useful utilities, + you are not required to use it as a base class. + Any Java class can be used as an Action, if you like. +

    + +

    + It is a good practice to provide a base class with utilities + that can be shared by an application's Action classes. + The framework does this with ActionSupport, + and the MailReader application does the same with the MailreaderSupport class. +

    + +
    +
    Best Practice:
    +
    +

    "Use a base class to define common functionality."

    +
    +
    + +

    + But, what happens if Login returns INPUT instead of SUCCESS. + How does the framework know what to do next? +

    + +

    + To answer that question, + we need to turn back to the Struts configuration + and look at how Login is declared. +

    + + +

    Login Configuration

    + +

    + The Login action element outlines how the Login workflow operates, + including what to do when the Action returns "input", + or the default result name "success". +

    + +
    +
    mailreader-support.xml Login
    +
    <action name="Login_*" method="{1}" class="mailreader2.Login">
    +  <result name="input">/pages/Login.jsp</result>
    +  <result name="cancel" type="redirect-action">Welcome</result>
    +  <result type="redirect-action">MainMenu</result>
    +  <result name="expired" type="chain">ChangePassword</result>
    +  <exception-mapping
    +    exception="org.apache.struts.apps.mailreader.dao.ExpiredPasswordException"
    +  result="expired"/>
    +  <interceptor-ref name="guest"/>
    +</action>
    +
    + +

    + You might notice that the name of the Login action element is not "Login" + but "Login_*". + The asterisk is a special "wildcard" notation that tells the framework to match any series + of character at this point. + In the method attribute, + the "{1}" notation indicates that framework should substitute whatever characters match + the asterisk at runtime. + When we cite actions like "Login_cancel" or "Login_input", + the framework matches "cancel" or "input" with the wildcard and fills in the blanks. +

    + +

    + The "trailing bang" notation was hardwired into WebWork 2. + To provide backward compatibility, + the notation is supported by Struts 2.0. + If you prefer to use wildcards to emulate the same notation, + as the Mailreader does, + you should disable the old notation in the Struts properties file. +

    + +
    +
    struts.properties
    +
    struts.enable.DynamicMethodInvocation = false
    +
    + +

    + Using wildcards with a exclamation point (or "bang") is not the only way we can use + wilcards to invoke methods. + If we wanted to use actions like "inputLogin", + we could move the asterisk and use an action name like "*Login". +

    + +

    + Within the Login action element, the first result element is named "input". + If validation or authentification fail, + the Action class will return "input" and the framework will transfer control to the + "Login.jsp" page. +

    + +

    + The second result element is named cancel. + If someone presses the cancel button on the Login page, + the Action class will return "cancel", this result will be selected, + and the framework will issue a redirect to the Welcome action. +

    + +

    + The third result has no name, + so it will be called if the default success token is returned. + So, if the Login succeeds, + control will transfer to the MainMenu action. +

    + +

    + The MailReader DAO exposes a "ExpiredPasswordException". + If the DAO throws this exception when the User logs in, + the framework will process the exception-mapping + and transfer control to the "ChangePassword" action. +

    + +

    + Just in case any other Exceptions are thrown, + the MailReader application also defines a global handler. +

    + +
    +
    mailreader-default.xml exception-mapping
    +
    <global-exception-mappings>
    +  <exception-mapping
    +    result="error"
    +    exception="java.lang.Exception"/>
    +</global-exception-mappings>
    +
    + +

    + If an unexpected Exception is thrown, + the exception-mapping will transfer control to the action's "error" result, + or to a global "error" result. + The MailReader defines a global "error" result + which transfers control to an "Error.jsp" page + that can display the error message. +

    + +
    +
    Error.jsp
    +
    <%@ page contentType="text/html; charset=UTF-8" %>
    +<%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
    +  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    +    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    +  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    +  <head>
    +    <title>Unexpected Error</title>
    +  </head>
    +  <body>
    +    <h2>An unexpected error has occured</h2>
    +    <p>
    +      Please report this error to your system administrator
    +      or appropriate technical support personnel.
    +      Thank you for your cooperation.
    +    </p>
    +    <hr />
    +    <h3>Error Message</h3>
    +    <s:actionerror />
    +    <p>
    +      <s:property value="%{exception.message}"/>
    +    </p>
    +    <hr />
    +    <h3>Technical Details</h3>
    +    <p>
    +      <s:property value="%{exceptionStack}"/>
    +    </p>
    +    <jsp:include page="Footer.jsp"/>
    +  </body>
    +</html>
    +
    + +

    + The Error page uses property tags to expose + the Exception message and the Exception stack. +

    + +

    + Finally, the Login action specifies an InterceptorStack + named defaultStack. + If you've worked with Struts 2 or WebWork 2 before, that might seem strange, + since "defaultStack" is the factory default. +

    + +

    + In the MailReader application, most of the actions are only available + to authenticated users. + The exceptions are the Welcome, Login, and Register actions + which are available to everyone. + To authenticate clients, + the MailReader uses a custom Interceptor and a custom Interceptor stack. +

    + +
    +
    mailreader2.AuthenticationInterceptor
    +
    package mailreader2;
    +import com.opensymphony.xwork2.interceptor.Interceptor;
    +import com.opensymphony.xwork2.ActionInvocation;
    +import com.opensymphony.xwork2.Action;
    +import java.util.Map;
    +import org.apache.struts.apps.mailreader.dao.User;
    +
    +public class AuthenticationInterceptor implements Interceptor {
    +  public void destroy () {}
    +  public void init() {}
    +  public String intercept(ActionInvocation actionInvocation) throws Exception {
    +    Map session = actionInvocation.getInvocationContext().getSession();
    +    User user = (User) session.get(Constants.USER_KEY);
    +    boolean isAuthenticated = (null!=user) && (null!=user.getDatabase());
    +    if (isAuthenticated) {
    +      return actionInvocation.invoke();
    +    }
    +    else {
    +      return Action.LOGIN;
    +    }
    +  }
    +}
    +
    + +

    + The AuthenticationInterceptor looks to see if a User object + has been stored in the client's session state. + If so, it returns normally, and the next Interceptor in the set would be invoked. + If the User object is missing, the Interceptors returns "login". + The framework would match "login" to the global result, + and transfer control to the Login action. +

    + +

    + The MailReader defines three custom Interceptor stacks: "user", "user-submit", + and "guest". +

    + +
    +
    mailreader-default.xml interceptors
    +
    <interceptors>
    +  <interceptor name="authentication"
    +               class="mailreader2.AuthenticationInterceptor"/>
    +  <interceptor-stack name="user" >
    +      <interceptor-ref name="authentication" />
    +      <interceptor-ref name="defaultStack"/>
    +  </interceptor-stack>
    +  <interceptor-stack name="user-submit" >
    +      <interceptor-ref name="token-session" />
    +      <interceptor-ref name="user"/>
    +  </interceptor-stack>
    +  <interceptor-stack name="guest" >
    +      <interceptor-ref name="defaultStack"/>
    +  </interceptor-stack>
    +</interceptors>
    +<default-interceptor-ref name="user"/>
    +
    + +

    + The user stacks require that the client be authenticated. + In other words, that a User object is present in the session. + The actions using a guest stack can be accessed by any client. + The -submit versions of each can be used with actions + with forms, to guard against double submits. +

    + +
    Double Submits
    + +

    + A common problem with designing web applications is that users are impatient + and response times can vary. + Sometimes, people will press a submit button a second time. + When this happens, the browser submits the request again, + so that we now have two requests for the same thing. + In the case of registering a user, if someone does press the submit button + again, and their timing is bad, + it could result in the system reporting that the username has already been + used. + (The first time the button was pressed.) + In practice, this would probably never happen, but for a longer running + process, like checking out a shopping cart, + it's easier for a double submit to occur. +

    + +

    + To forestall double submits, and "back button" resubmits, + the framework can generate a token that is embedded in the form + and also kept in the session. + If the value of the tokens do not compare, + then we know that there has been a problem, + and that a form has been submitted twice or out of sequence. +

    + +

    + The Token Session Interceptor will also attempt to provide intelligent + fail-over in the event of multiple requests using the same session. + That is, it will block subsequent requests until the first request is complete, + and then instead of returning the "invalid.token" code, + it will attempt to display the same response that the + original, valid action invocation would have displayed +

    + +

    + Because the default interceptor stack will now authenticate the client, + we need to specify the standard "defaultStack" for the three + "guest actions", Welcome, Login, and Register. + Requiring authentification by default is the better practice, since it + means that we won't forget to enable it when creating new actions. + Meanwhile, those pesky users will ensure that we don't forget to disable + authentification for "guest" services. +

    + +

    MainMenu

    + +

    + On a successful login, the Main Menu page displays. + If you logged in using the demo account, + the page title should be "Main Menu Options for John Q. User". + Below this legend should be two links: +

    + +
      +
    • + Edit your user registration profile +
    • +
    • + Log off MailReader Demonstration Application +
    • +
    + +

    + Let's review the source for the "MainMenu" action mapping, + and the "MainMenu.jsp". +

    + +
    +
    Action mapping element for MainMenu
    +
    <action name="MainMenu" class="mailreader2.MailreaderSupport">
    +    <result>/pages/MainMenu.jsp</result>
    +    </action>
    + +
    MainMenu.jsp
    +
    <%@ page contentType="text/html; charset=UTF-8" %>
    +<%@ taglib prefix="s" uri="http://struts.apache.org/tags"  %>
    +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    +  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    +  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    +  <head>
    +    <title><s:text name="mainMenu.title"/></title>
    +      <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
    +      type="text/css"/>
    +  </head>
    +
    +  <body>
    +  <h3><s:text name="mainMenu.heading"/> <s:property
    +    value="user.fullName"/></h3>
    +  <ul>
    +    <li><a href="<s:url action="Registration_input" />">
    +        <s:text name="mainMenu.registration"/>
    +      </a>
    +    </li>
    +    <li><a href="<s:url action="Logout" />">
    +      <s:text name="mainMenu.logout"/>
    +      </a>
    +    </ul>
    +  </body>
    +</html>
    +
    + +

    + The source for "MainMenu.jsp" also contains a new tag, + property, which we use to customize the page with the + "fullName" property of the authenticated user. +

    + +

    + Displaying the user's full name is the reason the MainMenu action + references the MailreaderSupport class. + The MailreaderSupport class has a User property that the text tag + can access. + If we did not utilize MailreaderSupport, + the property tag would not be able to find the User object to print + the full name. +

    + +

    + The customized MainMenu page offers two standard links. + One is to "Edit your user registration profile". + The other is to "Logout the MailReader Demonstration Application". +

    + +

    Registration page +

    + +

    + If you follow the "Edit your user registration profile" link from the Main + Menu page, + we will finally reach the heart of the MailReader application: the + Registration, or "Profile", page. + This page displays everything MailReader knows about you + (or at least your login), + while utilizing several interesting techniques. +

    + +

    + To do double duty as the "Create" Registration page and the "Edit" + Registration page, + the "Registration.jsp" makes extensive use of the test tags, + to make it appears as though there are two distinct pages. +

    + +
    +
    Registration.jsp - head element
    +
    <head>
    +  <s:if test="task=='Create'">
    +    <title><s:text name="registration.title.create"/></title>
    +  </s:if>
    +  <s:if test="task=='Edit'">
    +    <title><s:text name="registration.title.edit"/></title>
    +  </s:if>
    +  <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
    +    type="text/css"/>
    +</head>
    +
    + +

    + For example, if client is editing the form (task == 'Edit'), + the page inserts the username from the User object. + For a new Registration (task == 'Create'), + the page creates an empty data-entry field. +

    + +
    +
    Note:
    +
    +

    + Presention Logic - + The "test" tag is a convenient way to express presentation + logic within your pages. + Customized pages help to prevent user error, + and dynamic customization reduces the number of server pages your + application needs to maintain, among other benefits. +

    +
    +
    + +

    + The page also uses logic tags to display a list of subscriptions + for the given user. + If the RegistrationForm has task set to "Edit", + the lower part of the page that lists the subscriptions is exposed. +

    + +
    +
    +
    <s:if test="task == 'Edit'">
    +  <div align="center">
    +    <h3><s:text name="heading.subscriptions"/></h3>
    +  </div>
    +    <!-- ... -->
    +  </s:if>
    +<jsp:include page="Footer.jsp"/>
    +</body></html>
    +
    + +

    + Otherwise, the page contains just the top portion -- + a data-entry form for managing the user's registration. +

    + +

    iterator

    + +

    + Besides "if" there are several other control tags that you can use + to sort, filter, or iterate over data. + The Registration page includes a good example of using the iterator + tag to display the User's Subscriptions. +

    + +

    + The subscriptions are stored in a hashtable object, which is in turn + stored in the user object. + So to display each subscription, we have to reach into the user object, + and loop through the members of the subscription collection. + Using the iterator tag, you can code it the way it sounds. +

    + +
    +
    Using iterator to list the Subscriptions
    +
    <s:iterator value="user.subscriptions">
    +  <tr>
    +    <td align="left">
    +      <s:property value="host"/>
    +    </td>
    +    <td align="left">
    +       <s:property value="username"/>
    +   </td>
    +  <td align="center">
    +      <s:property value="type"/>
    +  </td>
    +  <td align="center">
    +     <s:property value="autoConnect"/>
    +  </td>
    +  <td align="center">
    +    <a href="<s:url action="Subscription_delete"><s:param name="host" value="host"/></s:url>">
    +      <s:text name="registration.deleteSubscription"/>
    +    </a> 
    +    <a href="<s:url action="Subscription_edit"><s:param name="host" value="host"/></s:url>">
    +      <s:text name="registration.editSubscription"/>
    +     </a>
    +   </td>
    + </tr>
    +</s:iterator>
    +
    + +

    + When the iterator renders, it generates a list of Subscriptions for the current User. +

    + +
    + +
    +

    Current Subscriptions

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + +
    + Host Name + + User Name + + Server Type + + Auto + + Action +
    + mail.hotmail.com + + user1234 + + pop3 + + false + + + Delete + +   + + Edit + +
    + mail.yahoo.com + + jquser + + imap + + false + + + Delete + +   + + Edit + +
    + Add + +
    + +

    + Now look back at the code used to generate this block. +

    +

    + Notice anything nifty? +

    +

    + How about that the markup between the iterator tag is + actually simpler than the markup that we would use to render one row of the + table? +

    +

    + Instead of using a qualified reference like "value=user.subscription[0].host", + we use the simplest possible reference: "value=host". + We didn't have to define a local variable, and reference that local in the loop code. + The reference to each item in the list is automatically resolved, no fuss, no muss. +

    +

    + Nice trick! +

    + +

    + The secret to this magic is the value stack. + Next to Interceptors, the value stack is probably the coolest thing there is about the + framework. + To explain the value stack, let's step back and start from the beginning. +

    + +

    + Merging dynamic data into static web pages is a primary reason + we create web applications. + The Java API has a mechanism that allows you to + place objects in a servlet scope (page, request, session, or + application), and then retrieve them using a JSP scriplet. + If the object is placed directly in one of the scopes, + a JSP tag or scriptlet can find that object by searching page scope and + then request scope, and session scope, and finally application scope. +

    + +

    + The value stack works much the same way, only better. + When you push an object on the value stack, + the public properties of that object become first-class properties of the stack. + The object's properties become the stack's properties. + If another object on the stack has properties of the same name, + the last object pushed onto the stack wins. (Last-In, First-Out.) +

    + +

    + When the iterator tag loops through a collection, + it pushes each item in the collection onto the stack. + The item's properties become the stack's property. + In the case of the Subscriptions, + if the Subscription has a public Host property, + then during that iteration, + the stack can access the same property. +

    + +

    + Of course, at the end of each iteration, the tag "pops" the item off the stack. + If we were to try and access the Host property later in the page, + it won't be there. +

    + +

    + When an Action is invoked, the Action class is pushed onto the value stack. + Since the Action is on the value stack, + our tags can access any property of the Action + as if it were an implicit property of the page. + The tags don't access the Action directly. + If a textfield tag is told to render the "Username" property, + the tag asks the value stack for the value of "Username", + and the value stack returns the first property it finds by that name, + on any object on the stack. +

    + +

    + The Validators also use the stack. + When validation fails on a field, + the value for the field is pushed onto the value stack. + As a result, if the client enters text into an Integer field, + the framework can still redisplay whatever was entered. + An invalid input value is not stored in the field (even if it could be). + The invalid input is pushed onto the stack for the scope of the request. +

    + +

    + The Subscription list uses another new tag: the param tag. + As tags go, "param" takes very few parameters of its own: just "name" and "value", + and neither is required. + Although simple, "param" is one of the most powerful tags the framework provides. + Not so much because of what it does, + but because of what "param" allows the other tags to do. +

    + +

    + Essentially, the "param" tag provides parameters to other tags. + A tag like "text" might be retrieving a message template with several replaceable + parameters. + No matter how many parameters are in the template, and no matter what they are named, + you can use the "param" tag to pass in whatever you need. +

    + +
    pager.legend = Displaying {current} of {count} items matching {criteria}.
    +...
    +<s:text name="pager.legend">
    +    <s:param name="current" value="42" />
    +    <s:param name="count" value="314" />
    +    <s:param name="criteria" value="Life, the Universe, and Everything" />
    +</s:text>
    + +

    + In the case of an "url" tag, + we can use "param" to create the query string. + A statement like this: +

    + +
    
    +  <s:url action="Subscription_edit"><s:param name="host" value="host"/></s:url>">
    +
    + +

    + can render a hyperlink like this: +

    + +
    
    +  <a href="/struts2-mailreader/Subscription_edit.do?host=mail.yahoo.com">Edit</a>
    +
    + + + +

    + If a hyperlink needs more parameters, + you can use "param" to add as many parameters as needed. +

    + +

    + Subscription +

    + +

    + If we follow one of the "Edit" subscription links on the Registration page, + we come to the Subscriptions page, + which displays the details of our description in a data-entry form. + Let's have a look at the Subscription configuration + and follow the bouncing ball from page to action to page. +

    + +
    +
    mailreader-support.xml Subscription element
    +
    <action name="Subscription_*" method="{1}" class="mailreader2.Subscription">
    +  <result name="input">/pages/Subscription.jsp</result>
    +  <result type="redirect-action">Registration_input</result>
    +</action>
    +
    + +

    + The Edit link specified the Subscription action, + but also includes the qualifier _edit. + The wildcard notation tells the framework to use any characters given after "Subscription_" + as the name of a method to invoke on the Action class, + instead of the default execute method. + The "alternate" execute methods are called alias methods. +

    + +
    +
    Subscription edit alias
    +
    public String edit() {
    +  setTask(Constants.EDIT);>
    +  return find();
    +}
    +
    +public String find() {
    +  org.apache.struts.apps.mailreader.dao.Subscription
    +    sub = findSubscription();
    +   if (sub == null) {
    +       return ERROR;
    +   }
    +   setSubscription(sub);
    +   return INPUT;
    +}
    +
    + +

    + The "edit" alias has two responsibilities. + First, it must set the Task property to "Edit". + The Subscription page will render itself differently + depending on the value of the Task property. + Second, "edit" must locate the relevant Subscription + and set it to the Subscription property. + If all goes well, "edit" returns the INPUT token, + so that the "input" result will be invoked. +

    + +

    + In the normal course, the Subscription should always be found, + since we selected the entry from a system-generated list. + If the Subscription is not found, + it would be because the database disappeared + or the request is being spoofed. + If the Subscription is not found, + edit returns the token for the global "error" result, + because this condition is unexpected. +

    + +

    + The business logic for the "edit" alias is a simple wrapper + around the MailReader DAO classes. +

    + +
    +
    MailreaderSupport findSubscription()
    +
    public Subscription findSubscription() {
    +    return findSubscription(getHost());
    +}
    +
    +public Subscription findSubscription(String host) {
    +    Subscription subscription;
    +    subscription = getUser().findSubscription(host);
    +    return subscription;
    +}
    +
    + +

    + This code is very simple + and doesn't seem to provide much in the way of error handling. + But, that's OK. + Since the page is suppose to be entered from a link that we created, + we do expect everything to go right here. + But, if it doesn't, the global exception handler we defined in the + MailReader configuration will trap the exception for us. +

    + +

    + Likewise, the AuthentificationInterceptor will ensure that only clients + with a valid User object can try to edit a Subscription. + If the session expired, or someone bookmarked the page, + the client will be redirected to the Login page automatically. +

    + +

    + As a final layer of defense, we also configured a validator for Subscription, + to ensure that we are passed a Host parameter. +

    + +
    +
    Subscription-validation.xml
    +
    <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
    +<validators>
    +  <field name="host">
    +    <field-validator type="requiredstring">
    +        <message key="error.host.required"/>
    +    </field-validator>
    +  </field>
    +</validators>
    +
    + +

    + By keeping routine safety precautions out of the Action class, + the all-important Action becomes smaller and easier to maintain. +

    + +

    + After setting the relevent Subscription object to the Subscription property, + the framework transfers control to the (you guessed it) Subscription page. +

    + +
    +
    Subscription.jsp
    +
    <%@ page contentType="text/html; charset=UTF-8" %>
    +<%@ taglib prefix="s" uri="http://struts.apache.org/tags" %>
    +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    +  <head>
    +    <s:if test="task=='Create'">
    +        <title><s:text name="subscription.title.create"/></title>
    +    </s:if>
    +    <s:if test="task=='Edit'">
    +        <title><s:text name="subscription.title.edit"/></title>
    +    </s:if>
    +    <s:if test="task=='Delete'">
    +        <title><s:text name="subscription.title.delete"/></title>
    +    </s:if>
    +    <link href="<s:url value="/css/mailreader.css"/>" rel="stylesheet"
    +          type="text/css"/>
    +  </head>
    +  <body onLoad="self.focus();document.Subscription.username.focus()">
    +
    +    <s:actionerror/>
    +    <s:form action="Subscription_save" validate="true">
    +      <s:token />
    +      <s:hidden name="task"/>
    +      <s:label key="username" name="user.username"/>
    +
    +      <s:if test="task == 'Create'">
    +        <s:textfield key="mailHostname" name="host"/>
    +      </s:if>
    +      <s:else>
    +        <s:label key="mailHostname" name="host"/>
    +        <s:hidden name="host"/>
    +      </s:else>
    +
    +      <s:if test="task == 'Delete'">
    +        <s:label key="subscription.username"/>
    +        <s:label key="subscription.password"/>
    +        <s:label key="subscription.type"/>
    +        <s:label key="subscription.autoConnect"/>
    +        <s:submit key="button.confirm"/>
    +      </s:if>
    +      <s:else>
    +        <s:textfield key="subscription.username"/>
    +        <s:textfield key="subscription.password"/>
    +        <s:select key="subscription.type" list="types"/>
    +        <s:checkbox key="subscription.autoConnect"/>
    +        <s:submit key="button.save"/>
    +        <s:reset key="button.reset"/>
    +      </s:else>
    +
    +      <s:submit action="Registration_input"
    +                key="button.cancel"
    +                onclick="form.onsubmit=null"/>
    +  </s:form>
    +
    +  <jsp:include page="Footer.jsp"/>
    +  </body>
    +</html>
    +
    + +

    + As before, we'll discuss the tags and attributes that are new to this page: + "token", "hidden", "label", "select", and "checkbox". +

    + +

    + The token tag works with the Token Session Interceptor to foil double + submits. + The tag generates a key that is embedded in the form and cached in the session. + Without this tag, the Interceptor can't work it's magic. +

    + +

    + The hidden tag embeds the Task property into the form. + When the form is submitted, + the Subscription_save action will use the Task property to decide + whether to insert or update the form. +

    + +

    + The label renders a "read only" version of a property, + suitable for placement in the form. + In Edit or Delete mode, we want the Host property to be immutable, + since it is used as a key. (As unwise as that might sound.) + In Delete mode, all of the properties are immutable, + since we are simply confirming the delete operation. +

    + +

    + Saving the best for last, the Subscription form utilizes two more interesting + tags, "select" and "checkbox". +

    + +

    + Unsurprisingly, the select tag renders a select control, + but the tag does so without requiring a lot of markup or redtape. +

    + +
    <s:select key="subscription.type" list="types" />
    +
    + +

    + The interesting attribute of the "select" tag is "list", + which, in our case, specifies a value of "types". + If we take another look at the Subscription action, + we can see that it implements an interface named Preparable + and populates a Types property in a method named "prepare". +

    + +
    +
    Subscription-validation.xml
    +
    public class Subscription extends MailreaderSupport
    +  implements Preparable {
    +
    +  private Map types = null;
    +  public Map getTypes() {
    +    return types;
    +   }
    +
    +   public void prepare() {
    +     Map m = new LinkedHashMap();
    +       m.put("imap", "IMAP Protocol");
    +       m.put("pop3", "POP3 Protocol");
    +       types = m;
    +       setHost(getSubscriptionHost());
    +    }
    +
    +    // ... 
    +
    + +

    + The default Interceptor stack includes the PrepareInterceptor, + which observes the Preparable interface. +

    + +
    +
    PrepareInterceptor
    +
    public class PrepareInterceptor extends AroundInterceptor {
    +
    +  protected void after(ActionInvocation dispatcher, String result) throws Exception {
    +  }
    +
    +  protected void before(ActionInvocation invocation) throws Exception {
    +    Object action = invocation.getAction();
    +     if (action instanceof Preparable) {
    +        ((Preparable) action).prepare();
    +    }
    +  }
    +}
    + +

    + The PrepareInterceptor ensures that the "prepare" method will always be called + before "execute" or an alias method is invoked. + We use "prepare" to setup the list of items for the select list to display. + We also transfer the Host property from our Subscription object + to a local property, where it is easier to manage. +

    + +

    + Subscription.java +

    + +

    + Like many applications, the MailReader uses mainly String properties. + One exception is the AutoConnect property of the Subscription object. + On the HTML form, the AutoConnect property is represented by a checkbox. +

    + +

    + When writing web applications, the checkbox can be a tricky control. + The Subscription object has a boolean AutoConnect property, + and the checkbox simply has to represent its state. + The problem is, if you clear a checkbox, the browser client will not submit anything. + Nada. Zip. + It is as if the checkbox control never existed. + The HTTP protocol has no way to affirm "false". + If the control is missing, we need to figure out it's been unclicked. +

    + +

    + In Struts 1, + we use the reset method to work around checkbox issues. + In Struts 2, checkbox state is handled automatically. + The framework can detect when a checkbox tag has not been sent back, + and when that happens, + a default "false" value is used for the checkbox value. + No worries, mate. +

    + +

    + If we press the SAVE button, + the form will be submitted to the Subscription_save action. + Since the save method needs some additional validation, + we can add a validation file. +

    + +
    +
    Subscription-Subscription_save-validation.xml
    +
    <!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
    +    "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
    +<validators>
    +  <field name="host">
    +    <field-validator type="requiredstring">
    +        <message key="error.host.required"/>
    +    </field-validator>
    +  </field>
    +</validators>
    +
    + +

    + The validators follow the same type of inheritance path as the classes. + SubscriptionSave extends Subscription, + so when Subscription_save is validated, + the Host property specified by "Subscription-validation.xml" will also be required. +

    + +

    + If validation succeeds, the save method of Subscription will fire. +

    + +
    +
    Subscription
    + +
    public String save() throws Exception {
    +
    +  if (Constants.DELETE.equals(getTask())) {
    +   removeSubscription();
    +  }
    +
    +  if (Constants.CREATE.equals(getTask())) {
    +    copySubscription(getHost());
    +  }
    +
    +  saveUser();
    +  return SUCCESS;
    +}
    +
    + +

    + The save method uses the Task property to handle + the special cases of deleting and creating, + and then updates the state of the User object. +

    + +

    + The removeSubscription method calls the DAO facade, + and then updates the application state. +

    + +
    +
    removeSubscription
    +
    public void removeSubscription() throws Exception {
    +  getUser().removeSubscription(getSubscription());
    +  getSession().remove(Constants.SUBSCRIPTION_KEY);
    +}
    +
    + +

    + The copySubscription method is a bit more interesting. + The MailReader DAO layer API includes some immutable fields + that can't be set once the object is created. + Because key fields are immutable, + we can't just create a Subscription, let the framework populate all the fields, + and then save it when we are done -- because some fields can't be populated, + except at construction. +

    + +

    + One workaround would be to declare properties on the Action + for all the properties we need to pass to the Subscription or User objects. + When we are ready to create the object, + we could pass the new object values from the Action properties. +

    + +

    + Another workaround is to declare only the immutable properties on the Action, + and then use what we can from the domain object. +

    + +

    + This implementation of the MailReader utilizes the second alternative. + We define User and Subscription objects on our base Action, + and add other properties only as needed. +

    + +

    + To add a new Subscription or User, + we create a blank object to capture whatever fields we can. + When this "input" object returns, we create a new object, + setting the immutable fields to appropriate values, + and copy over the rest of the properties. +

    + +
    +
    copySubscription
    +
    public void copySubscription(String host) {
    +  Subscription input = getSubscription();
    +  Subscription sub = createSubscription(host);
    +  if (null != sub) {
    +    BeanUtils.setValues(sub, input, null);
    +    setSubscription(sub);
    +    setHost(sub.getHost());
    +  }
    +}
    +
    + +

    + Of course, this is not a preferred solution, + but merely a way to work around an issue in the MailReader DAO API + that would not be easy for us change. +

    + +

    Subscription Submit

    + +

    + When we pressed the SAVE button, there was one step that we overlooked. + The Mailreader application uses a "double submit" guard to keep people + from clicking the SAVE button multiple times and submitting the form again. +

    + +

    + To add the double-submit guard, we can change the actions default processing + stack to user-submit. + But, we don't want to just copy and paste the other action settings from + the main Subscription action. + What we can do is put the subscription actions in their own package, + so that they can share result types. +

    + +
    +
    mailreader-support.xml
    +
    
    +</package>
    +
    +<package name="subscription" namespace="/" extends="mailreader-support">
    +
    +    <global-results>
    +        <result name="input">/Subscription.jsp</result>
    +        <result type="redirect-action">Registration_input</result>
    +    </global-results>
    +
    +    <action name="Subscription_save" method="save" class="mailreader2.Subscription">
    +        <interceptor-ref name="user-submit" />
    +    </action>
    +
    +    <action name="Subscription_*" method="{1}" class="mailreader2.Subscription" />
    +
    +</package>
    +
    +<package name="wildcard" namespace="/" extends="mailreader-support">
    +
    +    <action name="*" class="mailreader2.MailreaderSupport">
    +        <result>/{1}.jsp</result>
    +    </action>
    +
    +</package>
    +}
    +
    + +

    + Aftering a successful save, + the Subscription Action will return "success", + and the framework will redirect us back to Registration input. +

    + +

    Summary

    +

    + At this point, we've booted the application, logged on, + reviewed a Registration record, and edited a Subscription. + Of course, there's more, but from here on, it is mostly more of the same. + The full source code for MailReader is + + available online + and in the distribution. +

    + +

    + Enjoy! +

    +
    + + diff --git a/STRUTS_2_0_X/apps/pom.xml b/STRUTS_2_0_X/apps/pom.xml new file mode 100644 index 000000000..6ddea6129 --- /dev/null +++ b/STRUTS_2_0_X/apps/pom.xml @@ -0,0 +1,170 @@ + + 4.0.0 + + org.apache.struts + struts2-parent + 2.0.14 + + org.apache.struts + struts2-apps + pom + Webapps + + blank + mailreader + portlet + showcase + + + + scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps + scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps + http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_0_14/apps + + + + + apache-site + scp://people.apache.org/www/struts.apache.org/struts2/apps + + + + + + hostedqa + + + com.hostedqa + hostedqa-remote-ant + 1.0-SNAPSHOT + test + + + + + codehaus + codehaus + http://repository.codehaus.org + + + maven-hostedqa + maven-hostedqa + + true + always + ignore + + + true + + http://maven.hostedqa.com + + + + + + + src/main/java + + **/*.properties + **/*.xml + + + + + + maven-antrun-plugin + org.apache.maven.plugins + + + package + + run + + + + + + + + + + + + + + com.hostedqa + hostedqa-remote-ant + 1.0-SNAPSHOT + + + + + + + + + + + + org.codehaus.cargo + cargo-maven2-plugin + 0.3.1 + + + tomcat5x + ${cargo.tomcat5x.home} + ${project.build.directory}/tomcat5x.log + ${project.build.directory}/tomcat5x.out + + + ${project.build.directory}/tomcat5x + + + + + + maven-antrun-plugin + + + copy-sources + process-sources + + + + + + + + + + + + run + + + + + + + ${pom.artifactId} + + + + + + + org.apache.struts + struts2-core + ${pom.version} + + + + org.springframework + spring-mock + 2.0.1 + test + + + + diff --git a/STRUTS_2_0_X/apps/portlet/README.txt b/STRUTS_2_0_X/apps/portlet/README.txt new file mode 100644 index 000000000..efcb67bbc --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/README.txt @@ -0,0 +1,17 @@ +README.txt - portlet + +This is a simple example of using the portlet API with Struts applications. + +For more on getting started with Struts, see + +* http://cwiki.apache.org/WW/home.html + +WARNING - Additional configuration required for deployment + +Due to difference in portlet contrainer implementations, the porlet +WAR is not ready-to-run. Extract the porlet WAR, and then copy the +contents of apps/portlet/src/main/etc// into the +WAR's WEB-INF directory. + + +---------------------------------------------------------------------------- \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/portlet/pom.xml b/STRUTS_2_0_X/apps/portlet/pom.xml new file mode 100644 index 000000000..8cf601fe0 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + + org.apache.struts + struts2-apps + 2.0.14 + + org.apache.struts + struts2-portlet + war + Portlet Webapp + + + scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps/portlet + scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps/portlet + http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_0_14/apps/portlet + + + + + portlet-api + portlet-api + 1.0 + provided + + + org.apache.struts + struts2-spring-plugin + ${pom.version} + + + javax.servlet + servlet-api + + + + + org.apache.struts + struts2-core + ${pom.version} + + + velocity + velocity + 1.4 + + + + velocity-tools + velocity-tools + 1.1 + + + commons-digester + commons-digester + 1.8 + + + commons-lang + commons-lang + 2.1 + + + commons-fileupload + commons-fileupload + 1.1.1 + + + commons-collections + commons-collections + 3.1 + + + log4j + log4j + 1.2.12 + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/exo/web.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/exo/web.xml new file mode 100644 index 000000000..675c913d0 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/exo/web.xml @@ -0,0 +1,63 @@ + + + + struts-portlet + + + contextConfigLocation + /WEB-INF/applicationContext*.xml + + + action2 + + org.apache.struts2.dispatcher.FilterDispatcher + + + + + action2 + /* + + + + org.springframework.web.context.ContextLoaderListener + + + + + org.apache.struts2.portlet.context.ServletContextHolderListener + + + + + org.exoplatform.services.portletcontainer.impl.servlet.PortletApplicationListener + + + + + preparator + + org.apache.struts2.portlet.context.PreparatorServlet + + + + dwr + uk.ltd.getahead.dwr.DWRServlet + + + PortletWrapper + + org.exoplatform.services.portletcontainer.impl.servlet.ServletWrapper + + + + + dwr + /dwr/* + + + PortletWrapper + /PortletWrapper + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/README-gridsphere.txt b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/README-gridsphere.txt new file mode 100644 index 000000000..e502e0699 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/README-gridsphere.txt @@ -0,0 +1,2 @@ +Put the empty 'struts-portlet' file in the $CATALINA_HOME/webapps/gridsphere/WEB-INF/CustomPortal/portlets +folder of your Gridsphere installation. You will need to add the gridsphere-ui-tags-2.1.2.jar to your project. diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/gridsphere-portlet.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/gridsphere-portlet.xml new file mode 100644 index 000000000..ed15d11cb --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/gridsphere-portlet.xml @@ -0,0 +1,24 @@ + + + + + + + JSR Portlet Servlet + PortletServlet + + + + + Portlet Servlet + en + + Portlet Servlet + Portlet Servlet + A JSR Portlet Loader + portlet servlet + + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/group.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/group.xml new file mode 100644 index 000000000..d04e4e7b1 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/group.xml @@ -0,0 +1,10 @@ + + + StrutsPortlet + StrutsPortlet Example Application + PUBLIC + + struts-portlet#StrutsPortlet + USER + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/layout.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/layout.xml new file mode 100644 index 000000000..14a160bd9 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/layout.xml @@ -0,0 +1,19 @@ + + + StrutsPortlet Example + + + StrutsPortlet Example Application + + + + + struts-portlet#StrutsPortlet + + + + + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/struts-portlet b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/struts-portlet new file mode 100644 index 000000000..e69de29bb diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/web.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/web.xml new file mode 100644 index 000000000..e453c960b --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/gridsphere/web.xml @@ -0,0 +1,63 @@ + + + + struts-portlet + + + contextConfigLocation + /WEB-INF/applicationContext*.xml + + + action2 + + org.apache.struts2.dispatcher.FilterDispatcher + + + + + action2 + /* + + + + org.springframework.web.context.ContextLoaderListener + + + + + org.apache.struts2.portlet.context.ServletContextHolderListener + + + + + org.gridlab.gridsphere.provider.portlet.jsr.PortletServlet + + + + + preparator + + org.apache.struts2.portlet.context.PreparatorServlet + + + + dwr + uk.ltd.getahead.dwr.DWRServlet + + + PortletServlet + + org.gridlab.gridsphere.provider.portlet.jsr.PortletServlet + + + + + dwr + /dwr/* + + + PortletServlet + /jsr/struts-portlet + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-app.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-app.xml new file mode 100644 index 000000000..02e09d53b --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-app.xml @@ -0,0 +1,3 @@ + + struts-portlet + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-portlet.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-portlet.xml new file mode 100644 index 000000000..663eaf395 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-portlet.xml @@ -0,0 +1,12 @@ + + + StrutsPortlet + + + + + StrutsPortlet2 + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-web.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-web.xml new file mode 100644 index 000000000..9d9c645cc --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/jboss-web.xml @@ -0,0 +1,3 @@ + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/portlet-instances.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/portlet-instances.xml new file mode 100644 index 000000000..c22073d5c --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/portlet-instances.xml @@ -0,0 +1,11 @@ + + + + StrutsPortletInstance + StrutsPortlet + + + StrutsPortlet2Instance + StrutsPortlet2 + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/struts-portlet-pages.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/struts-portlet-pages.xml new file mode 100644 index 000000000..255c4530d --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.0/struts-portlet-pages.xml @@ -0,0 +1,18 @@ + + default + + struts-portlet + + StrutsPortletWindow + struts-portlet.StrutsPortlet.StrutsPortletInstance + left + 0 + + + StrutsPortletWindow2 + struts-portlet.StrutsPortlet2.StrutsPortlet2Instance + right + 0 + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-app.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-app.xml new file mode 100644 index 000000000..02e09d53b --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-app.xml @@ -0,0 +1,3 @@ + + struts-portlet + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-portlet.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-portlet.xml new file mode 100644 index 000000000..663eaf395 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-portlet.xml @@ -0,0 +1,12 @@ + + + StrutsPortlet + + + + + StrutsPortlet2 + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-web.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-web.xml new file mode 100644 index 000000000..9d9c645cc --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/jboss-web.xml @@ -0,0 +1,3 @@ + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/struts-portlet-object.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/struts-portlet-object.xml new file mode 100644 index 000000000..2e062ad2a --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jbossportal2.2/struts-portlet-object.xml @@ -0,0 +1,25 @@ + + + + overwrite + default + + + StrutsPortlet Example + + + StrutsWindow + StrutsPortletInstance + center + 0 + + + + + overwrite + + StrutsPortletInstance + struts-portlet.StrutsPortlet + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jetspeed2/README-jetspeed2.txt b/STRUTS_2_0_X/apps/portlet/src/main/etc/jetspeed2/README-jetspeed2.txt new file mode 100644 index 000000000..acde566d3 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jetspeed2/README-jetspeed2.txt @@ -0,0 +1 @@ +Copy the struts-portlet.psml file to the JETSPEED2_INSTALL_DIR/webapps/jetspeed/WEB-INF/pages directory. diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/jetspeed2/struts-portlet.psml b/STRUTS_2_0_X/apps/portlet/src/main/etc/jetspeed2/struts-portlet.psml new file mode 100644 index 000000000..d6c795489 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/jetspeed2/struts-portlet.psml @@ -0,0 +1,20 @@ + + + Struts Portlet Example Application + Struts Portlet Example Application + + + + + + + + + + public-view + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/portlet/src/main/etc/liferay3.6.1/web.xml b/STRUTS_2_0_X/apps/portlet/src/main/etc/liferay3.6.1/web.xml new file mode 100644 index 000000000..b5fedfbad --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/etc/liferay3.6.1/web.xml @@ -0,0 +1,75 @@ + + + + struts-portlet + + contextConfigLocation + /WEB-INF/applicationContext*.xml + + + company_id + struts.apache.org + + + action2 + + org.apache.struts2.dispatcher.FilterDispatcher + + + + + action2 + /* + + + + com.liferay.portal.servlet.PortletContextListener + + + + + org.springframework.web.context.ContextLoaderListener + + + + + org.apache.struts2.portlet.context.ServletContextHolderListener + + + + + + StrutsPortlet + + com.liferay.portal.servlet.PortletServlet + + + portlet-class + + org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher + + + 0 + + + + preparator + + org.apache.struts2.portlet.context.PreparatorServlet + + + + dwr + uk.ltd.getahead.dwr.DWRServlet + + + + dwr + /dwr/* + + + StrutsPortlet + /StrutsPortlet/* + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/ExampleAction.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/ExampleAction.java new file mode 100644 index 000000000..d3e0741b2 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/ExampleAction.java @@ -0,0 +1,39 @@ +/* + * $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.portlet.example; + +import java.util.Map; + +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ActionSupport; + +public class ExampleAction extends ActionSupport { + + private String name = "PortletWork Example"; + + public String getName() { + return name; + } + + public Map getRenderParameters() { + return ActionContext.getContext().getParameters(); + } +} diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExample.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExample.java new file mode 100644 index 000000000..36d27965c --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExample.java @@ -0,0 +1,50 @@ +/* + * $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.portlet.example; + +import com.opensymphony.xwork2.ActionSupport; + +/** + */ +public class FormExample extends ActionSupport { + + String firstName = null; + String lastName = null; + public String execute() throws Exception { + // TODO Auto-generated method stub + return super.execute(); + } + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } + public String displayResult() { + return "displayResult"; + } +} diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExampleModelDriven.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExampleModelDriven.java new file mode 100644 index 000000000..1eee98b24 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExampleModelDriven.java @@ -0,0 +1,37 @@ +/* + * $Id: FormExample.java 471756 2006-11-06 15:01:43Z husted $ + * + * 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.portlet.example; + +import org.apache.struts2.portlet.example.model.Name; + +import com.opensymphony.xwork2.ActionSupport; +import com.opensymphony.xwork2.ModelDriven; + +/** + */ +public class FormExampleModelDriven extends ActionSupport implements ModelDriven { + + private Name name = new Name(); + + public Name getModel() { + return name; + } +} diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExampleWithValidation.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExampleWithValidation.java new file mode 100644 index 000000000..a26609c13 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormExampleWithValidation.java @@ -0,0 +1,47 @@ +/* + * $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.portlet.example; + +import com.opensymphony.xwork2.ActionSupport; + +/** + */ +public class FormExampleWithValidation extends ActionSupport { + private String firstName = null; + private String lastName = null; + + public String input() { + return SUCCESS; + } + + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } +} diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormResultAction.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormResultAction.java new file mode 100644 index 000000000..6e9aeae22 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormResultAction.java @@ -0,0 +1,49 @@ +/* + * $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.portlet.example; + +import java.util.Collection; +import java.util.Map; + +import javax.portlet.RenderRequest; + +import org.apache.struts2.portlet.context.PortletActionContext; +import com.opensymphony.xwork2.ActionSupport; + +/** + */ +public class FormResultAction extends ActionSupport { + + private String result = null; + + public String getResult() { + return result; + } + public void setResult(String result) { + this.result = result; + } + + public Collection getRenderParams() { + RenderRequest req = PortletActionContext.getRenderRequest(); + Map params = req.getParameterMap(); + return params.entrySet(); + } +} diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormTestAction.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormTestAction.java new file mode 100644 index 000000000..ebbe102df --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/FormTestAction.java @@ -0,0 +1,36 @@ +/* + * $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.portlet.example; + +import com.opensymphony.xwork2.ActionSupport; + +/** + */ +public class FormTestAction extends ActionSupport { + + private String name = null; + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } +} diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/SavePrefsAction.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/SavePrefsAction.java new file mode 100644 index 000000000..1998e3796 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/SavePrefsAction.java @@ -0,0 +1,62 @@ +/* + * $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.portlet.example; + +import javax.portlet.ActionRequest; +import javax.portlet.PortletPreferences; + +import org.apache.struts2.portlet.context.PortletActionContext; +import com.opensymphony.xwork2.ActionSupport; + +/** + */ +public class SavePrefsAction extends ActionSupport { + private String preferenceOne = null; + private String preferenceTwo = null; + public String getPreferenceOne() { + return preferenceOne; + } + public void setPreferenceOne(String preferenceOne) { + this.preferenceOne = preferenceOne; + } + public String getPreferenceTwo() { + return preferenceTwo; + } + public void setPreferenceTwo(String preferenceTwo) { + this.preferenceTwo = preferenceTwo; + } + + public String execute() throws Exception { + ActionRequest req = PortletActionContext.getActionRequest(); + PortletPreferences prefs = req.getPreferences(); + prefs.setValue("preferenceOne", preferenceOne); + prefs.setValue("preferenceTwo", preferenceTwo); + prefs.store(); + return SUCCESS; + } + + public String showForm() throws Exception { + PortletPreferences prefs = PortletActionContext.getRequest().getPreferences(); + preferenceOne = prefs.getValue("preferenceOne", "not set"); + preferenceTwo = prefs.getValue("preferenceTwo", "not set"); + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/fileupload/FileUploadAction.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/fileupload/FileUploadAction.java new file mode 100644 index 000000000..c021714d3 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/fileupload/FileUploadAction.java @@ -0,0 +1,81 @@ +/* + * $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.portlet.example.fileupload; + +import java.io.File; + +import org.apache.struts2.dispatcher.DefaultActionSupport; + +/** + * File Upload example's action. FileUploadAction + * + */ +public class FileUploadAction extends DefaultActionSupport { + + private static final long serialVersionUID = 5156288255337069381L; + + private String contentType; + private File upload; + private String fileName; + private String caption; + + // since we are using the file name will be + // obtained through getter/setter of FileName + public String getUploadFileName() { + return fileName; + } + public void setUploadFileName(String fileName) { + this.fileName = fileName; + } + + + // since we are using the content type will be + // obtained through getter/setter of ContentType + public String getUploadContentType() { + return contentType; + } + public void setUploadContentType(String contentType) { + this.contentType = contentType; + } + + + // since we are using the File itself will be + // obtained through getter/setter of + public File getUpload() { + return upload; + } + public void setUpload(File upload) { + this.upload = upload; + } + + + public String getCaption() { + return caption; + } + public void setCaption(String caption) { + this.caption = caption; + } + + public String upload() throws Exception { + return SUCCESS; + } + +} diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/model/Name.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/model/Name.java new file mode 100644 index 000000000..1e59e1187 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/model/Name.java @@ -0,0 +1,18 @@ +package org.apache.struts2.portlet.example.model; + +public class Name { + private String firstName; + private String lastName; + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } +} diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/spring/SpringAction.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/spring/SpringAction.java new file mode 100644 index 000000000..8688423d6 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/spring/SpringAction.java @@ -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.portlet.example.spring; + +import java.util.List; + +import org.apache.commons.lang.StringUtils; + +import com.opensymphony.xwork2.ActionSupport; + +/** + */ +public class SpringAction extends ActionSupport { + + private ThingManager thingManager = null; + private String thing = null; + + public void setThingManager(ThingManager thingManager) { + this.thingManager = thingManager; + } + + public List getThings() { + return thingManager.getThings(); + } + + public String getThing() { + return thing; + } + + public void setThing(String thing) { + this.thing = thing; + } + + public String execute() { + if(StringUtils.isNotEmpty(thing)) { + thingManager.addThing(thing); + } + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/spring/ThingManager.java b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/spring/ThingManager.java new file mode 100644 index 000000000..ba117a5a7 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/java/org/apache/struts2/portlet/example/spring/ThingManager.java @@ -0,0 +1,38 @@ +/* + * $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.portlet.example.spring; + +import java.util.ArrayList; +import java.util.List; + +/** + */ +public class ThingManager { + private List things = new ArrayList(); + + public void addThing(String thing) { + things.add(thing); + } + + public List getThings() { + return things; + } +} diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/LICENSE.txt b/STRUTS_2_0_X/apps/portlet/src/main/resources/LICENSE.txt new file mode 100644 index 000000000..dd5b3a58a --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/LICENSE.txt @@ -0,0 +1,174 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/NOTICE.txt b/STRUTS_2_0_X/apps/portlet/src/main/resources/NOTICE.txt new file mode 100644 index 000000000..cd13ec449 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/NOTICE.txt @@ -0,0 +1,5 @@ +Apache Struts +Copyright 2000-2007 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/log4j.xml b/STRUTS_2_0_X/apps/portlet/src/main/resources/log4j.xml new file mode 100644 index 000000000..c6803daad --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/log4j.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/org/apache/struts2/portlet/example/FormExample-processValidationExample-validation.xml b/STRUTS_2_0_X/apps/portlet/src/main/resources/org/apache/struts2/portlet/example/FormExample-processValidationExample-validation.xml new file mode 100644 index 000000000..4effe04b1 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/org/apache/struts2/portlet/example/FormExample-processValidationExample-validation.xml @@ -0,0 +1,13 @@ + + + + + You must enter a first name + + + + + You must enter a last name + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-edit.xml b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-edit.xml new file mode 100644 index 000000000..73ec598dc --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-edit.xml @@ -0,0 +1,48 @@ + + + + + + + /WEB-INF/edit/index.jsp + + + /WEB-INF/edit/test.jsp + + + + /WEB-INF/edit/formExampleInput.jsp + + + + + + /WEB-INF/edit/formExampleInput.jsp + + + /edit/processFormExampleForward.action?firstName=${firstName}&lastName=${lastName} + + + + + + /WEB-INF/edit/formExample.jsp + + + + + + + /WEB-INF/edit/namespaceTest.jsp + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-help.xml b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-help.xml new file mode 100644 index 000000000..742a8d29c --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-help.xml @@ -0,0 +1,14 @@ + + + + + + + /WEB-INF/help/index.jsp + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-view.xml b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-view.xml new file mode 100644 index 000000000..2fa0b21fb --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts-view.xml @@ -0,0 +1,130 @@ + + + + + + + /WEB-INF/view/index.jsp + + + + + /WEB-INF/view/formExampleInput.jsp + + + + + + /WEB-INF/view/formExampleInput.jsp + + + /WEB-INF/view/formExample.jsp + + + + + + /WEB-INF/view/formExampleInputPrg.jsp + + + formExamplePrg + displayResult + ${firstName} + ${lastName} + + + /WEB-INF/view/formExample.jsp + + + + + + /WEB-INF/view/formExampleInputModelDriven.jsp + + + /WEB-INF/view/formExample.jsp + + + + + + /WEB-INF/view/formExampleInputValidation.jsp + + + + + + /WEB-INF/view/formExample.jsp + + + /WEB-INF/view/formExampleInputValidation.jsp + + + + + + /WEB-INF/view/fileUpload.jsp + + + /WEB-INF/view/fileUploadSuccess.jsp + + + + + + /WEB-INF/view/tokenExampleInput.jsp + + + + + + /WEB-INF/view/tokenExampleInput.jsp + + + /WEB-INF/view/tokenExampleInput.jsp + + + /WEB-INF/view/tokenExample.jsp + + + + + + + /WEB-INF/view/springExample.jsp + + + + + + /WEB-INF/view/freeMarkerExampleInput.ftl + + + + + /view/processFreeMarkerView.action?firstName=${firstName}&lastName=${lastName} + + + + /WEB-INF/view/freeMarkerExample.ftl + + + + /WEB-INF/view/helloWorld.vm + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/struts.properties b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts.properties new file mode 100644 index 000000000..cb40069a7 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts.properties @@ -0,0 +1 @@ +struts.objectFactory = spring diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/struts.xml b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts.xml new file mode 100644 index 000000000..f348c9f95 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/struts.xml @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/template/xhtml/components/checkbox.vm b/STRUTS_2_0_X/apps/portlet/src/main/resources/template/xhtml/components/checkbox.vm new file mode 100644 index 000000000..6d952f938 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/template/xhtml/components/checkbox.vm @@ -0,0 +1,12 @@ +
    +
    + $!struts.htmlEncode($parameters.label) +
    diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/template/xhtml/components/datefield.vm b/STRUTS_2_0_X/apps/portlet/src/main/resources/template/xhtml/components/datefield.vm new file mode 100644 index 000000000..7b3f44bef --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/template/xhtml/components/datefield.vm @@ -0,0 +1,8 @@ +#set ($name = $parameters.name) +#set ($label = $parameters.label) +#set ($size = $parameters.mysize) +#set ($yearsize = $parameters.yearsize) +$label: + / + / + (dd/mm/yyyy) diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/template/xhtml/components/mytextfield.vm b/STRUTS_2_0_X/apps/portlet/src/main/resources/template/xhtml/components/mytextfield.vm new file mode 100644 index 000000000..21c75be32 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/template/xhtml/components/mytextfield.vm @@ -0,0 +1,15 @@ +
    +
    + $!struts.htmlEncode($parameters.label) +
    diff --git a/STRUTS_2_0_X/apps/portlet/src/main/resources/validators.xml b/STRUTS_2_0_X/apps/portlet/src/main/resources/validators.xml new file mode 100644 index 000000000..a47094fe4 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/resources/validators.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/applicationContext.xml b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/applicationContext.xml new file mode 100644 index 000000000..6bd3e54ba --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/applicationContext.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/dwr.xml b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/dwr.xml new file mode 100644 index 000000000..4ede30035 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/dwr.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + ); + ]]> + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/defaultEdit.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/defaultEdit.jsp new file mode 100644 index 000000000..61b05c612 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/defaultEdit.jsp @@ -0,0 +1,5 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> +

    StrutsPortlet

    +This is the default edit page! +

    +">Set some prefs diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/formExample.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/formExample.jsp new file mode 100644 index 000000000..7d62563ab --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/formExample.jsp @@ -0,0 +1,5 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +

    Hello

    +

    +">Back to front page diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/formExampleInput.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/formExampleInput.jsp new file mode 100644 index 000000000..43c981df6 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/formExampleInput.jsp @@ -0,0 +1,8 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +

    Input your name

    + + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/index.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/index.jsp new file mode 100644 index 000000000..6b03c99f3 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/index.jsp @@ -0,0 +1,11 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> +There are no examples in edit mode yet + +

    +">Test +

    +">Form test +

    +">Dummy test +

    +">Back to view mode diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/namespaceTest.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/namespaceTest.jsp new file mode 100644 index 000000000..7e373a131 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/namespaceTest.jsp @@ -0,0 +1,4 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> +">Test page for namespace /edit/test +

    +">Back to edit index diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/prefsForm.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/prefsForm.jsp new file mode 100644 index 000000000..af8b02cd7 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/prefsForm.jsp @@ -0,0 +1,6 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/prefsSaved.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/prefsSaved.jsp new file mode 100644 index 000000000..6aca664f1 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/prefsSaved.jsp @@ -0,0 +1,5 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +The preferences has been saved. + +">Back diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/test.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/test.jsp new file mode 100644 index 000000000..615860c47 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/edit/test.jsp @@ -0,0 +1,4 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> +">Test page +

    +">Back to edit index diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/help/defaultHelp.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/help/defaultHelp.jsp new file mode 100644 index 000000000..c8fb774f7 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/help/defaultHelp.jsp @@ -0,0 +1 @@ +This is the default help page! diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/help/index.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/help/index.jsp new file mode 100644 index 000000000..ea58ff820 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/help/index.jsp @@ -0,0 +1 @@ +There are no examples in help mode yet diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/portlet.xml b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/portlet.xml new file mode 100644 index 000000000..91e7c1eba --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/portlet.xml @@ -0,0 +1,132 @@ + + + + + + Struts Test Portlet + StrutsPortlet + Struts Test Portlet + + org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher + + + + viewNamespace + /view + + + + + defaultViewAction + index + + + + + editNamespace + /edit + + + + + defaultEditAction + index + + + + + helpNamespace + /help + + + + + defaultHelpAction + index + + + 0 + + + text/html + edit + help + view + + + en + + + My StrutsPortlet portlet + SP + struts,portlet + + + + + Struts Test Portlet2 + StrutsPortlet2 + Struts Test Portlet2 + + org.apache.struts2.portlet.dispatcher.Jsr168Dispatcher + + + + viewNamespace + /view + + + + + defaultViewAction + index + + + + + editNamespace + /edit + + + + + defaultEditAction + index + + + + + helpNamespace + /help + + + + + defaultHelpAction + index + + + 0 + + + text/html + edit + help + view + + + en + + + My StrutsPortlet portlet2 + SP2 + struts,portlet + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/readme.txt b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/readme.txt new file mode 100644 index 000000000..53633149c --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/readme.txt @@ -0,0 +1,10 @@ +Configurations: + +JBoss Portal specific configuration files +----------------------------------------- +jboss-app.xml +jboss-portlet.xml +jboss-web.xml +portlet-instances.xml +struts-example-object.xml +struts-example-pages.xml diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajax.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajax.jsp new file mode 100644 index 000000000..e24ec7c17 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajax.jsp @@ -0,0 +1 @@ +

    Hello from Ajax!

    diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajaxData.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajaxData.jsp new file mode 100644 index 000000000..796b0d77d --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajaxData.jsp @@ -0,0 +1 @@ +This data is fetched via Ajax! The server time is <%= new java.util.Date() %> diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajaxExample.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajaxExample.jsp new file mode 100644 index 000000000..79ed4aa21 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/ajaxExample.jsp @@ -0,0 +1,48 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +"> +This is a tabbed pane with two panels that fetches data from a remote action via ajax + + + + This is the left pane
    + +
    + +
    +
    + " id="ryh1" theme="ajax" label="remote one" /> + + middle tab
    + +
    + +
    +
    + " id="ryh21" theme="ajax" label="remote right" /> +
    + +

    +A DIV that waits for 5 seconds before loading the contents +" + delay="5000" + loadingText="loading..."> + Waiting for data +

    +A DIV that is updated every 2 seconds +" + theme="ajax" + delay="2000" + updateFreq="2000" + errorText="There was an error" + loadingText="loading...">Initial Content + +

    +">Back to front page diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/fileUpload.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/fileUpload.jsp new file mode 100644 index 000000000..bf702bdbf --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/fileUpload.jsp @@ -0,0 +1,13 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +

    Fileupload sample

    + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/fileUploadSuccess.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/fileUploadSuccess.jsp new file mode 100644 index 000000000..3c0259f8f --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/fileUploadSuccess.jsp @@ -0,0 +1,14 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +

    Fileupload sample

    + +

    +

      +
    • ContentType:
    • +
    • FileName:
    • +
    • File:
    • +
    • Caption:
    • +
    +

    + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExample.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExample.jsp new file mode 100644 index 000000000..7d62563ab --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExample.jsp @@ -0,0 +1,5 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +

    Hello

    +

    +">Back to front page diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInput.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInput.jsp new file mode 100644 index 000000000..468d0eb4f --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInput.jsp @@ -0,0 +1,8 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +

    Input your name

    + + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInputModelDriven.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInputModelDriven.jsp new file mode 100644 index 000000000..bbb852f54 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInputModelDriven.jsp @@ -0,0 +1,8 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +

    Input your name

    + + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInputPrg.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInputPrg.jsp new file mode 100644 index 000000000..aaada2568 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInputPrg.jsp @@ -0,0 +1,8 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +

    Input your name

    + + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInputValidation.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInputValidation.jsp new file mode 100644 index 000000000..f64745747 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/formExampleInputValidation.jsp @@ -0,0 +1,8 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> +"> +

    Input your name

    + + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/freeMarkerExample.ftl b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/freeMarkerExample.ftl new file mode 100644 index 000000000..cb70dc7c4 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/freeMarkerExample.ftl @@ -0,0 +1,3 @@ +Hello from FreeMarker, ${firstName} ${lastName}! +

    +">Back to front page diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/freeMarkerExampleInput.ftl b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/freeMarkerExampleInput.ftl new file mode 100644 index 000000000..86ebbfbe7 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/freeMarkerExampleInput.ftl @@ -0,0 +1,5 @@ +<@s.form action="processFreeMarkerExample" method="POST"> + <@s.textfield label="First name" name="firstName"/> + <@s.textfield label="Last name" name="lastName"/> + <@s.submit value="Say hello!"/> + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/helloWorld.vm b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/helloWorld.vm new file mode 100644 index 000000000..5007bf76a --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/helloWorld.vm @@ -0,0 +1,4 @@ +Hello World from velocity! +

    +#surl ("id=url" "action=index") +Back to the front page diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/index.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/index.jsp new file mode 100644 index 000000000..d7ad46784 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/index.jsp @@ -0,0 +1,17 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> +

    Welcome to the Struts example portlet

    +

    +Here you'll find examples of what is possible with the Struts Portlet integration framework. +

    diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/notImplemented.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/notImplemented.jsp new file mode 100644 index 000000000..a3af7eb2b --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/notImplemented.jsp @@ -0,0 +1 @@ +

    This example has not yet been implemented

    diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/springExample.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/springExample.jsp new file mode 100644 index 000000000..8a0da4287 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/springExample.jsp @@ -0,0 +1,16 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +

    Example of Spring managed singleton. All the 'things' are contained in a Spring defined ThingManager

    + +Things in the list: +

    + +
    +
    +

    + + + + +

    +">Back to front page diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/tokenExample.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/tokenExample.jsp new file mode 100644 index 000000000..e41c9e96e --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/tokenExample.jsp @@ -0,0 +1,5 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +

    The form was successfully submitted with a valid token

    + +"/>Back to front page diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/tokenExampleInput.jsp b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/tokenExampleInput.jsp new file mode 100644 index 000000000..7aa2e31aa --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/view/tokenExampleInput.jsp @@ -0,0 +1,20 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + ERROR:
    + + +
    +
    +
    +
    +

    Form with invalid token

    + + + + +

    Form with valid token

    + + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/web.xml b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..4b64cb5b2 --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,30 @@ + + + + + + + + + contextConfigLocation + /WEB-INF/applicationContext*.xml + + + + Struts2 + org.apache.struts2.dispatcher.FilterDispatcher + + + + Struts2 + /* + + + + org.springframework.web.context.ContextLoaderListener + + + + diff --git a/STRUTS_2_0_X/apps/portlet/src/main/webapp/styles/styles.css b/STRUTS_2_0_X/apps/portlet/src/main/webapp/styles/styles.css new file mode 100644 index 000000000..3dafc085a --- /dev/null +++ b/STRUTS_2_0_X/apps/portlet/src/main/webapp/styles/styles.css @@ -0,0 +1,7 @@ +.wwFormTable {} +.label {font-style:italic; } +.errorLabel {font-style:italic; color:red; } +.errorMessage {font-weight:bold; text-align: center; color:red; } +.checkboxLabel {} +.checkboxErrorLabel {color:red; } +.required {color:red;} diff --git a/STRUTS_2_0_X/apps/showcase/README.txt b/STRUTS_2_0_X/apps/showcase/README.txt new file mode 100644 index 000000000..4d483c78c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/README.txt @@ -0,0 +1,10 @@ +README.txt - showcase + +Showcase is a collection of examples with code that you might be adopt and +adapt in your own applications. + +For more on getting started with Struts, see + +* http://cwiki.apache.org/WW/home.html + +---------------------------------------------------------------------------- \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/pom.xml b/STRUTS_2_0_X/apps/showcase/pom.xml new file mode 100644 index 000000000..f24c0b8d8 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/pom.xml @@ -0,0 +1,185 @@ + + + 4.0.0 + + org.apache.struts + struts2-apps + 2.0.14 + + org.apache.struts + struts2-showcase + war + Showcase Webapp + + + scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps/showcase + scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/apps/showcase + http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_0_14/apps/showcase + + + + + + hostedqa + + 12 + 9 + 8 + 7 + + + + + + + org.apache.struts + struts2-struts1-plugin + ${pom.version} + + + + org.apache.struts + struts2-jsf-plugin + ${pom.version} + + + + org.apache.struts + struts2-config-browser-plugin + ${pom.version} + + + + org.apache.struts + struts2-sitemesh-plugin + ${pom.version} + + + + org.apache.struts + struts2-tiles-plugin + ${pom.version} + + + + org.apache.tiles + tiles-jsp + 2.0.4 + runtime + + + + org.apache.struts + struts2-codebehind-plugin + ${pom.version} + + + + org.apache.struts + struts2-spring-plugin + ${pom.version} + + + + javax.servlet + servlet-api + 2.4 + provided + + + + + velocity + velocity + 1.4 + + + + velocity-tools + velocity-tools + 1.1 + + + + + opensymphony + sitemesh + 2.2.1 + + + uk.ltd.getahead + dwr + 1.1-beta-3 + + + log4j + log4j + 1.2.9 + + + commons-logging + commons-logging + 1.0.4 + + + org.apache.myfaces.core + myfaces-impl + 1.1.2 + + + org.apache.myfaces.core + myfaces-api + 1.1.2 + + + commons-fileupload + commons-fileupload + 1.1.1 + + + + + + + + + org.mortbay.jetty + maven-jetty-plugin + 6.0.1 + + 10 + + + + org.apache.myfaces.core + myfaces-impl + 1.1.2 + + + org.apache.myfaces.core + myfaces-api + 1.1.2 + + + log4j + log4j + 1.2.9 + + + + + + + + src/main/resources + + + src/main/java + + **/*.java + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/DateAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/DateAction.java new file mode 100644 index 000000000..c84e0b5a2 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/DateAction.java @@ -0,0 +1,106 @@ +/* + * $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.showcase; + +import java.text.DateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * DateAction + * + */ +public class DateAction extends ActionSupport { + + private static DateFormat DF = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM); + + private Date now; + private Date past; + private Date future; + private Date after; + private Date before; + + + public String getDate() { + return DF.format(new Date()); + } + + + /** + * @return Returns the future. + */ + public Date getFuture() { + return future; + } + + /** + * @return Returns the now. + */ + public Date getNow() { + return now; + } + + /** + * @return Returns the past. + */ + public Date getPast() { + return past; + } + + /** + * + * @return Returns the before date. + */ + public Date getBefore() { + return before; + } + + /** + * + * @return Returns the after date. + */ + public Date getAfter() { + return after; + } + + /** + */ + public String browse() throws Exception { + Calendar cal = GregorianCalendar.getInstance(); + now = cal.getTime(); + cal.roll(Calendar.DATE, -1); + cal.roll(Calendar.HOUR, -3); + past = cal.getTime(); + cal.roll(Calendar.DATE, 2); + future = cal.getTime(); + + cal.roll(Calendar.YEAR, -1); + before = cal.getTime(); + + cal.roll(Calendar.YEAR, 2); + after = cal.getTime(); + return SUCCESS; + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/DynamicTreeSelectAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/DynamicTreeSelectAction.java new file mode 100644 index 000000000..5d22be5ef --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/DynamicTreeSelectAction.java @@ -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 org.apache.struts2.showcase; + +import org.apache.struts2.showcase.ajax.tree.Category; + +import com.opensymphony.xwork2.ActionSupport; + +//START SNIPPET: treeExampleDynamicJavaSelected + +public class DynamicTreeSelectAction extends ActionSupport { + + private long nodeId; + private Category currentCategory; + + + public void setNodeId(long nodeId) { + this.nodeId = nodeId; + } + public long getNodeId() { + return nodeId; + } + + + public String execute() throws Exception { + currentCategory = Category.getById(nodeId); + return SUCCESS; + } + + + public String getNodeName() { + return currentCategory.getName(); + } +} + +//START SNIPPET: treeExampleDynamicJavaSelected + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfOptiontransferselectAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfOptiontransferselectAction.java new file mode 100644 index 000000000..3649b039b --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfOptiontransferselectAction.java @@ -0,0 +1,286 @@ +/* + * $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.showcase; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.ArrayList; + +import com.opensymphony.xwork2.ActionSupport; + +/** + */ +public class LotsOfOptiontransferselectAction extends ActionSupport { + + private List _favouriteCartoonCharactersKeys; + private List _notFavouriteCartoonCharactersKeys; + + private List _favouriteCarsKeys; + private List _notFavouriteCarsKeys; + + private List _favouriteMotorcyclesKeys; + private List _notFavouriteMotorcyclesKeys; + + private List _favouriteCountriesKeys; + private List _notFavouriteCountriesKeys; + + private List _favouriteSportsKeys; + private List _nonFavouriteSportsKeys; + + private List _favouriteCities; + + private List _prioritisedFavouriteCartoonCharacters; + private List _prioritisedFavouriteCars; + private List _prioritisedFavouriteCountries; + + + + // Cartoon Characters + public Map getDefaultFavouriteCartoonCharacters() { + Map m = new LinkedHashMap(); + m.put("heMan", "He-Man"); + m.put("popeye", "Popeye"); + m.put("mockeyMouse", "Mickey Mouse"); + return m; + } + + public Map getDefaultNotFavouriteCartoonCharacters() { + Map m = new LinkedHashMap(); + m.put("donaldDuck", "Donald Duck"); + m.put("atomicAnt", "Atomic Ant"); + m.put("pinkPainter", "Pink Painter"); + return m; + } + + public List getFavouriteCartoonCharacters() { + return _favouriteCartoonCharactersKeys; + } + + public void setFavouriteCartoonCharacters(List favouriteCartoonCharacters) { + _favouriteCartoonCharactersKeys = favouriteCartoonCharacters; + } + + public List getNotFavouriteCartoonCharacters() { + return _notFavouriteCartoonCharactersKeys; + } + + public void setNotFavouriteCartoonCharacters(List notFavouriteCartoonCharacters) { + _notFavouriteCartoonCharactersKeys = notFavouriteCartoonCharacters; + } + + + + + + // Cars + public Map getDefaultFavouriteCars() { + Map m = new LinkedHashMap(); + m.put("alfaRomeo", "Alfa Romeo"); + m.put("Toyota", "Toyota"); + m.put("Mitsubitshi", "Mitsubitshi"); + return m; + } + + public Map getDefaultNotFavouriteCars() { + Map m = new LinkedHashMap(); + m.put("ford", "Ford"); + m.put("landRover", "Land Rover"); + m.put("mercedes", "Mercedes"); + return m; + } + + public List getFavouriteCars() { + return _favouriteCarsKeys; + } + + public void setFavouriteCars(List favouriteCars) { + _favouriteCarsKeys = favouriteCars; + } + + public List getNotFavouriteCars() { + return _notFavouriteCarsKeys; + } + + public void setNotFavouriteCars(List notFavouriteCars) { + _notFavouriteCarsKeys = notFavouriteCars; + } + + + + // Motorcycles + public Map getDefaultFavouriteMotorcycles() { + Map m = new LinkedHashMap(); + m.put("honda", "Honda"); + m.put("yamaha", "Yamaha"); + m.put("Aprillia", "Aprillia"); + return m; + } + + public Map getDefaultNotFavouriteMotorcycles() { + Map m = new LinkedHashMap(); + m.put("cagiva", "Cagiva"); + m.put("harleyDavidson", "Harley Davidson"); + m.put("suzuki", "Suzuki"); + return m; + } + + public List getFavouriteMotorcycles() { + return _favouriteMotorcyclesKeys; + } + + public void setFavouriteMotorcycles(List favouriteMotorcycles) { + _favouriteMotorcyclesKeys = favouriteMotorcycles; + } + + public List getNotFavouriteMotorcycles() { + return _notFavouriteMotorcyclesKeys; + } + + public void setNotFavouriteMotorcycles(List notFavouriteMotorcycles) { + _notFavouriteMotorcyclesKeys = notFavouriteMotorcycles; + } + + + + // Countries + public Map getDefaultFavouriteCountries() { + Map m = new LinkedHashMap(); + m.put("england", "England"); + m.put("america", "America"); + m.put("brazil", "Brazil"); + return m; + } + + public Map getDefaultNotFavouriteCountries() { + Map m = new LinkedHashMap(); + m.put("germany", "Germany"); + m.put("china", "China"); + m.put("russia", "Russia"); + return m; + } + + public List getFavouriteCountries() { + return _favouriteCountriesKeys; + } + + public void setFavouriteCountries(List favouriteCountries) { + _favouriteCountriesKeys = favouriteCountries; + } + + public List getNotFavouriteCountries() { + return _notFavouriteCountriesKeys; + } + + public void setNotFavouriteCountries(List notFavouriteCountries) { + _notFavouriteCountriesKeys = notFavouriteCountries; + } + + // Sports + public Map getDefaultNonFavoriteSports() { + Map m = new LinkedHashMap(); + m.put("basketball", "Basketball"); + m.put("football", "Football"); + m.put("baseball", "Baseball"); + return m; + } + + public Map getDefaultFavoriteSports() { + return new LinkedHashMap(); + } + + public List getFavouriteSports() { + return _favouriteSportsKeys; + } + + public void setFavouriteSports(List favouriteSportsKeys) { + this._favouriteSportsKeys = favouriteSportsKeys; + } + + public List getNonFavouriteSports() { + return _nonFavouriteSportsKeys; + } + + public void setNonFavouriteSports(List notFavouriteSportsKeys) { + this._nonFavouriteSportsKeys = notFavouriteSportsKeys; + } + + + + + public List getPrioritisedFavouriteCartoonCharacters() { + return _prioritisedFavouriteCartoonCharacters; + } + public void setPrioritisedFavouriteCartoonCharacters(List prioritisedFavouriteCartoonCharacters) { + _prioritisedFavouriteCartoonCharacters = prioritisedFavouriteCartoonCharacters; + } + + public List getPrioritisedFavouriteCars() { + return _prioritisedFavouriteCars; + } + public void setPrioritisedFavouriteCars(List prioritisedFavouriteCars) { + _prioritisedFavouriteCars = prioritisedFavouriteCars; + } + + + public List getPrioritisedFavouriteCountries() { + return _prioritisedFavouriteCountries; + } + public void setPrioritisedFavouriteCountries(List prioritisedFavouriteCountries) { + _prioritisedFavouriteCountries = prioritisedFavouriteCountries; + } + + + + public Map getAvailableCities() { + Map map = new LinkedHashMap(); + map.put("boston", "Boston"); + map.put("new york", "New York"); + map.put("london", "London"); + map.put("rome", "Rome"); + return map; + } + + public List getDefaultFavouriteCities() { + List list = new ArrayList(); + list.add("boston"); + list.add("rome"); + return list; + } + + public List getFavouriteCities() { + return _favouriteCities; + } + + public void setFavouriteCities(List favouriteCities) { + this._favouriteCities = favouriteCities; + } + + // actions + + public String input() throws Exception { + return SUCCESS; + } + + public String submit() throws Exception { + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfRichtexteditorAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfRichtexteditorAction.java new file mode 100644 index 000000000..410a499c7 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfRichtexteditorAction.java @@ -0,0 +1,78 @@ +/* + * $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.showcase; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * + */ +public class LotsOfRichtexteditorAction extends ActionSupport { + + public String description1; + public String description2 = "This is Description 2"; + public String description3; + public String description4 = "This is Description 4"; + + public String getDescription1() { + return this.description1; + } + public void setDescription1(String description1) { + this.description1 = description1; + } + + + public String getDescription2() { + return this.description2; + } + public void setDescription2(String description2) { + this.description2 = description2; + } + + + public String getDescription3() { + return this.description3; + } + public void setDescription3(String description3) { + this.description3 = description3; + } + + + + + public String getDescription4() { + return this.description4; + } + public void setDescription4(String description4) { + this.description4 = description4; + } + + + + + public String input() throws Exception { + return SUCCESS; + } + + public String submit() throws Exception { + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/MoreSelectsAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/MoreSelectsAction.java new file mode 100644 index 000000000..516f4314a --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/MoreSelectsAction.java @@ -0,0 +1,135 @@ +/* + * $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.showcase; + +import com.opensymphony.xwork2.ActionSupport; + +import java.util.List; +import java.util.Map; +import java.util.LinkedHashMap; +import java.util.ArrayList; + +/** + */ +public class MoreSelectsAction extends ActionSupport { + + + private List _prioritisedFavouriteCartoonCharacters; + private List _prioritisedFavouriteCars; + private List _prioritisedFavouriteCountries; + private List favouriteNumbers; + + + // Cartoon Characters + public Map getDefaultFavouriteCartoonCharacters() { + Map m = new LinkedHashMap(); + m.put("heMan", "He-Man"); + m.put("popeye", "Popeye"); + m.put("mockeyMouse", "Mickey Mouse"); + return m; + } + + + // Cars + public Map getDefaultFavouriteCars() { + Map m = new LinkedHashMap(); + m.put("alfaRomeo", "Alfa Romeo"); + m.put("Toyota", "Toyota"); + m.put("Mitsubitshi", "Mitsubitshi"); + return m; + } + + + + // Countries + public Map getDefaultFavouriteCountries() { + Map m = new LinkedHashMap(); + m.put("england", "England"); + m.put("america", "America"); + m.put("brazil", "Brazil"); + return m; + } + + public List getDefaultFavouriteNumbers() { + List list = new ArrayList(); + list.add("Three"); + list.add("Seven"); + return list; + } + + + + public List getPrioritisedFavouriteCartoonCharacters() { + return _prioritisedFavouriteCartoonCharacters; + } + public void setPrioritisedFavouriteCartoonCharacters(List prioritisedFavouriteCartoonCharacters) { + _prioritisedFavouriteCartoonCharacters = prioritisedFavouriteCartoonCharacters; + } + + public List getPrioritisedFavouriteCars() { + return _prioritisedFavouriteCars; + } + public void setPrioritisedFavouriteCars(List prioritisedFavouriteCars) { + _prioritisedFavouriteCars = prioritisedFavouriteCars; + } + + + public List getPrioritisedFavouriteCountries() { + return _prioritisedFavouriteCountries; + } + public void setPrioritisedFavouriteCountries(List prioritisedFavouriteCountries) { + _prioritisedFavouriteCountries = prioritisedFavouriteCountries; + } + + public List getFavouriteNumbers() { + return favouriteNumbers; + } + + public void setFavouriteNumbers(List favouriteNumbers) { + this.favouriteNumbers = favouriteNumbers; + } + + public Map getAvailableCities() { + Map map = new LinkedHashMap(); + map.put("boston", "Boston"); + map.put("new york", "New York"); + map.put("london", "London"); + map.put("rome", "Rome"); + return map; + } + + public List getDefaultFavouriteCities() { + List list = new ArrayList(); + list.add("boston"); + list.add("rome"); + return list; + } + + // actions + + public String input() throws Exception { + return SUCCESS; + } + + public String submit() throws Exception { + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ShowDynamicTreeAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ShowDynamicTreeAction.java new file mode 100644 index 000000000..fcbe56d0a --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ShowDynamicTreeAction.java @@ -0,0 +1,37 @@ +/* + * $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.showcase; + +import org.apache.struts2.showcase.ajax.tree.Category; + +import com.opensymphony.xwork2.ActionSupport; + +// START SNIPPET: treeExampleDynamicJavaShow + +public class ShowDynamicTreeAction extends ActionSupport { + + public Category getTreeRootNode() { + return Category.getById(1); + } +} + +// END SNIPPET: treeExampleDynamicJavaShow + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/UITagExample.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/UITagExample.java new file mode 100644 index 000000000..95fa0dded --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/UITagExample.java @@ -0,0 +1,322 @@ +/* + * $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.showcase; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.struts2.ServletActionContext; + +import com.opensymphony.xwork2.ActionSupport; +import com.opensymphony.xwork2.Validateable; +import com.opensymphony.xwork2.util.ValueStack; + +/** + */ +public class UITagExample extends ActionSupport implements Validateable { + + private static final long serialVersionUID = -94044809860988047L; + + + String name; + Date birthday; + String bio; + String favouriteColor; + List friends; + boolean legalAge; + String state; + String region; + File picture; + String pictureContentType; + String pictureFileName; + String favouriteLanguage; + String favouriteVehicalType = "MotorcycleKey"; + String favouriteVehicalSpecific = "YamahaKey"; + + List leftSideCartoonCharacters; + List rightSideCartoonCharacters; + + List favouriteLanguages = new ArrayList(); + List vehicalTypeList = new ArrayList(); + Map vehicalSpecificMap = new HashMap(); + + String thoughts; + + public UITagExample() { + favouriteLanguages.add(new Language("EnglishKey", "English Language")); + favouriteLanguages.add(new Language("FrenchKey", "French Language")); + favouriteLanguages.add(new Language("SpanishKey", "Spanish Language")); + + VehicalType car = new VehicalType("CarKey", "Car"); + VehicalType motorcycle = new VehicalType("MotorcycleKey", "Motorcycle"); + vehicalTypeList.add(car); + vehicalTypeList.add(motorcycle); + + List cars = new ArrayList(); + cars.add(new VehicalSpecific("MercedesKey", "Mercedes")); + cars.add(new VehicalSpecific("HondaKey", "Honda")); + cars.add(new VehicalSpecific("FordKey", "Ford")); + + List motorcycles = new ArrayList(); + motorcycles.add(new VehicalSpecific("SuzukiKey", "Suzuki")); + motorcycles.add(new VehicalSpecific("YamahaKey", "Yamaha")); + + vehicalSpecificMap.put(car, cars); + vehicalSpecificMap.put(motorcycle, motorcycles); + } + + + + public List getLeftSideCartoonCharacters() { + return leftSideCartoonCharacters; + } + public void setLeftSideCartoonCharacters(List leftSideCartoonCharacters) { + this.leftSideCartoonCharacters = leftSideCartoonCharacters; + } + + + public List getRightSideCartoonCharacters() { + return rightSideCartoonCharacters; + } + public void setRightSideCartoonCharacters(List rightSideCartoonCharacters) { + this.rightSideCartoonCharacters = rightSideCartoonCharacters; + } + + + public String getFavouriteVehicalType() { + return favouriteVehicalType; + } + + public void setFavouriteVehicalType(String favouriteVehicalType) { + this.favouriteVehicalType = favouriteVehicalType; + } + + public String getFavouriteVehicalSpecific() { + return favouriteVehicalSpecific; + } + + public void setFavouriteVehicalSpecific(String favouriteVehicalSpecific) { + this.favouriteVehicalSpecific = favouriteVehicalSpecific; + } + + public List getVehicalTypeList() { + return vehicalTypeList; + } + + public List getVehicalSpecificList() { + ValueStack stack = ServletActionContext.getValueStack(ServletActionContext.getRequest()); + Object vehicalType = stack.findValue("top"); + if (vehicalType != null && vehicalType instanceof VehicalType) { + List l = (List) vehicalSpecificMap.get(vehicalType); + return l; + } + return Collections.EMPTY_LIST; + } + + public List getFavouriteLanguages() { + return favouriteLanguages; + } + + public String execute() throws Exception { + return SUCCESS; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Date getBirthday() { + return birthday; + } + + public void setBirthday(Date birthday) { + this.birthday = birthday; + } + + public String getBio() { + return bio; + } + + public void setBio(String bio) { + this.bio = bio; + } + + public String getFavouriteColor() { + return favouriteColor; + } + + public void setFavouriteColor(String favoriteColor) { + this.favouriteColor = favoriteColor; + } + + public List getFriends() { + return friends; + } + + public void setFriends(List friends) { + this.friends = friends; + } + + public boolean isLegalAge() { + return legalAge; + } + + public void setLegalAge(boolean legalAge) { + this.legalAge = legalAge; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public void setPicture(File picture) { + this.picture = picture; + } + + public File getPicture() { + return this.picture; + } + + public void setPictureContentType(String pictureContentType) { + this.pictureContentType = pictureContentType; + } + + public void setPictureFileName(String pictureFileName) { + this.pictureFileName = pictureFileName; + } + + public void setFavouriteLanguage(String favouriteLanguage) { + this.favouriteLanguage = favouriteLanguage; + } + + public String getFavouriteLanguage() { + return favouriteLanguage; + } + + + public void setThoughts(String thoughts) { + this.thoughts = thoughts; + } + + public String getThoughts() { + return this.thoughts; + } + + + + public String doSubmit() { + return SUCCESS; + } + + + + // === inner class + public static class Language { + String description; + String key; + + public Language(String key, String description) { + this.key = key; + this.description = description; + } + + public String getKey() { + return key; + } + public String getDescription() { + return description; + } + + } + + + public static class VehicalType { + String key; + String description; + public VehicalType(String key, String description) { + this.key = key; + this.description = description; + } + + public String getKey() { return this.key; } + public String getDescription() { return this.description; } + + public boolean equals(Object obj) { + if (! (obj instanceof VehicalType)) { + return false; + } + else { + return key.equals(((VehicalType)obj).getKey()); + } + } + + public int hashCode() { + return key.hashCode(); + } + } + + + public static class VehicalSpecific { + String key; + String description; + public VehicalSpecific(String key, String description) { + this.key = key; + this.description = description; + } + + public String getKey() { return this.key; } + public String getDescription() { return this.description; } + + public boolean equals(Object obj) { + if (! (obj instanceof VehicalSpecific)) { + return false; + } + else { + return key.equals(((VehicalSpecific)obj).getKey()); + } + } + + public int hashCode() { + return key.hashCode(); + } + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/AbstractCRUDAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/AbstractCRUDAction.java new file mode 100644 index 000000000..0e53d3832 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/AbstractCRUDAction.java @@ -0,0 +1,97 @@ +/* + * $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.showcase.action; + +import java.io.Serializable; +import java.util.Collection; + +import org.apache.log4j.Logger; +import org.apache.struts2.showcase.dao.Dao; +import org.apache.struts2.showcase.model.IdEntity; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * AbstractCRUDAction. + * + */ + +public abstract class AbstractCRUDAction extends ActionSupport { + + private static final Logger log = Logger.getLogger(AbstractCRUDAction.class); + + private Collection availableItems; + private String[] toDelete; + + protected abstract Dao getDao(); + + + public Collection getAvailableItems() { + return availableItems; + } + + public String[] getToDelete() { + return toDelete; + } + + public void setToDelete(String[] toDelete) { + this.toDelete = toDelete; + } + + public String list() throws Exception { + this.availableItems = getDao().findAll(); + if (log.isDebugEnabled()) { + log.debug("AbstractCRUDAction - [list]: " + (availableItems !=null?""+availableItems.size():"no") + " items found"); + } + return execute(); + } + + public String delete() throws Exception { + if (toDelete != null) { + int count=0; + for (int i = 0, j=toDelete.length; i < j; i++) { + count = count + getDao().delete(toDelete[i]); + } + if (log.isDebugEnabled()) { + log.debug("AbstractCRUDAction - [delete]: " + count + " items deleted."); + } + } + return SUCCESS; + } + + /** + * Utility method for fetching already persistent object from storage for usage in params-prepare-params cycle. + * + * @param tryId The id to try to get persistent object for + * @param tryObject The object, induced by first params invocation, possibly containing id to try to get persistent + * object for + * @return The persistent object, if found. null otherwise. + */ + protected IdEntity fetch(Serializable tryId, IdEntity tryObject) { + IdEntity result = null; + if (tryId != null) { + result = getDao().get(tryId); + } else if (tryObject != null) { + result = getDao().get(tryObject.getId()); + } + return result; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/EmployeeAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/EmployeeAction.java new file mode 100644 index 000000000..8af63fa23 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/EmployeeAction.java @@ -0,0 +1,126 @@ +/* + * $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.showcase.action; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.apache.log4j.Logger; +import org.apache.struts2.showcase.application.TestDataProvider; +import org.apache.struts2.showcase.dao.Dao; +import org.apache.struts2.showcase.dao.EmployeeDao; +import org.apache.struts2.showcase.model.Employee; +import org.apache.struts2.showcase.model.Skill; + +import com.opensymphony.xwork2.Preparable; + +/** + * JsfEmployeeAction. + */ + +public class EmployeeAction extends AbstractCRUDAction implements Preparable { + + private static final long serialVersionUID = 7047317819789938957L; + + private static final Logger log = Logger.getLogger(EmployeeAction.class); + + private Long empId; + protected EmployeeDao employeeDao; + private Employee currentEmployee; + private List selectedSkills; + + public Long getEmpId() { + return empId; + } + + public void setEmpId(Long empId) { + this.empId = empId; + } + + public Employee getCurrentEmployee() { + return currentEmployee; + } + + public void setCurrentEmployee(Employee currentEmployee) { + this.currentEmployee = currentEmployee; + } + + public String[] getAvailablePositions() { + return TestDataProvider.POSITIONS; + } + + public List getAvailableLevels() { + return Arrays.asList(TestDataProvider.LEVELS); + } + + public List getSelectedSkills() { + return selectedSkills; + } + + public void setSelectedSkills(List selectedSkills) { + this.selectedSkills = selectedSkills; + } + + protected Dao getDao() { + return employeeDao; + } + + public void setEmployeeDao(EmployeeDao employeeDao) { + if (log.isDebugEnabled()) { + log.debug("JsfEmployeeAction - [setEmployeeDao]: employeeDao injected."); + } + this.employeeDao = employeeDao; + } + + /** + * This method is called to allow the action to prepare itself. + * + * @throws Exception thrown if a system level exception occurs. + */ + public void prepare() throws Exception { + Employee preFetched = (Employee) fetch(getEmpId(), getCurrentEmployee()); + if (preFetched != null) { + setCurrentEmployee(preFetched); + } + } + + public String execute() throws Exception { + if (getCurrentEmployee() != null && getCurrentEmployee().getOtherSkills() != null) { + setSelectedSkills(new ArrayList()); + Iterator it = getCurrentEmployee().getOtherSkills().iterator(); + while (it.hasNext()) { + getSelectedSkills().add(((Skill) it.next()).getName()); + } + } + return super.execute(); + } + + public String save() throws Exception { + if (getCurrentEmployee() != null) { + setEmpId((Long) employeeDao.merge(getCurrentEmployee())); + employeeDao.setSkills(getEmpId(), getSelectedSkills()); + } + return SUCCESS; + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/SkillAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/SkillAction.java new file mode 100644 index 000000000..96d10fc3d --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/action/SkillAction.java @@ -0,0 +1,89 @@ +/* + * $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.showcase.action; + +import org.apache.log4j.Logger; +import org.apache.struts2.showcase.dao.Dao; +import org.apache.struts2.showcase.dao.SkillDao; +import org.apache.struts2.showcase.model.Skill; + +import com.opensymphony.xwork2.Preparable; + +/** + * SkillAction. + * + */ + +public class SkillAction extends AbstractCRUDAction implements Preparable { + + private static final Logger log = Logger.getLogger(SkillAction.class); + + private String skillName; + protected SkillDao skillDao; + private Skill currentSkill; + + public String getSkillName() { + return skillName; + } + + public void setSkillName(String skillName) { + this.skillName = skillName; + } + + protected Dao getDao() { + return skillDao; + } + + public void setSkillDao(SkillDao skillDao) { + if (log.isDebugEnabled()) { + log.debug("SkillAction - [setSkillDao]: skillDao injected."); + } + this.skillDao = skillDao; + } + + public Skill getCurrentSkill() { + return currentSkill; + } + + public void setCurrentSkill(Skill currentSkill) { + this.currentSkill = currentSkill; + } + + /** + * This method is called to allow the action to prepare itself. + * + * @throws Exception thrown if a system level exception occurs. + */ + public void prepare() throws Exception { + Skill preFetched = (Skill) fetch(getSkillName(), getCurrentSkill()); + if (preFetched != null) { + setCurrentSkill(preFetched); + } + } + + public String save() throws Exception { + if (getCurrentSkill() != null) { + setSkillName((String) skillDao.merge(getCurrentSkill())); + } + return SUCCESS; + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain1.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain1.java new file mode 100644 index 000000000..26fb309da --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain1.java @@ -0,0 +1,45 @@ +/* + * $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.showcase.actionchaining; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * + */ +public class ActionChain1 extends ActionSupport { + + private static final long serialVersionUID = -6811701750042275153L; + + private String actionChain1Property1 = "Property Set In Action Chain 1"; + + public String getActionChain1Property1() { + return actionChain1Property1; + } + public void setActionChain1Property1(String actionChain1Property1) { + this.actionChain1Property1 = actionChain1Property1; + } + + + public String input() throws Exception { + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain2.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain2.java new file mode 100644 index 000000000..603d19fd9 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain2.java @@ -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.showcase.actionchaining; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * + */ +public class ActionChain2 extends ActionSupport { + + private static final long serialVersionUID = 3951745956044674809L; + + private String actionChain1Property1; + private String actionChain2Property1 = "Property Set in Action Chain 2"; + + + public String getActionChain1Property1() { + return actionChain1Property1; + } + public void setActionChain1Property1(String actionChain1Property1) { + this.actionChain1Property1 = actionChain1Property1; + } + + + + public String getActionChain2Property1() { + return actionChain2Property1; + } + public void setActionChain2Property1(String actionChain2Property1) { + this.actionChain2Property1 = actionChain2Property1; + } + + + + + public String execute() throws Exception { + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain3.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain3.java new file mode 100644 index 000000000..f2ec60cc9 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain3.java @@ -0,0 +1,68 @@ +/* + * $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.showcase.actionchaining; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * + */ +public class ActionChain3 extends ActionSupport { + + private static final long serialVersionUID = -1456568865075250621L; + + private String actionChain1Property1; + private String actionChain2Property1; + private String actionChain3Property1 = "Property set in Action Chain 3"; + + + public String getActionChain1Property1() { + return actionChain1Property1; + } + public void setActionChain1Property1(String actionChain1Property1) { + this.actionChain1Property1 = actionChain1Property1; + } + + + + public String getActionChain2Property1() { + return actionChain2Property1; + } + public void setActionChain2Property1(String actionChain2Property1) { + this.actionChain2Property1 = actionChain2Property1; + } + + + + public String getActionChain3Property1() { + return actionChain3Property1; + } + public void setActionChain3Property1(String actionChain3Property1) { + this.actionChain3Property1 = actionChain3Property1; + } + + + + + public String execute() throws Exception { + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AjaxTestAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AjaxTestAction.java new file mode 100644 index 000000000..c078ca74c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AjaxTestAction.java @@ -0,0 +1,54 @@ +/* + * $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.showcase.ajax; + +import com.opensymphony.xwork2.Action; + +import java.io.Serializable; + + +/** + */ +public class AjaxTestAction implements Action, Serializable { + + private static int counter = 0; + private String data; + + public long getServerTime() { + return System.currentTimeMillis(); + } + + public int getCount() { + return ++counter; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + + public String execute() throws Exception { + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AutocompleterExampleAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AutocompleterExampleAction.java new file mode 100644 index 000000000..3c149fc0b --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AutocompleterExampleAction.java @@ -0,0 +1,39 @@ +package org.apache.struts2.showcase.ajax; + +import java.util.ArrayList; +import java.util.List; + +import com.opensymphony.xwork2.ActionSupport; + +public class AutocompleterExampleAction extends ActionSupport { + private String select; + private List options = new ArrayList(); + + private static final long serialVersionUID = -8481638176160014396L; + + public String execute() throws Exception { + if ("fruits".equals(select)) { + options.add("apple"); + options.add("banana"); + options.add("grape"); + options.add("pear"); + } else if ("colors".equals(select)) { + options.add("red"); + options.add("green"); + options.add("blue"); + } + return SUCCESS; + } + + public String getSelect() { + return select; + } + + public void setSelect(String select) { + this.select = select; + } + + public List getOptions() { + return options; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example4ShowPanelAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example4ShowPanelAction.java new file mode 100644 index 000000000..6ff756de9 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example4ShowPanelAction.java @@ -0,0 +1,75 @@ +/* + * $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.showcase.ajax; + +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * @version $Date$ $Id$ + */ +public class Example4ShowPanelAction extends ActionSupport { + + private String name; + private String gender; + + private static final long serialVersionUID = 7751976335066456596L; + + public String panel1() throws Exception { + return SUCCESS; + } + + public String panel2() throws Exception { + return SUCCESS; + } + + public String panel3() throws Exception { + return SUCCESS; + } + + public String getGender() { + return gender; + } + + public void setGender(String gender) { + this.gender = gender; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getTodayDate() { + SimpleDateFormat sdf = new SimpleDateFormat("dd-MMMM-yyyy"); + return sdf.format(new Date()); + } + + public String getTodayTime() { + SimpleDateFormat sdf = new SimpleDateFormat("kk:mm:ss"); + return sdf.format(new Date()); + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example5Action.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example5Action.java new file mode 100644 index 000000000..4fcc516eb --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example5Action.java @@ -0,0 +1,43 @@ +/* + * $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.showcase.ajax; + +import com.opensymphony.xwork2.ActionSupport; + +public class Example5Action extends ActionSupport { + + private static final long serialVersionUID = 2111967621952300611L; + + private String name; + private Integer age; + + + public String getName() { return name; } + public void setName(String name) { this.name = name; } + + public Integer getAge() { return age; } + public void setAge(Integer age) { this.age = age; } + + @Override + public String execute() throws Exception { + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Category.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Category.java new file mode 100644 index 000000000..b3a9859b0 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Category.java @@ -0,0 +1,104 @@ +/* + * $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.showcase.ajax.tree; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + */ +public class Category { + private static Map catMap = new HashMap(); + + static { + new Category(1, "Root", + new Category(2, "Java", + new Category(3, "Web Frameworks", + new Category(4, "Struts"), + new Category(7, "Stripes"), + new Category(8, "Rife")), + new Category(9, "Persistence", + new Category(10, "iBatis"), + new Category(11, "Hibernate"), + new Category(12, "JDO"), + new Category(13, "JDBC"))), + new Category(14, "JavaScript", + new Category(15, "Dojo"), + new Category(16, "Prototype"), + new Category(17, "Scriptaculous"), + new Category(18, "OpenRico"), + new Category(19, "DWR"))); + } + + public static Category getById(long id) { + return catMap.get(id); + } + + private long id; + private String name; + private List children; + private boolean toggle; + + public Category(long id, String name, Category... children) { + this.id = id; + this.name = name; + this.children = new ArrayList(); + for (Category child : children) { + this.children.add(child); + } + + catMap.put(id, this); + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + public void toggle() { + toggle = !toggle; + } + + public boolean isToggle() { + return toggle; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/GetCategory.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/GetCategory.java new file mode 100644 index 000000000..69f6bd064 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/GetCategory.java @@ -0,0 +1,49 @@ +/* + * $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.showcase.ajax.tree; + +import com.opensymphony.xwork2.ActionSupport; + +/** + */ +public class GetCategory extends ActionSupport { + private long catId; + private Category category; + + public String execute() throws Exception { + if (catId < 1) { + // force the root + catId = 1; + } + + category = Category.getById(catId); + + return SUCCESS; + } + + public void setCatId(long catId) { + this.catId = catId; + } + + public Category getCategory() { + return category; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Toggle.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Toggle.java new file mode 100644 index 000000000..165b22266 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Toggle.java @@ -0,0 +1,34 @@ +/* + * $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.showcase.ajax.tree; + + +/** + */ +public class Toggle extends GetCategory { + public String execute() throws Exception { + super.execute(); + + getCategory().toggle(); + + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/MemoryStorage.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/MemoryStorage.java new file mode 100644 index 000000000..f1f2d7093 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/MemoryStorage.java @@ -0,0 +1,142 @@ +/* + * $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.showcase.application; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.apache.struts2.showcase.exception.CreateException; +import org.apache.struts2.showcase.exception.DuplicateKeyException; +import org.apache.struts2.showcase.exception.StorageException; +import org.apache.struts2.showcase.exception.UpdateException; +import org.apache.struts2.showcase.model.IdEntity; + +/** + * MemoryStorage. + * Very simple in-memory persistence emulation. + * + */ + +public class MemoryStorage implements Storage { + + private static final long serialVersionUID = 8611213748834904125L; + + + private Map memory = new HashMap(); + + private Map getEntityMap ( Class entityClass ) { + if (entityClass != null) { + Map tryMap = (Map) memory.get(entityClass); + if (tryMap == null) { + synchronized(memory) { + tryMap = new HashMap(); + memory.put(entityClass, tryMap); + } + } + return tryMap; + } else { + return null; + } + } + + private IdEntity intStore( Class entityClass, IdEntity object ) { + getEntityMap(entityClass).put(object.getId(), object); + return object; + } + + public IdEntity get( Class entityClass, Serializable id ) { + if (entityClass != null && id != null) { + return (IdEntity) getEntityMap(entityClass).get(id); + } else { + return null; + } + } + + public Serializable create ( IdEntity object ) throws CreateException { + if (object == null) { + throw new CreateException("Either given class or object was null"); + } + if (object.getId() == null) { + throw new CreateException("Cannot store object with null id"); + } + if (get(object.getClass(), object.getId()) != null) { + throw new DuplicateKeyException("Object with this id already exists."); + } + return intStore(object.getClass(), object).getId(); + } + + public IdEntity update ( IdEntity object ) throws UpdateException { + if (object == null) { + throw new UpdateException("Cannot update null object."); + } + if ( get(object.getClass(), object.getId())==null ) { + throw new UpdateException("Object to update not found."); + } + return intStore(object.getClass(), object); + } + + public Serializable merge ( IdEntity object ) throws StorageException { + if (object == null) { + throw new StorageException("Cannot merge null object"); + } + if (object.getId() == null || get(object.getClass(), object.getId())==null) { + return create(object); + } else { + return update(object).getId(); + } + } + + public int delete( Class entityClass, Serializable id ) throws CreateException { + try { + if (get(entityClass, id) != null) { + getEntityMap(entityClass).remove(id); + return 1; + } else { + return 0; + } + } catch (Exception e) { + throw new CreateException(e); + } + } + + public int delete( IdEntity object ) throws CreateException { + if (object == null) { + throw new CreateException("Cannot delete null object"); + } + return delete(object.getClass(), object.getId()); + } + + public Collection findAll( Class entityClass ) { + if (entityClass != null) { + return getEntityMap(entityClass).values(); + } else { + return new ArrayList(); + } + } + + public void reset() { + this.memory = new HashMap(); + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/Storage.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/Storage.java new file mode 100644 index 000000000..74d81e3b4 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/Storage.java @@ -0,0 +1,50 @@ +/* + * $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.showcase.application; + +import java.io.Serializable; +import java.util.Collection; + +import org.apache.struts2.showcase.exception.CreateException; +import org.apache.struts2.showcase.exception.StorageException; +import org.apache.struts2.showcase.exception.UpdateException; +import org.apache.struts2.showcase.model.IdEntity; + +/** + * Storage. Interface. + * + */ + +public interface Storage extends Serializable { + IdEntity get( Class entityClass, Serializable id ); + + Serializable create ( IdEntity object ) throws CreateException; + + IdEntity update ( IdEntity object ) throws UpdateException; + + Serializable merge ( IdEntity object ) throws StorageException; + + int delete( Class entityClass, Serializable id ) throws CreateException; + + int delete( IdEntity object ) throws CreateException; + + Collection findAll( Class entityClass ); +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/TestDataProvider.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/TestDataProvider.java new file mode 100644 index 000000000..0cd0056df --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/application/TestDataProvider.java @@ -0,0 +1,118 @@ +/* + * $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.showcase.application; + +import java.io.Serializable; +import java.util.Arrays; +import java.util.Date; + +import org.apache.log4j.Logger; +import org.apache.struts2.showcase.dao.EmployeeDao; +import org.apache.struts2.showcase.dao.SkillDao; +import org.apache.struts2.showcase.exception.StorageException; +import org.apache.struts2.showcase.model.Employee; +import org.apache.struts2.showcase.model.Skill; +import org.springframework.beans.factory.InitializingBean; + +/** + * TestDataProvider. + * + */ + +public class TestDataProvider implements Serializable, InitializingBean { + + private static final long serialVersionUID = 1L; + + private static final Logger log = Logger.getLogger(TestDataProvider.class); + + public static final String[] POSITIONS = { + "Developer", + "System Architect", + "Sales Manager", + "CEO" + }; + + public static final String[] LEVELS = { + "Junior", + "Senior", + "Master" + }; + + private static final Skill[] TEST_SKILLS = { + new Skill("WW-SEN", "Struts Senior Developer"), + new Skill("WW-JUN", "Struts Junior Developer"), + new Skill("SPRING-DEV", "Spring Developer") + }; + + public static final Employee[] TEST_EMPLOYEES = { + new Employee(new Long(1), "Alan", "Smithee", new Date(), new Float(2000f), true, POSITIONS[0], + TEST_SKILLS[0], null, "alan", LEVELS[0], "Nice guy"), + new Employee(new Long(2), "Robert", "Robson", new Date(), new Float(10000f), false, POSITIONS[1], + TEST_SKILLS[1], Arrays.asList(TEST_SKILLS).subList(1,TEST_SKILLS.length), "rob", LEVELS[1], "Smart guy") + }; + + private SkillDao skillDao; + private EmployeeDao employeeDao; + + public void setSkillDao(SkillDao skillDao) { + this.skillDao = skillDao; + } + + public void setEmployeeDao(EmployeeDao employeeDao) { + this.employeeDao = employeeDao; + } + + protected void addTestSkills() { + try { + for (int i = 0, j = TEST_SKILLS.length; i < j; i++) { + skillDao.merge(TEST_SKILLS[i]); + } + if (log.isInfoEnabled()) { + log.info("TestDataProvider - [addTestSkills]: Added test skill data."); + } + } catch (StorageException e) { + log.error("TestDataProvider - [addTestSkills]: Exception catched: " + e.getMessage()); + } + } + + protected void addTestEmployees() { + try { + for (int i = 0, j = TEST_EMPLOYEES.length; i < j; i++) { + employeeDao.merge(TEST_EMPLOYEES[i]); + } + if (log.isInfoEnabled()) { + log.info("TestDataProvider - [addTestEmployees]: Added test employee data."); + } + } catch (StorageException e) { + log.error("TestDataProvider - [addTestEmployees]: Exception catched: " + e.getMessage()); + } + } + + protected void addTestData() { + addTestSkills(); + addTestEmployees(); + } + + public void afterPropertiesSet() throws Exception { + addTestData(); + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatAuthenticationInterceptor.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatAuthenticationInterceptor.java new file mode 100644 index 000000000..281f67347 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatAuthenticationInterceptor.java @@ -0,0 +1,60 @@ +/* + * $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.showcase.chat; + + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.dispatcher.SessionMap; + +import com.opensymphony.xwork2.Action; +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ActionInvocation; +import com.opensymphony.xwork2.interceptor.Interceptor; + +public class ChatAuthenticationInterceptor implements Interceptor { + + private static final long serialVersionUID = 1L; + + private static final Log _log = LogFactory.getLog(ChatAuthenticationInterceptor.class); + + public static final String USER_SESSION_KEY = "chatUserSessionKey"; + + public void destroy() { + } + + public void init() { + } + + public String intercept(ActionInvocation invocation) throws Exception { + + _log.debug("Authenticating chat user"); + + SessionMap session = (SessionMap) ActionContext.getContext().get(ActionContext.SESSION); + User user = (User) session.get(USER_SESSION_KEY); + + if (user == null) { + return Action.LOGIN; + } + return invocation.invoke(); + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatException.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatException.java new file mode 100644 index 000000000..50b5e9b81 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatException.java @@ -0,0 +1,36 @@ +/* + * $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.showcase.chat; + +public class ChatException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public enum ErrorType { + ROOM_ALREADY_EXISTS, + USER_ALREADY_EXISTS, + NO_SUCH_ROOM_EXISTS + } + + public ChatException(String description, ErrorType type) { + super(description); + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatInterceptor.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatInterceptor.java new file mode 100644 index 000000000..4e9afbda0 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatInterceptor.java @@ -0,0 +1,61 @@ +/* + * $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.showcase.chat; + +import javax.servlet.http.HttpSession; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.opensymphony.xwork2.Action; +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ActionInvocation; +import com.opensymphony.xwork2.interceptor.Interceptor; + +/** + * Authenticate showcase chat example, make sure everyone have a username. + */ +public class ChatInterceptor implements Interceptor { + + private static final Log _log = LogFactory.getLog(ChatInterceptor.class); + + private static final long serialVersionUID = 1L; + + public static final String CHAT_USER_SESSION_KEY = "ChatUserSessionKey"; + + public void destroy() { + } + + public void init() { + } + + public String intercept(ActionInvocation invocation) throws Exception { + HttpSession session = (HttpSession) ActionContext.getContext().get(ActionContext.SESSION); + User chatUser = (User) session.getAttribute(CHAT_USER_SESSION_KEY); + if (chatUser == null) { + _log.debug("Chat user not logged in"); + return Action.LOGIN; + } + return invocation.invoke(); + } +} + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLoginAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLoginAction.java new file mode 100644 index 000000000..570d54523 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLoginAction.java @@ -0,0 +1,68 @@ +/* + * $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.showcase.chat; + +import java.util.Map; + +import org.apache.struts2.interceptor.SessionAware; + +import com.opensymphony.xwork2.ActionSupport; + +public class ChatLoginAction extends ActionSupport implements SessionAware { + + private static final long serialVersionUID = 1L; + + private ChatService chatService; + private Map session; + + private String name; + + public ChatLoginAction(ChatService chatService) { + this.chatService = chatService; + } + + public String getName() { + return this.name; + } + public void setName(String name) { + this.name = name; + } + + + public String execute() throws Exception { + try { + chatService.login(new User(name)); + session.put(ChatAuthenticationInterceptor.USER_SESSION_KEY, new User(name)); + } + catch(ChatException e) { + e.printStackTrace(); + addActionError(e.getMessage()); + return INPUT; + } + return SUCCESS; + } + + + // === SessionAware === + public void setSession(Map session) { + this.session = session; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLogoutAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLogoutAction.java new file mode 100644 index 000000000..c4a4bcd5e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLogoutAction.java @@ -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.showcase.chat; + +import java.util.Map; + +import org.apache.struts2.interceptor.SessionAware; + +import com.opensymphony.xwork2.ActionSupport; + +public class ChatLogoutAction extends ActionSupport implements SessionAware { + + private static final long serialVersionUID = 1L; + + private ChatService chatService; + + private Map session; + + + public ChatLogoutAction(ChatService chatService) { + this.chatService = chatService; + } + + public String execute() throws Exception { + + User user = (User) session.get(ChatAuthenticationInterceptor.USER_SESSION_KEY); + if (user != null) { + chatService.logout(user.getName()); + session.remove(ChatAuthenticationInterceptor.USER_SESSION_KEY); + } + + return SUCCESS; + } + + + // === SessionAware === + public void setSession(Map session) { + this.session = session; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatMessage.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatMessage.java new file mode 100644 index 000000000..3426eec0e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatMessage.java @@ -0,0 +1,49 @@ +/* + * $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.showcase.chat; + +import java.util.Date; + +public class ChatMessage { + + private Date creationDate; + private String message; + private User creator; + + public ChatMessage(String message, User creator) { + assert(message != null); + assert(creator != null); + + this.creationDate = new Date(System.currentTimeMillis()); + this.message = message; + this.creator = creator; + } + + public Date getCreationDate() { + return creationDate; + } + public User getCreator() { + return creator; + } + public String getMessage() { + return message; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatService.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatService.java new file mode 100644 index 000000000..907f77e00 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatService.java @@ -0,0 +1,37 @@ +/* + * $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.showcase.chat; + +import java.util.List; + +public interface ChatService { + List getAvailableUsers(); + void login(User user); + void logout(String name); + + List getAvailableRooms(); + void addRoom(Room room); + void enterRoom(User user, String roomName); + void exitRoom(String userName, String roomName); + List getMessagesInRoom(String roomName); + void sendMessageToRoom(String roomName, User user, String message); + List getUsersAvailableInRoom(String roomName); +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatServiceImpl.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatServiceImpl.java new file mode 100644 index 000000000..0cd783d7d --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatServiceImpl.java @@ -0,0 +1,115 @@ +/* + * $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.showcase.chat; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class ChatServiceImpl implements ChatService { + + private Map availableUsers = new LinkedHashMap(); + private Map availableRooms = new LinkedHashMap(); + + + public List getAvailableUsers() { + return new ArrayList(availableUsers.values()); + } + + public List getAvailableRooms() { + return new ArrayList(availableRooms.values()); + } + + public void addRoom(Room room) { + if (availableRooms.containsKey(room.getName())) { + throw new ChatException("room ["+room.getName()+"] is already available", ChatException.ErrorType.valueOf("ROOM_ALREADY_EXISTS")); + } + availableRooms.put(room.getName(), room); + } + + public void login(User user) { + assert(user != null); + if (availableUsers.containsKey(user.getName())) { + throw new ChatException("User ["+user.getName()+"] already exists", ChatException.ErrorType.valueOf("USER_ALREADY_EXISTS")); + } + availableUsers.put(user.getName(), user); + } + + public void logout(String name) { + assert(name != null); + assert(name.trim().length() > 0); + availableUsers.remove(name); + for (Room room : availableRooms.values()) { + if (room.hasMember(name)) { + room.memberExit(name); + } + } + } + + public void exitRoom(String userName, String roomName) { + assert(roomName != null); + assert(roomName.trim().length()> 0); + + if (availableRooms.containsKey(roomName)) { + Room room = availableRooms.get(roomName); + room.memberExit(userName); + } + } + + public void enterRoom(User user, String roomName) { + assert(roomName != null); + assert(roomName.trim().length() > 0); + if (! availableRooms.containsKey(roomName)) { + throw new ChatException("No such room exists ["+roomName+"]", ChatException.ErrorType.NO_SUCH_ROOM_EXISTS); + } + Room room = availableRooms.get(roomName); + room.memberEnter(user); + } + + public List getMessagesInRoom(String roomName) { + assert(roomName != null); + assert(roomName.trim().length() > 0); + if (! availableRooms.containsKey(roomName)) { + throw new ChatException("No such room exists ["+roomName+"]", ChatException.ErrorType.NO_SUCH_ROOM_EXISTS); + } + Room room = availableRooms.get(roomName); + return room.getChatMessages(); + } + + public void sendMessageToRoom(String roomName, User user, String message) { + assert(roomName != null); + if (! availableRooms.containsKey(roomName)) { + throw new ChatException("No such room exists ["+roomName+"]", ChatException.ErrorType.NO_SUCH_ROOM_EXISTS); + } + Room room = availableRooms.get(roomName); + room.addMessage(new ChatMessage(message, user)); + } + + public List getUsersAvailableInRoom(String roomName) { + assert(roomName != null); + if (! availableRooms.containsKey(roomName)) { + throw new ChatException("No such room exists ["+roomName+"]", ChatException.ErrorType.NO_SUCH_ROOM_EXISTS); + } + Room room = availableRooms.get(roomName); + return room.getMembers(); + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatSessionListener.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatSessionListener.java new file mode 100644 index 000000000..0e6d430fe --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatSessionListener.java @@ -0,0 +1,53 @@ +/* + * $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.showcase.chat; + +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpSessionEvent; +import javax.servlet.http.HttpSessionListener; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +public class ChatSessionListener implements HttpSessionListener { + + private static final Log _log = LogFactory.getLog(ChatSessionListener.class); + + public void sessionCreated(HttpSessionEvent event) { + } + + public void sessionDestroyed(HttpSessionEvent event) { + HttpSession session = event.getSession(); + WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(session.getServletContext()); + if (context != null) { + User user = (User) session.getAttribute(ChatInterceptor.CHAT_USER_SESSION_KEY); + if (user != null) { + ChatService service = (ChatService) context.getBean("chatService"); + service.logout(user.getName()); + + _log.info("session expired, logged user ["+user.getName()+"] out"); + } + } + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/Constants.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/Constants.java new file mode 100644 index 000000000..39ad1fb4d --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/Constants.java @@ -0,0 +1,25 @@ +/* + * $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.showcase.chat; + +public class Constants { + public static String UPDATE_FREQ = "30000"; +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/CrudRoomAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/CrudRoomAction.java new file mode 100644 index 000000000..dcbf24096 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/CrudRoomAction.java @@ -0,0 +1,64 @@ +/* + * $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.showcase.chat; + +import com.opensymphony.xwork2.ActionSupport; + +public class CrudRoomAction extends ActionSupport { + + private static final long serialVersionUID = 1L; + + private ChatService chatService; + + private String name; + private String description; + + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public CrudRoomAction(ChatService chatService) { + this.chatService = chatService; + } + + public String create() throws Exception { + try { + chatService.addRoom(new Room(name, description)); + } + catch(ChatException e) { + addActionError(e.getMessage()); + } + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/DateConverter.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/DateConverter.java new file mode 100644 index 000000000..72b707813 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/DateConverter.java @@ -0,0 +1,59 @@ +/* + * $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.showcase.chat; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.util.StrutsTypeConverter; + +public class DateConverter extends StrutsTypeConverter { + + private static final Log _log = LogFactory.getLog(DateConverter.class); + + public Object convertFromString(Map context, String[] values, Class toClass) { + + if (values.length > 0 && values[0] != null && values[0].trim().length() > 0) { + SimpleDateFormat sdf = new SimpleDateFormat(); + try { + return sdf.parse(values[0]); + } + catch(ParseException e) { + _log.error("error converting value ["+values[0]+"] to Date ", e); + } + } + return null; + } + + public String convertToString(Map context, Object o) { + + if (o instanceof Date) { + SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss"); + return sdf.format((Date) o); + } + return ""; + } +} + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/EnterRoomAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/EnterRoomAction.java new file mode 100644 index 000000000..52e872258 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/EnterRoomAction.java @@ -0,0 +1,62 @@ +/* + * $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.showcase.chat; + +import java.util.Map; + +import org.apache.struts2.interceptor.SessionAware; + +import com.opensymphony.xwork2.ActionSupport; + +public class EnterRoomAction extends ActionSupport implements SessionAware { + + private static final long serialVersionUID = 1L; + + private ChatService chatService; + private Map session; + private String roomName; + + public String getRoomName() { return this.roomName; } + public void setRoomName(String roomName) { this.roomName = roomName; } + + public EnterRoomAction(ChatService chatService) { + this.chatService = chatService; + } + + public String execute() throws Exception { + + User user = (User) session.get(ChatAuthenticationInterceptor.USER_SESSION_KEY); + try { + chatService.enterRoom(user, roomName); + } + catch(Exception e) { + addActionError(e.getMessage()); + } + return SUCCESS; + } + + + // === SessionAware === + public void setSession(Map session) { + this.session = session; + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ExitRoomAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ExitRoomAction.java new file mode 100644 index 000000000..5d0990f04 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ExitRoomAction.java @@ -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.showcase.chat; + +import java.util.Map; + +import org.apache.struts2.interceptor.SessionAware; + +import com.opensymphony.xwork2.ActionSupport; + +public class ExitRoomAction extends ActionSupport implements SessionAware { + + private static final long serialVersionUID = 1L; + + private String roomName; + + private Map session; + + public String getRoomName() { return roomName; } + public void setRoomName(String roomName) { this.roomName = roomName; } + + private ChatService chatService; + + public ExitRoomAction(ChatService chatService) { + this.chatService = chatService; + } + + public String execute() throws Exception { + User user = (User) session.get(ChatAuthenticationInterceptor.USER_SESSION_KEY); + chatService.exitRoom(user.getName(), roomName); + + return SUCCESS; + } + + // === SessionAware === + public void setSession(Map session) { + this.session = session; + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/MessagesAvailableInRoomAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/MessagesAvailableInRoomAction.java new file mode 100644 index 000000000..ffb6e54e3 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/MessagesAvailableInRoomAction.java @@ -0,0 +1,59 @@ +/* + * $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.showcase.chat; + +import java.util.ArrayList; +import java.util.List; + +import com.opensymphony.xwork2.ActionSupport; + +public class MessagesAvailableInRoomAction extends ActionSupport { + + private static final long serialVersionUID = 1L; + + private String roomName; + private ChatService chatService; + private List messagesAvailableInRoom = new ArrayList(); + + public String getRoomName() { return this.roomName; } + public void setRoomName(String roomName) { + this.roomName = roomName; + } + + public List getMessagesAvailableInRoom() { + return messagesAvailableInRoom; + } + + public MessagesAvailableInRoomAction(ChatService chatService) { + this.chatService = chatService; + } + + public String execute() throws Exception { + try { + messagesAvailableInRoom = chatService.getMessagesInRoom(roomName); + } + catch(ChatException e) { + addActionError(e.getMessage()); + } + return SUCCESS; + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/Room.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/Room.java new file mode 100644 index 000000000..1ac856ef7 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/Room.java @@ -0,0 +1,101 @@ +/* + * $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.showcase.chat; + +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class Room { + + private static final int MAX_CHAT_MESSAGES = 10; + + private String name; + private String description; + private Date creationDate; + + private List messages = new ArrayList(); + + private Map members = new LinkedHashMap(); + + public Room(String name, String description) { + this.name = name; + this.description = description; + this.creationDate = new Date(System.currentTimeMillis()); + } + + + // properties + public Date getCreationDate() { + return creationDate; + } + + public String getDescription() { + return description; + } + + public String getName() { + return name; + } + + + // (behaviour) members + public List getMembers() { + return new ArrayList(members.values()); + } + public User findMember(String name) { + assert(name != null); + return members.get(name); + } + public boolean hasMember(String name) { + assert(name != null); + return members.containsKey(name); + } + public void memberEnter(User member) { + assert(member != null); + if (! hasMember(member.getName())) { + members.put(member.getName(), member); + } + } + + public void memberExit(String memberName) { + assert(memberName != null); + assert(memberName.trim().length() > 0); + members.remove(memberName); + } + + + // (behaviour) chat messags + public void addMessage(ChatMessage chatMessage) { + if (messages.size() > MAX_CHAT_MESSAGES) { + // messages.remove(messages.size() - 1); + messages.remove(0); + } + messages.add(chatMessage); + } + + public List getChatMessages() { + return new ArrayList(messages); + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/RoomsAvailableAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/RoomsAvailableAction.java new file mode 100644 index 000000000..25084d4ee --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/RoomsAvailableAction.java @@ -0,0 +1,48 @@ +/* + * $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.showcase.chat; + +import java.util.ArrayList; +import java.util.List; + +import com.opensymphony.xwork2.ActionSupport; + +public class RoomsAvailableAction extends ActionSupport { + + private static final long serialVersionUID = 1L; + + private List availableRooms = new ArrayList(); + + private ChatService chatService; + + public RoomsAvailableAction(ChatService chatService) { + this.chatService = chatService; + } + + public String execute() throws Exception { + availableRooms = chatService.getAvailableRooms(); + return SUCCESS; + } + + public List getAvailableRooms() { + return availableRooms; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/SendMessageToRoomAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/SendMessageToRoomAction.java new file mode 100644 index 000000000..a24e6c6c1 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/SendMessageToRoomAction.java @@ -0,0 +1,70 @@ +/* + * $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.showcase.chat; + +import java.util.Map; + +import org.apache.struts2.interceptor.SessionAware; + +import com.opensymphony.xwork2.ActionSupport; + +public class SendMessageToRoomAction extends ActionSupport implements SessionAware { + + private static final long serialVersionUID = 1L; + + private ChatService chatService; + + private String roomName; + private String message; + private Map session; + + + public SendMessageToRoomAction(ChatService chatService) { + this.chatService = chatService; + } + + public String getRoomName() { return this.roomName; } + public void setRoomName(String roomName) { + this.roomName = roomName; + } + + public String getMessage() { return this.message; } + public void setMessage(String message) { + this.message = message; + } + + + public String execute() throws Exception { + User user = (User) session.get(ChatAuthenticationInterceptor.USER_SESSION_KEY); + try { + chatService.sendMessageToRoom(roomName, user, message); + }catch(ChatException e) { + addActionError(e.getMessage()); + } + return SUCCESS; + } + + public void setSession(Map session) { + this.session = session; + } + + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/User.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/User.java new file mode 100644 index 000000000..b649aca5d --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/User.java @@ -0,0 +1,48 @@ +/* + * $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.showcase.chat; + +import java.io.Serializable; +import java.util.Date; + +/** + * Represends a user in the Chat example. + */ +public class User implements Serializable { + + private static final long serialVersionUID = -1434958919516089297L; + + private String name; + private Date creationDate; + + + public User(String name) { + this.name = name; + this.creationDate = new Date(System.currentTimeMillis()); + } + + public Date getCreationDate() { + return creationDate; + } + public String getName() { + return name; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableAction.java new file mode 100644 index 000000000..eae9a8cfe --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableAction.java @@ -0,0 +1,49 @@ +/* + * $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.showcase.chat; + +import java.util.ArrayList; +import java.util.List; + +import com.opensymphony.xwork2.ActionSupport; + +public class UsersAvailableAction extends ActionSupport { + + private static final long serialVersionUID = 1L; + + private List availableUsers = new ArrayList(); + private ChatService chatService; + + public UsersAvailableAction(ChatService chatService) { + this.chatService = chatService; + } + + public String execute() throws Exception { + + availableUsers = chatService.getAvailableUsers(); + + return SUCCESS; + } + + public List getAvailableUsers() { + return availableUsers; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableInRoomAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableInRoomAction.java new file mode 100644 index 000000000..f56f4334c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableInRoomAction.java @@ -0,0 +1,61 @@ +/* + * $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.showcase.chat; + +import java.util.ArrayList; +import java.util.List; + +import com.opensymphony.xwork2.ActionSupport; + +public class UsersAvailableInRoomAction extends ActionSupport { + + private static final long serialVersionUID = 1L; + + private ChatService chatService; + private List usersAvailableInRoom = new ArrayList(); + + private String roomName; + + public UsersAvailableInRoomAction(ChatService chatService) { + this.chatService = chatService; + } + + + public String getRoomName() { return this.roomName; } + public void setRoomName(String roomName) { + this.roomName = roomName; + } + + public List getUsersAvailableInRoom() { + return usersAvailableInRoom; + } + + public String execute() throws Exception { + try { + usersAvailableInRoom = chatService.getUsersAvailableInRoom(roomName); + } + catch(ChatException e) { + addActionError(e.getMessage()); + } + return SUCCESS; + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/Address.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/Address.java new file mode 100644 index 000000000..371def7b6 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/Address.java @@ -0,0 +1,38 @@ +/* + * $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.showcase.conversion; + + +/** + * @version $Date$ $Id$ + */ +public class Address { + + private String id; + private String address; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + + public String getAddress() { return address; } + public void setAddress(String address) { this.address = address; } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/AddressAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/AddressAction.java new file mode 100644 index 000000000..a0d20d903 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/AddressAction.java @@ -0,0 +1,47 @@ +/* + * $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.showcase.conversion; + +import java.util.LinkedHashSet; +import java.util.Set; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * @version $Date$ $Id$ + */ +public class AddressAction extends ActionSupport { + + private Set addresses = new LinkedHashSet(); + + public Set getAddresses() { return addresses; } + public void setAddresses(Set addresses) { this.addresses = addresses; } + + + public String input() throws Exception { + return SUCCESS; + } + + public String submit() throws Exception { + System.out.println(addresses); + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/EnumTypeConverter.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/EnumTypeConverter.java new file mode 100644 index 000000000..6efa44cf3 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/EnumTypeConverter.java @@ -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.showcase.conversion; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.struts2.util.StrutsTypeConverter; + +/** + * @version $Date$ $Id$ + */ +public class EnumTypeConverter extends StrutsTypeConverter { + + @Override + public Object convertFromString(Map context, String[] values, Class toClass) { + List result = new ArrayList(); + for (int a=0; a< values.length; a++) { + Enum e = Enum.valueOf(OperationsEnum.class, values[a]); + if (e != null) + result.add(e); + } + return result; + } + + @Override + public String convertToString(Map context, Object o) { + List l = (List) o; + String result ="<"; + for (Iterator i = l.iterator(); i.hasNext(); ) { + result = result + "["+ i.next() +"]"; + } + result = result+">"; + return result; + } + + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnum.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnum.java new file mode 100644 index 000000000..e9a77988f --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnum.java @@ -0,0 +1,33 @@ +/* + * $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.showcase.conversion; + +/** + * + * @version $Date$ $Id$ + */ +public enum OperationsEnum { + ADD, + MINUS, + DIVIDE, + MULTIPLY, + REMAINDER; +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnumAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnumAction.java new file mode 100644 index 000000000..2769858a3 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnumAction.java @@ -0,0 +1,56 @@ +/* + * $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.showcase.conversion; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * + * @version $Date$ $Id$ + */ +public class OperationsEnumAction extends ActionSupport { + + private static final long serialVersionUID = -2229489704988870318L; + + private List selectedOperations = new LinkedList(); + + public List getSelectedOperations() { return this.selectedOperations; } + public void setSelectedOperations(List selectedOperations) { + this.selectedOperations = selectedOperations; + } + + + public List getAvailableOperations() { + return Arrays.asList(OperationsEnum.values()); + } + + public String input() throws Exception { + return SUCCESS; + } + public String submit() throws Exception { + return SUCCESS; + } +} + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/Person.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/Person.java new file mode 100644 index 000000000..ed63fd42c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/Person.java @@ -0,0 +1,37 @@ +/* + * $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.showcase.conversion; + +import java.io.Serializable; + +/** + * + */ +public class Person implements Serializable { + private String name; + private Integer age; + + public void setName(String name) { this.name = name; } + public String getName() { return this.name; } + + public void setAge(Integer age) { this.age = age; } + public Integer getAge() { return this.age; } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/PersonAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/PersonAction.java new file mode 100644 index 000000000..96ff77d40 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/PersonAction.java @@ -0,0 +1,46 @@ +/* + * $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.showcase.conversion; + +import java.util.List; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * + */ +public class PersonAction extends ActionSupport { + + private List persons; + + public List getPersons() { return persons; } + public void setPersons(List persons) { this.persons = persons; } + + + + public String input() throws Exception { + return SUCCESS; + } + + public String submit() throws Exception { + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/AbstractDao.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/AbstractDao.java new file mode 100644 index 000000000..aae90e729 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/AbstractDao.java @@ -0,0 +1,77 @@ +/* + * $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.showcase.dao; + +import java.io.Serializable; +import java.util.Collection; + +import org.apache.struts2.showcase.application.Storage; +import org.apache.struts2.showcase.exception.CreateException; +import org.apache.struts2.showcase.exception.StorageException; +import org.apache.struts2.showcase.exception.UpdateException; +import org.apache.struts2.showcase.model.IdEntity; + +/** + * AbstractDao. + * + */ + +public abstract class AbstractDao implements Serializable, Dao { + + private Storage storage; + + public Storage getStorage() { + return storage; + } + + public void setStorage(Storage storage) { + this.storage = storage; + } + + public IdEntity get(Serializable id) { + return getStorage().get(getFeaturedClass(), id); + } + + public Serializable create(IdEntity object) throws CreateException { + return getStorage().create(object); + } + + public IdEntity update(IdEntity object) throws UpdateException { + return getStorage().update(object); + } + + public Serializable merge(IdEntity object) throws StorageException { + return getStorage().merge(object); + } + + public int delete(Serializable id) throws CreateException { + return getStorage().delete(getFeaturedClass(), id); + } + + public int delete(IdEntity object) throws CreateException { + return getStorage().delete(object); + } + + public Collection findAll() { + return getStorage().findAll(getFeaturedClass()); + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/Dao.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/Dao.java new file mode 100644 index 000000000..9a88319da --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/Dao.java @@ -0,0 +1,53 @@ +/* + * $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.showcase.dao; + +import java.io.Serializable; +import java.util.Collection; + +import org.apache.struts2.showcase.exception.CreateException; +import org.apache.struts2.showcase.exception.StorageException; +import org.apache.struts2.showcase.exception.UpdateException; +import org.apache.struts2.showcase.model.IdEntity; + +/** + * Dao. Interface. + * + */ + +public interface Dao { + + Class getFeaturedClass(); + + IdEntity get(Serializable id); + + Serializable create(IdEntity object) throws CreateException; + + IdEntity update(IdEntity object) throws UpdateException; + + Serializable merge(IdEntity object) throws StorageException; + + int delete(Serializable id) throws CreateException; + + int delete(IdEntity object) throws CreateException; + + Collection findAll(); +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/EmployeeDao.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/EmployeeDao.java new file mode 100644 index 000000000..ebec67348 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/EmployeeDao.java @@ -0,0 +1,67 @@ +/* + * $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.showcase.dao; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.struts2.showcase.model.Employee; +import org.apache.struts2.showcase.model.Skill; + +/** + * EmployeeDao. + * + */ + +public class EmployeeDao extends AbstractDao { + + private static final long serialVersionUID = -6615310540042830594L; + + protected SkillDao skillDao; + + public void setSkillDao(SkillDao skillDao) { + this.skillDao = skillDao; + } + + public Class getFeaturedClass() { + return Employee.class; + } + + public Employee getEmployee( Long id ) { + return (Employee) get(id); + } + + public Employee setSkills(Employee employee, List skillNames) { + if (employee!= null && skillNames != null) { + employee.setOtherSkills(new ArrayList()); + for (int i = 0, j = skillNames.size(); i < j; i++) { + Skill skill = (Skill) skillDao.get((String) skillNames.get(i)); + employee.getOtherSkills().add(skill); + } + } + return employee; + } + + public Employee setSkills(Long empId, List skillNames) { + return setSkills((Employee) get(empId), skillNames); + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/SkillDao.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/SkillDao.java new file mode 100644 index 000000000..f51421d5c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/dao/SkillDao.java @@ -0,0 +1,41 @@ +/* + * $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.showcase.dao; + +import org.apache.struts2.showcase.model.Skill; + +/** + * SkillDao. + * + */ + +public class SkillDao extends AbstractDao { + + private static final long serialVersionUID = -8160406514074630866L; + + public Class getFeaturedClass() { + return Skill.class; + } + + public Skill getSkill( String name ) { + return (Skill) get(name); + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/CreateException.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/CreateException.java new file mode 100644 index 000000000..23cc287e5 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/CreateException.java @@ -0,0 +1,43 @@ +/* + * $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.showcase.exception; + +/** + * CreateException. + * + */ + +public class CreateException extends StorageException { + + private static final long serialVersionUID = 6734349565111633783L; + + public CreateException(String message) { + super(message); + } + + public CreateException(String message, Throwable cause) { + super(message, cause); + } + + public CreateException(Throwable cause) { + super(cause); + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/DeleteException.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/DeleteException.java new file mode 100644 index 000000000..f2d2dfcbb --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/DeleteException.java @@ -0,0 +1,44 @@ +/* + * $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.showcase.exception; + +/** + * DeleteException. + * + */ + +public class DeleteException extends StorageException { + + private static final long serialVersionUID = -5286362812955627352L; + + public DeleteException(String message) { + super(message); + } + + public DeleteException(Throwable cause) { + super(cause); + } + + public DeleteException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/DuplicateKeyException.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/DuplicateKeyException.java new file mode 100644 index 000000000..1ae17ddae --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/DuplicateKeyException.java @@ -0,0 +1,44 @@ +/* + * $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.showcase.exception; + +/** + * DuplicateKeyException. + * + */ + +public class DuplicateKeyException extends CreateException { + + private static final long serialVersionUID = 989620752592415898L; + + public DuplicateKeyException(String message) { + super(message); + } + + public DuplicateKeyException(Throwable cause) { + super(cause); + } + + public DuplicateKeyException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/StorageException.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/StorageException.java new file mode 100644 index 000000000..7628bc2f5 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/StorageException.java @@ -0,0 +1,44 @@ +/* + * $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.showcase.exception; + +/** + * StorageException. + * + */ + +public class StorageException extends Exception { + + private static final long serialVersionUID = -2528721270540362905L; + + public StorageException(String message) { + super(message); + } + + public StorageException(Throwable cause) { + super(cause); + } + + public StorageException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/UpdateException.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/UpdateException.java new file mode 100644 index 000000000..3f5023c81 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/exception/UpdateException.java @@ -0,0 +1,45 @@ +/* + * $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.showcase.exception; + + +/** + * UpdateException. + * + */ + +public class UpdateException extends StorageException { + + private static final long serialVersionUID = -4728238600375630452L; + + + public UpdateException(String message) { + super(message); + } + + public UpdateException(Throwable cause) { + super(cause); + } + + public UpdateException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/filedownload/FileDownloadAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/filedownload/FileDownloadAction.java new file mode 100644 index 000000000..5e3cc5679 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/filedownload/FileDownloadAction.java @@ -0,0 +1,50 @@ +/* + * $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.showcase.filedownload; + +import java.io.InputStream; + +import org.apache.struts2.ServletActionContext; + +import com.opensymphony.xwork2.Action; + +/** + * Demonstrates file resource download. + * Set filePath to the local file resource to download, + * relative to the application root ("/images/struts.gif"). + * + */ +public class FileDownloadAction implements Action { + + private String inputPath; + public void setInputPath(String value) { + inputPath = value; + } + + public InputStream getInputStream() throws Exception { + return ServletActionContext.getServletContext().getResourceAsStream(inputPath); + } + + public String execute() throws Exception { + return SUCCESS; + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/FileUploadAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/FileUploadAction.java new file mode 100644 index 000000000..e0b7c06a0 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/FileUploadAction.java @@ -0,0 +1,85 @@ +/* + * $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.showcase.fileupload; + +import java.io.File; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * Show case File Upload example's action. FileUploadAction + * + */ +public class FileUploadAction extends ActionSupport { + + private static final long serialVersionUID = 5156288255337069381L; + + private String contentType; + private File upload; + private String fileName; + private String caption; + + // since we are using the file name will be + // obtained through getter/setter of FileName + public String getUploadFileName() { + return fileName; + } + public void setUploadFileName(String fileName) { + this.fileName = fileName; + } + + + // since we are using the content type will be + // obtained through getter/setter of ContentType + public String getUploadContentType() { + return contentType; + } + public void setUploadContentType(String contentType) { + this.contentType = contentType; + } + + + // since we are using the File itself will be + // obtained through getter/setter of + public File getUpload() { + return upload; + } + public void setUpload(File upload) { + this.upload = upload; + } + + + public String getCaption() { + return caption; + } + public void setCaption(String caption) { + this.caption = caption; + } + + public String input() throws Exception { + return SUCCESS; + } + + public String upload() throws Exception { + return SUCCESS; + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingArrayAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingArrayAction.java new file mode 100644 index 000000000..944db2df3 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingArrayAction.java @@ -0,0 +1,66 @@ +/* + * $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.showcase.fileupload; + +import java.io.File; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * Showcase action - mutiple file upload using array. + * + * @version $Date$ $Id$ + */ +public class MultipleFileUploadUsingArrayAction extends ActionSupport { + + private File[] uploads; + private String[] uploadFileNames; + private String[] uploadContentTypes; + + public File[] getUpload() { return this.uploads; } + public void setUpload(File[] upload) { this.uploads = upload; } + + public String[] getUploadFileName() { return this.uploadFileNames; } + public void setUploadFileName(String[] uploadFileName) { this.uploadFileNames = uploadFileName; } + + 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:"); + for (File u: uploads) { + System.out.println("*** "+u+"\t"+u.length()); + } + System.out.println("filenames:"); + for (String n: uploadFileNames) { + System.out.println("*** "+n); + } + System.out.println("content types:"); + for (String c: uploadContentTypes) { + System.out.println("*** "+c); + } + System.out.println("\n\n"); + return SUCCESS; + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction.java new file mode 100644 index 000000000..2e6ea7d15 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction.java @@ -0,0 +1,83 @@ +/* + * $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.showcase.fileupload; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * Showcase action - multiple file upload using List + * @version $Date$ $Id$ + */ +public class MultipleFileUploadUsingListAction extends ActionSupport { + + private List uploads = new ArrayList(); + private List uploadFileNames = new ArrayList(); + private List uploadContentTypes = new ArrayList(); + + + public List getUpload() { + return this.uploads; + } + public void setUpload(List uploads) { + this.uploads = uploads; + } + + public List getUploadFileName() { + return this.uploadFileNames; + } + public void setUploadFileName(List uploadFileNames) { + this.uploadFileNames = uploadFileNames; + } + + public List getUploadContentType() { + return this.uploadContentTypes; + } + public void setUploadContentType(List contentTypes) { + this.uploadContentTypes = contentTypes; + } + + + + + public String upload() throws Exception { + + System.out.println("\n\n upload1"); + System.out.println("files:"); + for (File u: uploads) { + System.out.println("*** "+u+"\t"+u.length()); + } + System.out.println("filenames:"); + for (String n: uploadFileNames) { + System.out.println("*** "+n); + } + System.out.println("content types:"); + for (String c: uploadContentTypes) { + System.out.println("*** "+c); + } + System.out.println("\n\n"); + return SUCCESS; + } + + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManager.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManager.java new file mode 100644 index 000000000..a38a9cdd2 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManager.java @@ -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.showcase.freemarker; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.freemarker.FreemarkerManager; +import org.apache.struts2.views.freemarker.ScopesHashModel; + +import com.opensymphony.xwork2.util.OgnlValueStack; +import com.opensymphony.xwork2.util.ValueStack; + +/** + * This is an example of a custom FreemarkerManager, mean to be + * instantiated through Spring. + *

    + * + * It will add into Freemarker's model + * an utility class called {@link CustomFreemarkerManagerUtil} as a simple + * example demonstrating how to extends FreemarkerManager. + *

    + * + * The {@link CustomFreemarkerManagerUtil} will be created by Spring and + * injected through constructor injection. + *

    + */ +public class CustomFreemarkerManager extends FreemarkerManager { + + private CustomFreemarkerManagerUtil util; + + public CustomFreemarkerManager(CustomFreemarkerManagerUtil util) { + this.util = util; + } + + protected void populateContext(ScopesHashModel model, ValueStack stack, Object action, HttpServletRequest request, HttpServletResponse response) { + super.populateContext(model, stack, action, request, response); + model.put("customFreemarkerManagerUtil", util); + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManagerUtil.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManagerUtil.java new file mode 100644 index 000000000..d80932378 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManagerUtil.java @@ -0,0 +1,42 @@ +/* + * $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.showcase.freemarker; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * This class is just a simple util that gets injected into + * {@link CustomFreemarkerManager} through Spring's constructor + * injection, serving as a simple example in Struts' Showcase. + */ +public class CustomFreemarkerManagerUtil { + + public String getTodayDate() { + SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); + return sdf.format(new Date()); + } + + public String getTimeNow() { + SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss"); + return sdf.format(new Date()); + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/StandardTagsAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/StandardTagsAction.java new file mode 100644 index 000000000..ce881b62c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/StandardTagsAction.java @@ -0,0 +1,67 @@ +/* + * $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.showcase.freemarker; + +import com.opensymphony.xwork2.ActionSupport; +import com.opensymphony.xwork2.Preparable; + +import java.text.DateFormatSymbols; + +/** + * Showcase action for freemarker templates. + */ +public class StandardTagsAction extends ActionSupport implements Preparable { + + private String name; + private String[] gender; + private String[] months; + + public void prepare() { + months = new DateFormatSymbols().getMonths(); + name = StandardTagsAction.class.getName().substring(StandardTagsAction.class.getName().lastIndexOf(".")+1); + gender = new String[] { "Male", "Femal" }; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String[] getMonths() { + return months; + } + + public void setMonths(String[] months) { + this.months = months; + } + + + public String[] getGender() { + return gender; + } + + public void setGender(String[] gender) { + this.gender = gender; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GetUpdatedHangmanAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GetUpdatedHangmanAction.java new file mode 100644 index 000000000..e0c99b205 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GetUpdatedHangmanAction.java @@ -0,0 +1,59 @@ +/* + * $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.showcase.hangman; + +import java.util.Map; + +import org.apache.struts2.interceptor.SessionAware; + +import com.opensymphony.xwork2.ActionSupport; + +public class GetUpdatedHangmanAction extends ActionSupport implements SessionAware { + + private static final long serialVersionUID = 5506025785406043027L; + + private Map session; + private Hangman hangman; + + + public String execute() throws Exception { + hangman = (Hangman) session.get(HangmanConstants.HANGMAN_SESSION_KEY); + + System.out.println("\n\n\n"); + System.out.println("hangman="+hangman); + System.out.println("available = "+hangman.getCharactersAvailable().size()); + System.out.println("guess left="+hangman.guessLeft()); + System.out.println("\n\n\n"); + + return SUCCESS; + } + + public void setSession(Map session) { + this.session = session; + } + + public Hangman getHangman() { + return hangman; + } + public void setHangman(Hangman hangman) { + this.hangman = hangman; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GuessCharacterAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GuessCharacterAction.java new file mode 100644 index 000000000..d15c223d4 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GuessCharacterAction.java @@ -0,0 +1,59 @@ +/* + * $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.showcase.hangman; + +import java.util.Map; + +import org.apache.struts2.interceptor.SessionAware; + +import com.opensymphony.xwork2.ActionSupport; + +public class GuessCharacterAction extends ActionSupport implements SessionAware { + + private static final long serialVersionUID = 9050915577007590674L; + + private Map session; + private Character character; + private Hangman hangman; + + public String execute() throws Exception { + hangman = (Hangman) session.get(HangmanConstants.HANGMAN_SESSION_KEY); + hangman.guess(character); + + return SUCCESS; + } + + public Hangman getHangman() { + return hangman; + } + + public void setSession(Map session) { + this.session = session; + } + + public void setCharacter(Character character) { + this.character = character; + } + + public Character getCharacter() { + return this.character; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Hangman.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Hangman.java new file mode 100644 index 000000000..1fdf2daa4 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Hangman.java @@ -0,0 +1,109 @@ +/* + * $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.showcase.hangman; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Hangman implements Serializable { + + private static final long serialVersionUID = 8566954355839652509L; + + private Vocab vocab; + + private Boolean win = false; + + private int guessLeft = 5; + public List charactersAvailable; + public List charactersGuessed; + + public Hangman(Vocab vocab) { + // Arrays.asList(...) returns List that doesn't support remove(), hence + // we wrap it with an ArrayList to avoid UnsupportedOperationException + // when doing a remove() + charactersAvailable = new ArrayList(Arrays.asList( + new Character[] { + Character.valueOf('A'), Character.valueOf('B'), Character.valueOf('C'), + Character.valueOf('D'), Character.valueOf('E'), Character.valueOf('F'), + Character.valueOf('G'), Character.valueOf('H'), Character.valueOf('I'), + Character.valueOf('J'), Character.valueOf('K'), Character.valueOf('L'), + Character.valueOf('M'), Character.valueOf('N'), Character.valueOf('O'), + Character.valueOf('P'), Character.valueOf('Q'), Character.valueOf('R'), + Character.valueOf('S'), Character.valueOf('T'), Character.valueOf('U'), + Character.valueOf('V'), Character.valueOf('W'), Character.valueOf('X'), + Character.valueOf('Y'), Character.valueOf('Z') + })); + charactersGuessed = new ArrayList(); + this.vocab = vocab; + } + + public void guess(Character character) { + assert(character != null); + + synchronized(charactersAvailable) { + if (guessLeft < 0) { + throw new HangmanException( + HangmanException.Type.valueOf("GAME_ENDED"), "Game already eneded"); + } + Character characterInUpperCase = Character.toUpperCase(character); + boolean ok = charactersAvailable.remove(characterInUpperCase); + if (ok) { + charactersGuessed.add(characterInUpperCase); + if (! vocab.containCharacter(characterInUpperCase)) { + guessLeft = guessLeft - 1; + } + } + if (vocab.containsAllCharacter(charactersGuessed)) { + win = true; + } + System.out.println(" *********************************** "+win); + } + } + + public Boolean isWin() { + return this.win; + } + + public Vocab getVocab() { + return vocab; + } + + public Boolean gameEnded() { + return ((guessLeft < 0) || win); + } + + public Integer guessLeft() { + return guessLeft; + } + + public List getCharactersAvailable() { + synchronized(charactersAvailable) { + return new ArrayList(charactersAvailable); + //return charactersAvailable; + } + } + + public boolean characterGuessedBefore(Character character) { + return charactersGuessed.contains(character); + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanConstants.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanConstants.java new file mode 100644 index 000000000..bae60ded0 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanConstants.java @@ -0,0 +1,26 @@ +/* + * $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.showcase.hangman; + +public class HangmanConstants { + // keeps a Hangman object in HttpSession + public static final String HANGMAN_SESSION_KEY = "Hangman_Session_Key"; +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanException.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanException.java new file mode 100644 index 000000000..feffb1c22 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanException.java @@ -0,0 +1,44 @@ +/* + * $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.showcase.hangman; + +public class HangmanException extends RuntimeException { + + private static final long serialVersionUID = -8500292863595941335L; + + enum Type { + GAME_ENDED, + NO_VOCAB, + NO_VOCAB_SOURCE; + } + + + private Type type; + + public HangmanException (Type type, String reason) { + super(reason); + this.type = type; + } + + public Type getType() { + return type; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanService.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanService.java new file mode 100644 index 000000000..410acd85c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/HangmanService.java @@ -0,0 +1,34 @@ +/* + * $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.showcase.hangman; + +public class HangmanService { + + public VocabSource vocabSource; + + public HangmanService(VocabSource vocabSource) { + this.vocabSource = vocabSource; + } + + public Hangman startNewGame() { + return new Hangman(vocabSource.getRandomVocab()); + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/PropertiesVocabSource.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/PropertiesVocabSource.java new file mode 100644 index 000000000..0ab443977 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/PropertiesVocabSource.java @@ -0,0 +1,71 @@ +/* + * $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.showcase.hangman; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +public class PropertiesVocabSource implements VocabSource { + + private Properties prop; + private List vocabs; + + public PropertiesVocabSource() { + } + + public PropertiesVocabSource(Properties prop) { + assert(prop != null); + this.prop = prop; + vocabs = readVocab(prop); + } + + public void setVocabProperties(Properties prop) { + assert(prop != null); + this.prop = prop; + vocabs = readVocab(prop); + } + + public Vocab getRandomVocab() { + if (vocabs == null) { + throw new HangmanException(HangmanException.Type.valueOf("NO_VOCAB_SOURCE"), "No vocab source"); + } + if (vocabs.size() <= 0) { + throw new HangmanException(HangmanException.Type.valueOf("NO_VOCAB"), "No vocab"); + } + long vocabIndex = Math.round((Math.random() * (double)prop.size())); + vocabIndex = vocabIndex == vocabs.size() ? vocabs.size() - 1 : vocabIndex; + return vocabs.get((int)vocabIndex); + } + + protected List readVocab(Properties prop) { + List vocabList = new ArrayList(); + + for (Map.Entry e : prop.entrySet()) { + String vocab = (String) e.getKey(); + String hint = (String) e.getValue(); + + vocabList.add(new Vocab(vocab, hint)); + } + return vocabList; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/StartHangmanAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/StartHangmanAction.java new file mode 100644 index 000000000..4c8aed099 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/StartHangmanAction.java @@ -0,0 +1,61 @@ +/* + * $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.showcase.hangman; + +import static org.apache.struts2.showcase.hangman.HangmanConstants.HANGMAN_SESSION_KEY; + +import java.util.Map; + +import org.apache.struts2.interceptor.SessionAware; + +import com.opensymphony.xwork2.ActionSupport; + +public class StartHangmanAction extends ActionSupport implements SessionAware { + + private static final long serialVersionUID = 2333463075324892521L; + + private HangmanService service; + private Hangman hangman; + private Map session; + + + public StartHangmanAction(HangmanService service) { + this.service = service; + } + + public String execute() throws Exception { + + hangman = service.startNewGame(); + session.put(HANGMAN_SESSION_KEY, hangman); + + return SUCCESS; + } + + public Hangman getHangman() { + return hangman; + } + + + // === SessionAware === + public void setSession(Map session) { + this.session = session; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Vocab.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Vocab.java new file mode 100644 index 000000000..da1cf1541 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Vocab.java @@ -0,0 +1,86 @@ +/* + * $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.showcase.hangman; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Vocab implements Serializable { + + private static final long serialVersionUID = 1L; + + private String vocab; + private String hint; + private Character[] characters; // character this vocab is made up of + + public Vocab(String vocab, String hint) { + assert(vocab != null); + assert(hint != null); + + this.vocab = vocab.toUpperCase(); + this.hint = hint; + } + + public String getVocab() { return this.vocab; } + public String getHint() { return this.hint; } + + public Boolean containCharacter(Character character) { + assert(character != null); + + return (vocab.contains(character.toString())) ? true : false; + } + + public Character[] inCharacters() { + if (characters == null) { + char[] c = vocab.toCharArray(); + characters = new Character[c.length]; + for (int a=0; a< c.length; a++) { + characters[a] = Character.valueOf(c[a]); + } + } + return characters; + } + + public boolean containsAllCharacter(List charactersGuessed) { + Character[] chars = inCharacters(); + List tmpChars = Arrays.asList(chars); + return charactersGuessed.containsAll(tmpChars); + } + + public static void main(String args[]) throws Exception { + Vocab v = new Vocab("JAVA", "a java word"); + + List list1= new ArrayList(); + list1.add(new Character('J')); + list1.add(new Character('V')); + + List list2 = new ArrayList(); + list2.add(new Character('J')); + list2.add(new Character('V')); + list2.add(new Character('A')); + + System.out.println(v.containsAllCharacter(list1)); + System.out.println(v.containsAllCharacter(list2)); + + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/VocabSource.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/VocabSource.java new file mode 100644 index 000000000..b2d64a6a3 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/VocabSource.java @@ -0,0 +1,25 @@ +/* + * $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.showcase.hangman; + +public interface VocabSource { + Vocab getRandomVocab(); +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/EditGangsterAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/EditGangsterAction.java new file mode 100644 index 000000000..d90b67547 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/EditGangsterAction.java @@ -0,0 +1,44 @@ +/* + * $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.showcase.integration; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; + +public class EditGangsterAction extends Action { + + /* (non-Javadoc) + * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { + // Some code to load the gangster from the db as necessary + + return mapping.findForward("success"); + } + + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/GangsterForm.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/GangsterForm.java new file mode 100644 index 000000000..5bb5c4142 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/GangsterForm.java @@ -0,0 +1,108 @@ +/* + * $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.showcase.integration; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.struts.action.ActionErrors; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.validator.ValidatorForm; + +public class GangsterForm extends ValidatorForm { + + private String name; + private String age; + private String description; + private boolean bustedBefore; + + /* (non-Javadoc) + * @see org.apache.struts.action.ActionForm#reset(org.apache.struts.action.ActionMapping, javax.servlet.http.HttpServletRequest) + */ + @Override + public void reset(ActionMapping arg0, HttpServletRequest arg1) { + bustedBefore = false; + } + + /* (non-Javadoc) + * @see org.apache.struts.action.ActionForm#validate(org.apache.struts.action.ActionMapping, javax.servlet.http.HttpServletRequest) + */ + @Override + public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { + ActionErrors errors = super.validate(mapping, request); + if (name == null || name.length() == 0) { + errors.add("name", new ActionMessage("The name must not be blank")); + } + + return errors; + } + + /** + * @return the age + */ + public String getAge() { + return age; + } + /** + * @param age the age to set + */ + public void setAge(String age) { + this.age = age; + } + /** + * @return the bustedBefore + */ + public boolean isBustedBefore() { + return bustedBefore; + } + /** + * @param bustedBefore the bustedBefore to set + */ + public void setBustedBefore(boolean bustedBefore) { + this.bustedBefore = bustedBefore; + } + /** + * @return the description + */ + public String getDescription() { + return description; + } + /** + * @param description the description to set + */ + public void setDescription(String description) { + this.description = description; + } + /** + * @return the name + */ + public String getName() { + return name; + } + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/SaveGangsterAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/SaveGangsterAction.java new file mode 100644 index 000000000..ab68d7e58 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/integration/SaveGangsterAction.java @@ -0,0 +1,51 @@ +/* + * $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.showcase.integration; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts.action.Action; +import org.apache.struts.action.ActionForm; +import org.apache.struts.action.ActionForward; +import org.apache.struts.action.ActionMapping; +import org.apache.struts.action.ActionMessage; +import org.apache.struts.action.ActionMessages; + +public class SaveGangsterAction extends Action { + + /* (non-Javadoc) + * @see org.apache.struts.action.Action#execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { + + // Some code to save the gangster to the db as necessary + GangsterForm gform = (GangsterForm) form; + ActionMessages messages = new ActionMessages(); + messages.add("msg", new ActionMessage("Gangster "+gform.getName()+" added successfully")); + addMessages(request, messages); + + return mapping.findForward("success"); + } + + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/jsf/JsfEmployeeAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/jsf/JsfEmployeeAction.java new file mode 100644 index 000000000..d1bcc234e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/jsf/JsfEmployeeAction.java @@ -0,0 +1,122 @@ +/* + * $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.showcase.jsf; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.struts2.showcase.action.EmployeeAction; +import org.apache.struts2.showcase.dao.SkillDao; +import org.apache.struts2.showcase.model.Employee; +import org.apache.struts2.showcase.model.Skill; + +/** + * Overriding the EmployeeAction to main provide getters returning the data in + * the form required by the JSF components + */ +public class JsfEmployeeAction extends EmployeeAction { + + private static final long serialVersionUID = 1L; + + /** + * Creating a default employee and main skill, since the JSF EL can't handle + * creating new objects as necessary + * + */ + public JsfEmployeeAction() { + Employee e = new Employee(); + e.setMainSkill(new Skill()); + setCurrentEmployee(e); + } + + private SkillDao skillDao; + + public void setSkillDao(SkillDao skillDao) { + this.skillDao = skillDao; + } + + /** + * Returning a List because the JSF dataGrid can't handle a Set for some + * reason + */ + @Override + public Collection getAvailableItems() { + return new ArrayList(super.getAvailableItems()); + } + + /** + * Changing the String array into a Map + */ + public Map getAvailablePositionsAsMap() { + Map map = new LinkedHashMap(); + for (String val : super.getAvailablePositions()) { + map.put(val, val); + } + return map; + } + + /** + * Converting the list into a map + */ + public Map getAvailableLevelsAsMap() { + Map map = new LinkedHashMap(); + for (Object val : super.getAvailableLevels()) { + map.put(val, val); + } + return map; + } + + /** + * Converting the Skill object list into a map + */ + public Map getAvailableSkills() { + Map map = new HashMap(); + for (Object val : skillDao.findAll()) { + Skill skill = (Skill) val; + map.put(skill.getDescription(), skill.getName()); + } + return map; + } + + /** + * Gets the selected Skill objects as a list + */ + public List getSelectedSkillsAsList() { + System.out.println("asked for skills"); + List list = new ArrayList(); + List skills = super.getSelectedSkills(); + if (skills != null) { + for (Object val : skills) { + if (val instanceof Skill) { + list.add(((Skill) val).getDescription()); + } else { + Skill skill = skillDao.getSkill((String) val); + list.add(skill.getDescription()); + } + } + } + return list; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Employee.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Employee.java new file mode 100644 index 000000000..ed93b20df --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Employee.java @@ -0,0 +1,176 @@ +/* + * $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.showcase.model; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * Employee. + * + */ + +public class Employee implements IdEntity { + + private static final long serialVersionUID = -6226845151026823748L; + + private Long empId; //textfield w/ conversion + private String firstName; + private String lastName; + private Date birthDate; //datepicker + private Float salary; //textfield w/ conversion + private boolean married; //checkbox + private String position; //combobox + private Skill mainSkill; //select + private List otherSkills; //doubleSelect + private String password; //password + private String level; //radio + private String comment; //textarea + + public Employee() { + } + + public Employee(Long empId, String firstName, String lastName) { + this.empId = empId; + this.firstName = firstName; + this.lastName = lastName; + } + + public Employee(Long empId, String firstName, String lastName, Date birthDate, Float salary, boolean married, String position, Skill mainSkill, List otherSkills, String password, String level, String comment) { + this.empId = empId; + this.firstName = firstName; + this.lastName = lastName; + this.birthDate = birthDate; + this.salary = salary; + this.married = married; + this.position = position; + this.mainSkill = mainSkill; + this.otherSkills = otherSkills; + this.password = password; + this.level = level; + this.comment = comment; + } + + public Long getEmpId() { + return empId; + } + + public void setEmpId(Long empId) { + this.empId = empId; + } + + public Serializable getId() { + return getEmpId(); + } + + public void setId(Serializable id) { + setEmpId((Long) id); + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public Date getBirthDate() { + return birthDate; + } + + public void setBirthDate(Date birthDate) { + this.birthDate = birthDate; + } + + public Float getSalary() { + return salary; + } + + public void setSalary(Float salary) { + this.salary = salary; + } + + public boolean isMarried() { + return married; + } + + public void setMarried(boolean married) { + this.married = married; + } + + public String getPosition() { + return position; + } + + public void setPosition(String position) { + this.position = position; + } + + public Skill getMainSkill() { + return mainSkill; + } + + public void setMainSkill(Skill mainSkill) { + this.mainSkill = mainSkill; + } + + public List getOtherSkills() { + return otherSkills; + } + + public void setOtherSkills(List otherSkills) { + this.otherSkills = otherSkills; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getLevel() { + return level; + } + + public void setLevel(String level) { + this.level = level; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/IdEntity.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/IdEntity.java new file mode 100644 index 000000000..9e1353803 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/IdEntity.java @@ -0,0 +1,36 @@ +/* + * $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.showcase.model; + +import java.io.Serializable; + +/** + * IdEntity. Interface. + * + */ + +public interface IdEntity extends Serializable { + + Serializable getId (); + + void setId ( Serializable id ); + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Skill.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Skill.java new file mode 100644 index 000000000..e105ba0db --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Skill.java @@ -0,0 +1,72 @@ +/* + * $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.showcase.model; + +import java.io.Serializable; + +/** + * Skill. + * + */ + +public class Skill implements IdEntity { + + private static final long serialVersionUID = -4150317722693212439L; + + private String name; + private String description; + + public Skill() { + } + + public Skill(String name, String description) { + this.name = name; + this.description = description; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Serializable getId() { + return getName(); + } + + public void setId(Serializable id) { + setName((String) id); + } + + public String toString() { + return getName(); + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/Gangster.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/Gangster.java new file mode 100644 index 000000000..aa9591fb6 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/Gangster.java @@ -0,0 +1,62 @@ +/* + * $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.showcase.modelDriven; + +import java.io.Serializable; + +/** + * A model class to be used by the simple Model-Driven example. + * + */ +public class Gangster implements Serializable { + + private static final long serialVersionUID = 3688389475320294992L; + + private String name; + private int age; + private String description; + private boolean bustedBefore; + + public int getAge() { + return age; + } + public void setAge(int age) { + this.age = age; + } + public boolean isBustedBefore() { + return bustedBefore; + } + public void setBustedBefore(boolean bustedBefore) { + this.bustedBefore = bustedBefore; + } + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/ModelDrivenAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/ModelDrivenAction.java new file mode 100644 index 000000000..4ab545710 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/ModelDrivenAction.java @@ -0,0 +1,45 @@ +/* + * $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.showcase.modelDriven; + +import com.opensymphony.xwork2.ActionSupport; +import com.opensymphony.xwork2.ModelDriven; + +/** + * Action to demonstrate simple model-driven feature of the framework. + * + */ +public class ModelDrivenAction extends ActionSupport implements ModelDriven { + + private static final long serialVersionUID = 1271130427666936592L; + + public String input() throws Exception { + return SUCCESS; + } + + public String execute() throws Exception { + return SUCCESS; + } + + public Object getModel() { + return new Gangster(); + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java new file mode 100644 index 000000000..208f23a0a --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java @@ -0,0 +1,84 @@ +/* + * $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.showcase.person; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.struts2.config.Result; +import org.apache.struts2.config.Results; +import org.apache.struts2.dispatcher.ServletRedirectResult; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * EditPerson + * + */ +@Result(name="list", value="listPeople.action", type=ServletRedirectResult.class) +public class EditPersonAction extends ActionSupport { + + private static final long serialVersionUID = 7699491775215130850L; + + PersonManager personManager; + List persons = new ArrayList(); + + public void setPersonManager(PersonManager personManager) { + this.personManager = personManager; + } + + public List getPersons() { + return persons; + } + + public void setPersons(List persons) { + this.persons = persons; + } + + /** + * A default implementation that does nothing an returns "success". + * + * @return {@link #SUCCESS} + */ + public String execute() throws Exception { + persons.addAll(personManager.getPeople()); + return SUCCESS; + } + + /** + * A default implementation that does nothing an returns "success". + * + * @return {@link #SUCCESS} + */ + public String save() throws Exception { + + // Set people = personManager.getPeople(); + + for ( Iterator iter = persons.iterator(); iter.hasNext();) { + Person p = (Person) iter.next(); + personManager.getPeople().remove(p); + personManager.getPeople().add(p); + } + return "list"; + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java new file mode 100644 index 000000000..4c3bd25c0 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java @@ -0,0 +1,56 @@ +/* + * $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.showcase.person; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.struts2.config.Result; +import org.apache.struts2.views.freemarker.FreemarkerResult; + +import com.opensymphony.xwork2.ActionSupport; + +public class ListPeopleAction extends ActionSupport { + + private static final long serialVersionUID = 3608017189783645371L; + + PersonManager personManager; + List people = new ArrayList(); + + public void setPersonManager(PersonManager personManager) { + this.personManager = personManager; + } + + public String execute() { + people.addAll(personManager.getPeople()); + + return SUCCESS; + } + + public List getPeople() { + return people; + } + + public int getPeopleCount() { + return people.size(); + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java new file mode 100644 index 000000000..b477c5a5e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java @@ -0,0 +1,57 @@ +/* + * $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.showcase.person; + +import org.apache.struts2.config.ParentPackage; +import org.apache.struts2.config.Result; +import org.apache.struts2.config.Results; +import org.apache.struts2.views.freemarker.FreemarkerResult; + +import com.opensymphony.xwork2.ActionSupport; + +/** + */ +@ParentPackage("person") +public class NewPersonAction extends ActionSupport { + + private static final long serialVersionUID = 200410824352645515L; + + PersonManager personManager; + Person person; + + public void setPersonManager(PersonManager personManager) { + this.personManager = personManager; + } + + public String execute() { + personManager.createPerson(person); + + return SUCCESS; + } + + public Person getPerson() { + return person; + } + + public void setPerson(Person person) { + this.person = person; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/Person.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/Person.java new file mode 100644 index 000000000..440966a45 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/Person.java @@ -0,0 +1,86 @@ +/* + * $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.showcase.person; + +/** + */ +public class Person { + Long id; + String name; + String lastName; + + public Person() { + } + + public Person(Long id, String name, String lastName) { + this.id = id; + this.name = name; + this.lastName = lastName; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + final Person person = (Person) o; + + if (id != null ? !id.equals(person.id) : person.id != null) return false; + + return true; + } + + public int hashCode() { + return (id != null ? id.hashCode() : 0); + } + + + public String toString() { + return "Person{" + + "id=" + id + + ", name='" + name + '\'' + + ", lastName='" + lastName + '\'' + + '}'; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/PersonManager.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/PersonManager.java new file mode 100644 index 000000000..cf7e28c28 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/person/PersonManager.java @@ -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.showcase.person; + +import java.util.HashSet; +import java.util.Set; + +/** + */ +public class PersonManager { + private static Set people = new HashSet(5); + private static long COUNT = 5; + + static { + // create some imaginary persons + Person p1 = new Person(new Long(1), "Patrick", "Lightbuddie"); + Person p2 = new Person(new Long(2), "Jason", "Carrora"); + Person p3 = new Person(new Long(3), "Alexandru", "Papesco"); + Person p4 = new Person(new Long(4), "Jay", "Boss"); + Person p5 = new Person(new Long(5), "Rainer", "Hermanos"); + people.add(p1); + people.add(p2); + people.add(p3); + people.add(p4); + people.add(p5); + } + + public void createPerson(Person person) { + person.setId(new Long(++COUNT)); + people.add(person); + } + + public void updatePerson(Person person) { + people.add(person); + } + + public Set getPeople() { + return people; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/source/ViewSourceAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/source/ViewSourceAction.java new file mode 100644 index 000000000..80d5c98e3 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/source/ViewSourceAction.java @@ -0,0 +1,224 @@ +/* + * $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.showcase.source; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletContext; + +import org.apache.struts2.util.ServletContextAware; + +import com.opensymphony.xwork2.ActionSupport; +import com.opensymphony.xwork2.util.ClassLoaderUtil; + +/** + * Processes configuration, page, and action class paths to create snippets + * of the files for display. + */ +public class ViewSourceAction extends ActionSupport implements ServletContextAware { + + private String page; + private String className; + private String config; + + private List pageLines; + private List classLines; + private List configLines; + + private int configLine; + private int padding = 10; + + private ServletContext servletContext; + + public String execute() throws MalformedURLException, IOException { + + if (page != null && page.trim().length() > 0) { + + InputStream in = ClassLoaderUtil.getResourceAsStream(page.substring(page.indexOf("//")+1), getClass()); + page = page.replace("//", "/"); + + if (in == null) { + in = servletContext.getResourceAsStream(page); + while (in == null && page.indexOf('/', 1) > 0) { + page = page.substring(page.indexOf('/', 1)); + in = servletContext.getResourceAsStream(page); + } + } + pageLines = read(in, -1); + + if (in != null) { + in.close(); + } + } + + if (className != null && className.trim().length() > 0) { + className = "/" + className.replace('.', '/') + ".java"; + InputStream in = getClass().getResourceAsStream(className); + if (in == null) { + in = servletContext.getResourceAsStream("/WEB-INF/src"+className); + } + classLines = read(in, -1); + + if (in != null) { + in.close(); + } + } + + if (config != null && config.trim().length() > 0) { + int pos = config.lastIndexOf(':'); + configLine = Integer.parseInt(config.substring(pos+1)); + config = config.substring(0, pos).replace("//", "/"); + configLines = read(new URL(config).openStream(), configLine); + } + return SUCCESS; + } + + /** + * @param className the className to set + */ + public void setClassName(String className) { + this.className = className; + } + + /** + * @param config the config to set + */ + public void setConfig(String config) { + this.config = config; + } + + /** + * @param page the page to set + */ + public void setPage(String page) { + this.page = page; + } + + /** + * @param padding the padding to set + */ + public void setPadding(int padding) { + this.padding = padding; + } + + /** + * @return the classLines + */ + public List getClassLines() { + return classLines; + } + + /** + * @return the configLines + */ + public List getConfigLines() { + return configLines; + } + + /** + * @return the pageLines + */ + public List getPageLines() { + return pageLines; + } + + /** + * @return the className + */ + public String getClassName() { + return className; + } + + /** + * @return the config + */ + public String getConfig() { + return config; + } + + /** + * @return the page + */ + public String getPage() { + return page; + } + + /** + * @return the configLine + */ + public int getConfigLine() { + return configLine; + } + + /** + * @return the padding + */ + public int getPadding() { + return padding; + } + + /** + * Reads in a strea, optionally only including the target line number + * and its padding + * + * @param in The input stream + * @param targetLineNumber The target line number, negative to read all + * @return A list of lines + */ + private List read(InputStream in, int targetLineNumber) { + List snippet = null; + if (in != null) { + snippet = new ArrayList(); + int startLine = 0; + int endLine = Integer.MAX_VALUE; + if (targetLineNumber > 0) { + startLine = targetLineNumber - padding; + endLine = targetLineNumber + padding; + } + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + + int lineno = 0; + String line; + while ((line = reader.readLine()) != null) { + lineno++; + if (lineno >= startLine && lineno <= endLine) { + snippet.add(line); + } + } + } catch (Exception ex) { + // ignoring as snippet not available isn't a big deal + } + } + return snippet; + } + + public void setServletContext(ServletContext arg0) { + this.servletContext = arg0; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actionPrefix/SubmitAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actionPrefix/SubmitAction.java new file mode 100644 index 000000000..a8b350c85 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actionPrefix/SubmitAction.java @@ -0,0 +1,42 @@ +/* + * $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.showcase.tag.nonui.actionPrefix; + +import com.opensymphony.xwork2.ActionSupport; + +public class SubmitAction extends ActionSupport { + + private static final long serialVersionUID = -7832803019378213087L; + + private String text; + + public String getText() { return text; } + public void setText(String text) { this.text = text; } + + public String execute() throws Exception { + return SUCCESS; + } + + public String alternateMethod() { + return "methodPrefixResult"; + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actiontag/ActionTagDemo.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actiontag/ActionTagDemo.java new file mode 100644 index 000000000..6de46d258 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actiontag/ActionTagDemo.java @@ -0,0 +1,38 @@ +/* + * $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.showcase.tag.nonui.actiontag; + +import com.opensymphony.xwork2.ActionSupport; + +/** + */ +public class ActionTagDemo extends ActionSupport { + + private static final long serialVersionUID = -2749145880590245184L; + + public String show() throws Exception { + return SUCCESS; + } + + public String doInclude() throws Exception { + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/AppendIteratorTagDemo.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/AppendIteratorTagDemo.java new file mode 100644 index 000000000..a47ee62a0 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/AppendIteratorTagDemo.java @@ -0,0 +1,80 @@ +/* + * $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.showcase.tag.nonui.iteratortag; + +import com.opensymphony.xwork2.ActionSupport; +import com.opensymphony.xwork2.Validateable; + +/** + * + */ +public class AppendIteratorTagDemo extends ActionSupport implements Validateable { + + private static final long serialVersionUID = -6525059998526094664L; + + private String iteratorValue1; + private String iteratorValue2; + + + public void validate() { + if (iteratorValue1 == null || iteratorValue1.trim().length() <= 0 ) { + addFieldError("iteratorValue1", "iterator value 1 cannot be empty"); + } + else if (iteratorValue1.trim().indexOf(",") <= 0) { + addFieldError("iteratorValue1", "iterator value 1 needs to be comma separated"); + } + if (iteratorValue2 == null || iteratorValue2.trim().length() <= 0) { + addFieldError("iteratorValue2", "iterator value 2 cannot be empty"); + } + else if (iteratorValue2.trim().indexOf(",") <= 0) { + addFieldError("iteratorValue2", "iterator value 2 needs to be comma separated"); + } + } + + + + + public String getIteratorValue1() { + return iteratorValue1; + } + public void setIteratorValue1(String iteratorValue1) { + this.iteratorValue1 = iteratorValue1; + } + + + + public String getIteratorValue2() { + return iteratorValue2; + } + public void setIteratorValue2(String iteratorValue2) { + this.iteratorValue2 = iteratorValue2; + } + + + + public String input() throws Exception { + return SUCCESS; + } + + public String submit() throws Exception { + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo.java new file mode 100644 index 000000000..f4b74fd2a --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo.java @@ -0,0 +1,69 @@ +/* + * $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.showcase.tag.nonui.iteratortag; + +import com.opensymphony.xwork2.ActionSupport; + +/** + */ +public class IteratorGeneratorTagDemo extends ActionSupport { + + private static final long serialVersionUID = 6893616642389337039L; + + private String value; + private Integer count; + private String separator; + + + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + } + + + public Integer getCount() { + return count; + } + public void setCount(Integer count) { + this.count = count; + } + + + + public String getSeparator() { + return this.separator; + } + public void setSeparator(String separator) { + this.separator = separator; + } + + + public String submit() throws Exception { + return SUCCESS; + } + + + public String input() throws Exception { + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/MergeIteratorTagDemo.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/MergeIteratorTagDemo.java new file mode 100644 index 000000000..64dbe87b1 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/MergeIteratorTagDemo.java @@ -0,0 +1,81 @@ +/* + * $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.showcase.tag.nonui.iteratortag; + +import com.opensymphony.xwork2.ActionSupport; +import com.opensymphony.xwork2.Validateable; + + +/** + */ +public class MergeIteratorTagDemo extends ActionSupport implements Validateable { + + private static final long serialVersionUID = 4401107963952961695L; + + private String iteratorValue1; + private String iteratorValue2; + + + public void validate() { + if (iteratorValue1 == null || iteratorValue1.trim().length() <= 0 ) { + addFieldError("iteratorValue1", "iterator value 1 cannot be empty"); + } + else if (iteratorValue1.trim().indexOf(",") <= 0) { + addFieldError("iteratorValue1", "iterator value 1 needs to be comma separated"); + } + if (iteratorValue2 == null || iteratorValue2.trim().length() <= 0) { + addFieldError("iteratorValue2", "iterator value 2 cannot be empty"); + } + else if (iteratorValue2.trim().indexOf(",") <= 0) { + addFieldError("iteratorValue2", "iterator value 2 needs to be comma separated"); + } + } + + + + public String getIteratorValue1() { + return this.iteratorValue1; + } + public void setIteratorValue1(String iteratorValue1) { + this.iteratorValue1 = iteratorValue1; + } + + + + public String getIteratorValue2() { + return this.iteratorValue2; + } + public void setIteratorValue2(String iteratorValue2) { + this.iteratorValue2 = iteratorValue2; + } + + + + + + public String input() throws Exception { + return SUCCESS; + } + + public String submit() throws Exception { + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/SubsetIteratorTagDemo.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/SubsetIteratorTagDemo.java new file mode 100644 index 000000000..c4002e908 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/SubsetIteratorTagDemo.java @@ -0,0 +1,88 @@ +/* + * $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.showcase.tag.nonui.iteratortag; + +import com.opensymphony.xwork2.ActionSupport; +import com.opensymphony.xwork2.Validateable; + +/** + * + */ +public class SubsetIteratorTagDemo extends ActionSupport implements Validateable { + + private static final long serialVersionUID = -8151855954644052650L; + + private String iteratorValue; + private Integer count; + private Integer start; + + + public void validate() { + if (iteratorValue == null || iteratorValue.trim().length() <= 0 ) { + addFieldError("iteratorValue1", "iterator value 1 cannot be empty"); + } + else if (iteratorValue.trim().indexOf(",") <= 0) { + addFieldError("iteratorValue1", "iterator value 1 needs to be comma separated"); + } + } + + + + public String getIteratorValue() { + return this.iteratorValue; + } + public void setIteratorValue(String iteratorValue) { + this.iteratorValue = iteratorValue; + } + + + + public Integer getCount() { + return this.count; + } + public void setCount(Integer count) { + this.count = count; + } + + + + public Integer getStart() { + return this.start; + } + public void setStart(Integer start) { + this.start = start; + } + + + + + + public String input() throws Exception { + return SUCCESS; + } + + public String submit() throws Exception { + return SUCCESS; + } + + + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/token/TokenAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/token/TokenAction.java new file mode 100644 index 000000000..6ec8046eb --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/token/TokenAction.java @@ -0,0 +1,84 @@ +/* + * $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.showcase.token; + +import java.util.Date; + +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ActionSupport; + +/** + * Example to illustrate the token and token-session interceptor. + * + */ +public class TokenAction extends ActionSupport { + + private static final long serialVersionUID = 616150375751184884L; + + private int amount; + + public String execute() throws Exception { + // transfer from source to destination + + Integer balSource = (Integer) ActionContext.getContext().getSession().get("balanceSource"); + Integer balDest = (Integer) ActionContext.getContext().getSession().get("balanceDestination"); + + Integer newSource = new Integer(balSource.intValue() - amount); + Integer newDest = new Integer(balDest.intValue() + amount); + + ActionContext.getContext().getSession().put("balanceSource", newSource); + ActionContext.getContext().getSession().put("balanceDestination", newDest); + ActionContext.getContext().getSession().put("time", new Date()); + + Thread.sleep(2000); // to simulate processing time + + return SUCCESS; + } + + public String input() throws Exception { + // prepare input form + Integer balSource = (Integer) ActionContext.getContext().getSession().get("balanceSource"); + Integer balDest = (Integer) ActionContext.getContext().getSession().get("balanceDestination"); + + if (balSource == null) { + // first time set up an initial account balance + balSource = new Integer(1200); + ActionContext.getContext().getSession().put("balanceSource", balSource); + } + + if (balDest == null) { + // first time set up an initial account balance + balDest = new Integer(2500); + ActionContext.getContext().getSession().put("balanceDestination", balDest); + } + + return INPUT; + } + + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + this.amount = amount; + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AbstractValidationActionSupport.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AbstractValidationActionSupport.java new file mode 100644 index 000000000..346745d3d --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AbstractValidationActionSupport.java @@ -0,0 +1,36 @@ +/* + * $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.showcase.validation; + +import com.opensymphony.xwork2.ActionSupport; + +/** + */ +public abstract class AbstractValidationActionSupport extends ActionSupport { + + public String submit() throws Exception { + return "success"; + } + + public String input() throws Exception { + return "input"; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.java new file mode 100644 index 000000000..e1c4c41bf --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.java @@ -0,0 +1,107 @@ +/* + * $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.showcase.validation; + +import java.sql.Date; + +/** + */ + +// START SNIPPET: fieldValidatorsExample + +public class FieldValidatorsExampleAction extends AbstractValidationActionSupport { + + private static final long serialVersionUID = -4829381083003175423L; + + private String requiredValidatorField = null; + private String requiredStringValidatorField = null; + private Integer integerValidatorField = null; + private Date dateValidatorField = null; + private String emailValidatorField = null; + private String urlValidatorField = null; + private String stringLengthValidatorField = null; + private String regexValidatorField = null; + private String fieldExpressionValidatorField = null; + + + + public Date getDateValidatorField() { + return dateValidatorField; + } + public void setDateValidatorField(Date dateValidatorField) { + this.dateValidatorField = dateValidatorField; + } + public String getEmailValidatorField() { + return emailValidatorField; + } + public void setEmailValidatorField(String emailValidatorField) { + this.emailValidatorField = emailValidatorField; + } + public Integer getIntegerValidatorField() { + return integerValidatorField; + } + public void setIntegerValidatorField(Integer integerValidatorField) { + this.integerValidatorField = integerValidatorField; + } + public String getRegexValidatorField() { + return regexValidatorField; + } + public void setRegexValidatorField(String regexValidatorField) { + this.regexValidatorField = regexValidatorField; + } + public String getRequiredStringValidatorField() { + return requiredStringValidatorField; + } + public void setRequiredStringValidatorField(String requiredStringValidatorField) { + this.requiredStringValidatorField = requiredStringValidatorField; + } + public String getRequiredValidatorField() { + return requiredValidatorField; + } + public void setRequiredValidatorField(String requiredValidatorField) { + this.requiredValidatorField = requiredValidatorField; + } + public String getStringLengthValidatorField() { + return stringLengthValidatorField; + } + public void setStringLengthValidatorField(String stringLengthValidatorField) { + this.stringLengthValidatorField = stringLengthValidatorField; + } + public String getFieldExpressionValidatorField() { + return fieldExpressionValidatorField; + } + public void setFieldExpressionValidatorField( + String fieldExpressionValidatorField) { + this.fieldExpressionValidatorField = fieldExpressionValidatorField; + } + + public String getUrlValidatorField() { + return urlValidatorField; + } + + public void setUrlValidatorField(String urlValidatorField) { + this.urlValidatorField = urlValidatorField; + } +} + + +// END SNIPPET: fieldValidatorsExample + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction.java new file mode 100644 index 000000000..447b17c79 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction.java @@ -0,0 +1,60 @@ +/* + * $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.showcase.validation; + +/** + */ + +// START SNIPPET: nonFieldValidatorsExample + +public class NonFieldValidatorsExampleAction extends AbstractValidationActionSupport { + + private static final long serialVersionUID = -524460368233581186L; + + private String someText; + private String someTextRetype; + private String someTextRetypeAgain; + + public String getSomeText() { + return someText; + } + public void setSomeText(String someText) { + this.someText = someText; + } + public String getSomeTextRetype() { + return someTextRetype; + } + public void setSomeTextRetype(String someTextRetype) { + this.someTextRetype = someTextRetype; + } + public String getSomeTextRetypeAgain() { + return someTextRetypeAgain; + } + public void setSomeTextRetypeAgain(String someTextRetypeAgain) { + this.someTextRetypeAgain = someTextRetypeAgain; + } +} + + +// END SNIPPET: nonFieldValidatorsExample + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/QuizAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/QuizAction.java new file mode 100644 index 000000000..81e27360b --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/QuizAction.java @@ -0,0 +1,64 @@ +/* + * $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.showcase.validation; + +import com.opensymphony.xwork2.ActionSupport; + +/** + */ + +// START SNIPPET: quizAction + +public class QuizAction extends ActionSupport { + + private static final long serialVersionUID = -7505437345373234225L; + + String name; + int age; + String answer; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getAnswer() { + return answer; + } + + public void setAnswer(String answer) { + this.answer = answer; + } +} + +// END SNIPPET: quizAction + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/SubmitApplication.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/SubmitApplication.java new file mode 100644 index 000000000..99bf87479 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/SubmitApplication.java @@ -0,0 +1,60 @@ +/* + * $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.showcase.validation; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * + * @version $Date$ $Id$ + */ +public class SubmitApplication extends ActionSupport { + + private String name; + private Integer age; + + public void setName(String name) { + this.name = name; + } + public String getName() { + return this.name; + } + + public void setAge(Integer age) { + this.age = age; + } + public Integer getAge() { + return age; + } + + public String submitApplication() throws Exception { + return SUCCESS; + } + + public String applicationOk() throws Exception { + addActionMessage("Your application looks ok."); + return SUCCESS; + } + public String cancelApplication() throws Exception { + addActionMessage("So you have decided to cancel the application"); + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/User.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/User.java new file mode 100644 index 000000000..111f8be52 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/User.java @@ -0,0 +1,53 @@ +/* + * $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.showcase.validation; + +import java.sql.Date; + +/** + */ +public class User { + + private String name; + private Integer age; + private Date birthday; + + + public Integer getAge() { + return age; + } + public void setAge(Integer age) { + this.age = age; + } + public Date getBirthday() { + return birthday; + } + public void setBirthday(Date birthday) { + this.birthday = birthday; + } + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } +} + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction.java new file mode 100644 index 000000000..91391a314 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction.java @@ -0,0 +1,42 @@ +/* + * $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.showcase.validation; + + +// START SNIPPET: visitorValidatorsExample + +public class VisitorValidatorsExampleAction extends AbstractValidationActionSupport { + + private static final long serialVersionUID = 4375454086939598216L; + + private User user; + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } +} + + +// END SNIPPET: visitorValidatorsExample diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/LongProcessAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/LongProcessAction.java new file mode 100644 index 000000000..e449d9f09 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/LongProcessAction.java @@ -0,0 +1,50 @@ +/* + * $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.showcase.wait; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * Example to illustrate the execAndWait interceptor. + * + */ +public class LongProcessAction extends ActionSupport { + + private static final long serialVersionUID = 2471910747833998708L; + + private int time; + + public int getTime() { + return time; + } + + public void setTime(int time) { + this.time = time; + } + + public String execute() throws Exception { + System.err.println("time: " + time); + Thread.sleep(time); + + return SUCCESS; + } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/xslt/JVMAction.java b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/xslt/JVMAction.java new file mode 100644 index 000000000..d888e2929 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/java/org/apache/struts2/showcase/xslt/JVMAction.java @@ -0,0 +1,103 @@ +/* + * $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.showcase.xslt; + +import java.util.Map; +import java.util.Properties; + +import com.opensymphony.xwork2.ActionSupport; + +import org.apache.struts2.interceptor.ServletRequestAware; + +import javax.servlet.http.HttpServletRequest; + +public class JVMAction implements ServletRequestAware { + + private ImportantInfo info; + private Map environment; + + /** Captured only to show that undesired data can creep into the result. */ + private HttpServletRequest servletRequest; + + + public String execute() { + environment = System.getenv(); + Properties props = System.getProperties(); + + String classpath = environment.get("CLASSPATH"); + info = new ImportantInfo(classpath, props); + + return ActionSupport.SUCCESS; + } + + + public HttpServletRequest getServletRequest() { + return servletRequest; + } + + public void setServletRequest(HttpServletRequest servletRequest) { + this.servletRequest = servletRequest; + } + + public Map getEnvironment() { + return environment; + } + + public void setEnvironment(Map environment) { + this.environment = environment; + } + + + public ImportantInfo getInfo() { + return info; + } + + public void setInfo(ImportantInfo info) { + this.info = info; + } + + public class ImportantInfo { + private String classpath; + private Properties systemProperties; + + + public ImportantInfo(String classpath, Properties properties) { + this.classpath = classpath; + this.systemProperties = properties; + } + + public String getClasspath() { + return classpath; + } + + public void setClasspath(String classpath) { + this.classpath = classpath; + } + + public Properties getSystemProperties() { + return systemProperties; + } + + public void setSystemProperties(Properties systemProperties) { + this.systemProperties = systemProperties; + } + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/LICENSE.txt b/STRUTS_2_0_X/apps/showcase/src/main/resources/LICENSE.txt new file mode 100644 index 000000000..dd5b3a58a --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/LICENSE.txt @@ -0,0 +1,174 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/NOTICE.txt b/STRUTS_2_0_X/apps/showcase/src/main/resources/NOTICE.txt new file mode 100644 index 000000000..28aacd493 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/NOTICE.txt @@ -0,0 +1,6 @@ +Apache Struts +Copyright 2000-2007 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). +Nifty Corners (http://www.html.it/articoli/nifty/index.html). diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/globalMessages.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/globalMessages.properties new file mode 100644 index 000000000..24a39d45c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/globalMessages.properties @@ -0,0 +1,7 @@ +save=Save + +item.edit=Edit {0} +item.create=Create {0} +item.list={0} List + +token.transfer.time=The bank transfer was executed at {0,date,HH:mm:ss MM-dd-yyyy} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/globalMessages_de.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/globalMessages_de.properties new file mode 100644 index 000000000..0dc66efa8 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/globalMessages_de.properties @@ -0,0 +1,7 @@ +save=Speichern + +item.edit={0} bearbeiten +item.create={0} neu anlegen +item.list={0}-Liste + +token.transfer.time=Die \u00dcberweisung wurde am {0,date,HH:mm:ss MM-dd-yyyy} durchgef\u00fchrt diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/log4j.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/log4j.properties new file mode 100644 index 000000000..226f3de08 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/log4j.properties @@ -0,0 +1,31 @@ +# +# Log4J Settings for log4j 1.2.x (via jakarta-commons-logging) +# +# The five logging levels used by Log are (in order): +# +# 1. DEBUG (the least serious) +# 2. INFO +# 3. WARN +# 4. ERROR +# 5. FATAL (the most serious) + + +# Set root logger level to WARN and append to stdout +log4j.rootLogger=WARN, stdout + +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout + +# Pattern to output the caller's file name and line number. +log4j.appender.stdout.layout.ConversionPattern=%d %5p (%c:%L) - %m%n + +# Print only messages of level ERROR or above in the package noModule. +log4j.logger.noModule=FATAL + +# OpenSymphony Stuff +log4j.logger.com.opensymphony=INFO +log4j.logger.org.apache.struts2=DEBUG + +# Spring Stuff +log4j.logger.org.springframework=INFO + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/myTemplateDir/myTheme/myAnotherTemplate.ftl b/STRUTS_2_0_X/apps/showcase/src/main/resources/myTemplateDir/myTheme/myAnotherTemplate.ftl new file mode 100644 index 000000000..544f44e60 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/myTemplateDir/myTheme/myAnotherTemplate.ftl @@ -0,0 +1,6 @@ +

    +

    +Freemarker Custom Template - +parameter 'paramName' - ${parameters.paramName} +

    +
    diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/DateAction.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/DateAction.properties new file mode 100644 index 000000000..d49c743a5 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/DateAction.properties @@ -0,0 +1 @@ +struts.date.format=yyyy/MM/dd hh:mm:ss \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/LotsOfRichtexteditorAction-lotsOfRichtexteditorSubmit-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/LotsOfRichtexteditorAction-lotsOfRichtexteditorSubmit-validation.xml new file mode 100644 index 000000000..8bf17c7c1 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/LotsOfRichtexteditorAction-lotsOfRichtexteditorSubmit-validation.xml @@ -0,0 +1,30 @@ + + + + + + Description1 Is Required !!! + + + + + + Description2 Is Required !!! + + + + + + Description3 Is Required !!! + + + + + + Description4 Is Required !!! + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/UITagExample-conversion.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/UITagExample-conversion.properties new file mode 100644 index 000000000..2415dcf3c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/UITagExample-conversion.properties @@ -0,0 +1 @@ +Element_friends = java.lang.String diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-conversion.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-conversion.properties new file mode 100644 index 000000000..21d3eda97 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-conversion.properties @@ -0,0 +1 @@ +Element_selectedSkills=java.lang.String diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-validation.xml new file mode 100644 index 000000000..c49959888 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-validation.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + true + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction.properties new file mode 100644 index 000000000..e2e548b3c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction.properties @@ -0,0 +1,9 @@ +employee=Employee +employee.firstName=First Name +employee.lastName=Last Name +employee.description=Description + +employee.id.required=Id is required +employee.lastName.required=Last Name is required +employee.birthDate.required=Birthdate is required +employee.backtolist=Back to Employee List diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction_de.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction_de.properties new file mode 100644 index 000000000..ca594de4d --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction_de.properties @@ -0,0 +1,9 @@ +employee=Mitarbeiter +employee.firstName=Vorname +employee.lastName=Nachname +employee.description=Beschreibung + +employee.id.required=ID muß angegeben werden +employee.lastName.required=Nachname wird benötigt +employee.birthDate.required=Geburtsdatum wird benötigt +employee.backtolist=Zurück zur Mitarbeiterliste diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction-validation.xml new file mode 100644 index 000000000..486e79f61 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction-validation.xml @@ -0,0 +1,11 @@ + + + + + + + true + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction.properties new file mode 100644 index 000000000..27b7c81df --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction.properties @@ -0,0 +1,6 @@ +skill=Skill +skill.name=Name +skill.description=Description + +skill.name.required=Name is required +skill.backtolist=Back to Skill List diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction_de.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction_de.properties new file mode 100644 index 000000000..7c7156f71 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction_de.properties @@ -0,0 +1,6 @@ +skill=Kenntnis +skill.name=Name +skill.description=Beschreibung + +skill.name.required=Name muss angegeben werden +skill.backtolist=Zurück zur Kenntnis Liste diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/ajax/Example5Action-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/ajax/Example5Action-validation.xml new file mode 100644 index 000000000..b80e7d54a --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/ajax/Example5Action-validation.xml @@ -0,0 +1,19 @@ + + + + + + + Name is required + + + + + Age is required + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/ChatLoginAction-chatLogin-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/ChatLoginAction-chatLogin-validation.xml new file mode 100644 index 000000000..d4ab29906 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/ChatLoginAction-chatLogin-validation.xml @@ -0,0 +1,14 @@ + + + + + + + true + Name is required + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/ChatMessage-conversion.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/ChatMessage-conversion.properties new file mode 100644 index 000000000..8869d38e6 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/ChatMessage-conversion.properties @@ -0,0 +1 @@ +creationDate=org.apache.struts2.showcase.chat.DateConverter diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/CrudRoomAction-createRoom-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/CrudRoomAction-createRoom-validation.xml new file mode 100644 index 000000000..bf8977c3b --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/CrudRoomAction-createRoom-validation.xml @@ -0,0 +1,20 @@ + + + + + + + true + Room name is required + + + + + true + Room description is required + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/Room-conversion.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/Room-conversion.properties new file mode 100644 index 000000000..8869d38e6 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/Room-conversion.properties @@ -0,0 +1 @@ +creationDate=org.apache.struts2.showcase.chat.DateConverter diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/SendMessageToRoomAction-sendMessageToRoom-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/SendMessageToRoomAction-sendMessageToRoom-validation.xml new file mode 100644 index 000000000..b4197a443 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/chat/SendMessageToRoomAction-sendMessageToRoom-validation.xml @@ -0,0 +1,15 @@ + + + + + + + true + Message is required + + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/AddressAction-conversion.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/AddressAction-conversion.properties new file mode 100644 index 000000000..1a6d70055 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/AddressAction-conversion.properties @@ -0,0 +1,6 @@ + +KeyProperty_addresses=id +Element_addresses=org.apache.struts2.showcase.conversion.Address +CreateIfNull_addresses=true + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/OperationsEnumAction-conversion.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/OperationsEnumAction-conversion.properties new file mode 100644 index 000000000..621beafba --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/OperationsEnumAction-conversion.properties @@ -0,0 +1,4 @@ + +selectedOperations=org.apache.struts2.showcase.conversion.EnumTypeConverter +Element_selectedOperations=org.apache.struts2.showcase.conversion.OperationsEnum + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/PersonAction-conversion.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/PersonAction-conversion.properties new file mode 100644 index 000000000..12f602f16 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/PersonAction-conversion.properties @@ -0,0 +1 @@ +Element_persons=org.apache.struts2.showcase.conversion.Person diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/FileUploadAction-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/FileUploadAction-validation.xml new file mode 100644 index 000000000..d81d2292c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/FileUploadAction-validation.xml @@ -0,0 +1,19 @@ + + + + + + + 0]]> + File cannot be empty + + + + + Caption cannot be empty + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction-conversion.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction-conversion.properties new file mode 100644 index 000000000..fbf3d7730 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction-conversion.properties @@ -0,0 +1 @@ +Element_upload=java.io.File diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/EditPersonAction-conversion.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/EditPersonAction-conversion.properties new file mode 100644 index 000000000..00b2a0365 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/EditPersonAction-conversion.properties @@ -0,0 +1,3 @@ +KeyProperty_persons=id +Element_persons=org.apache.struts2.showcase.person.Person +CreateIfNull_persons=true diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml new file mode 100644 index 000000000..6d19ebdf6 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/Person-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/Person-validation.xml new file mode 100644 index 000000000..da2c81f0c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/Person-validation.xml @@ -0,0 +1,13 @@ + + + + + You must enter a first name. + + + + + You must enter a last name + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo-validation.xml new file mode 100644 index 000000000..55f9577b2 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo-validation.xml @@ -0,0 +1,22 @@ + + + + + + + true + Value must not be empty + + + + + + + Count must be an integer + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-conversion.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-conversion.properties new file mode 100644 index 000000000..2f970dc18 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-conversion.properties @@ -0,0 +1 @@ +dateValidatorField=java.util.Date \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitClientSideValidationExample-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitClientSideValidationExample-validation.xml new file mode 100644 index 000000000..ab6eabd0e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitClientSideValidationExample-validation.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + true + + + + + + true + + + + + + 1 + 10 + + + + + + 01/01/1990 + 01/01/2000 + + + + + + + + + + + + + + + + 4 + 2 + true + + + + + + .*\.txt + + + + + + (fieldExpressionValidatorField == requiredValidatorField) + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitFieldValidatorsExamples-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitFieldValidatorsExamples-validation.xml new file mode 100644 index 000000000..97250cf93 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitFieldValidatorsExamples-validation.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + true + + + + + + 1 + 10 + + + + + + 01/01/1990 + 01/01/2000 + + + + + + + + + + + + + + + + 4 + 2 + true + + + + + + .*\.txt + + + + + + (fieldExpressionValidatorField == requiredValidatorField) + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.properties b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.properties new file mode 100644 index 000000000..14f04121a --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.properties @@ -0,0 +1 @@ +i18n.requiredstring=Test String for required Strings... diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction-submitNonFieldValidatorsExamples-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction-submitNonFieldValidatorsExamples-validation.xml new file mode 100644 index 000000000..cba25b09e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction-submitNonFieldValidatorsExamples-validation.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/QuizAction-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/QuizAction-validation.xml new file mode 100644 index 000000000..dd716fade --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/QuizAction-validation.xml @@ -0,0 +1,23 @@ + + + + + + + + You must enter a name + + + + + 13 + 19 + Only people ages 13 to 19 may take this quiz + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/SubmitApplication-submitApplication-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/SubmitApplication-submitApplication-validation.xml new file mode 100644 index 000000000..0dbb123f9 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/SubmitApplication-submitApplication-validation.xml @@ -0,0 +1,24 @@ + + + + + + + You must provide a name + + + + + You must provide your age + + + 18 + 50 + Your age must be between 18 and 50 + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/User-userContext-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/User-userContext-validation.xml new file mode 100644 index 000000000..508eb6590 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/User-userContext-validation.xml @@ -0,0 +1,27 @@ + + + + + + + + Name Required + + + + + 1 + 100 + Age Required (1-100) + + + + + Birthday Required + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction-submitVisitorValidatorsExamples-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction-submitVisitorValidatorsExamples-validation.xml new file mode 100644 index 000000000..a8af8f005 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction-submitVisitorValidatorsExamples-validation.xml @@ -0,0 +1,20 @@ + + + + + + + + + + userContext + true + User: + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-actionchaining.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-actionchaining.xml new file mode 100644 index 000000000..f0818a0b4 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-actionchaining.xml @@ -0,0 +1,21 @@ + + + + + + + + actionChain2 + + + actionChain3 + + + /actionchaining/actionChainingResult.jsp + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-ajax.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-ajax.xml new file mode 100644 index 000000000..04dbe51f8 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-ajax.xml @@ -0,0 +1,78 @@ + + + + + + /ajax/AjaxResult.jsp + + + + /ajax/AjaxResult2.js + + + + /ajax/AjaxResult3.jsp + + + + /ajax/remoteforms/test2.jsp + + + + /ajax/remoteforms/test3.jsp + + + + /ajax/testjs.jsp + + + + /ajax/JSONList.js + + + + /ajax/tree/tree.jsp + + + + /ajax/tree/getCategory.jsp + + + + /ajax/tree/toggle.jsp + + + + /ajax/tabbedpanel/example4.ftl + + + + /ajax/tabbedpanel/example5.jsp + /ajax/tabbedpanel/example5Ok.jsp + + + + + + + /ajax/tabbedpanel/nodecorate/panel1.ftl + + + /ajax/tabbedpanel/nodecorate/panel2.ftl + + + /ajax/tabbedpanel/nodecorate/panel3.ftl + + + /ajax/tabbedpanel/nodecorate/panel2Submit.ftl + + + /ajax/tabbedpanel/nodecorate/panel3Submit.ftl + + + /ajax/options.ftl + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-chat.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-chat.xml new file mode 100644 index 000000000..173d3bcee --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-chat.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + input,back,cancel,browse + + + input,back,cancel,browse + + + + + + + /chat/chatLogin.ftl + + + + + /chat/roomSelection.ftl + + + + + /chat/showRooms.action + /chat/chatLogin.ftl + + + + + /chat/main.action + + + + + /chat/roomSelection.ftl + + + + + /chat/showRoom.ftl + + + + + /chat/showRooms.action + + + + + + + + + + + + + + + + + + + + + + + input,back,cancel,browse + + + input,back,cancel,browse + + + + + + + + + /chat/usersAvailable.ftl + + + + + /chat/roomsAvailable.ftl + + + + + /chat/createRoom.ftl + /chat/createRoom.ftl + + + + + /chat/messagesAvailableInRoom.ftl + /chat/messagesAvailableInRoom.ftl + + + + + /chat/sendMessageToRoomResult.ftl + /chat/sendMessageToRoomResult.ftl + + + + + /chat/usersAvailableInRoom.ftl + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-conversion.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-conversion.xml new file mode 100644 index 000000000..c3259e6a9 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-conversion.xml @@ -0,0 +1,75 @@ + + + + + + + + + + enterPersonInfo.jsp + + + showPersonInfo.jsp + enterPersonInfo.jsp + + + /conversion/enterPersonInfo.jsp + + + /conversion/PersonAction.java.txt + + + /conversion/Person.java.txt + + + + + + enterAddressInfo.jsp + + + showAddressInfo.jsp + enterAddressInfo.jsp + + + /conversion/enterAddressInfo.jsp + + + /conversion/AddressAction.java.txt + + + /conversion/Address.java.txt + + + + + + enterOperations.jsp + + + showOperations.jsp + enterOperations.jsp + + + /conversion/enterOperations.jsp + + + /conversion/OperationsEnum.java.txt + + + /conversion/OperationsEnumAction.java.txt + + + /conversion/EnumTypeConverter.java.txt + + + /conversion/OperationsEnumActionConversion.txt + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-filedownload.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-filedownload.xml new file mode 100644 index 000000000..3442ef85d --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-filedownload.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + /images/struts.gif + + image/gif + inputStream + filename="struts.gif" + 4096 + + + + + /images/struts-gif.zip + + application/zip + inputStream + filename="struts-gif.zip" + 4096 + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-fileupload.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-fileupload.xml new file mode 100644 index 000000000..e94c2073a --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-fileupload.xml @@ -0,0 +1,40 @@ + + + + + + + + + upload.jsp + + + + upload.jsp + upload-success.jsp + + + + multipleUploadUsingList.jsp + + + + multipleUploadUsingList-success.jsp + + + + + multipleUploadUsingArray.jsp + + + + multipleUploadUsingArray-success.jsp + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-freemarker.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-freemarker.xml new file mode 100644 index 000000000..5ce761a2a --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-freemarker.xml @@ -0,0 +1,18 @@ + + + + + + + + + /freemarker/customFreemarkerManagerUsage.ftl + + + + /freemarker/standardTags.ftl + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-hangman.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-hangman.xml new file mode 100644 index 000000000..b12ddcee4 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-hangman.xml @@ -0,0 +1,48 @@ + + + + + + + + /hangman/hangmanMenu.ftl + + + /hangman/hangmanAjax.ftl + + + /hangman/hangmanNonAjax.ftl + + + /hangman/test.ftl + + + /hangman/blank.ftl + + + /hangman/hangmanNonAjax.ftl + + + + + + + + /hangman/blank.ftl + + + /hangman/updateVocabCharacters.ftl + + + /hangman/updateCharacterAvailable.ftl + + + /hangman/updateScaffold.ftl + + + /hangman/updateGuessLeft.ftl + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-integration.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-integration.xml new file mode 100644 index 000000000..4d7b3dcd2 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-integration.xml @@ -0,0 +1,49 @@ + + + + + + + + + + org.apache.struts2.showcase.integration.GangsterForm + gangsterForm + + + /org/apache/struts/validator/validator-rules.xml,/WEB-INF/validation.xml + + + + + + + + + + + + + + + + + + + org.apache.struts2.showcase.integration.EditGangsterAction + modelDriven.jsp + + + + + org.apache.struts2.showcase.integration.SaveGangsterAction + true + modelDriven.jsp + modelDrivenResult.jsp + + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-jsf.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-jsf.xml new file mode 100644 index 000000000..2ef59b500 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-jsf.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + list.action + list.action + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-model-driven.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-model-driven.xml new file mode 100644 index 000000000..bf3d57e4e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-model-driven.xml @@ -0,0 +1,20 @@ + + + + + + + + + modelDriven.jsp + + + + + modelDrivenResult.jsp + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-person.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-person.xml new file mode 100644 index 000000000..63dfb8c3c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-person.xml @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tags-non-ui.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tags-non-ui.xml new file mode 100644 index 000000000..244acd50f --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tags-non-ui.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + /tags/non-ui/actionTag/showActionTagDemo.jsp + + + /tags/non-ui/actionTag/includedPage.jsp + + + /tags/non-ui/actionTag/includedPage2.jsp + + + /tags/non-ui/actionTag/includedPage3.jsp + + + /tags/non-ui/actionTag/showActionTagDemo.jsp + + + + + + + + + + /tags/non-ui/iteratorTag/showIteratorGeneratorTagDemo.jsp + + + /tags/non-ui/iteratorTag/showIteratorGeneratorTagDemo.jsp + /tags/non-ui/iteratorTag/iteratorGeneratorTagDemoResult.jsp + + + + + + + + + + /tags/non-ui/iteratorTag/showAppendIteratorTagDemo.jsp + + + /tag/non-ui/iteratorTag/showAppendIteratorTagDemo.jsp + /tags/non-ui/iteratorTag/appendIteratorTagDemoResult.jsp + + + + + + + + + + /tags/non-ui/iteratorTag/showMergeIteratorTagDemo.jsp + + + /tags/non-ui/iteratorTag/showMergeIteratorTagDemo.jsp + /tags/non-ui/iteratorTag/mergeIteratorTagDemoResult.jsp + + + + + + + + + /tags/non-ui/iteratorTag/subsetIteratorTagDemo.jsp + + + /tags/non-ui/iteratorTag/subsetIteratorTagDemo.jsp + /tags/non-ui/iteratorTag/subsetIteratorTagDemoResult.jsp + + + + + + + + + /tags/non-ui/actionPrefix/actionPrefixExample.ftl + + + /tags/non-ui/actionPrefix/normalSubmit.ftl + + + /tags/non-ui/actionPrefix/methodPrefix.ftl + + + /tags/non-ui/actionPrefix/actionPrefix.ftl + + + /tags/non-ui/actionPrefix/redirectPrefix.ftl + + + /tags/non-ui/actionPrefix/redirectActionPrefix.ftl + + + redirectActionPrefix + + + /tags/non-ui/actionPrefix/actionPrefixExample.ftl + + + + + + + + + /tags/non-ui/ifTag/testIf.jsp + + + /tags/non-ui/ifTag/testIf.ftl + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tags-ui.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tags-ui.xml new file mode 100644 index 000000000..5f9568ee5 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tags-ui.xml @@ -0,0 +1,70 @@ + + + + + + + + example.jsp + example.jsp + + + exampleSubmited.jsp + example.jsp + + + example.vm + example.vm + + + exampleSubmited.vm + example.vm + + + + lotsOfOptiontransferselect.jsp + + + lotsOfOptiontransferselect.jsp + lotsOfOptiontransferselectSubmit.jsp + + + + moreSelects.jsp + + + moreSelects.jsp + moreSelectsSubmit.jsp + + + + + + /tags/ui/treeExampleDynamic.jsp + + + + + + + /tags/ui/componentTagExample.jsp + + + + + + + + + + /tags/ui/staticTreeSelect.jsp + + + /tags/ui/dynamicTreeSelect.jsp + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tags.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tags.xml new file mode 100644 index 000000000..4b5995241 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tags.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tiles.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tiles.xml new file mode 100644 index 000000000..e49a5faad --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-tiles.xml @@ -0,0 +1,31 @@ + + + + + + + + + + showcase.index + showcase.index + + + + showcase.freemarker + + + + showcase.freemarkerLayout + + + + /tiles/layout.jsp + /tiles/layout.jsp + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-token.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-token.xml new file mode 100644 index 000000000..a06098c37 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-token.xml @@ -0,0 +1,63 @@ + + + + + + + example1.jsp + + + + + + doublePost.jsp + transferDone.jsp + + + + + + + example2.jsp + + + + + + doublePost.jsp + transferDone.jsp + + + + + + + example3.jsp + + + + + + doublePost.jsp + transferDone.jsp + + + + + + + example4.ftl + + + + + + doublePost.jsp + transferDone.jsp + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-validation.xml new file mode 100755 index 000000000..3cedcf4aa --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-validation.xml @@ -0,0 +1,124 @@ + + + + + + quiz-basic.jsp + quiz-success.jsp + + + + quiz-client.jsp + quiz-success.jsp + + + + quiz-client-css.jsp + quiz-success.jsp + + + + quiz-ajax.jsp + quiz-success.jsp + + + + + + + + index.jsp + + + + + + + + + /validation/fieldValidatorsExample.jsp + + + + /validation/fieldValidatorsExample.jsp + /validation/successFieldValidatorsExample.jsp + + + + + + + + + + /validation/nonFieldValidatorsExample.jsp + + + + /validation/nonFieldValidatorsExample.jsp + /validation/successNonFieldValidatorsExample.jsp + + + + + + + + + + /validation/visitorValidatorsExample.jsp + + + + /validation/visitorValidatorsExample.jsp + /validation/successVisitorValidatorsExample.jsp + + + + + + + + + + /validation/clientSideValidationExample.jsp + + + + /validation/clientSideValidationExample.jsp + /validation/successClientSideValidationExample.jsp + + + + + + + + + STORE + + + /validation/resubmitApplication.action + /validation/applicationOk.action + + + + RETRIEVE + + /validation/storeErrorsAcrossRequestExample.jsp + + + + RETRIEVE + + /validation/storeErrorsAcrossRequestOk.jsp + + + /validation/storeErrorsAcrossRequestCancel.jsp + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-wait.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-wait.xml new file mode 100644 index 000000000..e39863416 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-wait.xml @@ -0,0 +1,35 @@ + + + + + + + + wait.jsp + complete.jsp + + + + + + 2000 + + wait.jsp + complete.jsp + + + + + + 3000 + 1000 + + wait.jsp + complete.jsp + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-xslt.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-xslt.xml new file mode 100644 index 000000000..916394fc4 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts-xslt.xml @@ -0,0 +1,40 @@ + + + + + + + + + + index.jsp + + + + + info.classpath + + + + + + info + + + + + + + + + + /xslt/environment.xsl + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/resources/struts.xml b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts.xml new file mode 100644 index 000000000..8f1cf527d --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/resources/struts.xml @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + showcase.jsp + + + + viewSource.jsp + + + + /date.jsp + + + + + + + + + /empmanager/listSkills.jsp + + + + /empmanager/editSkill.jsp + + + + + /empmanager/editSkill.jsp + edit.action?skillName=${currentSkill.name} + + + /empmanager/editSkill.jsp + edit.action?skillName=${currentSkill.name} + + + + + + + + /empmanager/listEmployees.jsp + + + + {1} + /empmanager/editEmployee.jsp + execute + + + /empmanager/editEmployee.jsp + edit-${currentEmployee.empId}.action + + + /empmanager/editEmployee.jsp + edit-${currentEmployee.empId}.action + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/applicationContext.xml b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/applicationContext.xml new file mode 100644 index 000000000..cec8c6871 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/applicationContext.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A popular programming language that is used to create the Struts framework + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/decorators.xml b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/decorators.xml new file mode 100644 index 000000000..31936b952 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/decorators.xml @@ -0,0 +1,27 @@ + + + + + + /debug.jsp + /styles/* + /scripts/* + /images/* + /dojo/* + /struts/* + /ajax/AjaxResult* + /AjaxTest.action + /ajax/remoteforms/AjaxRemoteForm.action + /tags/ui/ajax/* + /chat/ajax/* + /hangman/ajax/* + /nodecorate/* + + + + /* + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp new file mode 100644 index 000000000..ca47952ea --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp @@ -0,0 +1,120 @@ + + +<% + response.setHeader("Pragma", "no-cache"); + response.setHeader("Cache-Control", "no-cache"); + response.setDateHeader("Expires", 0); + + // Calculate the view sources url + String sourceUrl = request.getContextPath()+"/viewSource.action"; + com.opensymphony.xwork2.ActionInvocation inv = com.opensymphony.xwork2.ActionContext.getContext().getActionInvocation(); + org.apache.struts2.dispatcher.mapper.ActionMapping mapping = org.apache.struts2.ServletActionContext.getActionMapping(); + if (inv != null) { + com.opensymphony.xwork2.util.location.Location loc = inv.getProxy().getConfig().getLocation(); + sourceUrl += "?config="+(loc != null ? loc.getURI()+":"+loc.getLineNumber() : ""); + sourceUrl += "&className="+inv.getProxy().getConfig().getClassName(); + + if (inv.getResult() != null && inv.getResult() instanceof org.apache.struts2.dispatcher.StrutsResultSupport) { + sourceUrl += "&page="+mapping.getNamespace()+"/"+((org.apache.struts2.dispatcher.StrutsResultSupport)inv.getResult()).getLastFinalLocation(); + } + } else { + sourceUrl += "?page="+request.getServletPath(); + } +%> +<%@taglib prefix="decorator" uri="http://www.opensymphony.com/sitemesh/decorator" %> +<%@taglib prefix="page" uri="http://www.opensymphony.com/sitemesh/page" %> +<%@taglib prefix="s" uri="/struts-tags" %> + + + + <decorator:title default="Struts Showcase"/> + + + + + + + + + + + + + + +
    +
    + +
    + + + +
    +

    + View Sources +

    +
    + +

    + +

    + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/dwr.xml b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/dwr.xml new file mode 100644 index 000000000..99869bf4a --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/dwr.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + ); + ]]> + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/sitemesh-decorator.tld b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/sitemesh-decorator.tld new file mode 100644 index 000000000..18f525c6e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/sitemesh-decorator.tld @@ -0,0 +1,79 @@ + + + + + + 1.0 + 1.1 + SiteMesh Decorator Tags + sitemesh-decorator + + + head + com.opensymphony.module.sitemesh.taglib.decorator.HeadTag + JSP + + + + body + com.opensymphony.module.sitemesh.taglib.decorator.BodyTag + JSP + + + + title + com.opensymphony.module.sitemesh.taglib.decorator.TitleTag + JSP + + default + false + true + + + + + getProperty + com.opensymphony.module.sitemesh.taglib.decorator.PropertyTag + JSP + + property + true + true + + + default + false + true + + + writeEntireProperty + false + true + + + + + usePage + com.opensymphony.module.sitemesh.taglib.decorator.UsePageTag + com.opensymphony.module.sitemesh.taglib.decorator.UsePageTEI + JSP + + id + true + false + + + + + useHtmlPage + com.opensymphony.module.sitemesh.taglib.decorator.UsePageTag + com.opensymphony.module.sitemesh.taglib.decorator.UseHTMLPageTEI + JSP + + id + true + false + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/sitemesh-page.tld b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/sitemesh-page.tld new file mode 100644 index 000000000..797ec5d61 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/sitemesh-page.tld @@ -0,0 +1,95 @@ + + + + + + 1.0 + 1.1 + SiteMesh Page Tags + sitemesh-page + + + applyDecorator + com.opensymphony.module.sitemesh.taglib.page.ApplyDecoratorTag + JSP + + name + false + true + + + page + false + true + + + title + false + true + + + id + false + true + + + contentType + false + true + + + encoding + false + true + + + + + + apply-decorator + com.opensymphony.module.sitemesh.taglib.page.ApplyDecoratorTag + JSP + + name + false + true + + + page + false + true + + + title + false + true + + + id + false + true + + + contentType + false + true + + + encoding + false + true + + + + + param + com.opensymphony.module.sitemesh.taglib.page.ParamTag + JSP + + name + false + true + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/sitemesh.xml b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/sitemesh.xml new file mode 100644 index 000000000..35d70168c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/sitemesh.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/tiles.xml b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/tiles.xml new file mode 100644 index 000000000..38664fed0 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/tiles.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/validation.xml b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/validation.xml new file mode 100644 index 000000000..284975364 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/validation.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + +
    + + + +
    + +
    + +
    diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/web.xml b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..e33323bb4 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,165 @@ + + + + Struts Showcase Application + + + struts-cleanup + org.apache.struts2.dispatcher.ActionContextCleanUp + + + + struts + org.apache.struts2.dispatcher.FilterDispatcher + + actionPackages + org.apache.struts2.showcase.person + + + + + sitemesh + com.opensymphony.module.sitemesh.filter.PageFilter + + + + struts-cleanup + /* + + + + sitemesh + /* + + + + struts + /* + + + + org.springframework.web.context.ContextLoaderListener + + + + + org.apache.myfaces.webapp.StartupServletContextListener + + + + + + org.apache.struts2.tiles.StrutsTilesListener + + + + + + + org.apache.struts2.showcase.chat.ChatSessionListener + + + + + + + dwr + uk.ltd.getahead.dwr.DWRServlet + + debug + true + + + + + + faces + javax.faces.webapp.FacesServlet + 1 + + + JspSupportServlet + org.apache.struts2.views.JspSupportServlet + 1 + + + + + + faces + *.action + + + + dwr + /dwr/* + + + + + + + + + + index.jsp + default.jsp + index.html + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/actionchaining/actionChainingResult.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/actionchaining/actionChainingResult.jsp new file mode 100644 index 000000000..b16511308 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/actionchaining/actionChainingResult.jsp @@ -0,0 +1,14 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + + Showcase - Action Chaining Result + + +

    Action Chaining Result:

    +
    +
    +
    + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/AjaxResult.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/AjaxResult.jsp new file mode 100644 index 000000000..3dc852161 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/AjaxResult.jsp @@ -0,0 +1,12 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +<% + request.setAttribute("decorator", "none"); + response.setHeader("Cache-Control","no-cache"); //HTTP 1.1 + response.setHeader("Pragma","no-cache"); //HTTP 1.0 + response.setDateHeader ("Expires", 0); //prevents caching at the proxy server +%> + +Result: @ +
    + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/AjaxResult2.js b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/AjaxResult2.js new file mode 100644 index 000000000..537c3905d --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/AjaxResult2.js @@ -0,0 +1,2 @@ +alert('This JavaScript currently being evaluated is the result...'); +alert('... of an action executed on the server!'); diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/AjaxResult3.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/AjaxResult3.jsp new file mode 100644 index 000000000..45cb2b0ce --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/AjaxResult3.jsp @@ -0,0 +1,12 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +<% + request.setAttribute("decorator", "none"); + response.setHeader("Cache-Control","no-cache"); //HTTP 1.1 + response.setHeader("Pragma","no-cache"); //HTTP 1.0 + response.setDateHeader ("Expires", 0); //prevents caching at the proxy server +%> + +Result: @ + +The value you entered was:
    diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/JSONList.js b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/JSONList.js new file mode 100644 index 000000000..eee667727 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/JSONList.js @@ -0,0 +1,63 @@ +[ + ["Alabama","AL"], + ["Alaska","AK"], + ["American Samoa","AS"], + ["Arizona","AZ"], + ["Arkansas","AR"], + ["Armed Forces Europe","AE"], + ["Armed Forces Pacific","AP"], + ["Armed Forces the Americas","AA"], + ["California","CA"], + ["Colorado","CO"], + ["Connecticut","CT"], + ["Delaware","DE"], + ["District of Columbia","DC"], + ["Federated States of Micronesia","FM"], + ["Florida","FL"], + ["Georgia","GA"], + ["Guam","GU"], + ["Hawaii","HI"], + ["Idaho","ID"], + ["Illinois","IL"], + ["Indiana","IN"], + ["Iowa","IA"], + ["Kansas","KS"], + ["Kentucky","KY"], + ["Louisiana","LA"], + ["Maine","ME"], + ["Marshall Islands","MH"], + ["Maryland","MD"], + ["Massachusetts","MA"], + ["Michigan","MI"], + ["Minnesota","MN"], + ["Mississippi","MS"], + ["Missouri","MO"], + ["Montana","MT"], + ["Nebraska","NE"], + ["Nevada","NV"], + ["New Hampshire","NH"], + ["New Jersey","NJ"], + ["New Mexico","NM"], + ["New York","NY"], + ["North Carolina","NC"], + ["North Dakota","ND"], + ["Northern Mariana Islands","MP"], + ["Ohio","OH"], + ["Oklahoma","OK"], + ["Oregon","OR"], + ["Pennsylvania","PA"], + ["Puerto Rico","PR"], + ["Rhode Island","RI"], + ["South Carolina","SC"], + ["South Dakota","SD"], + ["Tennessee","TN"], + ["Texas","TX"], + ["Utah","UT"], + ["Vermont","VT"], + ["Virgin Islands, U.S.","VI"], + ["Virginia","VA"], + ["Washington","WA"], + ["West Virginia","WV"], + ["Wisconsin","WI"], + ["Wyoming","WY"] +] diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/autocompleter/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/autocompleter/index.jsp new file mode 100644 index 000000000..b17c2b54b --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/autocompleter/index.jsp @@ -0,0 +1,83 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Ajax Examples + + + + + + + + + + + +Using a JSON list returned from an action (href="/JSONList.action"), without autoComplete (autoComplete="false"), use indicator, search substring (searchType="substring") +
    + + + +
    +
    + +Reload on type (loadOnTextChange="true"), after 3 characters (loadMinimumCout="3", it is "3" by default), without the down arrow button (showDownArrow="false") +
    + + + +
    +
    + +Using a JSON list returned from an action (href="/JSONList.action"), with autoComplete (autoComplete="true") +
    + + +
    +
    + +Using a local list (list="{'apple','banana','grape','pear'}") +
    + + +
    +
    + +Force valid options (forceValidOption="true") +
    + + +
    +
    + +Make dropdown's height to 180px (dropdownHeight="180") +
    + + +
    +
    + +Disabled combobox (disabled="true") +
    + + +
    +
    + + + + +Link two autocompleter elements. When the selected value in 'Autocompleter 1' changes, the available values in 'Autocompleter 2' will change also. +
    +
    +

    Autocompleter 1

    +
    +Autocompleter 2 + +
    +
    + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/commonInclude.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/commonInclude.jsp new file mode 100644 index 000000000..f004910a3 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/commonInclude.jsp @@ -0,0 +1,4 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/footer.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/footer.jsp new file mode 100644 index 000000000..cc9114bac --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/footer.jsp @@ -0,0 +1,8 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + +
    + + + +Back To AJAX Examples  + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/index.jsp new file mode 100644 index 000000000..4434c4b11 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/index.jsp @@ -0,0 +1,23 @@ + +AJAX Examples + + + +

    AJAX Example

    + +

    +Note: The Ajax tags are experimental. These examples have only been tested under FireFox 1.5 and IE 6. +

    + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/options.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/options.ftl new file mode 100644 index 000000000..2e2818b24 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/options.ftl @@ -0,0 +1,5 @@ +[ +<#list options as option> + ["${option}"], + +] \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotebutton/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotebutton/index.jsp new file mode 100644 index 000000000..59b408403 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotebutton/index.jsp @@ -0,0 +1,65 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax Examples + + + + + + + +
    Div 1
    + + + +

    + +A submit button, with an indicator + + + +

    + +A submit button, with "notifyTopics" + + +

    + +Use an image as submit + + +

    + + +

    + +Use a button as submit (custom text) + + + + + +

    + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example1.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example1.jsp new file mode 100644 index 000000000..99ccc84a6 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example1.jsp @@ -0,0 +1,24 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax Examples + + + + + + + + + Initial Content + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example10.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example10.jsp new file mode 100644 index 000000000..09034b7dd --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example10.jsp @@ -0,0 +1,31 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax Examples + + + + + + + + + + Initial Content + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example2.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example2.jsp new file mode 100644 index 000000000..f2c320d8c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example2.jsp @@ -0,0 +1,28 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax Examples + + + + + + + + + + Initial Content + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example3.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example3.jsp new file mode 100644 index 000000000..b5ef77069 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example3.jsp @@ -0,0 +1,27 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax Examples + + + + + + + + +Initial Content + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example4.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example4.jsp new file mode 100644 index 000000000..6b93de8c6 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example4.jsp @@ -0,0 +1,27 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax Examples + + + + + + + +loading now + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example5.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example5.jsp new file mode 100644 index 000000000..75b6e1928 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example5.jsp @@ -0,0 +1,27 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax Examples + + + + + + + +loading now + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example6.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example6.jsp new file mode 100644 index 000000000..3088742bc --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example6.jsp @@ -0,0 +1,24 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax Examples + + + + + +loading now + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example7.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example7.jsp new file mode 100644 index 000000000..356d62c44 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example7.jsp @@ -0,0 +1,27 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax Examples + + + + + + + + +loading now + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example8.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example8.jsp new file mode 100644 index 000000000..37fc6da14 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example8.jsp @@ -0,0 +1,56 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax Examples + + + + + + +
    + + +
    + +

    + + + + + + + + + Initial Content + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example9.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example9.jsp new file mode 100644 index 000000000..3ea37dc99 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/example9.jsp @@ -0,0 +1,56 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax Examples + + + + + + + + + + + + + + + Initial Content + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/index.jsp new file mode 100644 index 000000000..4f0e1995f --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotediv/index.jsp @@ -0,0 +1,55 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + AJAX-based remote DIV tag + <%@ include file="/ajax/commonInclude.jsp" %> + + + + +

    Examples

    + +

    +

      +
    1. + A simple DIV that refreshes only once +
    2. + +
    3. + A simple DIV that uses a custom handler +
    4. + +
    5. + A simple DIV that updates every 2 seconds, with indicator +
    6. + +
    7. + A simple DIV that updates every 5 seconds with loading text and reloading text and delay +
    8. + +
    9. + A simple DIV's that cannot contact the server, with fixed error message +
    10. + + +
    11. + A div that calls the server, and JS in the resulting page is executed +
    12. + +
    13. + A div that will listen to events to refresh and start/stop autoupdate +
    14. + +
    15. + A div that will listen to events to refresh and start/stop autoupdate, publish notifyTopics +
    16. + +
    + + +

    + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/index.jsp new file mode 100644 index 000000000..7e19f48bd --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/index.jsp @@ -0,0 +1,109 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax Examples + + + + + + + + + +Remote form replacing another div:
    + +
    initial content
    + + + + + + + + + +Remote form replacing the forms content:
    + + + + + + + + +Remote form evaluating suplied JS on completion:
    + + + + + + + + +Remote form replacing the forms content after confirming results:
    + + + + + + + + +Remote form replacing the forms content after running a function:
    + + + + + + + + +A form with no remote submit (so should not be ajaxified):
    + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/test1.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/test1.jsp new file mode 100644 index 000000000..f4fba5b27 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/test1.jsp @@ -0,0 +1,18 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + + + + + + Test 1 Form + + + +test2 - before + +test3 - before + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/test2.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/test2.jsp new file mode 100644 index 000000000..7a06ed74a --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/test2.jsp @@ -0,0 +1,6 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Test 2 form + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/test3.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/test3.jsp new file mode 100644 index 000000000..9862ad25b --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remoteforms/test3.jsp @@ -0,0 +1,8 @@ + + + + + +Test 3 Page + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotelink/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotelink/index.jsp new file mode 100644 index 000000000..b4125de65 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/remotelink/index.jsp @@ -0,0 +1,102 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax Examples + + + + + + + +
    Div 1
    + +
    + +
    Div 2
    + +

    + + + + +

    + +Update 'Div 1' and 'Div 2', publish topic '/after', use indicator + + +

    + +Try to update 'Div 1', use custom error message + +

    + +Update 'Div 1', use custom loading message + +

    + +Update 'Div 2' and execute returned javascript + +

    + +Update 'Div 2' using a custom handler + + +

    + + + +
    + +
    + +

    + +Update 'Div 2' with the content of the textbox + + +

    + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example1.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example1.jsp new file mode 100644 index 000000000..ff9a99c9b --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example1.jsp @@ -0,0 +1,115 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax examples - tabbled panel + + + "> + "> + " media="print"> + + + + + + + + + + + + + + + + + +
    + + + This is the first pane
    + +
    + +
    +
    + + This is the second panel + + + This is the three + +
    +
    + + + This is the left pane
    + +
    + +
    +
    + + + middle tab
    + +
    + +
    +
    + +
    +
    + + + + + + + + + + + Outer one
    + + Inner 1 + Inner 2 + Inner 3 + +
    + + Outer two
    + + Inner 21 + Inner 22 + Inner 23 + +
    + + Outer three
    + + Inner 31 + Inner 32 + Inner 33 + +
    +
    +
    + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example2.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example2.jsp new file mode 100644 index 000000000..ab2d7118f --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example2.jsp @@ -0,0 +1,31 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax examples - tabbled panel + + + "> + + + + + + + + + I'm a Tab!!! + + + I'm the other Tab!!! + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example3.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example3.jsp new file mode 100644 index 000000000..5b7a3af3e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example3.jsp @@ -0,0 +1,59 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax examples - tabbled panel + + + "> + "> + " media="print"> + + + + + + + + + + + + +
    + + + + This is the left pane
    + +
    + +
    +
    + + + middle tab
    + +
    + +
    +
    + +
    + +
    + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example4.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example4.jsp new file mode 100644 index 000000000..caaf1ee3f --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example4.jsp @@ -0,0 +1,20 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Example 4 + + " /> + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example5.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example5.jsp new file mode 100644 index 000000000..fde5838a9 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example5.jsp @@ -0,0 +1,31 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax examples - tabbled panel + + + "> + + + + + + + + + I'm a Tab!!! + + + I'm the other Tab!!! + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example5Ok.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example5Ok.jsp new file mode 100644 index 000000000..5c3b801ee --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/example5Ok.jsp @@ -0,0 +1,9 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<%@taglib prefix="s" uri="/struts-tags" %> + +

    OK

    +
    +
    + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/index.jsp new file mode 100644 index 000000000..c3ebf34ad --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/index.jsp @@ -0,0 +1,27 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Tabbed Panes + <%@ include file="/ajax/commonInclude.jsp" %> + + + + +

    Examples

    + +

    +

      +
    1. A local tabbed panel width fixed size (doLayout="true")
    2. +
    3. A remote (href != "") and local tabbed panel
    4. +
    5. Various remote and local tabbed panels (with enclosed tabbed pannels) with layout (doLayout="false")
    6. +
    7. A local tabbed panel width fixed size (doLayout="true") with close button on tabs(closeButton="tab"), and tabs on the right (labelposition="right")
    8. +
    9. A local tabbed panel width fixed size (doLayout="true") with close button on the tab pane (closeButton="pane"), and tabs on the bottom (labelposition="bottom")
    10. +
    + + +

    + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel1.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel1.ftl new file mode 100644 index 000000000..601c06058 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel1.ftl @@ -0,0 +1,3 @@ + +Hello,
    +Today is ${todayDate}, the time now is ${todayTime} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel2.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel2.ftl new file mode 100644 index 000000000..b027ee088 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel2.ftl @@ -0,0 +1,7 @@ + +
    +
    +<@s.form action="panel2Submit" namespace="/nodecorate" theme="ajax"> + <@s.textfield label="Name" name="name" theme="ajax" /> + <@s.submit theme="ajax" resultDivId="result" /> + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel2Submit.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel2Submit.ftl new file mode 100644 index 000000000..34e4e0d15 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel2Submit.ftl @@ -0,0 +1,2 @@ + +Hello, ${name} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel3.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel3.ftl new file mode 100644 index 000000000..1d0a374b4 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel3.ftl @@ -0,0 +1,9 @@ + +
    +
    + +<@s.form action="panel3Submit" namespace="/nodecorate" theme="ajax"> + <@s.select label="Gender" name="gender" list=r"%{#{'Male':'Male','Female':'Female'}}" theme="ajax" /> + <@s.submit theme="ajax" resultDivId="result" /> + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel3Submit.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel3Submit.ftl new file mode 100644 index 000000000..ee436e125 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tabbedpanel/nodecorate/panel3Submit.ftl @@ -0,0 +1,2 @@ + +So, you are a ${gender} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/testjs.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/testjs.jsp new file mode 100644 index 000000000..5223ef707 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/testjs.jsp @@ -0,0 +1,14 @@ +<% + request.setAttribute("decorator", "none"); + response.setHeader("Cache-Control","no-cache"); //HTTP 1.1 + response.setHeader("Pragma","no-cache"); //HTTP 1.0 + response.setDateHeader ("Expires", 0); //prevents caching at the proxy server +%> + + +Show me some text also + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/getCategory.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/getCategory.jsp new file mode 100644 index 000000000..d9e6934c3 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/getCategory.jsp @@ -0,0 +1,24 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> +<%@include file="partialChunkHeader.jsp"%> +
      + +
    • + + + + + +
    • + + + + + + › + + +
      +
    \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/partialChunkHeader.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/partialChunkHeader.jsp new file mode 100644 index 000000000..01113d688 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/partialChunkHeader.jsp @@ -0,0 +1,6 @@ +<% + request.setAttribute("decorator", "none"); + response.setHeader("Cache-Control","no-cache"); //HTTP 1.1 + response.setHeader("Pragma","no-cache"); //HTTP 1.0 + response.setDateHeader ("Expires", 0); //prevents caching at the proxy server +%> diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/toggle.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/toggle.jsp new file mode 100644 index 000000000..35010bb5e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/toggle.jsp @@ -0,0 +1,12 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> +<%@include file="partialChunkHeader.jsp"%> +<% + response.setContentType("text/javascript"); +%> +dojo.event.topic.publish("children_"); +var d = document.getElementById("children_"); +if (d.style.display != "none") { + d.style.display = "none"; +} else { + d.style.display = ""; +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/tree.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/tree.jsp new file mode 100644 index 000000000..6d8e18c34 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/tree/tree.jsp @@ -0,0 +1,13 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Tree + + + + + + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/widgets/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/widgets/index.jsp new file mode 100644 index 000000000..ef8382ffa --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/ajax/widgets/index.jsp @@ -0,0 +1,39 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Ajax Widgets + + + + + +
    +NOTES: +
      +
    • Make sure that there is a 'value' attribute in the textarea with the content for the editor
    • +
    • This is experimental
    • +
    + + +Default Editor configuration:
    + + + + +
    + +Configured Editor configuration:
    + + + textGroup;|;justifyGroup;|;listGroup;|;indentGroup + + + +
    + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/chatLogin.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/chatLogin.ftl new file mode 100644 index 000000000..1dfa3ca8c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/chatLogin.ftl @@ -0,0 +1,16 @@ + + + + Showcase - Chat - Login + <@s.head theme="ajax" /> + + + <@s.actionerror /> + <@s.actionmessage /> + <@s.fielderror /> + <@s.form action="login" namespace="/chat" method="POST"> + <@s.textfield name="name" label="Name" required="true" /> + <@s.submit/> + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/createRoom.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/createRoom.ftl new file mode 100644 index 000000000..fbe71cc91 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/createRoom.ftl @@ -0,0 +1,2 @@ +<@s.actionerror /> +<@s.fielderror /> diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/index.jsp new file mode 100644 index 000000000..b58d7a302 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/index.jsp @@ -0,0 +1,3 @@ + +<% response.sendRedirect("main.action"); %> + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/messagesAvailableInRoom.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/messagesAvailableInRoom.ftl new file mode 100644 index 000000000..2550dcd2d --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/messagesAvailableInRoom.ftl @@ -0,0 +1,33 @@ + + + + + + + +<@s.iterator id="message" value="%{messagesAvailableInRoom}" status="stat"> + + <#if stat.odd> + + <#if stat.odd> + + <#if stat.odd> + + + +
    SenderDateMessage
    + <#else> + + + <@s.property value="%{#message.creator.name}" /> + + <#else> + + + <@s.property value="%{#message.creationDate}" /> + + <#else> + + + <@s.property value="%{#message.message}" /> +
    diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/roomSelection.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/roomSelection.ftl new file mode 100644 index 000000000..595595978 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/roomSelection.ftl @@ -0,0 +1,165 @@ + + + + + Showcase - Chat - Room Selection + <@s.head theme="ajax" /> + + + +
    + + +
    +
    +

    Operations

    + <@s.url id="url" action="logout" namespace="/chat" /> +
      +
    • <@s.a href="%{#url}">Logout
    • +
    +
    + <#if (actionErrors?size gt 0)> +
    +

    Action Errors

    + <@s.actionerrors /> +
    + +
    +

    Users Available In Chat

    + <@s.url id="usersAvailableUrl" action="usersAvailable" namespace="/chat/ajax" /> + <@s.div id="usersAvailable" delay="1" updateFreq="%{@org.apache.struts2.showcase.chat.Constants@UPDATE_FREQ}" + theme="ajax" href="%{usersAvailableUrl}" + class="box"> + Initial Loading Users ... + +
    +
    + + +
    +
    +

    Rooms Available In Chat

    + <@s.url id="roomsAvailableUrl" action="roomsAvailable" namespace="/chat/ajax" /> + <@s.div id="roomsAvailable" listenTopics="topicRoomCreated" + delay="1" updateFreq="%{@org.apache.struts2.showcase.chat.Constants@UPDATE_FREQ}" + theme="ajax" href="%{roomsAvailableUrl}" > + Initial Loading Rooms ... + +
    + +
    +

    Create Room In Chat

    +
    + <@s.form id="createRoomId" action="createRoom" namespace="/chat/ajax" method="POST" theme="ajax"> + <@s.textfield label="Room Name" required="true" name="name" /> + <@s.textarea theme="xhtml" label="Room Description" required="true" name="Description" /> + <@s.submit value="%{'Create Room'}" resultDivId="createRoomResult" notifyTopics="topicRoomCreated" theme="ajax" align="left" /> + +
    +
    + +
    + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/roomsAvailable.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/roomsAvailable.ftl new file mode 100644 index 000000000..1d343c00e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/roomsAvailable.ftl @@ -0,0 +1,44 @@ + + + + + + + + +<@s.iterator id="room" value="%{availableRooms}" status="stat"> + + <#if stat.isOdd()> + + <#if stat.odd> + + <#if stat.odd> + + <#if stat.odd> + + + +
    OperationNameDescriptionDate Created
    + <#else> + + + <@s.url id="url" action="enterRoom" namespace="/chat"> + <@s.param name="roomName" value="%{#room.name}" /> + + <@s.a href="%{url}">Enter + + <#else> + + + <@s.property value="%{#room.name}" /> + + <#else> + + + <@s.property value="%{#room.description}" /> + + <#else> + + + <@s.property value="%{#room.creationDate}" /> +
    diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/sendMessageToRoomResult.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/sendMessageToRoomResult.ftl new file mode 100644 index 000000000..c75d32bca --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/sendMessageToRoomResult.ftl @@ -0,0 +1,2 @@ + +<@s.fielderror /> diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/showRoom.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/showRoom.ftl new file mode 100644 index 000000000..759fab89e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/showRoom.ftl @@ -0,0 +1,161 @@ + + + + Showcase - Chat - Show Room + <@s.head theme="ajax" /> + + + +
    +
    +
    +

    Operation

    + <@s.url id="url" action="exitRoom" namespace="/chat"> + <@s.param name="roomName" value="%{roomName}" /> + +
      +
    • <@s.a href="%{#url}">Exit Room
    • +
    +
    +
    +

    Users Available In Chat

    + <@s.url id="usersAvailableUrl" action="usersAvailable" namespace="/chat/ajax" /> + <@s.div id="usersAvailable" href="%{usersAvailableUrl}" + theme="ajax" delay="1" updateFreq="%{@org.apache.struts2.showcase.chat.Constants@UPDATE_FREQ}"> + Initial Users Available ... + +
    +
    + +
    +
    +

    Messages Posted In Room [${roomName?default('')}]

    + <@s.url id="url" value="/chat/ajax/messagesAvailableInRoom.action" includeContext="true"> + <@s.param name="roomName" value="%{roomName}" /> + + <@s.div id="messagesInRoom" href="%{#url}" includeContext="true" + theme="ajax" delay="1" updateFreq="%{@org.apache.struts2.showcase.chat.Constants@UPDATE_FREQ}" + listenTopics="topicMessageSend"> + Initial Messages In Room ... + +
    + +
    +

    Send Messages

    + <@s.form id="sendMessageForm" action="sendMessageToRoom" namespace="/chat/ajax" method="POST" theme="ajax"> +
    + <@s.textarea label="Message"name="message" theme="xhtml" /> + <@s.hidden name="roomName" value="%{roomName}" /> + <@s.submit id="submit" theme="ajax" resultDivId="sendMessageResult" notifyTopics="topicMessageSend" value="%{'Send'}" /> + +
    +
    + + +
    +
    +

    Users Available In Room [${roomName?default('')}]

    + <@s.url id="url" value="/chat/ajax/usersAvailableInRoom.action" includeContext="true"> + <@s.param name="roomName" value="%{roomName}" /> + + <@s.div id="usersAvailableInRoom" href="%{#url}" includeContext="true" + theme="ajax" delay="1" updateFreq="%{@org.apache.struts2.showcase.chat.Constants@UPDATE_FREQ}"> + Initial Users Available In Room ... + +
    +
    + + +
    + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/usersAvailable.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/usersAvailable.ftl new file mode 100644 index 000000000..e03fa37d0 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/usersAvailable.ftl @@ -0,0 +1,6 @@ + +
      +<#list availableUsers as user> +
    • ${user.name}
    • + +
    diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/usersAvailableInRoom.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/usersAvailableInRoom.ftl new file mode 100644 index 000000000..95822bf7a --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/chat/usersAvailableInRoom.ftl @@ -0,0 +1,8 @@ + +
      +<@s.iterator id="member" value="%{usersAvailableInRoom}"> +
    • <@s.property value="%{#member.name}" />
    • + +
    + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/Address.java.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/Address.java.txt new file mode 100644 index 000000000..bf501834e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/Address.java.txt @@ -0,0 +1,35 @@ +/* + * $Id: Person.java 440597 2006-09-06 03:34:39Z tmjee $ + * + * Copyright 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. + */ +package org.apache.struts2.showcase.conversion; + + +/** + * @version $Date$ $Id$ + */ +public class Address { + + private String id; + private String address; + + public String getId() { return id; } + public void setId(String id) { this.id = id; } + + public String getAddress() { return address; } + public void setAddress(String address) { this.address = address; } + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/AddressAction.java.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/AddressAction.java.txt new file mode 100644 index 000000000..35f17f5fd --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/AddressAction.java.txt @@ -0,0 +1,44 @@ +/* + * $Id: Person.java 440597 2006-09-06 03:34:39Z tmjee $ + * + * Copyright 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. + */ +package org.apache.struts2.showcase.conversion; + +import java.util.LinkedHashSet; +import java.util.Set; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * @version $Date$ $Id$ + */ +public class AddressAction extends ActionSupport { + + private Set addresses = new LinkedHashSet(); + + public Set getAddresses() { return addresses; } + public void setAddresses(Set addresses) { this.addresses = addresses; } + + + public String input() throws Exception { + return SUCCESS; + } + + public String submit() throws Exception { + System.out.println(addresses); + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/EnumTypeConverter.java.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/EnumTypeConverter.java.txt new file mode 100644 index 000000000..0a1b1aa38 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/EnumTypeConverter.java.txt @@ -0,0 +1,55 @@ +/* + * $Id: Person.java 440597 2006-09-06 03:34:39Z tmjee $ + * + * Copyright 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. + */ +package org.apache.struts2.showcase.conversion; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.struts2.util.StrutsTypeConverter; + +/** + * @version $Date$ $Id$ + */ +public class EnumTypeConverter extends StrutsTypeConverter { + + @Override + public Object convertFromString(Map context, String[] values, Class toClass) { + List result = new ArrayList(); + for (int a=0; a< values.length; a++) { + Enum e = Enum.valueOf(OperationsEnum.class, values[a]); + if (e != null) + result.add(e); + } + return result; + } + + @Override + public String convertToString(Map context, Object o) { + List l = (List) o; + String result ="<"; + for (Iterator i = l.iterator(); i.hasNext(); ) { + result = result + "["+ i.next() +"]"; + } + result = result+">"; + return result; + } + + +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnum.java.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnum.java.txt new file mode 100644 index 000000000..2db119448 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnum.java.txt @@ -0,0 +1,30 @@ +/* + * $Id: Person.java 440597 2006-09-06 03:34:39Z tmjee $ + * + * Copyright 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. + */ +package org.apache.struts2.showcase.conversion; + +/** + * + * @version $Date$ $Id$ + */ +public enum OperationsEnum { + ADD, + MINUS, + DIVIDE, + MULTIPLY, + REMAINDER; +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnumAction.java.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnumAction.java.txt new file mode 100644 index 000000000..ee2327ff3 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnumAction.java.txt @@ -0,0 +1,53 @@ +/* + * $Id: Person.java 440597 2006-09-06 03:34:39Z tmjee $ + * + * Copyright 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. + */ +package org.apache.struts2.showcase.conversion; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * + * @version $Date$ $Id$ + */ +public class OperationsEnumAction extends ActionSupport { + + private static final long serialVersionUID = -2229489704988870318L; + + private List selectedOperations = new LinkedList(); + + public List getSelectedOperations() { return this.selectedOperations; } + public void setSelectedOperations(List selectedOperations) { + this.selectedOperations = selectedOperations; + } + + + public List getAvailableOperations() { + return Arrays.asList(OperationsEnum.values()); + } + + public String input() throws Exception { + return SUCCESS; + } + public String submit() throws Exception { + return SUCCESS; + } +} + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnumActionConversion.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnumActionConversion.txt new file mode 100644 index 000000000..621beafba --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/OperationsEnumActionConversion.txt @@ -0,0 +1,4 @@ + +selectedOperations=org.apache.struts2.showcase.conversion.EnumTypeConverter +Element_selectedOperations=org.apache.struts2.showcase.conversion.OperationsEnum + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/Person.java.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/Person.java.txt new file mode 100644 index 000000000..2ce9e0fdb --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/Person.java.txt @@ -0,0 +1,34 @@ +/* + * $Id: AbstractDao.java 394498 2006-04-16 15:28:06Z tmjee $ + * + * Copyright 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. + */ +package org.apache.struts2.showcase.conversion; + +import java.io.Serializable; + +/** + * + */ +public class Person implements Serializable { + private String name; + private Integer age; + + public void setName(String name) { this.name = name; } + public String getName() { return this.name; } + + public void setAge(Integer age) { this.age = age; } + public Integer getAge() { return this.age; } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/PersonAction.java.txt b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/PersonAction.java.txt new file mode 100644 index 000000000..015fab018 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/PersonAction.java.txt @@ -0,0 +1,43 @@ +/* + * $Id: AbstractDao.java 394498 2006-04-16 15:28:06Z tmjee $ + * + * Copyright 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. + */ +package org.apache.struts2.showcase.conversion; + +import java.util.List; + +import com.opensymphony.xwork2.ActionSupport; + +/** + * + */ +public class PersonAction extends ActionSupport { + + private List persons; + + public List getPersons() { return persons; } + public void setPersons(List persons) { this.persons = persons; } + + + + public String input() throws Exception { + return SUCCESS; + } + + public String submit() throws Exception { + return SUCCESS; + } +} diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterAddressInfo.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterAddressInfo.jsp new file mode 100644 index 000000000..2d028a869 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterAddressInfo.jsp @@ -0,0 +1,48 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<%@taglib prefix="s" uri="/struts-tags" %> + + + + +Showcase - Conversion - Set + + + +

    +An example populating a Set of object (Address.java) into Struts' action (AddressAction.java) + +

    + +See the jsp code here.
    +See the code for PersonAction.java here.
    +See the code for Person.java here.
    + +

    + + + + + + + + + <%-- + The following is how its done statically + --%> + <%-- + + + + + + + --%> + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterOperations.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterOperations.jsp new file mode 100644 index 000000000..c01d6489b --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterOperations.jsp @@ -0,0 +1,31 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<%@taglib prefix="s" uri="/struts-tags" %> + + + + +Showcase - Conversion - Tiger 5 Enum + + + +See the jsp code here.
    +See the code for OperationsEnum.java here.
    +See the code for OperationsEnumAction.java here.
    +See the code for EnumTypeConverter.java here.
    +See the properties for OperationsEnumAction-conversion.properties here. +
    +
    + + + + + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterPersonInfo.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterPersonInfo.jsp new file mode 100644 index 000000000..8e9c54166 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/enterPersonInfo.jsp @@ -0,0 +1,58 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Conversion - Populate Object into Struts' action List + + + +

    +An example populating a list of object (Person.java) into Struts' action (PersonAction.java) + +

    + +See the jsp code here.
    +See the code for PersonAction.java here.
    +See the code for Person.java here.
    + +

    + + + + + + <%-- + The following is done Dynamically + --%> + + + + + + + + <%-- + The following is done statically:- + --%> + <%-- + + + + + + + --%> + + + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/index.jsp new file mode 100644 index 000000000..69f17c460 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/index.jsp @@ -0,0 +1,26 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + + +Showcase - Conversion + + + +

      +
    • + + Populate into the Struts action class a List of Person.java Object +
    • +
    • + + Populate into Struts action class a Set of Address.java Object +
    • +
    • + + Populate into Struts action class a List of OperationEnum.java (Java5 Enum) +
    • +
    + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showAddressInfo.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showAddressInfo.jsp new file mode 100644 index 000000000..2f1d4e346 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showAddressInfo.jsp @@ -0,0 +1,15 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<%@taglib prefix="s" uri="/struts-tags" %> + + + + +Showcase - Conversion - Set + + + + ->
    +
    + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showOperations.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showOperations.jsp new file mode 100644 index 000000000..c4b885903 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showOperations.jsp @@ -0,0 +1,17 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<%@taglib prefix="s" uri="/struts-tags" %> + + + + +Showcase - Conversion - Tiger 5 Enum + + + + +
    +
    + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showPersonInfo.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showPersonInfo.jsp new file mode 100644 index 000000000..b0b10e1b1 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/conversion/showPersonInfo.jsp @@ -0,0 +1,17 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + + +Showcase - Conversion - Populate Object into Struts action List + + + + +
    +
    +
    + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/customTemplateDir/customTheme/ftlCustomTemplate.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/customTemplateDir/customTheme/ftlCustomTemplate.ftl new file mode 100644 index 000000000..415233443 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/customTemplateDir/customTheme/ftlCustomTemplate.ftl @@ -0,0 +1,7 @@ +
    +

    +Freemarker Custom Template - +parameter 'paramName' - ${parameters.paramName} +

    +
    + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/customTemplateDir/customTheme/jspCustomTemplate.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/customTemplateDir/customTheme/jspCustomTemplate.jsp new file mode 100644 index 000000000..311c32987 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/customTemplateDir/customTheme/jspCustomTemplate.jsp @@ -0,0 +1,8 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + +
    +

    +JSP Custom Template - +parameter 'paramName' - +

    +
    diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/date.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/date.jsp new file mode 100644 index 000000000..400cd6d24 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/date.jsp @@ -0,0 +1,2 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/editEmployee.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/editEmployee.jsp new file mode 100644 index 000000000..a47b9cb67 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/editEmployee.jsp @@ -0,0 +1,41 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + + + + + + + + <s:property value="#title"/> + + + + +

    + + + + + + + + + + + + + + + + + + +

    ">

    + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/editSkill.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/editSkill.jsp new file mode 100644 index 000000000..a5544b0ca --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/editSkill.jsp @@ -0,0 +1,27 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + + + + + + + + +<s:property value="#title"/> + + +

    + + + + + <%--s:submit name="%{#submitType}" value="%{getText('save')}" /--%> + + +

    ">

    + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/index.jsp new file mode 100644 index 000000000..b128df60c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/index.jsp @@ -0,0 +1,21 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - CRUD + + +

    CRUD

    + +

    +

      +
    • List available Skills
    • +
    • Create/Edit Skill
    • +
    • List available Employees
    • +
    • Create/Edit Employee
    • +
    +

    + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/listEmployees.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/listEmployees.jsp new file mode 100644 index 000000000..356bd0af4 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/listEmployees.jsp @@ -0,0 +1,26 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + +Available Employees + + +

    Available Employees

    + + + + + + + + + + + + + +
    IdFirst NameLast Name
    ">
    +

    ">Create new Employee

    +

    ">Back to Showcase Startpage

    + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/listSkills.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/listSkills.jsp new file mode 100644 index 000000000..3b1f77965 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/empmanager/listSkills.jsp @@ -0,0 +1,24 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + +Available Skills + + +

    Available Skills

    + + + + + + + + + + +
    NameDescription
    ">
    + +

    ">Create new Skill

    +

    ">Back to Showcase Startpage

    + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/filedownload/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/filedownload/index.jsp new file mode 100644 index 000000000..38d002c6c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/filedownload/index.jsp @@ -0,0 +1,23 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Showcase - Fileupload + + + +

    File Download Example

    + +
      +
    • + Download image file. + The browser should display the Struts logo. +
    • +
    • + Download ZIP file. + The browser should prompt for a location to save the ZIP file. +
    • +
    + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/index.jsp new file mode 100644 index 000000000..a1537c02e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/index.jsp @@ -0,0 +1,25 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + +Showcase - Fileupload + + + +
      +
    • + + Single File Upload +
    • +
    • + + Multiple File Upload (List) + +
    • +
    • + + Multiple File Upload (Array) +
    • +
    + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingArray-success.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingArray-success.jsp new file mode 100644 index 000000000..74fc4869f --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingArray-success.jsp @@ -0,0 +1,37 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + +Insert title here + + + + + + + + + + +
    File
    + + + + + + + + + +
    File Name
    + + + + + + + + +
    Content Type
    + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingArray.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingArray.jsp new file mode 100644 index 000000000..7fac4c744 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingArray.jsp @@ -0,0 +1,20 @@ +<%@ page + language="java" + contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<%@ taglib prefix="s" uri="/struts-tags" %> + + +Showcase - fileupload - multiple fileupload using List + + + + + + + + + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingList-success.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingList-success.jsp new file mode 100644 index 000000000..74fc4869f --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingList-success.jsp @@ -0,0 +1,37 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + +Insert title here + + + + + + + + + + +
    File
    + + + + + + + + + +
    File Name
    + + + + + + + + +
    Content Type
    + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingList.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingList.jsp new file mode 100644 index 000000000..ada475878 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/multipleUploadUsingList.jsp @@ -0,0 +1,20 @@ +<%@ page + language="java" + contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<%@ taglib prefix="s" uri="/struts-tags" %> + + +Showcase - fileupload - multiple fileupload using List + + + + + + + + + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/upload-success.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/upload-success.jsp new file mode 100644 index 000000000..15029cb54 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/upload-success.jsp @@ -0,0 +1,25 @@ +<%@ page + language="java" + contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Showcase + + + +

    Fileupload sample

    + +

    +

      +
    • ContentType:
    • +
    • FileName:
    • +
    • File:
    • +
    • Caption:
    • +
    +

    + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/upload.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/upload.jsp new file mode 100644 index 000000000..04150d2cf --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/fileupload/upload.jsp @@ -0,0 +1,23 @@ +<%@ page + language="java" + contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Showcase + + + +

    Fileupload sample

    + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/customFreemarkerManagerUsage.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/customFreemarkerManagerUsage.ftl new file mode 100644 index 000000000..23f2b5963 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/customFreemarkerManagerUsage.ftl @@ -0,0 +1,26 @@ + + + + Showcase - Freemarker - CustomFreemarkerManager Usage + + +

    Custom Freemarker Manager Usage

    + +

    + This page shows a simple example of using a custom freemarker manager. + The custom freemarker manager put into freemarker model an util classed + under the name 'customFreemarkerManagerUtil'. so one could use +

    +

      +
    • $ { customFreemarkerManagerUtil.getTodayDate() } - to get today's date
    • +
    • $ { customFreemarkerManagerUtil.todayDate } - to get today's date
    • +
    • $ { customFreemarkerManagerUtil.getTimeNow() } - to get the time now
    • +
    • $ { customFreemarkerManagerUtil.timeNow } - to get the time now
    • +
    + + Today's Date = ${customFreemarkerManagerUtil.todayDate}
    + Time now = ${customFreemarkerManagerUtil.getTimeNow()}
    + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/index.jsp new file mode 100644 index 000000000..10b9932e7 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/index.jsp @@ -0,0 +1,23 @@ + +<%@taglib prefix="s" uri="/struts-tags" %> + + + + Showcase - Freemarker + + + +
      +
    • + + Demo of usage of a Custom Freemarker Manager +

      + + Demo of Standard Struts Freemarker Tags +

    • +
    + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/standardTags.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/standardTags.ftl new file mode 100644 index 000000000..1afc40913 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/freemarker/standardTags.ftl @@ -0,0 +1,4 @@ +<@s.form action="test"> + <@s.textfield label="Name" name="name"/> + <@s.select label="Birth Month" headerValue="Select Month" list="months" /> + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/blank.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/blank.ftl new file mode 100644 index 000000000..e69de29bb diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/hangmanAjax.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/hangmanAjax.ftl new file mode 100644 index 000000000..379a2babf --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/hangmanAjax.ftl @@ -0,0 +1,241 @@ + + + + Showcase - Hangman + <@s.head theme="ajax" debug="false" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + <@s.url id="url" value="/hangman/images/hangman.png" /> + Hangman" + width="197" height="50" border="0"/> + + <#-- Guesses Left --> +
    + <@s.set name="guessLeftImageName" value="%{'Chalkboard_'+hangman.guessLeft()+'.png'}" /> + <@s.url id="url" value="%{'/hangman/images/'+#guessLeftImageName}" /> + No. Guesses Left" width="20" height="20" border="0" /> +
    +
    + <@s.url id="url" value="/hangman/images/guesses-left.png" /> + Guesses Left" width="164" height="11" border="0"/> +
    + <#-- Display Scaffold --> +
    + <@s.set name="scaffoldImageName" value="%{'scaffold_'+hangman.guessLeft()+'.png'}" /> + <@s.url id="url" value="%{'/hangman/images/'+#scaffoldImageName}" /> + " border="0"/> +
    +
    +

    + <@s.url id="url" value="/hangman/images/guess.png" /> + Current Guess" + align="MIDDLE" width="127" height="20" border="0"/>

    +
    + <#-- Display Vacab --> +
    + <@s.iterator id="currentCharacter" value="%{hangman.vocab.inCharacters()}" stat="stat"> + <#if hangman.characterGuessedBefore(currentCharacter)> + <@s.set name="chalkboardImageName" value="%{'Chalkboard_'+#currentCharacter.toString()+'.png'}" /> + <@s.url id="url" value="%{'/hangman/images/'+#chalkboardImageName}" /> + <@s.property value=" + src="<@s.property value="%{#url}" />" width="36" border="0"/> + <#else> + <@s.url id="url" value="/hangman/images/Chalkboard_underscroll.png" /> + _" width="36" border="0"/> + + +
    +
    +

    + <@s.url id="url" value="/hangman/images/choose.png" /> + Choose" + height="20" width="151" border="0"/> +

    +
    + + <#-- Show Characters Available --> +
    + <@s.iterator id="currentCharacter" value="%{hangman.charactersAvailable}" status="stat"> + <@s.set name="chalkboardImageName" value="%{'Chalkboard_'+#currentCharacter+'.png'}" /> + <@s.url id="chalkboardImageUrl" value="%{'/hangman/images/'+#chalkboardImageName}" /> + <@s.url id="spacerUrl" value="/hangman/images/letter-spacer.png" /> + + <@s.url id="blankUrl" value="ajax/blank.action" includeContext="false" /> + <@s.a theme="ajax" + href="%{blankUrl}" + id="%{#currentCharacter}" + notifyTopics="topicGuessMade" + showErrorTransportText="true"> + " width="36" border="0" /> + + +
    + + +
    + +
    + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/hangmanMenu.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/hangmanMenu.ftl new file mode 100644 index 000000000..717339e57 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/hangmanMenu.ftl @@ -0,0 +1,18 @@ + + + + Showcase - Hangman - Menu + + +
      +
    • + <@s.url id="url" action="hangmanNonAjax" namespace="/hangman" /> + <@s.a href="%{#url}">Hangman (Non Ajax) +
    • +
    • + <@s.url id="url" action="hangmanAjax" namespace="/hangman" /> + <@s.a href="%{#url}">Hangman (Ajax - Experimental) +
    • +
    + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/hangmanNonAjax.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/hangmanNonAjax.ftl new file mode 100644 index 000000000..73419f17f --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/hangmanNonAjax.ftl @@ -0,0 +1,135 @@ + + + Showcase - Hangman + <@s.head theme="xhtml" /> + + + + + + + + + + + + + + + + + + + + + + + + +
    + <@s.url id="url" value="/hangman/images/hangman.png" /> + Hangman" + width="197" height="50" border="0"/> + + <#-- Guesses Left --> +
    + <#if (hangman.guessLeft() >= 0)> + <@s.set name="guessLeftImageName" value="%{'Chalkboard_'+hangman.guessLeft()+'.png'}" /> + <@s.url id="url" value="%{'/hangman/images/'+#guessLeftImageName}" /> + No. Guesses Left" width="20" height="20" border="0" /> + +
    +
    + <@s.url id="url" value="/hangman/images/guesses-left.png" /> + Guesses Left" width="164" height="11" border="0"/> +
    + <#-- Display Scaffold --> +
    + <@s.set name="scaffoldImageName" value="%{'scaffold_'+hangman.guessLeft()+'.png'}" /> + <@s.url id="url" value="%{'/hangman/images/'+#scaffoldImageName}" /> + " border="0"/> +
    +
    +

    + <@s.url id="url" value="/hangman/images/guess.png" /> + Current Guess" + align="MIDDLE" width="127" height="20" border="0"/>

    +
    + <#-- Display Vacab --> +
    + <#if hangman.gameEnded()> + <@s.iterator id="currentCharacter" value="%{hangman.vocab.inCharacters()}" stat="stat"> + <@s.url id="url" value="%{'/hangman/images/Chalkboard_'+#currentCharacter.toString()+'.png'}" /> + <@s.property value=" + src="<@s.property value="%{#url}" />" width="36" border="0" /> + + <#else> + <@s.iterator id="currentCharacter" value="%{hangman.vocab.inCharacters()}" stat="stat"> + <#if hangman.characterGuessedBefore(currentCharacter)> + <@s.set name="chalkboardImageName" value="%{'Chalkboard_'+#currentCharacter.toString()+'.png'}" /> + <@s.url id="url" value="%{'/hangman/images/'+#chalkboardImageName}" /> + <@s.property value=" + src="<@s.property value="%{#url}" />" width="36" border="0"/> + <#else> + <@s.url id="url" value="/hangman/images/Chalkboard_underscroll.png" /> + _" width="36" border="0"/> + + + +
    +
    +

    + <@s.url id="url" value="/hangman/images/choose.png" /> + Choose" + height="20" width="151" border="0"/> +

    +
    + + <#-- Show Characters Available --> +
    + <#if hangman.gameEnded()> + <@s.set name="winImageName" value="%{'you-win.png'}" /> + <@s.set name="looseImageName" value="%{'you-lose.png'}" /> + <@s.set name="startImageName" value="%{'start.png'}" /> + <@s.url id="winImageUrl" value="%{'/hangman/images/'+#winImageName}" /> + <@s.url id="looseImageUrl" value="%{'/hangman/images/'+#looseImageName}" /> + <@s.url id="startImageUrl" value="%{'/hangman/images/'+#startImageName}" /> + <@s.url id="startHref" action="hangmanNonAjax" namespace="/hangman" /> + + <#if hangman.isWin()> + " width="341" height="44" /> + <#else> + " width="381" height="44" /> + + <@s.a href="%{#startHref}"> + " width="250" height="43" /> + + <#else> + <@s.iterator id="currentCharacter" value="%{hangman.charactersAvailable}" status="stat"> + <@s.set name="chalkboardImageName" value="%{'Chalkboard_'+#currentCharacter+'.png'}" /> + <@s.url id="chalkboardImageUrl" value="%{'/hangman/images/'+#chalkboardImageName}" /> + <@s.url id="spacerUrl" value="/hangman/images/letter-spacer.png" /> + <@s.url id="url" action="guessCharacterNonAjax" namespace="/hangman"> + <@s.param name="character" value="%{#currentCharacter}" /> + + + <@s.a href="%{#url}" + id="%{#currentCharacter}" + > + " width="36" border="0" /> + + + +
    + + +
    + +
    + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_0.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_0.png new file mode 100644 index 0000000000000000000000000000000000000000..7485012ddb6ae76bbb31d3a109bd9073a6b6b23e GIT binary patch literal 1307 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 literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_5.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_5.png new file mode 100644 index 0000000000000000000000000000000000000000..2fec709cdf1d8ff14825c8707bc6365eff86163e GIT binary patch literal 1260 zcmc(e{Yw>A7{{NBieBp?Wgv|T0vD`eW@qALN@&;St?r$9?+?`vqxEvK3A0Sfl90x* zSJt(lbtr2_udWwLY*Y?{+1lMsQO!j~v|b>Lh>R>+1*ebaKiE$@aPQ@L`##_A_t8z& zvCl)G(LEagNyF;1)#=b@E=#3;QKiH4q5$|z-(a(*$f*2-vQ zwQ`;ZWo?u(${OW7ExNT;#wu%-^DG(GP8p}HQ_hn{1gxP6FNm<2RbT_gH0{($@Ql`0 zYv&cRnAjL?jdorzJSZEht<}!!hZfz&Y3sD}cHkEF;0Fev7>Q^?1gxP6FNm-iXs`ie zns(|Wc-9!_twbS^gv%36 zw||MJ+IpvCHO`E+=A{O=EPiuvan;gfa!Kl^6;Bt{nTflXb(hRvzUS}ncO;wEzUVG{ z@}z%5!!8HAn9}r)=CrQ;bv@C|8J*92 zZqycsTTUPQbZcL*vn)AS+Y&r^>sdzk>)z%OEy4SvDgtN6pBXnjIySksF#Iw%aV|YR z*#&|XSw9xHS3mC?Xgf80PQ0M@vwNYUU$d8Ood0n~?jQYKudXc|eWCv1zj@n_bSB=$ zY96iouA`_fJ}ED9^HRgj*1lEii^gA16hEGrx>B$+f77giJ7ccBej1rKa#7>;w$Rb& zbo1wLt%=n=R~N=A=e(Iw-#cdN?a~F?>e>#KTsS;4H#OnIvkf;cM_Z3?Eo%Sz{KKC= bYU;`vH+bNmS!X0~=;o2iSolQ6f^XjgR>vr8 literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_A.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_A.png new file mode 100644 index 0000000000000000000000000000000000000000..837cae5404400e1ea3fdce416ecc62dbea8e02e7 GIT binary patch literal 1391 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDtRM>z^_bpI} zv%n*=n1O-o0|+xZtudJa6l6(v^mSxl*x1kgCy|wbftew|C&bk$*~u&0E2uaqsyHgD zIx4w3Ik_b{yCpljC%d?(xOhr&^_1$CDJ?B?T6*U6^epX}vUJLnwNvJ-oik_aoTXcr zuHCzK>)x$fk8Rz1Z13K4dykzvcI?`*bJxzDyLax|y=(V?;Q77hK=A(gdm#A!{yPx- z|NegzjE2DA2!ZECR#w2g!B`UH7tG-B>_!@p{nXRNF{I*FZ*cdf#R@#EUr$+t8JUE;>cJ-2OIu1;ioq{^ATZQkBMF5A$Q^84%#b{CglKXl<^I_G`W-mhOn zmN_2z(-7l+V&gsK=?t9w3h^C|a|3i<@Sa%Tz@{O7XjO~DN%bVRvtA|ED~?Rqz;oxk->kez zOW)?7H|XEBBJ1g)V3|u5bEY_ccsc7u`G;%loCZ0YqHesq(KK_m5OZFYs@T&-zq2`b z&+RpTch!AYOzwKkZo3t;o<*M7C!KH8H>>{Xlv@gI3YYcgEIR${ti_4yO)cAw|9)`M zTs}Be&0@pcs)Tg?`JX)a7f*`OShc+SyNvJQZ8xU`GVhsIaldL|;+1XlX7#@_v7G$( zaA&V`#fs4T+35#YPhRrpl??Cw(+>qx_ysaJ*~+IVrrBOv&wY+L!GB3*@PV-3(&nO7 z)u&y9Jy*KKuJpU!)!}DjIdRd61%8jkrd+W5FFkMjl?^_9GGd`?j~}niH9X(GFZaHV td*o%d^^>2y348ixuIkQx9N*@D6OUQ0U%WBZPYf9Q44$rjF6*2UngH*5|k%)r37@MeS!ki%Z$>FdgVnUPDtRPw_8BcFjn zoCO|{#S9EwA3&JVX^qJYpdd@Sqpu?a!^VE@KZ&di49pAxJ|V77$xdF`UO~k{QN>YF z)ltdS$;mCr*)7@GJ=w)Q#l=&KtEW`AOlfJE)6z4ir)O!;l%-RqterAv?VLGV=Pcd2 zbnV`?Tla3=dTi_7V|(|W+k5QXv18Ycox67K+`V(x?p?bF1kdk12ZHy{-vhz-_uqlw z|M&l+U^D~n?b2tdH@)F3r&l*E{~6`X$`ZgV@lWqF zU*p1anJtSJOp|SVy*V$WLb2+=NwMuJ+F|D}skqPG{_R3W)ZPmoi{`lM)qlRZdPm&3 zpw`A`S0^)^4Gh%0r=Y*~ht(6u98TwgZ<2>B&2@ObR%-+>7db3B{#L{FL~8fNOB>!O zc1FCLn_S-F(dD`SySzuWxKU7SlzidKhx2{*tQXzo{ZVw4?YHvjljKh+mpDdoTzu?k z)?VRc&vjAgsO)vYRX$ATziexb>Utd!#M<>+P-~OY-Ai3~&(QVx}cb}H-8rIVJ6Ybij%hl`5yO8;nE2!;H*d7U=FJ<$7 z{IHm3u&GqhYO1aOO@o-#!R`V3K04es)p##v{L1izu}2}(*Wl(wn`>Sc>=a+GU})@n zJv{N1VZf(fEJno#if6A?^?A2-?WrWE)3zPE?se>%(elLa`-)hDqtVQ*oqhRVk0=#R zo^1DW5mRt_w8XkCz0-bV-O09?`C|1=k)Qbzd3*QHdYS(FZvW@{Z`}MpEHCf8sVxIc OLJXd+elF{r5}E*VSqb$3 literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_C.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_C.png new file mode 100644 index 0000000000000000000000000000000000000000..17e14859536adb765d73eac386f77aa9eaf8d072 GIT binary patch literal 1271 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDtRNit=;xV8Q zXMsm#F#`kF2M}g-T4OQ;D9DoT=P zbyRY7a&k*@c1w14Pj+!naq*Pm>M7MNQ(9W)wDipB=~>z{W$BbDYp2XvJ7><;IZL-L zUAuSf*1cP|9^1P2*xtS8_8vQT?AWzq=dPVQckkS_d)Mv(!Sj31f#Ch~_dxLd{dXYv z|NZ|c7!85J5dzPPtgL`}gRvyYFPOpM*^M+HJJ-|2F{I+w+K}x2CIf*dOXHd~u8B=F zS-L*;|9|^EQ@Q6&3HI6Z^McQ`mnG%5RXyt#I9}{h{+?;Xe&EQj_6$AA^OJwCvs89I z;QT~cTF)(M@B6&xs$Ty0|70fRnQxR@)mhZtaZ>umTtW6rZ5Mo_4MQe+Bn!VUUe)I; zd!yA>J%6#@qoUd#qnoS_)Avq(kp0A|KyT@ZP@2zpXo;8gg`ami z6gQmM?X+1VT~ezsu#{JkZz<#UZm~sTt}4b17e0SmQeQneE>e>g_s9=ZPxYx7<+!T+PW*7TYlYTJ%T;Hy1Jz#cS+II)=Zf`HtXS@H zZ96$Hi~C~hL$m*KFN$RTMlAU2J!k6NMV3>VIUir$aaj1U$>|&4HY~RcK5Ks_rzd|; XmCBnbGx|(`vB2Qz>gTe~DWM4f@(ryM literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_D.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_D.png new file mode 100644 index 0000000000000000000000000000000000000000..886a380d6e6e3ed89be559ede0324cad7d737255 GIT binary patch literal 1420 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDtRHb8k$0MK+ zXMsm#F#`kF2M}g-T4OQ;D9DoT=P zbyRY7a&k*@c1w14Pj+!naq*Pm>M7MNQ(9W)wDipB=~>z{W$BbDYp2XvJ7><;IZL-L zUAuSf*1cP|9^1P2*xtS8_8vQT?AWzq=dPVQckkS_d)Mv(!Sj31f#Ch~_dxLd{dXYv z|NZ|c7!85J5dzPPtgL`}gRvyYFPOpM*^M*?1|}v?7srr_TXRFY^Ij|PuzH;e(2o{B zI4QN`Q_-LQ^%Zl&XXotQbxB8b=kfMr>FC59LkGX*=@b2q3(ftwt1Y6t<hw=bU@lB^C^Y(DFJGTh|d ziX-Q0WwZAyXG*QG)+l_dHEqjm=5mwoE53K^Nj!i literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_E.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_E.png new file mode 100644 index 0000000000000000000000000000000000000000..bcbea3fb802f47e213f1fbbbc00e985169c0b008 GIT binary patch literal 1363 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDtRP!6#mw2EM zXMsm#F#`kF2M}g-T4OQ;D9DoT=P zbyRY7a&k*@c1w14Pj+!naq*Pm>M7MNQ(9W)wDipB=~>z{W$BbDYp2XvJ7><;IZL-L zUAuSf*1cP|9^1P2*xtS8_8vQT?AWzq=dPVQckkS_d)Mv(!Sj31f#Ch~_dxLd{dXYv z|NZ|c7!85J5dzPPtgL`}gRvyYFPOpM*^M+H`=qCfV@SoVxgp(os||Qqqofp1OBxaJ=)#okM+&-H3Gci&fohbDz@C|fMnjErn`TWCkTI@x_ZGI>%!Qz zdF&ipWEHn@FIk{pw(Rl_XRll8C0pXwTsZsSfTj4Oe{&ga_(Ep*8*|Ep9F1RdZ$+ErDL;fU#?fJ>!y*cc66=TW;`is^tKb*0J?duz}r%XK@ zV(p@@E_!SAz0ub;VcGb6Q~dTsW$p_$Zkj*Xm%Ma7w=ZWTub_82V=`~Gp$axK-ns@ktF zzb*)7oSS-dC7TNbt1p8mYRak83jq<-qff|I{bZ)A8nfn9y!VwOx6QBh;zgpvHNx`I=lOw!_{9cZhwsUoEDcJuJqBgl{MS2E9q)~$<~v`_Ip)yEFODI z%RIGxQpg#X36AX2pBw^beQCJo?;Cp2cj4o_*uyM;mq@&q_`P(S`)~fWCHj8#`_@DN PW0=9y)z4*}Q$iB}AEMFJ literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_F.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_F.png new file mode 100644 index 0000000000000000000000000000000000000000..506a3c50f9cb5924deba065b3fcb6e4cb2af23d4 GIT binary patch literal 1270 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDtR9`+dFbgQe zS>O>_%)r3)0fZTy)|kuy3bLd-`Z_W&Z0zU$lgP@zz|0Wf6XNQW?Btd06;vD)RU8#n z9hF?2oZOO}-IAT%lU>|XTs)qv+m0sJ=yqg@b{nU?3p}#IKigE!pbtuA1_iC3cY=$ zGA(X)wO5i`SKyi{2aEr*eB3erUhfL)K`+5|1l(Z)}4J(t*Tve4)+5)rWE{gQnlIc_BGz@yv?dxc6MzI3R$NfGPAB+ zzjE4NvDm}ApQU%QERhg8GC`d4-l58nRkIW}sp;Ft_$kHwNz(lB?B2}%ij~y@QH82Y z&64NueP#RM&6I@y#Y<|%7Ty)u>##ubM_a}soAnSbQ{|5g7VG8gSp VuFET$3M$ALJYD@<);T3K0RT-wslfmM literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_G.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_G.png new file mode 100644 index 0000000000000000000000000000000000000000..ff73d7f0b2e0c45c5d3ffe7e92fde1e92bcedb5b GIT binary patch literal 1368 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDtjH}+~+B={S zXMsm#F#`kF2M}g-T4OQ;D9DoT=P zbyRY7a&k*@c1w14Pj+!naq*Pm>M7MNQ(9W)wDipB=~>z{W$BbDYp2XvJ7><;IZL-L zUAuSf*1cP|9^1P2*xtS8_8vQT?AWzq=dPVQckkS_d)Mv(!Sj31f#Ch~_dxLd{dXYv z|NZ|c7!85J5dzPPtgL`}gRvyYFPOpM*^M+H`<$nXV@SoVt--ga-B#c^V$t#|;J6<9 zbRm07_7cXo)(y-CYAS&N| z`NDT^tDc%9JA8b#ykq0dWr=J(JFV;*KZmo+-9PpDU75qNC5K<_4Zd%3WcBaf2`0ar zOpOC|5~AcjBreSCo~dyvR^m~__K2p1d&8YI@-)wTl-IoO)YxAcb78Lwcin|gA4IF_ zHy=KE=qBI0lj~P+J+djIZhs)B;SKrE)lsiE-FvHb>EjmV5}%asybEuYsyRn&z4}e- zFAK-?>QnDuVhxEVQF!f=r;<>Q%g=le)3rBjYyfn#tRYw!`^GvkraEt(fB$ z(_zqHmDf=G@>KC6kts^nXC#`d7&ZNGy6xR}UFMhE1p(IIAzKWWm02`p&YyVQl5hPc z@5kB`TldU9==0d1-GSrd7VRCsGi%p*EQ$EP|C0Fkg?U*r4{b8#4Jr)o*3VmJe@lPT XTD?211^NcSXlC$q^>bP0l+XkK86oH? literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_H.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_H.png new file mode 100644 index 0000000000000000000000000000000000000000..61e95d2b8a0e0dd29e70a0deba0e4122530f835d GIT binary patch literal 1310 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDtjGtdkDG?~d zS>O>_%)r3)0fZTy)|kuy3bLd-`Z_W&Z0zU$lgP@zz|0Wf6XNQW?Btd06;vD)RU8#n z9hF?2oZOO}-IAT%lU>|XTs)^`+bbry*BoKz>{;uU6X)hvc;v^O=)?OqmHIl#6}sB(`y9?~VxV@6 zHPm^|S8geu^mjWJ%$)GY@}o#{d+;x*i|f+)Z|vFhBzmiBgTl{)ypas6p2VK8G@bbQ zT$cM|u~ivQdf$9w^N-F@nENMX`I$+p>#gjR-fs_+Rm@#dH92|(?~H=}H14Y&NmHl0 zUYU34(7a{RV)1|GHoqOetA>rU9ZaSZ3{j5@RBvl#OF@U7nf#L@}-on z6MvnQzfi-2DQUX%+~<2$(ogfPSLXaW^-Io#7|*Q4Wv6?WT|DNuPkFC0EBmXOS;rD@ zyq(JVYZ2EaJuX!)yNn_=rQX0DT6+5$91g~v+iThQ^_Z2owX5iD?N;+!i<$rJEwGF1 zZ&wOleIfE{oU!Ac^8p#Fmdt9|vsUcJI{mux{5k(Uesp&p00i_ I>zopr06KZRegFUf literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_I.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_I.png new file mode 100644 index 0000000000000000000000000000000000000000..23cff08624ef81e2b17aa3183ddd74a3cc71dc05 GIT binary patch literal 1296 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDtOjugIP7f%= zS>O>_%)r3)0fZTy)|kuy3bLd-`Z_W&Z0zU$lgP@zz|0Wf6XNQW?Btd06;vD)RU8#n z9hF?2oZOO}-IAT%lU>|XTs)m%_wCON?N{$vtdY1qVdAyin|!YiHP+Wj3-0#kdacwDT9A~U zdHcsC4&G`8r`IR*_WZxGHt3yBoa9H_MN1w>7anA-=2#iBe69T6z;@f{b9QQfBy45! zY~0V3erT-=6%$LkK4+U=FaKfL4TZHI-QF*2@Mw|vyea!c z&*V)ph1YiN-mByt&i_rcc8$)T2icClEw2>L3d%Jq`Ke~#TfUN!MTIrKsL(z8H}|5~ z<(Ey=&uFTagqweKW?=tVd+8r{1+%URuSssPx_a|`zw_r(=j6T=GgN%q5_E6-P2DM< zf4LY3>b-v=C?3yUHRY3uNY8Tz!B}pFH7ifuePQ)f=Im$2$8+89&zl#&_UooUwe8RS zVl~eC>#zE%IiadL@T|h3s*fGbeFyj0uV8DwdTK|pPLx%((K)G`*F)E6D~leUe{xap w$pf!?Zk|k%)r37@MeS!ki%Z$>FdgVnUPDtOwD)7E?%Gz zXMsm#F#`kF2M}g-T4OQ;D9DoT=P zbyRY7a&k*@c1w14Pj+!naq*Pm>M7MNQ(9W)wDipB=~>z{W$BbDYp2XvJ7><;IZL-L zUAuSf*1cP|9^1P2*xtS8_8vQT?AWzq=dPVQckkS_d)Mv(!Sj31f#Ch~_dxLd{dXYv z|NZ|c7!85J5dzPPtgL`}gRvyYFPOpM*^M+H+uqZ~F{I+w(MgSc%?dnijL&&)Rz9~e z``~7?amv2`(sFs1=jKT6OgU+K@Jj#uY1<6S@|n3c7rjnTdE2!;+f_20@p-+52tXhU!%U}L2$(S71c)fPP%d|k%)r37@MeS!ki%Z$>FdgVnUPDtOxsxX*an~w zXMsm#F#`kF2M}g-T4OQ;D9DoT=P zbyRY7a&k*@c1w14Pj+!naq*Pm>M7MNQ(9W)wDipB=~>z{W$BbDYp2XvJ7><;IZL-L zUAuSf*1cP|9^1P2*xtS8_8vQT?AWzq=dPVQckkS_d)Mv(!Sj31f#Ch~_dxLd{dXYv z|NZ|c7!85J5dzPPtgL`}gRvyYFPOpM*^M*?1}0ul7srr_TfHH?lNT%S@J2nIktcrr z;H{-RPqm-@|9@DtWcBN>&&-Td6)G$Ds6;dzwYc+a>a=FNgZFGA_$o9DXZI^Gy!peN zwrTU$6z&Q4K5Sf)vWV;Lyrl>C%)4LA;1C)7eD0DPY4zSG#AP<06BYO1pB}&wI!pX| z`rOLKT}SkpW!8AEj4In3tkQM*Mw(iI$cKIR0wNEI1a6I9G)JxH*O{`I_Yw=Qb>vl4 z{XesAO+cc<)(XkH*A;>l*Zldw{dksq?5+OuFHU&(@|&!7R$LY|!B5^>&|}{_uM3k- zYI;;mU43Jg+qs91yXsfTdtd#vN&Aw(MTNSKiVFGGyzhGI)!B<*mvxpU1$+-Sk`7>* zIXmI-ZQ&Ol(=1EPcdgsrqA@-1uIw~*)8fWI%L;b9GrOuVEphYo*tM&k)%WHpESj#L zaJ6#jIfZnNvk$q}9g9q9c+X}k&sccp*s&c?#9laxl>AS*^kQ;e*n!F~nnycUTwQuM zD~oLom+T4d&2dgSC!f6+xH~>l|44$rjF6*2UngGMg|Ahbm literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_L.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_L.png new file mode 100644 index 0000000000000000000000000000000000000000..8ae5113b6874a6610a413147ea74e68a18ff2931 GIT binary patch literal 1252 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDtOy9(VX(dpI zv%n*=n1O-o0|+xZtudJa6l6(v^mSxl*x1kgCy|wbftew|C&bk$*~u&0E2uaqsyHgD zIx4w3Ik_b{yCpljC%d?(xOhr&^_1$CDJ?B?T6*U6^epX}vUJLnwNvJ-oik_aoTXcr zuHCzK>)x$fk8Rz1Z13K4dykzvcI?`*bJxzDyLax|y=(V?;Q77hK=A(gdm#A!{yPx- z|NegzjE2DA2!ZECR#w2g!B`UH7tG-B>_!@p9p&lb7*cU-?xfdw%?3QJjcG0%T1qZl z&VjRLKmJ~Sc#~ zuRRwH>&jCsUdnj&@s_pE-t}!|^l7@{cHr?^;iiJ9wdR`V`V8X!FI;W^GH9>N=k8hl z5e}lyj)klW{n+$U%HUgT)bnZ<<51Sg-!ohfUePSL*(Y#yGSdrgwPQ?4=egA8E>rQ& z6_N^^ert=c13@tS@`V{ppb0eSdD>SHK`=@O1TaS?83{1OOVB Bn#uqG literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_M.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_M.png new file mode 100644 index 0000000000000000000000000000000000000000..26ca8ffa5e050e2ef82b1cab8b7b5e7c76d93cd8 GIT binary patch literal 1353 zcmc&zTThf%6y1o5PMrpWQ^n{scxeSYDjbZ8(8@T-AeT;NXj2ptje5Ma0u`pB5vYO~ z9*UO;a-uPoi)P{##zr3`r7Z^19%%~N2J5BqMKIAZQCig2-NpF_edw!;_5k!<`WT!>+hgl{^MBTX>brx3>i`{u8 zM3$$cPnh#uVk0icZcfckC2BkP#^3A55rvZ{D>n`If=Ci6B2C057J{T8B}fZmlNOSs zBqd2pVpA;?NkvMLR>Y=RXp)+gCasALmSB=hib*rEfffWLw4xSCM59Lvp@h&vuo;Y4 zN};6CQn2BHv{XVVp_O1m3)NB!rG?gl4NEjj7K(*t!G<(MfHi1>7l>doMgbdO=tep6 zxWG|TYAM+$#9+iqNv$Ls!Qg?k(o$>5Mn7nwTCvnD+1LTMU=RF&0Zm~;Qg4pW z5cw}ZWc4(L@FCV^xKeY=Zhz(b$v-xJLP=&}P1KFz9pc26RgYck4t56zHvYD-sG-NX z=kD&4zy31&+v19jNPE$gfJO&ueC_ee$Klz2!h)yo^4dbjlSh z`)uB{y>sVtUAv>BscT#3*2aRAt$~XAl=jJsZ(6hCoqG#1YrhEw`U~glxita*U!Km| zga>!!_-RG2hClLgOzoreBby>Z)wk{p*B?FGka=anRqvS(*S5VA`{M^^>Nj6Il-#^) zLG;ar_wrA+bY+#ghFYuMJ~tefl-v?>ue9gcVt4L$USHC?$Tkuc|D-#y|DNq)pvQ6R zi`x%7FZ4Ptf4@F`d0lbzvE1#I-2?YG_}i;1QVJ{`F^|XmKFR*)aS?2v*?a% f>@M$n@w}2=zwDhiYjya_(HANsEys1ixo+RTon2Dw literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_N.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_N.png new file mode 100644 index 0000000000000000000000000000000000000000..bc3ef22649876c3cfd4f82df781ad3cf2b69cc0d GIT binary patch literal 1419 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDtob!L&Hc_Au zXMsm#F#`kF2M}g-T4OQ;D9DoT=P zbyRY7a&k*@c1w14Pj+!naq*Pm>M7MNQ(9W)wDipB=~>z{W$BbDYp2XvJ7><;IZL-L zUAuSf*1cP|9^1P2*xtS8_8vQT?AWzq=dPVQckkS_d)Mv(!Sj31f#Ch~_dxLd{dXYv z|NZ|c7!85J5dzPPtgL`}gRvyYFPOpM*^M*?1|~*N7srr_TXTb7_pMeCklW(r6J46Q zcDhj40gLzl+qjirCWw6d);2>F(+?$9(PG(A>;dphv(f< zdC_I1878}so2_0@?TCMd!(=aA{-y4l+%s)mdh&lvGF*0hQGZ(OQ>%BYuHF5&_U*Mr z`o=!(N~?<^cyF;Ce#990$8Eb01Y+tdl%PkZaRW!&e zZb~q!-p|$9v7E#9g`DRBtM~F&?h?Oi^7C97o9v>B%&$K+7kqxd%zN5or&&*LMwDFso%{a6&7Ke) z;YSho=f7@RzsqMHN9nW>L!pZi4!T{wl9JUrDihCiY1%9}B>R|IXw_0q>6c_OJ^pXGo literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_O.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_O.png new file mode 100644 index 0000000000000000000000000000000000000000..54c1923d2df3f90e80ecd81cabcfbdb9ffa6e1f6 GIT binary patch literal 1412 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDtoG;Nzc^goO zv%n*=n1O-o0|+xZtudJa6l6(v^mSxl*x1kgCy|wbftew|C&bk$*~u&0E2uaqsyHgD zIx4w3Ik_b{yCpljC%d?(xOhr&^_1$CDJ?B?T6*U6^epX}vUJLnwNvJ-oik_aoTXcr zuHCzK>)x$fk8Rz1Z13K4dykzvcI?`*bJxzDyLax|y=(V?;Q77hK=A(gdm#A!{yPx- z|NegzjE2DA2!ZECR#w2g!B`UH7tG-B>_!@p{mawEF{I+w+~C)fRx9wZZQazfw`fDu zG)KK-d;Uwy1#Dcq`**Urv6r5_;uG!`ouCkbYrCNUI_1ZFlksvUdx?2ZGh;rK9;o59vY2$Tm&mLDf}G_C$|WNGc}X0M~>LY0jP zx2jjW=WcASi)UQ8ec9IyJkmmQlFm-gk4!u6{yFnaf_3T2I_tv!j4v-5nfD~hoCPKc N22WQ%mvv4FO#nk^>S_Q0 literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_P.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_P.png new file mode 100644 index 0000000000000000000000000000000000000000..c7c1e00c5a413940f4703dd08f580846cd659f4f GIT binary patch literal 1371 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDtT$stmKOZQ> zS>O>_%)r3)0fZTy)|kuy3bLd-`Z_W&Z0zU$lgP@zz|0Wf6XNQW?Btd06;vD)RU8#n z9hF?2oZOO}-IAT%lU>|XTs)l18Pj!$u zA?TNU;M=1A{}12T(|5_o_;MM0isI={uNnooJ1o6+zwnh#RW`eE&)dQlPx{z_q!g2e=IM#K6*7; z_UNyE$*j2Gn$wd9HQv+0-bw|$TlQ>{$=Mm#XNZR;C-~%j+WvNd?fn~z{`R&^eDq#1 zJ9y?_m5ka-rcxb*Cvo7bgvoHha7IvyR`wEJ&$XZ8TaPMtU4RA=E#|t?>pF2 zvTq1^XPx@$rt|VrRe<7^Bl~LA`S-2gnB!Q$*wZ`1?ZlC_mG9fPC-qix>_6Z0`s+=W zdb8AX^Z2_qpRaGbqUL{f=L)0E*AidUM9=jUXv#jj^pjkH45Qq`Q}K5;MQF<`}?jNs0FMqaNeQ#~y3x5?m z!_3$kp2f~D|_`LUgt=9_n9ev)Az>siR@RaJLdFf_Ro$Z%rB(XHA}B|)E`w( Y4>z23J9E`6U`#W3y85}Sb4q9e0B{iDlK=n! literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_Q.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_Q.png new file mode 100644 index 0000000000000000000000000000000000000000..9b84be3ca07e8b862968994a4ef7b96ad23f5a26 GIT binary patch literal 1474 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 vVa{i5)7V<*{<2!{4;pE`njxgN@xNAR1W7d literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_T.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_T.png new file mode 100644 index 0000000000000000000000000000000000000000..fbc00e6057b95d14a860df0e171e96d7b7ae4983 GIT binary patch literal 1284 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDtg6&1+c5k2% zXMsm#F#`kF2M}g-T4OQ;D9DoT=P zbyRY7a&k*@c1w14Pj+!naq*Pm>M7MNQ(9W)wDc_PnX+`sl(kdlterDw>zt)qm#*Er zcI)1)TaRtsdu;FCb9;}SJ9g~av2)kXox6AL+P!P{fZ+MP=RolO`FkMv{{A}<{Qv%c z6pV(zpb3FCuQ`W-d4sVe$S;_|;n|HeAiK)b#WAGf*3{s)Ma>EVEQ{|Ms7ZBkn(}BB z-1}{xbg^ff>RP{V$1AtLD~LaELzp*8*1nGOL;Kvsxt(F>^0pOuZ4b&^JAHw|#rT^iC> z;is`cK}hS`Jh{^4AA-D(-JJcvExLMj$X$)asqtrd1tYB$AGw&g)h}yd&1H8=Z@(Az zwfvBxLs3%ZFC|&QUpfm#zUuQX^j%{dph~tEWKOgToZpSD? zw%6{nz7&hvuqPNQcYOM^@NmnriN4H+i4(&g^?L`FOy-W=c>l0#phKyGP}@7_-Rl#- zPu#HkO?J`K|k%)r37@MeS!ki%Z$>FdgVnUPDtg6rY=-w8k= z&H|6fVg?4T4?0v(btiIVPik{pF~y$24;o;pAc84WGAm|ub|?fsN$%o z>Zs)E}?}6a^`|m*T z|NH+@Fd71bBLtooSy=(|24hK(UoeBivm0qZ_H|De$B>F!OM~C`EjHjWk#Fr4U{6h4 zsOiPr`S^SNVdKUnkO`J7+rFSc_~o#_94NmA>w*WX@d^h}s=Hg1PY#;qreDjsojFKA%u^P(8!hr~ zn6-HNu@kFK*uP>m+~hXv&-F(#zOnDvZ?E0GOl9`E-)@`RZ@owid3C}uNHc|fqVAeS z+t$4Ll{#bDyYzYgl2ar*zVXhxmOJ;@b%`}|j&>@m&8y=pGryHouNEt!ZQ>Yby_q}y zr1s0leM?deqIG9-l zwjU}}PrtY`XP(FWwyUi(^|*Gv|8VMLwC@(T>Dw3n*uL&x*}`a(g*9;#&i7rg(!ITH z<*h|0X2#jeDA#BCWu465utD@rap~PvybpWp_WqhQW&Y(q5xtJb@8zZ3e*VE%MbpIh g@>gHR|DyXDH(u9Cz9Gzopr00L>}F8}}l literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_V.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_V.png new file mode 100644 index 0000000000000000000000000000000000000000..dea84433a39ca34de87aa09ea711d8b7c3a904ff GIT binary patch literal 1322 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDtLO^CMlN3;h zv%n*=n1O-o0|+xZtudJa6l6(v^mSxl*x1kgCy|wbftew|C&bk$*~u&0E2uaqsyHgD zIx4w3Ik_b{yCpljC%d?(xOhr&^_1$CDJ?B?T6*U6^epX}vUJLnwNvJ-oik_aoTXcr zuHCzK>)x$fk8Rz1Z13K4dykzvcI?`*bJxzDyLax|y=(V?;Q77hK=A(gdm#A!{yPx- z|NegzjE2DA2!ZECR#w2g!B`UH7tG-B>_!@py};AOF{I+w-oT5KmMHM>JUSWKcTTKz z`RRy^h7X?s6Vr+j~r`?dgf1LY&|7`5cbPU*J(U=uwQm zsdQj{-f6E(1+1G{s+c73x1#rnsH>bC7d(liag^H^SI;;+LlI{9|<4Ti#Zt>$%QL zv$f84cY;u->egbZ8}i*Yp5d>T-tsm{jOw;4o7`H=y~GJ+qIvYZ z^d3fYIGg!wkNRnFT1Ibz|k%)r37@MeS!ki%Z$>FdgVnUPDtLb|*D_9UPX zXMsm#F#`kF2M}g-T4OQ;D9DoT=P zbyRY7a&k*@c1w14Pj+!naq*Pm>M7MNQ(9W)wDipB=~>z{W$BbDYp2XvJ7><;IZL-L zUAuSf*1cP|9^1P2*xtS8_8vQT?AWzq=dPVQckkS_d)Mv(!Sj31f#Ch~_dxLd{dXYv z|NZ|c7!85J5dzPPtgL`}gRvyYFPOpM*^M*?1|~627srr_TWf=FPFifhGv#ckNa6_r z;RBD0Y81ZwuivpPQDO7RJvnRTf_B`U6s61lfP?7+gOEe?M23y=34b&j(iw{+BF|1V zVZIUlXN7@bzSxB0F+x8dJv5DA{o8h1?JLhhXSS&an8dU*7py9L*sUM5==>x$mhBUl zbKTf|XyuPPHglsw7U24 zIP1VS0c|2j&9?BR=kI&@@Wc6wXAbtSNEw#SAT-%`^=Tvd#_2GM8q$i zu=9RrxK&v&ms>uB{2oB z5DS|#m3?P~eM?)oyW&2UW*-Tse;=>dO=teP?d*{Y*;NZZ2@8v-F8%YcXzeu7+?}DWfg3&_Y5%o-`$w~X42mN9r&L?^Y5|iAgQu&X%Q~loCICKw`NaSL literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_X.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_X.png new file mode 100644 index 0000000000000000000000000000000000000000..29dff7c73d973e2d6980c14c0566d51b9f91a475 GIT binary patch literal 1397 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDtLeaOFNdYLt zS>O>_%)r3)0fZTy)|kuy3bLd-`Z_W&Z0zU$lgP@zz|0Wf6XNQW?Btd06;vD)RU8#n z9hF?2oZOO}-IAT%lU>|XTs)m7jvc#p?A*0;=kA@mcJJCfAb5W7IS{;m{vHUvzyA&d|G)nq z1*0J_XhPuYRQGyd-e4>V@(X5gcy=QV$bRkV;uunKt2MZDQnLb&@0P2H7k2e^1hsL^ z`1F7Nj*76|ckkXvyyV_Dow>nPqb~4D$rFp0<_vtZ4H$CNjN23vetoRl?-CwX6*#+k z-uVeCOjxVPLUbn^k@H&4_=LDAjC<_=Mkk*Uj=c^LI6$ zqDA}pNip>b*Yb~@44XCa>>WH_RbXudGht<#A^0KpPRG)fB7i?{#f|guC9~2WzS?yzvQeVIJtLC^}4+* zd+dG8E^bN6uZ)^mwQQce#`Wh1|LR&^ne#V!@|DH>dX}@7#!OLH$eyzO+{d{wHKJu2 ze{ZX$Ev;_bo3v&I|3Q=YQzmLYJ(KWga?_hBay6 literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_Y.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_Y.png new file mode 100644 index 0000000000000000000000000000000000000000..9e8a7328a11f3a1010c57637dc35090f32d66428 GIT binary patch literal 1318 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k%)r37@MeS!ki%Z$>FdgVnUPDt!sz5#=YK#U z&H|6fVg?4T4?0v(btiIVPik{pF~y$24;o;pAc84WGAm|ub|?fsN$%o z>Zs)E}?}6a^`|m*T z|NH+@Fd71bBLtooSy=(|24hK(UoeBivm0qZ_8dF!ts&W)S1a(eJbGbp?UzKx z-YFXu-aP#O|M2T-k@G8mPB^fs^W-8SquI(?JZ*jVCSP5CSxcIKs%mxfj30}=c{Beq zwI?Z`XJz0{@uKAd3KQe`jncJ~GKCkf>xDx0bc3{~dzDjvI;SKi(4*(`fZ{eM#= z`=W1#M_sD-DuhlreMdHJ;g0v8TlLpUK2Lk`BP=9q@}wut=htbr@?U**q5fTBV-5er zQ>-#eB+sxrE1!t)OX5&J;e2F*tE97Dh~bi}E5jCkvz|3ISJqrKdTQy5b5l8lyF_2h zUW`#R(X+p2r>ncGHc#oy@seFP3NNMeJIG)9wEg2Y@!P3krZznt*0mMvTRz`Dzf_*( z+H55$Gx7P;_n;d+6biUl*;AQol7xyF{`Vf-+L;P;UZ+!;8I`M5~ z_6zg%pR8~5Kh^bKM#+R}od<8z%URq(oV@X|6W*~+_|tS`tNGQxO(y?JZ*czMZ}C%j Uw}Dk71Q=-yp00i_>zopr0JLkvcmMzZ literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_Z.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/Chalkboard_Z.png new file mode 100644 index 0000000000000000000000000000000000000000..04b3e33d74e0e1795cee3fc0d21556965142deb8 GIT binary patch literal 1353 zcmc&!=}Xj66upD3#%PNl$}ED4(u~Yk*kY8^OgfF4A zt+Y@Gm2IejSejYJE6p%eVk%>3rBbqzjMwq~2Yu?nZ-)Esz2}~D?r)|bDKXaQAM8&= zMr)jT3BJemJ_G!S4Ch*xMI-2+Wlga3e{S#}GH`Zwq5BoC24=)9&m{8y*83PtSEhMz z*~b}^5JPmMXi(4EzC?bM6mPfSo)K{(K_rQkju|7)NHCI&luk2FoRi=rIVoMu1aUz^ zkQAhJGn2$62}x3t(pXFpS0ofkMM^_60uowLizK4n!x!vJ zm=H_~rZg>7bIF8cQZl7kqM0iu6qAZ6O&TJ=8Z^NRL@*hnfDJHoqa1l$;0Vqo=SnNY zV8lXjDY(*t!2@X_xs+UK{h);cBZX;=#{VIJIqJ@5ktKrtkOG_b%L zG{Fl*Fd5Lm1{k_gjyx`Kl-?PvghC8Ptn>=8e=Hmu#!9h6EDc-2TCfKg52s-*yo4QK ziDvi#1E3fZK^j9a0`PYvz8<#Ya;*hLB=G{ zSNsqQt>zfJtL>1z`bcfW0Gn;v{e#?9GGg_n{A~dub-gn)>S1bRfIF@Jbx6$&^OH}L zt8X;KJ0gCoeVI+|N2mWfkfu7_XN|K$t{=PW*E)MmsAbBX;Y+s9qSVI5r+t`DX6OM^0=$$QbUIkB$7&N<(2r&NWGy~d?GCV^XQG?o*$m>8B-b)x(&OsFZhDe%P0tefg< z$~s-%Sys6>ye!~j&CS~P=i?iLLRKy|k%)r37@MeS!ki%Z$>FdgVnUPDtl0`n}xf)Q2 zv%n*=n1O-o0|+xZtudJa6l6(v^mSxl*x1kgCy|wbftew|C&bk$*~u&0E2uaqsyHgD zIx4w3Ik_b{yCpljC%d?(xOhr&^_1$CDJ?B?T6*U6^epX}vUJLnwNvJ-oik_aoTXcr zuHCzK>)x$fk8Rz1Z13K4dykzvcI?`*bJxyYyLas#5In#490=Y&e-8xT-+u>!|KI%W8HnSqnv0Qa=rtp$Qu6fJ; zoqqbe{z&EG{3x@ih(z5t-<_Tqswh^5yi(tz`r{j;Oh{?-;ZKewJiDU{zaKj3=476? znO`KhF62>s@Di@g92ZY{bJyQJx0!kC)$bb*N-)ooG(Xw*^68!MiF%tZ)m=_Yzbn+_ zE0Pt+zxks5dNu{A{5@tIQO)xl4lh~%ry+I5^COq4vu~f&EwneB9&wuK`Gf5DN2s`l-(S8IRx3`kQ)e?mQEQ6@h{URua;C4)3o1$MRy5;4}g0t0#f}V(@hJb6Mw< G&;$U$m0QyQ literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/choose.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/choose.png new file mode 100644 index 0000000000000000000000000000000000000000..f445bebf39dab8cc365ac0dc2e297a10bcf7cb30 GIT binary patch literal 3321 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 DztrBi literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/guess.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/guess.png new file mode 100644 index 0000000000000000000000000000000000000000..011978e7d98a501989d95f4e5e80d971e65e8b12 GIT binary patch literal 2900 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 CSy%}G literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/letter-spacer.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/letter-spacer.png new file mode 100644 index 0000000000000000000000000000000000000000..bd6a7b010f4d2e0d3c2e0da342436e90e703fcc0 GIT binary patch literal 926 zcmeAS@N?(olHy`uVBq!ia0vp^Dj>|k3?#4J%UA`Z*h@TpUD+=)atT=K#@?&<0t#^! zctjR6FmQbUVMeDlCNqG7Ea{HEjtmSN`?>!lvNA9*GX(gAxVomh0;NX5Xb6nV5IAiu zE)VoMV@Z%-FoVOh8)-m}h^LEVNX4z>1PRu~2_ijBfetzh46G&$jMCp5Qb57v>FVdQ I&MBb@0L~sJYybcN literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/play-again.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/play-again.png new file mode 100644 index 0000000000000000000000000000000000000000..48f2455be98a32f292bcb9e79a90b4f2e5518cc8 GIT binary patch literal 8607 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%0A6H9Tqp!xTo|HCz?iE z?h`Drz1N>~1JJ^AaJ~Ts*}9Qq->|u!{n|ldyO&v0DrO7+&f`mLN&N5ZgCUruifSpI z+vJtF1Jj6uVjOM+Mry$_Njf*AjJiC8^=#tLn3R}?{VO~7en=xH^V@9fXtv!5Gi(%g z$}lp9@b>jRfepCEx;G<-4zTR0`s-a7&fbA{aSXx-o+}y#aPBfxWh`MqKVgkP@+d8| zGY=gl-;63r$(2W(CRRP~Vg7H;^mpzq(O^t|*Ea0zqo>Pf)$?enR!~5I=f-pl0R4;b zv1L86W?7%9P}~15{@eIXzo!}haAhC9o&}Senb>*OFf%sg)9iXd%+9tq@p8hg4_r#S zNy~ZNxVQ%uzeQEqj>MB__nIk#D%LhxexG2bv5tM)d5VZXn`#Qw!18YcZ zO4=^K3ua=fz_Vfq_byNBrDVIMPAr{0EdTr^mw%b^F+d(of>I^DD{GJ#RkO;=Xgsse z5pQC^+)IDvwjEvvP=KHZ(JKIE&;ITDOVKc#4RjQ^1%U%1q~PEGDZ%qWSx-LE92m*! zZUW*VdOVE71Pbs4AC@H_6^2Xa$u5RN&rGtn+jY(zsoUcw;{i9gA#7%@4UfAcwJX_X zM8D~k%z)qcoP%a>6Hy4(7C3eY>)Iif|N)Mr1Q>m55amX$yPHq%$B1fyD9*#l&vH#Zahi zk`&#bTi`IjXzYrF4Q=h;_mV?Z`>I34r`%Y=3x+MBe?mBMLF9f?L-_|k5B*b~e^>!7 zlC<5&S`_K9pEbWPOf)H1OxPI0@@%|(l z$4ry7&C6KtJ+h9e&`C-QY`R$&+Js7a;TCB*l8VuGQo(GkR6w!Pz_L&nPHd%-0zeLn zHQ@`)sFv)DYkHO{H4hUsEdzM6FsGD8V3rzjpLcN>T?Kx{-3%TB13wopPN~Cr_&@Izl2}H;rL#tfRU2Thy-D z($w1^N2+=3rEi=1bMOG`8Wn7;h-dT-Q%rUE_t*h=4C|SBw6-xhgl4^@IMR+%0Oiar z&#~|%%j4wEkXK~Xevr*kvu;~9Eg`U2a=%<+te8aoBu6EP2=8A+6Q*A358Nzkf#pPJ zx{0}ZSk9WKy<@;bH^%(OlG+dyPtp6TI;->OhU&qeC|Fc=sm@GTSC4k8f>+Ym^p?Lh z6ajkmm&~xLZ9Z{FOWEGFVW9tH7q;a|kK8cq7#~<3Y+>JW-`Bf+{PBzD*xn9@Ux&AE z@d#~;p_9HAwDzrTEBJgk08-Z`fV^@b=c#iCx@JyUJ lSWx#FX{+cQ82HG${{zXYbs$JlT_XSh002ovPDHLkV1jxPm5KlW literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/scaffold_-1.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/scaffold_-1.png new file mode 100644 index 0000000000000000000000000000000000000000..f0d65f8cd0906e4a5f798702d67fb659a4370fee GIT binary patch literal 9806 zcmYLvRa9I}6Yby@oCF9KG!Qhn2ZFmpg1f`uE`z&6a2PBEw}BzJ4({&m5ZvwZ{r9eQ zAG&*0?W*dk-F@nuhZCW!D20js5gh;kV9H2~s{#OU)Ng|d72!=2k}ux$wlKL!{BRL- zGBa|q0@{C4x3V(>s2RC@`pWZ3)Yak>I~yDOCw2~gP7Z!{zE8|-Tx@KV0Y~6BKNJ@k z1qqZXI7}>lqB2%}t2Y&zgY-{l000B;zX3P7;`j8XM6?i95Cs5g;xL|!kN^Pq5@mUH z2?+}cNlQs-D`|N<`JWy?4SfwAqa1C+Y)$-4v^})#!|kDl`B^hfO10MsMP#bw$d9Ng|yxP3s zncGOOnyw_@5HjE zveLh${;B?f>4CrqpmU6KL{3C)NA2&1-=lM*E88pUyX*VM`%4>3$;HVt%QJgNdyTz~ z9m5?Xvm?FZz0=Fng^7rn=6$&f!iiH?7>7TwO2SA8tSNy!FNx#<%vjdd7MN zrw7k2&*shB})2o5$wI4*wlC!J3vgmv;_#CKe{vch>8> z>+|dKTL)Ux%F@!y(_;%_>$~dzH2w)l3phGG+CSNc_CRM=W{&*n+@D^Yo?V>z|MCyY2-?`&0HuPiZ?Es}?=G$`F0U`IZm!1X z$E|{`fRRA60JGqX;E>D^brbI!Dz>)g{(N!$l*b zBBOn%T@k2Q^0y?nI@dSFx4gN0c6GLEv@5SJZ+dB3)lpU7N58VAQqxs)ZFjApu3&C$ zF1;*$bau3Dpv^YaHm)#E%}Gt&S=}PY!X?J#_U_g^&|KeJ-#f`$*HicI;V!NqPS!^D z@$vED@!^k*&e_`~hI3I>R0D|Y&YJ@OR9iCQqUs)t$GVR?+H)DJw$L<(uR3)?8@wwE zlFKl%EzB5X9A$Bw@g8*4aCKbTFI<=^>Vcb>WoVQIR?;T4^>!JDL|Hj7x^#RyW0qZ3 z-t2?nEDmV9sl!7Sab{4{SAw(j%a=xS!wUDBS$EG{=r_O}<4fc#As9eJR-qL9Cn9X< zaH`~XXjM+?G*xBD@*oV0kS^cMuQV54)wp#K6;2+2m*?!?$w6>?V$#>ns*vZK*qreT z9e=H8m5Hfolrr`gLGf<~9L2>FB%~uR_Byy|F1}hY=-YSo{TC$xhj03?_s~6z*F+2Y ze@igIi_5WMR#`4`w=c6@!U;iJd|bq7$EG6#8ClbnhhA1;Tqa~uT<*01V)?uIknBc6 z9|=JVE7bs~XXs{|?>kX=&6d{E6s+*YP;Ev;$>m^1q=IA-wgE==*?~ccofN03V=~t@f8sS#hW`rx)80|B-|W1!n~u@DQb~HN*F;&@KJq{E z&3omJLbBdvjaVh@n7yw-gCGNq%q(z^-#y)@@VFzI|Ge2h|Ka=@<2B8Ad+K#MB8w}p zafy_erG@$Po?T8}BalK3@2Iv?$!RA#v%nLvn5KR`>NJO(F_Cbf{fYjR$>J*3Z1$(h zm0J1Vq}~PUnG8Oz2br|bkMNOP?voC4mAaFh zo8>i@A&m2Xo?otz_Pg?js2k?OgdOBcD6B ztQVGc;Fx=f%M8*2iloSQq2e={Zgt0h8}tW!?o*Ww+_)or!(-UdpzY6`Coc69leOeU z?OX>}Q0EUb)+1Ll-z2QQAM%BqCZaUwI2ppzc-0c-a{T#XYT!#= zMEtj&@q<`FSB4w!+vSB9h=tV0q0oHlqbNcfd-65ZC1Kk$7q{wiM+xtbVg}{$0K|s~ zU)7AXa?EOVU6Vh&@hoceTelkHk+gJ8d_Yh+jWz`)d5Iu!-4SjJn72Er5BL5%FyYi2 zwryMKh77#F=s;cUh#P+Q&zV(-nuk&r|JP3K%(Hd^*Y!H$BEZD=z395@x_0ueKwrY< z2fOU@^$r?a08-Ds%(&RGHspI#`@ql#OP0L?36y^kPm43eaSZ@@tIE=kNN@{ zs~wn$gBDxdQ;a18=Wj^h$Evh5U8{*c85tD`#Oki{&s=L3v``_j;0(H1^Df?2Ulf|zkwP=tMFQVfpzhmB_-(yl9l2X?J?vtJXf zoObIK8BtDgc4<@gL-%Lp6!lo_m?tw`JRqS!wslfP-9_8MMX%y_PNmMj7n%9<>J;Xz zRWS~Q$@f*)NSxI5`04{Ivq~{+f1%J7yZpK-EfGDXLy2v~(}b1aUK==>6RyNv`vt>G zhwKO;BO2hX=%|heLFc`YK5UR(Pj2qcIm4KK;ts8(=)x@PEf98K zlaQit7^b%5WpS2~=+R*n;}wUepr z)x>I0>=7qhEg*I5LsX$LRqh>vQ2sB0)?h~EgA0O?iPA1q40#G2o~c)0rl4=EBy(3t zexxjE?mPMVBTr9!Y`;~>=${_Jum@DW-c?eooJtm8m1{p?Eio>q?0LCGkj+(~hGVXD zRAyby9>l!n%=VauMQ)}(TUn5mKk((r9v-O>6oGT?eK=2&0t;==v2B}VcxCgZb~*|- z5h5`Kh_`i5HvUQAW>A&&EMkyKD1>kp)+Vi-P^H~YoJfT@*h-qiQeAY6bOlY`i}^r|90DuHh6g_6Xs$J5L=Flc3mNN1 zMP>K_!!K4}*=H~j#TAg=+ZOv?0ghZD1H$2X**57G@^EuZRF?yuj}tm)mjXui%7&$X zV#~Urv&@X>^M=Bf$VG#Hn_VkQC*6QIv18)}A4u0{U zz!LhdHx^b6HbN5L0-e4LwSURTy5Sl-?Y`O|v9e1+Zk2g4>mhoJg&DKkm@&+~NwI7s z%po^6mNAKrbkU#E)l&hE(cj_9++|8+-j7bTowbk0a>ew%G817-28V}A~Ut@Z0eTDZT?U&tns{$dkTCd2;U~<<+{$-fs#VCkHsNgCPISj zbqB*HcR6oGJT6XX0usO$yRpgCDn__dnkF_@o9E$70cFc@ZFlq&TgBbmVoJxP#|;() z@cmeHOtMIeL?S4tJ~?qv#$tV{9!5F__tAcR2k#bm&G*oH-3Iojvu8a|l(+;EE7BBs ztB<(<;Iqpa5s4Q#%TV-p;py=n0@NVrkRTUI!Z0nC8Fv@l;4Fj*o*NobG(UKK<_>f& zF0CF}8^1&R-TG|k2VE07-!m9EC&S`V2x)<2J62_Ua0;EpB7-a$g_T!&Um;vIfEx*s zSjjMAJDSLQ*C`LN*@ZHb3BiEYZ|LDTR8`w0S?5ORNA6i_9=&uPN7yUYf#+4Dx#^-U zScG@^t|a718Vkbv;Vl9h48 zxsV@4Kg+eW;+DnNPq1kjMBw{Pb7Uy3X^kZcZiIFphxU>zX%HSN45V~<6|xWdzEraa?*Mvr zG{5gu0VrrzMls;Ntc>?F^iA50}Ybbll#1L?(AFMH z|AjwP943mSS54n$bV;m0MYdl5M?0obMTlK^Mk*Ko!poB`>{JXCEr$V9#VE?*A8DDu z9S4N>ps=|QyXCJq(s-<~VFeSQPvgU!PKOSk*4Ln-fw;)-P4FJjzrC{_R)u;qRUg&I zerD-8hYEaGsIpUC%c|l~a^Tj9FEbSn1h(o0Ef8fe64vHO7U_)xFgv~pA#x#wn*$m8K`wYNi^A7nRMJ*(IzW>-i*IzX z+3`w@C#EL( zw~93X(1XyY1DpZ#i%+n#$5CwcGndxEdwc|@hpwDbxoG}a!~y_;N_3=Jj!W_S&261QK<=4NLHC2uO^*tz@4aGp zV`;gj`h?A~)Q{8fH*w5b8*ZLRw#C{j(jLn+*K6}`qzlC#s@Isi_B$KTi>CWAl`~P% z&V#RZVqNhUtwWYy8sKwE^3vFJ1H#DHrg z{8w!_sDdC6k{&~9stp(a4)zkwyU$xo!Mv{B?ZvhiICtBY*69rcp|%$UjiGn&CyQ)% zim3dA8Tz_I6!|$iBu1N ziyw9%1~SDf^aa#rVb4n}SN#SMYH=nw0Yf z`a_2zr})n|(&*sNr=MDSbOLT(t>L`--k=Nz{!n899v zoa2NqQVHYUkg%SX*#4vVk|JSwK^lfLA)|j|xd~ZJlFbmwOML2#SNqfD*Npy2PJImm z(GqcVrlz`o$-NcErML;}g_$~ml!$2HXf&LEh~Gb{W$PQ`!8w8~&nDA(S8IiY*4dW? zgxJvqnrkZsD6+mzjvl+69zRnoiXUqxDF0O-OyV8`M$+(Aot8Ks>L}%G)n%83v(33l z4P!fuWfim=*jZ2McB-&XunDl?OW{~5t)y+h%v|_1XOe3D0b=wfcpoa6}Tzd6Be_ZqY7`KPz z7RE!3o6@4glS(~JEcayT-qUh^hkX>nPa!whQ`2^)*p%e0VR7I#@U0(_+0j(%BsLBA zYn~w+GGUabCun?hpV?_{olUe*o#G7o@D7 z;wE{?XJHVx^fDg7R|`RNO-#BW7b{8G>xAm?^zvT<>20B#lj@Pggde_koBq8JzeUwM zlu75P>wa?&f`^zSRfiLkg2|$SC58>*PX2tW2Zs~WfXQ0_uWU)nWQ>eyDfQV1mm^#x zQ>Tl{{0!vA`JXQ;;%_R zYgh>+8hG|005LBJ2(D*N*&u7J+$=3lI)pLzIqrU>|21!sknQY?Fc+6)Ng#hyb{CdqFKzA7hU?VW9mRiiWo1NA zcj4_$%ah{%Vkhj$P?m~yxzoi|VxLkHEpH46te zknkU98lXQ!fLj!(T=nKJdRsHYjas$%dDu8BQA7YC?^AdudZN4ekd3SiI3`>s3&e}H zzNN%~27%V%CVAeB*~q??QLYMa8HVj4Qb$hnQHZ4KO`GK@gQYd3GL zAlWw?5|IWkLh>6mU!lf0$5*ww8x!A+;N!{bTGU9Ggp5t0I$-e!s0g^6oi3Qaydjp~ zvyt(7z%|3O2lM7fF77~CWTPt695_q~BgUbhQe9J<(QPXFai9u`;B?)NLzR+FP{mFYOz_dV_`g{ZgOX9D9 zAKmR{*nee7!mqp$Q-=_P&=8Seq(F(9Q%1s3}8PlNi%f!dw_?XYq#4p!5nXZErcKD#4|0e z&R!`EB7rbOS~mN1P0aBf{EV%(?Hq?u1Htv)+6vMLGJmN8?8YT~B1`KTvb8%!c4`d^ z$gdR` z)3a=}CV+Mq5<8BcZ2P7b6=>%^Xtx|2Daq>1?>@@J+lRk$@JwrO2og z6=T6}J41Y_z+|Tqr&*^eKRadI8P)eRjA587EPEYHNh7CpXwyBo;?YO-ek0HKQJ1pG zm)2Lhc$V>%P2jKk=PUyrtw01$$8ElDKW+^Ho5@X67Xfl!dbNE2j9ivVD)^x%`$T{O zX{W7CB>nfl7AmNGWC(rS_> zQ^q3ODz{7r+zEKNS(24qi2L;u`6CMomg*mN!zU9z%$O~ol?FHzNH1^cHIKRpby(j7 zFE?K}Z>AMfZOye`Gu~c=9Rf1MNEXKZ^1FLN>-)jhVbD0;!G!7~#{qhl8qWGb112Y! z8I1tAxILDG3EnyPit0tr)z{mqT48#Pq{w9WfqcT&oin{tPf($WwAt_nCE|Qz$=YTO z&|`XO?2Ix5e$Fz|NjP+L=Ocfm)t^MtvPTz04=tJT$vTb2db&t2x=2fG!COUPj}V@Iq{^CPi&L(NOX7ogs`zsz7lvD zw@x~(D(5tQMkC6>q-HOgUE4TL*CvsFQpCW*qwv09ZT@IZL}#?c%_c|^@atU0zeb+j zjc6-ClG->Vxsugs6zGM=ZI6(|8@N8tz+&^; z=p_K)l& zdCUU<9_2+@8Ml^34d5%E(%1~2@7 z-40F;L>CJvI{h}TsCx<+SN!pRC**NO`6qxKQ9cfOt5~GCK_nJa1Ut65A@N#nW+pRO zkE4~miQEy-kp^KX_{JOxP4Yf9ZTr(lK5-yGeDWH+19`2s6^gsxdC7f<-IiNxXOP+a zOAmjb+d7s-o5ba&ZZV>%^WpjPEKZgQb<5aMC++LdbaNl}g|6Kg?0zIj1%{O@cy*WyF z+D`O1lG~zi=GFTzv||JjS5jTco}gqt<=}bkLm(x?UZBeVpeQ@>dD1oZ3c(zqcmn_tPU|}y2rUTYF)Ey z__JI!Q_B8%No6-Y*aA;2=ecr5Q6UzsR5VNauDei6Ohq0%~W z@U>`t(3%U|-?+=E=$qp<9uSVWG7}2Nwy)1QOgotucKdfHC81VT*S&LRf1F)4W1{K}`)cNvY3Zycm+;rkV_(|YE;~}Qd0oaS;@+|~o7#x?YMKh+@KAS=t;`8ey+sO)pYoJigHl-urP&rU?>mMi35 zb_n9gq~jgSy!i1kZ|-nnQhWZFvr~IA>Mew-s`km!Q)0Dk`C0teRUeX;<4&j2Kp?`U z@adIOpM<5P({YRd8Z7}gjCaGs)6ON6UpE^Vo$W1bd)-6A#mmhh=ppR?@cE?9dFoNA zzfXs@g8Qj&N5^Dr%)g$zFZPA)o7(+`RK6|KQ3rN^IYPQW!{8$IA|qaeu%NUt8(xz~ zBHQ;7Z{?S^QbL88PY{^037elz+-S~fTj)zb=ZVQ)4z`Zaxg=(6T?)mL^SApl!t4GK zp%nk>XDNzSqUQY>FVbN_)B@tHRmDJ1qTA$LY}Z-o;m4N4W-rT+korl<&H0-e=dmzp zF5Yz42Nc#L%7BShRCh8etE00Y(VMUDqV&W=7NOwk_2$2n7TXlbNwTJob-ZTzmAaaIDr%w SjoveluaFlr{Q)Es=&Vs2K{ob2qJ)SO%b+*|^j{M0P$JnZZ=0mr$}IAmA3A5zHw zU@@@-P@2*dF`*{ZpRzhGFfizN{|PK)_4fE5R!~JN#$l&uCC| zSzB3QQ=uEsEwwDwJ=Q%kH!`_284wIG^)pp+RFboiGx9OA4YgIUQ}9ak0@Z=WXU98+ zJ6Z=@|1JMB4=``)Z|a}y&#KO<>8|mJ^T@5sEo>~T?5K<@h;xp1j>(HjC`u@AD=%v; z^Go#$Ob>L7aCC`riO7zq>!~YhDw>?1T-{mS*xNWbIauCYPAX2CU76iK-ftOb=^5{t zn41^?56rC06f_i6byl?vwbl35_m1~!xohRr=IDFrYrAV3cpHEh!P^Jhf2aPA&Wv7M zUo5OI>>cm*P4um9udeT|ukEb$jP~1vnH|Evn zb&hnVm8YdwqyzJTjeU(JEhPbI0mtXZ2d4+kf177lXOGX0tGlYtF3(2)jqV)o3`2%T z{*5ecE{)BO`6T&tjdsni&Ht(TlTw;;czW2-*ASc;e0q6$d2_kEwLCOElw6Yh-R^sF zb8%!&)%ET5&D{-n0c;&? z?HK835nvIV5gd{kqVB4mQITR0@)?3!#G=t$LRt+SVpvyIMKzdjdkdB@FjSLrl49zfODFoTdZhaql!LhVBIAHTeBkoP2d8NK zZDLYP>fCVZ+z3J(oKjkObsN&W5`+P^ijTn+MKm$VGfmcIwm-c|GtHG6BIFd_0{^X^ zo$){4rhaj#uD5kjMwWoB7QT-?N9;I%z3Q485}p!*xzKtcd}sRx%PydsgQ9|uojO~r zcAnaq3S48$Pnm{bQ?M#Xj=iXhA{PAhO2&mtgP|ASe+#r?I$ItB`Wa=2Kht~gun>Oi z`rfId?V2S)&hkm|$0qfk1~qiFxm$Bf_z$+u=3=mZ!6o3=9QTdi9dFl;Q^ao!Q_3sN zF~4^9bCisdY=lnKD?)r}k%wGtIN29RG7@?COATgkAy~G90z|fF=CGV;7q#euPHYd6 zo|BLQILB*@0pI5jfe00z-Ws1Na2hciHBq8lP_@t`*HPH8ra&FF1nB8kj+1wto`m ze0>GMnNfoof;!+t>&(Q-$ga0zn$~5968?Z9^#2aiKW%9768l^_yZ zXK2>!BL>Xm#Q69sos(0CnoVSV!HXZ`KkCkUzM0dPJ?o5Z0C}GA^V;UzTrm^U;!aYj zUL*Jn;>dOb{i|Hoe5_!or&LYzcmkDr-8E2NYu!^?3)y z+AfSy^)hA4`+H}zZWbb#y{le$729h`-fMd#kN#JAD)Vc@?75^^&I1%Ek{ zMkNzVBB+zSX=jB*eg|cFFwL!uz{%&}=zWB5o13R;4dNT>3i$oq`@d4UKS+T3mBkNa z+du^a0Gy=HX_)_=d%X6ZP~9Yp^L|kV)XEr$8b3h_Hfh~RU{|_BB(Oaz*sL;WEwKKp zV>XSZRilz#qEwwySU8j+phFL)4|R{~=}?TAThA~I_Qrg*|1|y=T1CwI7`$())tJGt zM?N==R|8`AifsZ7@}Q+!9XdcdndmF8bPOaq;uA^BTCM~n!E_>vn^#-DN@rcm`OGfq zhP(kG=Unx$480CJ+CSJ!aWgTrbZezw1>$m6WMFSko8gj{L-hf6L)PAuR7_ z3poUdwRi4~GWi%!s?cKWe<_>II4t*zgapsHpsh1ty9@93AjsaBvx!(KYYcZi3CVLg z+iHCYl@8%K{RtgjM0av)TPkeXZ$MFb{Orf)o)%u?$%$}C@HrMvJh2{(gdYrk)UF`Nm!NNao4i`oD?_{1F8bKKL&G~ofH8(>)y z(CH13TYy0epH9pTTWAD?xcVigvVip`Wumaa{E@sb3g2F3Mb)nj8tM+=?5;WukgBSraRLIKUwK9S4x%mzB;iE!&Dc>uL9XsyJLt&AXz*um0 z-`eA+`vTRH@A6}flAVnK@DGF@hcIYMV(_pyfH3~XlsGIom#dw}sfvbkz9SWZi{qp( zA5&(MJZ_H`q>vBEr#DkR3z&&IYBUur5TssfE*gB9V#GPgH|-u|UG>%7X)q$H>5ev9 z&w(jeSDF+yOfgva$p;G1G>YB(J$viwu4u!hJ<~jp^J6j%&h5v(OG=cYa~!?&jw3}Q z0v`?2i0@tDIG9U zWb=xt{MrVrE9DalG;?#OA^sloPrm?Gk6Itg=c(*-_gsAXK$&&?QQI%bve$Bj8U4SV zaoa3StTmeP@66Mf)0M=3+Vq!n3-}H%0GR8>J^X)K8WxipZxu;))b|w{^<2fRGOK0_ zh-Q3+z=d6WJ0)$-Hi!oN8pI1fRY=ZKFDVML~>1 z8}r6M>7s9IF39k9sJ%t|(kFOSI51JYAFWeIo6=dlqa&A^KesZkxWcu5pqq5(j`eSz z_H*V8c5&0~&HO5PWXKkKu-^l0YWc}ZJkdEg2 z5F{z=jz*vujxC3UNNzw<=`w1;yBLtTyO{B@8=zX2{*Asb+ZZNtO zVe(fIk~Ew7>#L8HFC8%->Mu}YZgHI>JNY3(1_o<}$8l`tT(p3sEuAT(`2)oAEs=O4 zJ}coV>j~4%#RWP2lrmdEkf)(5!t3KI0-7u=KF!hnOf4UC45lB?qEDgPo5`K@&K&NL z7w<4kxKCK2lM0=^YC+PKyc&>J&e~emg0X#Biv2u)ITmeqiS(q~)2qHH?{zKO{<=Q| zg_8cM%yli#zD+fq(gXViUwI~|UErxK#5y*t8?-vXDx|O~zL+x?OGR1q;{WPA(5ojy zh9va;Nz6ym2{(xD9!UX?3Z2`asozX=z+e-F!kZ|*P3HMRxA zE^LZ^2|qsPzvfVrB7JO4sH5DIRK?L*@_k=NOwN$}!k1vvhv7hLIivI24y*LmLaR*F z)5xBKM@JSNP8^*$v3TOLi%MPkQDdliwwZ=UvHZeugnl~N@Tr4lIZ@sskdqbxs&A zj%rObqhe{>wAx@Gt$W<$NLaA07-75M8XW!2f@`a+qn%}*i4N@3B3)2rGkoThR(gCL zWzq?OepzPcPmGvm;XsrhLx0>~(C`eA;*`@s>AXM6qUwEc1!bH*1M&@yS{JJwk9A8- zvXC!Mwr4)&qLIM(;?`3_ooZ?)OTR1YX0GM5_XFxoG@3LbG7GQDaob6tPCnTtBFnM| z*6|P%IbygX_hJi*=mq{rJu&Z2dJXDQ4$P2t_E9R~(87JHsrEi@^LA#Qedr9(MC-4qej42Tr?%PaVTb*EkR@hJuf&(Ja1LlLGSUero^<=aqAmSC zmMPgeJcWd4JMo`GBA~9$QCr>#9eSgmX`8+rr3hM|FBr0fO@FgEAliFz7NZ~XS!ZU( zQT07i7FLjf(WRe_u4(V8ekCE;qxr+)d>a~GPC;n7*=2F-vD8iX#M2z2OJ_JHt^Jil9>~@TWMOKU<>qdo3&HxA}+DtWlUK(5g@uk8Y$T6 zt83CQsL%}%5itDCyQE>~HY5wJd$_m9*yG$JOvT1D=pX;2|%>Kf1+K#m^5;KjJP zh@lcX*z!hQP@;2NXNqnNqY^06&9rBB%kS^>sD&Sf(QJkHxm3v;QVJUh%UZQ{?9+7Zd7FatktH8@j}SGjR&x?9os- zvwQGHNI34scg0cN55;+Pkh~@M0eo9`@Znb{RWS`iq~d%%C-V+91We$}-g9=IuHwBk~@k_K(&;TSHig(Wgom zwXT(~*Ji7xY>ntyrjl3nM~E8{N)(@w{~IZN>OFp+I>k6Gi*%#c4Q%hLpTmrdT z;&Jh3$#wdLI*)TXN#;4R0K|t7=a?U31+CJ9(eU<|8>Fchpin#OH9f)K0EaS|mPw}+?h?R7UxNynQ? zI^H<=VhAXZ>@|*RrUVT6j!#}+?tTSMREqsZKS{^D=!<~-$wtisgWm= z71n|05QwIo7485s(`~lddAQV(2qqaywr-=K7z3=vd~)j<+>{N3YQ({5-p_n6K7JG` z>aG|O(Lrc!#wtGjdt4ck0zI}WjigTbUgkb!u_BB+w^s^S>tQe?sYKC*MDoIJ8Nc%B za$#{Iu#L~sP9@v7WiPr+$WcBKlrTo`t`W~Z_I5i4A<$u*xguUTxI|T6LS);^jCe}2 z>%X?|VR!^*7%mrd@f%rXZ`d_aYmI~>i1|f`qhUKFnF^(Osvx&`xKOK{f5p>B<@$hl zQ}R&GYn@+&{4pO9;Rgxfu8%jpPCc5gs~X|Y?!Q%MgcD^Ny9qj7&VQ|IL_J-~K1rbV zW6s~*!S^zNeGsve2xEM=1qkk`VMZ5D(K!yj!d1ccz5sTe_Rw*=W2E9Ba7}B2Ra3te z$OUO~G=&l-qJBR9t*AAXT?p(RJk7+5;F(a%F&L)5Zo8W+m8>uv5OS!)%s^Je$1&4F zCQAg;_12j8qT!73*nE@JMbGs|Ro-$Uy-FK4wKvDDqJuO6X^zPp8jU%GVn-}`^FE8JWaH2)`I-?)`zAzKBlUwDIjS@)Q{D$c?=o_>zG=9o zJ{zXmuD7o|m!#s)Lna?%yhK06XMbD!#Kk^ybV)O&A>BBint@Gs(>dF|paHPzFYJ*t zUc=8Ox&UfRpbx%$R(-3_Kl@}pjvR+_Yo-P2)Bwf)e5o4Rw1z$B-9@@CbR4*p{}&t? zMxV_gI?}=FP9bwwig-e$SJiiVg|?vB*cN}$B6rkXd-}CbiN&~EFL*l0X&b#Xo-CIa z7jFyoaE#&@NcRkey9>%OD9!pX&0RYnVTesI2%qu6gM6`=2IQnDOWNEVD|c zVrUETFwvkR%^Y;2a>QU%0v3yB!>R95hPxyY=7g4UUWWJkY(pK}!(9#j#+vd<@_C8J z1c;^$a1NQCYXB}X{^15VYLe(z5+|^exu|YWW9Y5%B$RQ!96|Tdu(-cvkaGzA-IxM~ zg96Mw=lLlGfF}~@+Gdsto)JVC4^C4?>sJpeTNd*zYSD&qKVj2wtFEIH;ZAEB{TX%iAgS-oQ^^)Z|D}SETb%dwFow7IjODcsCYeVKKmU+w<+pJ(z_}L3) zeniX!pd#o{=Lk7weo;hg=%0a0Ks_sfO&4-<@n{W%?QtmQ{=Oy2pY=!rhU=)l`1~7+ zfxsEcN9%SW@MW+4AVp~AT)0m7^?e|`ja6dHTbyYj zp*uF}L~|&D<3-tekSy0nzBN2LhGyq;=h|BS*Z)DQM|4Wsj~!+~CPNjA>sI}9YR&-C zK}cB1?Oq5{9jIFs1V0Xbta5=-TbtK$i|qfi|M6Adk=9KbGY7`TQO%!>E?Z z2$W|w<#(x-PT~o^DXoclMl{2nzR$wl06%X%QUbz=D?F;xi}aUspIG-S%VwlH)1xY^ zL*BFS{&;=?zfrM#6FuA^`MXA;8*y&P!HWH@y2+azyF)b)wy^WA+%Ox!+gUTDy6i3Y~m7 z6$0a^;juE@1Tlz_xoF{frCX6;gAht8P;pQ^B&f3>JPAzUgf(Jdf+(hCU6Vuihumq?_OLnuLDC@qv>E=SY?|F;!$Ni)^GeOiUuu1L$igVz;GE3wp~_&Ha3VSwNee4 z4@pEyNrr3xW$vUlUT7uZ^){o?m%^i!FX^C#Gi1lV`h6N%g(DyVYRqOJonBp|sWf45 zMm$%GIL$D6uz<9q3jb0&3S8N*hDKAvE{@S!K(E)E%c1(l+BpXr3Kag{Xe$~ z;2K_&BP<7ehYSrO58)MsIz7?sMS7U`*a??}{GpM|4b4b)=1)?{4e;=G=A@H!G`-SA zMy}rk*?XX?&o@Dw65Qm~HSV7Qn5Q|LLhnt)lwd5FLn{iYP?y6mAG}GiU{6njY8A8E z-`n^LvHqH1n&5%gKB`_7{GJvn8Yigwai_UX^braQ__3_}6rVDeK|x(4`bR{N`N{lE zxqA@utX-p-t_M>*CGF>Dybz#{;Wi$mJYLt|pt&u?@rQcF1Ro}jT$t9;J;OzXddb#d z$o6UPH(zq&s`M-yQEnuOnYul1y@k1M%itesn6k8y^5@EVvN12t>kvU3G?;IM^)J)s zNV_rHbEpjJw0I?^z)=&Rfur*6t2L*-W7IR2 zxOmAjb{JGfJ7r1|$C1v)YvaiA}5J2FOzX3S-n@lDuOVHzJ~B> zZxAez(;v)Vz0<6VU~RHsDS{?oHGJxw0TX;;eCMm=Pz-Y9u+Z~QXZ6HOw_(-|Xwg_# z9WVyV38Ucb2y9=zVEwx3%(^8cP5vI3nauKTT?jZr+ z!N#aHrxM~U3I5XN{q#c9qx@uNL{BL$^6bwd&q#t1i|<1#c33~3pGIZzW3Je)SuY6v zw^U&L_OO5u39D7%ZG)3Btkw|f>t>ugxlWjPSJHB-InS!_`uB^h#0~@M)2~}m2q4N< z=jhu*-i!>~Ha3(33YobeTCRv^yL)oGdTG|0mC%OmVIJULqV^Y)~9@l*njhYPv>#H|guUFsFRar`wLk$7dfy}a@KR& zgWZn|zT1D|f;+qaOWn{~l8lX(a58|8 zZTYE}SMCDco)s?=Y&=oKTOO0ui`Y&dAqH^yw!K$AxvsUh#xXmJxcon+I8P=8F0&Uk zRhpP>ap9&2aVUzgcKni?Oiy63xEIlRIS*%vJcUm#*7EqRq=PX+DINEq_6NOqW|a8p zoGm(IRJNsG2uj^*C}(ab4`p8Samw5hB$T~2@bAjN2QaX|JR2|7UV7hWw)>$Q8fMG0= zM0(1cPNax1Pcv@o6%~=c>|)5xQaknY{>(G-ZQPZ9JBI*puRWCK7j&1(&iB^;4sT|< za(8*5{C^SSFw!t#u3uM0q*w{9-wvme6)Lc87)~?65NW}LGW;FqOUr+ch93^=|D(U- zF#nG(ip$)>!VA5ql8q)5C}~XsmuaEg4n}o|QUSQ&(6_LNgC@k%Hkv+!@DkGmF6R*} z=_8;xM5zH>ei5xWKuWnpQNPI3%7Z3$+c%oZ?kA=A#`I&_iH2puH2^N!s1C$Bi+YFs zCqCcqdE=pPz~|mmHY=b(tE%pnC0tu`#Q%ck|77cS?7tR+Yog@jOLMAe^*e>1F@NJe+EV-Q=C0iqSQD5RC z{m)*vph*Tt*AtAVbJXVHmLwv-r^8vM9JpL-AmmJRlv7gb;;{czCz~Fc{+!{dD6OYOp)F13_F6V2A~xAn!x5 zM->MV@XCyu=M3LXjuwolTrph=t$2pGZ*D-YZo}up^HrQb;o<9P$qbIm<;Z}UFmO_xc@6n8$+cPuum->dW(~L6{n(~ZzI@buvO6iBo7p}n z9{J~j%;m8a=Es{=VpuBUqmiPUo|@@#JzsJ9(Oa!pbvnn$6oPLpEQff9M@xQD*?Sfu zwc7K1FGG1E@HjSg#A#}t^G54&mM=UtDDq0wOnDZ&&^5YtX0sZB@R7#8m6F6jVe4(Q z!FO~Mc}PP_*j&u2KHHreTfu;mLMr^i7jDH>*mFPF5mVoyDFsrrJO|v`^VMjIK9ulI z>slITofEvnKV9+qimx%y0D94Ms%%0(KdPAZ0JI+@fLPVS`khuijd&b*cp%M=+`w+W z!?csc?v{BKrV!a$y5qsgZpsdqzGfr~5B$a~sufm_Cw=w>#HN*<(<0@FbwQtE@U)wApY-A+cF|)PRrD5gM##I2$uVkcI z1B8<olSu4|l&XXHvQ1a8T^Nj9R{N4f2A-p!N?4Jv<6qt&YBg1-K&-!p$L z^jfdIu0}rpb5R+v%jlYT*-3W3PMKMk{kQ=fSur}V5vB6(&+z(F{neK0z%}Dwa`dQS zGOr3Kp&>QE;2P1y-8?LPU!EkK^cKhpav4?6vx?9*=F#oqukmtrv;UxAht02Jcq-`L zJ=Z__{y3BC2YIMssk|LcYTXQN6|PiqoNm;6zOp`Fh@D>X`qSj9=N%{6#(5lECa+|1 zs`LX~c&-K^Q8&tnEF~eCP&^UbIXMGso|C&;sBWCSK5*!-tEgW13hQd5YB=Ul8H&2E z-EL&zckwWh*;WaA?~XsDUzrWK?n~b0)-pD2!Da4IJiqbWmQ=}A#`xK%CTOSsJNnyk z^5TK% z{Cjynrl>WVsQ3|cnFP631cNTm1iU0tk^xiL$-LdqRGI)L?hoD7G7|Nzg&mERs~-P* z`*X7!A2RQyjruZ0e{04D2PevnxQPlt8OG@#oKQG|_a*Wkn+*jHby3cUjCSZ69qsaE z|CZ@x8nguwUUr$8^MM6eo z%+hYu*T!=+>$T6dl))up+I7z7u|wPVUDZQp!lMPj6r$m`6wkc#K_zjyDrp2!TXS?s i$sPJU;TO)=ez{r@Ix#vN9Nb$uSxGfGICvV^qDDi6A)$Gat+0*BRZ81c z!r9!!)yl!1Qp3v598TTDm6Dy8Qq0YQl7o$ngOY=jpNo^9;|nD-8#fypRp4VVJnf22# z!Z9j0s;srF@K2#zj9YS9vU{w1L{3CvX`*F_jtx=P2jsyy)LW zzsp<8%Ua6(ll_BIgB-#gT%ujVv%>2@bwz)QCKe}FcUCv{HV#e>mN%CZiWBBn=J${H zoBNwVW1#Vc@&2j)xs|zshJvb&s@B2Q`tJJfv2K7nAiFkO-%DTHUE9FhUg%u57LB9_>zpr#E&t z8hab_>hn5=J5tJ1QY%tp@?#o%8cUi>0#gEy&yEkE2TgrV^Q-g6r^nTu)u$JyBeNqr zhdV2(joM)p{F4vJp_6Iy|}(u-dY}<9!xAr z{A&BPxT!cIJ7QpZ;N<+|;ql?@^6dQb+&{@bI4yW{e={IC;O6e;{^9=e`ts`L>iYJ2 zYH7+U#L6MU!937BBrPN~JygS0BdsFs_U`uf{?;ng$~x3~Ykv!R4h>2Pnt{xuSEhqE zz_neq`3?C$GJjNeREK4RSp-?c6~=kQdGt^A#}~)@CHh6?M0&<~X4Pc5#<;3EtEE+@ zDLE*`7Q|}0YW7U@WY=W-Ci<#7tCzNvRt14{#HNku_@-DD+S?MFlY$C?CP`L80b&1~_8##>MMs1jbGVq&`7ywxp6m{R($8waIavEj=EWpnWkQ2PtSSWtsPH;fqqXT8A|@z zfOxmWTuH>J zUC|PcJY?K6$a31(vBCH)zEBQ%ZI3A8>6RVojrPT#kq`Wo)?}8S2?(8VtMGmrl1R~$ z$}jNuC%t{V+}3va7#Wg?nLO4b(XNx*jMajfhOXdoVfU}{ZEQJqF~58)as!+I?8NQ9 z2mi@k%+a*c6c1kDqp5s(w9gSBi01xYm-BI!XCQM|sDoF+xoK6+1tFSX{htC@2dZQn z5E2bdr{u5sqa{awFa>2X+E<3KPL+s|JU#}lfn_iU(gbv9sR1r?{sLErnW?{4+OjPr zE>>J@A;PD-nx7=8GemOs-rUny4{0+p;wEYiDbC)_3H>$q@hsq4SQ*YcrEY59Uo%Lz zpvU{(<~;X(H)-sZXHsRQDK-_qx`M!k!;z<0Cn;I8kABL!JvA{?s)qA?+=lh+%~;*Z z=63C#(uddg{Zqw%OL4!HOE@)s;n4T6QJPp5lyF)XE~3>k%go*xA!_<@g{I_W-A%AA zB%(#j`rH3Ob?wWxjTD z%H_vYUx9?&TtPvfTEd8Ad`UQEqBr%tAiq~+=J!vqUJ&FdaPmHRk?U`Fz^&v46x&$lMkBIzE;==Pn3I z_S%e9*izHRH8Xj zARvH5HSJ7LCPJ^Fu`UQPz6Kr-JO86tY%R$&`r#`*t6ok^TI>h192Y#h`_zEPaKD_# zHcRtqRBVlRfyX!Wf1W`qrOEF&4KRC5sULvjt|H0 zch$^v8kI{Nf~wW)Qnd9A7QmIJ1Y`v+l0VX`52HHT&A~z6B=iULfZyu`vqfuSBVLHx zT>pB;&H8DAUOD`H{Skh>vVFPpuyQwfc?t2-H6TlS(%io~Bq|*@R$a&U=MgqXpW`tc z(qZBs7W+*Y*X1_%Z6!q3QIJm9O&0wgG5_4#lc6}QQRA0;(ZLv0?0($gs*S*c$$C4X zXnpMk^i^;l7dj2ZZO3l8z13oPq0_WN}zHzCe+Alr3ppVsUmo}uSIu%F2 z(o-B|FMvb3JEnPBh9`6U$g6jVrx;x;UF%hZdiqzr=xcg1@~S-&Ouiqu$vo+Gtus`? z8Alo6JdsKVw)2fCb3u^UC;oXX6w<^+CFb0(#ny-<=7AS)G7Br6^VZwC18J&45}nJW zIsh49DJ;_tid;A~6VGJ$ZURZH4;q~5AM~0))a}KFDeL!M11WTj-@t7VMtI-(t;dAy z`Vg-wCp@jb4^sMa*VW0b8e7}k;Tal`#(s}RP_f}C77Pn5jU_mfJ7=hrU(5k$ZVCx; zzCL_peHD5UNhx&mXOi=@rO0s^xu`qjq%KVv`uHjuTe7Rfx`(dODkx>rP{!7SFgv)Q zc=Ni9qMV(t8tIr@(vC1Vh=^vqCeowO28ok;L>ND>}2!ytH)zH)1@G=3w%SUPTl=1x>Z9IHq00%Jx3} zqR58q603fZx+#Wlpc?G>?AK6POT;I}iLocvb_2L7dFeWWX@)|V0$`-+~| z(PG}R(PeT4FpqFXsJeA$bb$0q0=2m1YSz0xxAxTKIPW+oCNZ6($hP~obYP3 zd%r0*g0;j7AZ>SR5ChfcoDKfKOJ?VDb^y_y*NSdy3J6}Rui(c_!E5K?-lQOr(XoAz z>Ca*IRzkT~pJjRnH%s#eTLfhL<^YOfBiE3n6^D$ha7a2G$?uj$m$1_hzb^BB0uW@_ zSUHR#dHRhuCc~ejn!=%VC#J~-3Bg(NK-|*Vn?;^Sy+bv7%!TRrR1>{TD2~wuu_ZZe zuFSJ)OQoI8HlcpWCDY9H5C0v}As&-u%VE22sh3atjg)kspq}_DbW0ELXlUMZL2tQO z>A_6`I7K40%Kq^lTdgL_LaDU1TYV&m+WptWC~AnV7~PXvJF@IS?J!5&+ESlnZymz5 zi_D|mDGCoya%x;1dBO>vepz~_2WE7WP!O8pQB|EGk-R?9eq2-;b}EKr|mOv#rGAmD^pU zap#1QRmrx@V;ZjpDHy%KSx^-0lt$4BYhCb~f^OxV%0$)dh|#{AB#3xnVx&_{w)SwD zwNct5LtVONnO&EnC6teQ>N~o6FzB2ZE!Y1h`)hLXL(8+)e;oEM&ge2?dc{AF{$!8P z6C)v>aNl112^#LYjWpn4^qwmBqhK9qajtLu%acx>7$COQ9_EJIs<2iDs&^JG3 zdt^H=j$+(HZmV?SIEtPJ^1^GJ90JU{sw?W-D$fKYJM;i}Y|+7?BI3zmO+^XCW;q=m(z$70PQ9U}FW-;l_!ZG>i7gg^Rpe=!9xhToN z!h`+?8CB7b2Fvggm(G#H=e1Lsq98cgJsUh@d?k&vM+NnX=ifhf8&nyl-a)8^*))Xb z+)N(0aVgCWKZ%fjK6E@j8|SGVY<9+@D{Nr5?A-6_EgnElCmY_8`onDVMpWR{8x|Ud z4X4vk?nHJPmrwZR3V~zK_(#jQe#hF;F2nP+P$bzO{z)qP=hE>x){cOHvp7RC5At&{ zI<(ea%xPF~AWP>(uuP^8EBupH!6`{-?c=?~pybzh#X@_><~tU5I3f^7Q!J~nyz9du z+rt#D09G56C={+P_)Vl*AP>qEJVN&Fw%tfL0PP}8ZX}blZhwWmIzV&S?sGizTVX$c zz*@KIjx=!?9c~&*h=9z;V{|cTp7EnVf)==l5Wfw)N(3mS!BGEZqTCHM6NzeH^tw?< zP9-QiAQ_`ZT=9mxb|x+RG0M|)zY-acDo4@IRq_!C_EQ$SC2ldrYq)F(Do+KX?oRWg zzUg=a6Qd}Aa+`=LE(70`Ri7onIC;!G-h87Rbf#^zq9z|1)ysX zm4R}W7M5aKB@G+cnFrgfC&XXNVhdx>0{+uAxm2ZSIzrV9<@#Zvr)jU3MdA`C0=!v; z+BrSQerIp$L@rV@t>4S{WylU`?N#MB0&Rf89vClAnp%s?a^1AE%Y!Ohnj>fZ(XB6Z zb|)`MN_gi2>bRI!YGE3%LWjGex`>&W9*D4hyy3fSll*CeI9OWaW_YCICA)ExSpr(O z&|63+GX1WQGd^YbP~oVzKEX7rmIf!<#joM-bgQaGsO65*d*nV#`*pK0z#QVwP-3*) zA2E*kB^Id3eb=}+Z&s9LG0Kq*$aymqgT@x%NnKqS3hkPBn6~$1XIz6TMx!% zpDh>ksDrcZR6Sp4?1?|~V?yfYOtRf8cn?oHp8x0sjaN;~n8!pr4H}L-Rc$5-C#o!K zJ>4WITGz<$$qMNpvhzn#YZ|oQ%F}GNT7P$`BN9k3lx*2XLo>FNxw6g4|I%pWTjUU) z!+v+`0C)e2p7+Ut0-NXw-?h8_K55*7E8I0;G0&QPOZsN&KoZMWdgypBm9!HJo`Z#% z@auS@hc$P-w2UYsB@P8>g?%~PeK2mrx0erF?UPC@(P(>h*=4Z*`kEZ#5NP8a0Iti- z{tvf4k+u3w+2cIt2aElv%`BB!JCa4--QzLSjA-BvKT#az0jsL)W_Pq&6e@1DHT<3Z zJK7^MnIJ|Jl>7h|e19;#-IQy$Swle1=lr}3hge#hB(X^QJkry|rTNu7tHv?~j&Z=d zFK=&USe3bfpG=xx2iE*3n~~D0H{$Brb1gJ}Y>^|061DkKp^(XdG$~Ukn1#lD=(d{b z(A0E63(HGxVC8Vrk2~=ZAM149vrwe-Bw?YYU%0JwQpIV{3c7(q6*#JG95Utmjx@)% z==Hi<&bZ*&-Q8-~5BYE~zwTAQ)oNFwNES50p{Kynkrz`bhchkce%R!vwzH$C>Do{PfL-GivN8!9dDv%vceIb9@w|j_W|#;7@8cQ-T$bbNFT_lLJwrlANMW+e*XRxAcKcd|j_2 z(je5GM;{>y87Q=A1%LKav%$Epi*~n*?358CPgSj z$lLjwxCP#thKedHu5+dKl&=np*;wQroCpc0Ql!xn+_(`n5zGm98jSO`hBr~h9lO|U z@jC7;JK?-5&tiHWHPrf z@#@vQ)NnHOi$7uK<2&m0*Gs2^hs5ad;f9S*CVvLQDw;;HpQ}c4Vev3OizI5d!2EeG z0C}i@tB`mjNsdX|+ct4AKzD6jkWIMiX!6FuY@1y0h8Bvq7>CVg3bjR`tk0zE&V4Sn5i(@CG2q>f zGy2UBGTE0ss+^rW$GFuaKK3vQhGCC435uWgOp1CW*hNcf%mNj1p{ zoIdYit)HAr=p`aV=<1iA?1u~eMmPWqps`+P<-Bz12CO+L3N9l<&x3AGxn~ndY&6z) zR}>OkO9Wi9xJ%Ew)Prziks*Kckq-tl1%sE`Bp5GNZHgS&ekWHl2PGaW`mkG!G5lDs zY>|F;BYn`pC^-rqY%3Tsp}i)DQn6Q4Uh0~C%SFY-l12BKOnJJpp#2y*%~Cn@-1lo> z_F)~G`DB!~NH+MM{5*(2R3YV<#_;k$qJ)^0`vPSxB7#^)RBZZZg7K&Ncr@vFF6$!p zH}gcZEQ-8~RmYG@xy4HR<6HULF2%_3h&Wc=%bPEUo_~|tFVVBkj!9V@g#9KOBM>Ka zZTp`yzxna73EH||H>{|#oy0QN;{vyTYG0p}is*CKQweYAE-gi*Ua&UJt@`ym`D}(F zB`l#ei0M@*0!7rGCTj=`4e7}B*g5n3-=-HGF_>DAZAq8Bh3FX>a*hQCp{b0K;Kv^K z^78eo3U_zzbZgfJQm~B!O;&3Y2){AzSt$Q)QZ+_@0&iXSz7DdQ8h9@55TRWb7mC}E zhRfOZGbsT8M?3sdUS8szqBRF&xj>(H>i9RrW<)pJ0G>put)o+ zy~uQfOi4s}EEBA^!2rxfgZ2iNr-afpU?En0`;ash^HeOYIVO$+xd?{AbPe0c0Co&T z%Ry8an>Q8KtvS|%3%Lk@ai1DY9P#VfLV1v2RLK+y2o{D9sqKzdp!hEOWVs<-G~AAZ z!^`2j0uRj(BuN#14Y*aEnz#rAfv&m#mcMXk5X8Elz(Z*$Ul!(#GZ`+om(;0{8nCdo zu~K{D87F)&2F%|gys@Of`Mhl7x1~RKfD4ExJDx_unGz-)OLMSP8Mrl>vy86JPWfa{@%Um+e@RsD*N`~t3YJWt(5w(P}FzgH;4fC(Mwk1 z6ZL_?c}ZlMlBuv=PW%kL|Ewr9HBfc zu)6h!@F2~G~hzC#EHh1R{iuE9dS1+~zEL zRkGho0JqUt%wP(N|K~s{VfJt2zZ^n&F!3R58kW5(xo;)@Z{z>U^iO(U9?TmsTZ0o) z7*7lc)*T^)4?%)N#@KQj4bzS^9PuCXzup{An43vE6VW)v&lvxrll0`B%B4)5+%8OE zPc7c&2Qyybb?mflK@Zvkv%;&aZ$5emkQ%}yy2dG$I?KUwSYwfU@+==-o3aWkoG zU+oKhS-nE@Kc#T!@+lpi%boj-!Mm?|vQR1y!BDmWc6p{d5SkuKqmJu4I(pqKJh#g- zuP6tgX8jn-`kB=&9_dhGwGp>C&*xD#3uxDJSL0pF|NcZ{b4Cajiv1Pguv1YpRZsN#=e!?fW#-ySs7O{CwXTgJUD5ws+Fm*t<_v_c706 z>N0VJ?{SzWIRB7U!pQTbwL-@N--0_zYC+g~SqKYYTnPNUb3uIa@@{`mu;Mm6XVR~q zB*pfcI4HW@H`>lkU1^_S0)H}LxIKU;-**zLKS^ZerNM6L0H3L|Uc5U#&Z|z5Bk)gp+6E@*aK9Inyp_Dh6ztkXvBf&`f3|d*7q}Qc zBb^xTG~VckJl&0LTQ4Vqt}TbUqyK!zkKt)HFwcA&jWS_uTV{Fg6yFY1u;~P<#Z>WQ z0=xL%+DWIgzVqX3bK$9Y_m{A31%lsk+dR>`ur4)j>JzsUU>|<3=7b!IYA4_e2R7Sbk%aW@H1x|`ym(NhKoYHMpeYD7zWNnZ5$RK zu65fN{iN!9PB`X-vIp7xBmdsagI{b=Cne03B`0&tooe<+py7q#3wzS`*Gh{~c1)Gf zv@W)~+uuT02S+Ri!~EHmst(XYc}>lS)Jt^DA`ZRG3Qyj@ReAJhRDStJrMoyLFv^WeARIghR0JJJ(lPf6+ZoM5u&-P0)h?5)+yA&85! z`(*y(nBJF}wEBHBtIM4g-lZM=!%6eu&vhE93hq3yi66sxvjxGlweI#=auO?2>61PR z9gS<&-oml3V*4t`=lyX9{~jz@9FEpRFiQN{Y{e}``cHAiPHLlP{I2QLK_m`1`>_VyP ymtXsvjnr~XCIwMucY3TXJ@jSo2jJM2#oPEJZmvP#@I=>Gv$o5ptl literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/scaffold_2.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/scaffold_2.png new file mode 100644 index 0000000000000000000000000000000000000000..6a1e91d848ca3eb43abe2301f53fcbf720b8143b GIT binary patch literal 7260 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 literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/scaffold_3.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/scaffold_3.png new file mode 100644 index 0000000000000000000000000000000000000000..c65d235e0a2edf9d25a8967db28b7f7890d5779e GIT binary patch literal 6715 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 KT$PMT(EkF>6e%76 literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/scaffold_5.png b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/images/scaffold_5.png new file mode 100644 index 0000000000000000000000000000000000000000..a15006b00fe3b4aa2dcb60e957c0a11c6e6a7f3d GIT binary patch literal 4267 zcma)9S5y<)wgn4VDEFYC2vRLaAqr?fkg6acB~la#O#}%o)DQuYCPiAL_ufOK6H2Hd z0xG?eP^9;SY9IvUh3k3uUf(%q-1o7^-eaw?*P3&#xj%N$6HR62GndZL(a|xhswisH z(a{UimcXgww1|JEB8IjJ!<3%G9y+};g<09#@#$JYU(xB9!uUib_!L|qd}1OZVtitE zr0(945|iWuhyX=I_7&UAEV*^U-{-?-;K zEqDT=prJrVSNh@XzUfIix?{#q)OD418?QXFe57Kfq7GHpch!IK_Jw1JqivwAnU@*Z z6>Rt3PR~V8%TdeJ)6_lE{e9|thhT@$jL-s1K~80k3&JI?AP)Wk9-JN=gN(8CvwZ3G z5@ZijwN^FpFtG`+QMXlhk8;l_%jg*FsQX-3(^}I%+HdY-UWu#3b>UKqQ%V|3UWdO< zFH6rs=M>fzhG&O6g*t_0hDGK^qA;j}ngXvlFW&@T`yhMgFz2Aupt7d2+{)ap;jZ!7 z@yYqg#nr{psnO`X=)tkUg_VWsmg=UCrp}?xmY$Y@v4QN0?4tT2OdF;gTaN9(>cREW zO4AJ84WGlG8@(~=!S~E8&V1_r^mX9t`qui$w~_gk`R2~%@tN^&bKfRrCz{%uYCqR@ zk904SmNBiEvFWk7<+)yb@8sMh8i&p-&#eDaACHPp_?UpmLZF+``PKP8@jfeSD~rU% zs!vseiQ~WkFvJ8w!XRU73=jb@!izI zly{u>_nq&%l-{B>cvi60ZmJ7n@M*~;I_ z+TVJ5VVby3^o{rJBlIN|CgCUXrH!Ro6;Jm88MKU^-4ZjqQzwZibrnnu&#p$QmS-N^S0H-lOgfO$@z_ zd27cB(4aYw9;U6SLnl8!VnMTih^nH3t}B5!PSFEHE-^X`tvq-lA3AX3eL6oyo4*DL(ZK+Z-gAG(LcH!xChfpG84O_%sgE_ixy6jm>7ApEZ zS{q8r*nyU{>o?CN>t2Wx7GJo}gRR|y`V!8r4$H|rYpCjSMXzBhU&xTxn^AzGlR1jL zDCu+o)tH@ba5O({tVzxTbDEq>eLYe)O?8TbvgvT(u(p;>CSOgl90t^6u%S7gl8$t?fO7@-= zNeUj4D6+LugXrt+vgySi4BtS^O##Nl-l2r5z_^ayKj1eKlX|=h!ga0RbmlM$MO)YS zug0+R>I$9x5(sH%v{;n50AkO^kj)E0qt}Xmv_lh1KB3;4*R4x0=^O+?7oHW6C@yQurWbT0s*mq!;z z4S?gSX6WZNbdRS5;(D8Di7nCQHvW8_{| zozOWU-_z6BlDjgTXrge-y>0&`zZ^|aqR@(kIV^{?Kg6KH`g`}%Rb`xPd9-LZes#L6 zgNL!@Ytl7Kcg2S4@NL)ezOf43;na%8cJTLu)b~X*r!?FUhRO{Riw?X1Aq#cyD<=08 zyWAFpfSh;dB)MuXP%#7JH>X@$PpGU|>&Z{9o+jJ%ZrflE0`0g*Pw%Jq~XmqZ?|Z}8iT#0r0>J4gOGe^T4) zg++NnmQmgky~)10a{ys=_68!WuIS4Mmf)#=hDP3^`G|1 z7ZoFofcpE78|2$8F0CHkdn|Iz+{{rkpc&g*A{$Z^Hw{B+g8)(W5}fBO%Nx#dEc4zv za|URb$WsE&f+4hW!~G=fEA*+AJSsVvfT632JjD-3A21-{&YWhlC8Z)DRMebgx(Pt;mDM_0e&~Tn5gFuCK-^|91!qC(B#kM;6Bu^%$3ah_3 z4C^m5;Ot(VOwIBWZzzg?kGK>qv4NK3f1tdV-FfAPg*uC>T&8?44{({CZC^O@No#b@ z(8^Ub*rQ7`A8aEU#tb^IH>Ua>w7FWA7PX6O&sGZD0Y9Kf)nlh_p=0`i{#bdYj&iHE zPtr+tzKnpilgOew%#=_{a~gaM++s0oseAVTV8)+%)^_Q?HKS@-el^wM=;e<&phzx}te{F3;SE`I=~aiPf*55b+fY*i2pzSbhW-z*mq zw#{Oo=c=H!$IgPd(yW6r=GkV*eTG`+zADi8oXs%v660NWg#xc=NbF>LW9Zp@%H&B- zhKL}C_CaQ~l!6SowYE-Rki+h?xnsa#ZKp4(%e-@VrSlE8*{$llD-I4<{(o~l8sEQR z{>ni5pIS>GnjB_MG5vE>VWS;SNg%G!OCY=*W>nbzi);Rn=ig5GQ>&ko9J_Z67bYn3 zf49gJN0Gm?}yVr6YcK!h!#mSb?()WYY znMBX?)WJwL=UxT;Y<*S%hTbi#xc$*1jOOibbx?VBH|ctl-wv)T;XM&+JM-doJp?cU zS(LK8ENm>3oX2B5y!-Gz+Q9wwj^Ir#P8H>Tg8+Dx$?Oh#bWh#0@7~nw9VG#^t`E9f z3KB|1g-^EhE(nG^^c{G6xkamFw{BSmjr&40L6WT(zD5z!mfM8q*2Uj& z_iEm>wnQK#xq0*;cjg?@&IpqqErbZT{MhSq?4SH; zOt2f=_mEpn4jSP(F~Kj>g%TPbnvZ>lTWeS#2N*>}q}i-_6!7LHDl2PJGwu2yc7V-6 z3YEoRh3QeBWkGR1*A?7NymvD^S83G%&IRSSx(1aYcsicK&w@zIf%ot7nb=x~70Mu~ zQ@!YT9={7I_ADIV>q=LNh8tuKtx9<{dj}N|X<$O0L{j#eRCMsZ%HNs85i^+kJ3x}p zPKzfxq9r&(AO-`q#;A+I?zv}n4}w4u+{Qni|Hzu2ngUi47O5ta<;lE5E}Xvlq*eOSXArqStA zmZfcUR3ki}@v>E0npYnye^MOQhZ_Ewe1mP>_1MXfu44W3qit2|@>AVA0gnr%vfVPa z9c+oJW2}vetf{IWjH%^H`02F0QaMnpkfztIJC)?a4bR=Drq0#UvL9+|c{#bs_9({1 cDqWdKHUX&^B$AWC6wATls8GaxZEIx#akH8&tFFf}kR-Fer%00007bV*G` z2h#xx6AumT>Ts?A000SaNLh0L01FZT01FZU(%pXi00004XF*Lt006O%3;baP0001B zP)t-s0001EgkxiSV{3$KbBuFqjBA9Pgr&8mt-YUHh zr=4k&0Jfy1r6tj(xgV#d=l{sR>$Pb<^+u~7O_&>#(=_|Ww~a5QX^L-b;5eI4(>JH! zvTqvWGZ!>-V>ux;E|tcfO?&1JgP(nBnuSlAi4(ZIZ<1bJ>{V-XPtQxU@QMX&;qswsTo6KSkw+&!+G9X*d>w&zAjp7R&xm^7w=EE;zxabgYJ9qMupVBx|%M$Cet~a;GnTF1U}~V=gx@ zsnvP%VThe!gGJ7L+*Oks~1S0&xSam%LT4qB+`@w35j8(4C* z-h5?izNR*e&1ERQ_|5XdCi6f@oN;>XOPl8E#Z;pwTWr%7W6r_Z_IlMWZd1-SIosD0 z8}Ccr9jW^!mvx~x&NquOOW8iUloGfo&h6v;6OnB`gisSFR-X+aivG(Kplf4Y#O;pgObGsVvUr9iM|NP#bORo->20y> z%O*oqy*s*MTU;SiM&(MiB>Egp)6I4*fMu}F&D^HO4gm=J8uIDv}|MtLlBP~L1^hv9gWcM|TE!%J1wVGoy)UL4cj1KnZR%5 z;jhBIo=m6x7H2JS7oAv4<~#38gjgzox`}Q0Q6~&0h~mW$0T$rCXRZiDu#8PmB)QRX zh9$CJ4tOOyZ_7QuZrLbB zfR#OO+bs18iy?);A5(VoV&^C(3Pj;!w|s^>Wu;Eqk5swAY)ljlz+RLQGF^GW>ch=N zG8AUVO!h=Ah)P-Gz4Ipf>GKZd+D}7b-dvadr1-V8R0WQ(Zk_ z1hvl13TgI4J~f|2E=*1d4sxgi`sr;9EReyAw~3#_Gnfb1x|G#D<6U6`CHnaTi037H zAMdL}l#w#f4Dte;W1W4y>|&#vz|-{d-eK^uumpj%UZy5*o*#NDVkvWaTRoMPg8E@U&>Nxj`sngrdnsbi_h=8|dhShKB@j2A#%m2;(ZS_27U)FqT zLgq(EezR~Q&Z<+|dt_gL-sZ#W>XCQMR9+oY{l8tV9Opax2NRtEYDRCG%d9gG&y&AUie9N5pes$bKrpF+qOgPhXFCy+Z;}7?I3ACOp!SM+gkY zL199;<}MwY;B(cA4?qJl5(dcEY-Xdh8)R<0RJW+~wM~q;hSJ$|Axt5364=4iLQ{?4 zG?;_h1#Cf-!yQMUux66G$e~Q$xtHqKVWe%_0)X5%)!tUf&iDKW; zPG*!a=s3MDzuotEb5=|zRWbW(qo^B^XP1j#{eyAsLUO9qRl&D!h=IB(qFP|J}Oog{f8z-(S^jL>G`0!Q}4KS!s{%?T5)T?4Z%Yf{a{>bMI`ZFiNbxt=`1o zCoc!1`6*dICE(kPWxy@8bmW z@ITc#EzfJJO1^hT4+ky)Y-RPxCMuW}2&RZ9W&?rIlzU>NG$OZLwR&)ckz2Z)s1JRn7LLDSX?!QYR zmU|y56Cf48loVcEpU{!8U##2p%10LJY71E9^`-%ls7jaek}h9PtynQHuo|fgSHE{; zwS#eUcxa8Xs=V5DO%L>DS{s-|^aqTRjkCPto6iMB3Eib_y%XjC`+o#SrX0!uUW`; z<&myQ^|Uk39;1zBvh;Yh|7n3;dTH#T6i}Lkt$UuRiD5a*ebqObi2ml{LZ2s7UC7Hu zX0;0q1lm7LN4#42&ef)SH^#9eZ?;K|?Qix~2Gagn=U*!sw=kGzL?oT8%@QKICX}1n z5enMo*r-B6(|9jJ%}^(v>L*@WwSOK5Y1-52MRXodRGW{F|K;M2mEz0mvuexveE#9o zb2m+RX88NF^Y|i94-!Ap<&SZgcmf0jdvA$A(M^O}zL$sl=cJ60c=+Y`^6G3U|2{xY zsEREmj(yNv402PGP+YvcUv})-24_4l-Ack5+Q!@6dF?cYi7Ff8%Y-+UNEbbso7v9; ziPFc>sQ}TD?S;og7aS!KG*>kXlE^kh7F|3~i&>l7i>-2Tfj$d}KdsITVdqg5v@ z5`&k}ccKj^KS#ZCBmvGqpF8FE=kqcE?${X$E`+v*gkRL71!p$V+WIg>(`l5^hi)_e zpo9;A9%JKP`g`87)%nh8(qgUn+K4{EKb9v&`BVM6YU1FLN+lgMX{`8uRqs^kvDo?p8H4b;>9~^}$fv#G=tq=QMf2JCCac2$du}(uid@sZj%Wn~K%s39lOE;wan)!b3er zzj=gKa)&x!5i;dzb9A{wX-ok5&=9 zjf?k-SZ*LBYLhYj49{V*REC-!nLZ6_(l8vKbvKIqS?&s*ntFvCUp+Gn|^coosw|KKzEb2VI~LxRP&O**?x73tem17 zX-fAX#*>%)$kMqM!49+TvPP4rpjoxu;C+coknCfyw`@E5nC39`^bksc*w<$yQ>azQ z)LDuFG<&Ig;7>W5cVKlct4(w>`J=w)0IbzGnpH%fW+^z*bS?_{s`T9xn?9*8M5VJA1p0GoI^Ni( zcpzs0lQa&#Q)w)mLXEHCO_(!4lqdv~$TM zB#5w$FH*7JiF!Yd8fem~0nXJ**ERn*00K>x*ZHwJ5wFp%!gxzc?~}JU(~QvtXu_+h zQ>D3)%~+Miq!~S0iei#~oA`YaNzQOSb_R5~@WVN0<5KACjg%nN5D>B*x(KT(Nf4Qu z1f0LeWjhXHb~Dq-t_Vy2Pt${D^I6r$Cy}2ftFl0HInD2FW<)>dv>kPt(bS<&#W;wh z(<>C4`&9a;<3g6}8J(d@MmYXw1=%9RN==F~3L@OP4tJ!QL|!mcl8pE%>PuSD;Qyti zEGup1KTL1ec|m~_ta+{v9X(BVQURO2&EZXS(iT?slS>FpeF%p}AvH<{C^!IK!4*sR zb-6S5lpvJSMAE&t&~N93iLNrGP)CgT6)TF<)2ys9{Ze~~AM85RzLiFO_VbEK|1dq# z>d$LhDG{zd?1bmh3$qGm25E1eo#;*htCE>euNzxNh1t-$am^sYuxmN}w%pmm3R0D{ z>Hd22-S0cQ3@Qe0pm|EYkVxpms)i(MuwI{1jDKBqwCXIu1t%)$e>dH`bt&sCOOhVr zs0exoTTxPGJycj;As;oAfV2NEDP!|px3C#6l|kp|15(PDUlD(XtOJPmgTUgY7B8dIs~`dEeW$&%sK2NI<8` z+_rxGb>V>zvE8nkWXY&sdJ;_`^w5qn$c^vY(4-gUQcj`%qIq`feX0y7qGboUJSQ&w z)*$GCRT<1|{Vz6MZt7Z)PC;eb{S1%Oq{ohQGw*Ltly$Xj6bK`d583_=_?yNgO1?Z3 z_+0-C=O@cO$e_}@IV3aR-7{$lw4z-!?;(dJZ+6eCu2`fFg<4I_@RF)kcGk8HX#pLT za`|b=4o4b2XfKjAowYwO;sw{|8y>P<2(Qr}^;~#?kfl(Kf1MfL4@aqHa}+kzhX4uz z{XjfWH~}7JaW+ue^X8Pz?4U3e5It;}sJ_YRA?8R_ty{zj8ija`8Xw6JH6c^IQ(H@6 zMBDrjlMX;s<5dRHI%cRH%=^(t&G1Bp8j8OD>4#8Q)Pt&Pet%589cVEU&n-D<^PKGx zEdPBUszrX8HDFzZ?zEM_*2tdRa+G4FC%@Nkb}c)B--YMG`m(8=a9w z!W5rx4i9>mHKtn={b zF`J=CZ>Tjdz4P7s;|1AdqK$g+AepM1r7~#j_)U|Z^&~*8kWi+EXfF4xx9Vdhag6!% zLpqIqU1YW%R_Hsc+Mu}KvTDQve5?LO4-hmqEmgkgj{<7se0^|LCyQIIYbssrO15Q5 zYl%s`@N(Cn1j@st-WND>mv7tq)FVALyQp+|Xwcua;Dql(z0aNwJcgbwwjJB?V{9LK zTBrBd-ydwZlE*d4(UtY7YK-q^j-GJU?mFgBjJClu%po5I}GI)`|WWdKHUX&^B$AWC6wATls8GaxZEIx#moG&3MAFf}kR>~~X300007bV*G` z2h#xx6A~15?X+?L000SaNLh0L01FZT01FZU(%pXi00004XF*Lt006O%3;baP0001K zP)t-s0000|b5dG+T4Q@-T60=sgkwr;N^^{JYlLfSjBA9Pgsr`;rM0EK#=V@aoVCWa zwY{~*&c=I`dz7V=&eqPx*2a{rl$^DkjHQf>oQ&4q*1gWXLTf_a-rnBl-h`Bd=jZ3= z@8|FD?+x0GVgLXD0d!JMQvg8b*k%9#93e?WK~#9!)qB}?<2tOYoJnqRmPlD5TZ(i3 z|07QoD0xh}d!M!L!}Z?nB(^1jAW$d_Zkqr4=#9}XG;8GlIW)#uylTC|vr|W{n;4oB znGt}2=wo49B!s^wkYH)91XTAIFIaGD!kaDg@&?*?3eRpMN477Lzp6M2VM`@+{I z+p3|(Iwmy1@J1mT{9-@llJ37~se@=(G391S0SYm?Zs85j#y3GVCfn$8c7rqR>CiN@ zfmT!LxecWo?`2yPKd)4yaFdX@$&jH2!#5qCSG<%8Z*OGdayeK~5nv9?i0)M}u%Tw;qeh0n6eQ&SX_kK-x^a%t?xHKXDJ zqqiD=43P)A=5yq!=iKzrP7no$%Mm#3s~t2pIKFO*?6fLGo^sAgj7RHttF{B4bZ{+y zSz})DBc=>3$6$OF`?7%bLsbcmGib|uuF!bKzZK$SUK?{TNpJGF?ZO!wYwEk}Kq+ET zP4t1E8;6?(CK|ZX%DNH@1oqe_1#V-3aM*W~;ukm4W&>TC?KFN-jW)jMW-3bejSnWnJc6mx!8@T{dP6j>gRKl#3xD~~$nkHFp;OA~4u*<_ z8x13F;O|&3hJwxD04_)H%NhLjx$heOpsQjF%*TfiQ!@ct;C-bS>~zq2#PM3K%nRH* zIjH^&E#_reo7YSigVOcooM8W^Y>V|pyAxgrcoWAJsGl{-vzU4)4)AAS1+&%)HtgYn zNBHa)4>%C6f)YQvF(F&jz7~K6KG5Q%pmZ0x_a?$3Q;w^gBn}>;4Pr%s=|S`h7UrRk`i>Eb2Dj`;o41I&SZ^fDJB!-`xR zGt4BoL=EdG8s8vDZ?Yl?Ms6?26|g<*Lg}j$YCFx%hf>@TR@X56lyFZusX*D>8dHK7 z2W*V7QjSi~Q}LUUbBax_TWq}YFwZOg;QsKMH|xbCR2gu8^-jD@khVxTiIfdEO^k+t z64BfCSKIdUXyjIa@)T9^o6>#G3pXB^(UO4NBEJ-QfcK(%~(q?87_F zn+x7BvUc1jv%xR!=P|H4Swg|V?RR1e9zz2L&sh&29kGUv;tHc!l zXDKkL*Ja7)RqSqBf{HFiSAv8(!1V~MR}VtM??Ie2AlKc!{)zQHv zWWt#fegt!G>FEr234y(7b;t7n2c=C@4bGx~}p3 z#ZP_V(3h|#d?G9cdrZ#DiJY))6})}K_jf(o$<1mQ?p{W$0ml;SLY!5A0Y{ouf=2vE zOFaPa9N4iCz6G2v$FS+Z0iZlI1HJ@U89KWyH7VTE6Vb6kthxlAoY(c7*IXSGo5@}* z7wW(P#m#WL0$0AZ;_YFNP`wvGxja4+xIqA7#y7cXafp3{Z-L;1xCgc{-d+&_I9OW3 zOi!H>`V}dFHG1a*%^OH0qJh~UxoRrYj~ACW$0L5>IPj-KT+ikrvK_#3{FD3&5Tz$~ zx3N!Hj#XJzxJEp2N%PMGVr2nf6NOhqiJW#iRoCy1I}mX*EjLD5hgkp{A=Xu?_t|b91-F~;<+sjN zvRb_&!u9}Pdade*VitrG_$hp@0DaW12z}DeASqyu08ke*+JoE#$`HJj-1B&k3~#VNzI%zrOz7{QvZLYkNF8S_DtSW1Bd~4MktUmsWV}$8a%`LE}uF ziPhvkHN9S&r|>muHy~Cb0z4&NU@Bs{{hisp1641YI}X3)r^!GRC-?+xLG}TA({dHS z(|$legaI6hv(cX*5E4%Yk>Ujn06wcw%M{JJZHd7p;*OGDSVkiQWU+4#(g&J2@LzWi zRyPMYGK0baak!Wr0Ue!-AEj!LVoBx@LF*C8GHU}sZ}3WF?&3sx7=;9XYQ-?7MlA@g zNT;Ht&drb|En(zNj37&X5iOA2B_!WLs2{9agT_3FZ+hI%=wiLUcc-8V!VJ@bH;-S8 zs|dodn`%CU)ic3@;@6PIcw3C38wVAb?2PmRJB^4u8r)YwBZUz~ha@Zn#xPUQOI%XV zbOSGD!JcGNN(LNEd>Y6fOJ|h1mmaFEI??w5k}1PXKQ*!w2L(ykhDstUUvyniE3*Yr z5=l_EB9H`bR`dx`M@vnlJ27u)C+q^tGd4o}_eAQScx_GvY_0NT&#GRQoZ}VBHzi1Y zPHfN>|4r!C0aiJj9^SyR$jL#Ri5l1ha*`5WVfPM6U#Nt=X%omk^K_aNu-t@ob2}t4 zFfAooo9sw1JAii0P$saMSCIV`VjR;=B>M|D#S|Sx8ZP~t`ET-M85J>MBqmt*1Y$5s zxURYn$!|_0^#BBlI#u+AHBG5*!mMHB8%^ngsmBT8lH#(zOn6V8DY3=j4pS}WG2cfN zKro#cxNBN`0Bu7W51mVLB%6s60X5hK`0lP&<5}5#f|nMsV__$E_0OVAfi{yU3WkJV z6R8z)P8h9YL1J;Yfkfr6C2i!3cgk>Bny_+ioV2cN!wyCi<(SQF`kFIS9>}}l%?d<1 zpIOivnU{sIlR%eFK!Ydod)SE8qrM|22#qX8ZV1^sA3!F9oFfw#+-Tzc%Y{N{6mt~kMGsD{sBM6+C_zHM|?xARG zqVAwpjubR+1U-mAH+Ql?{hOjB=q7|mM!(B3(^bj9Hy=v*Y@l;!rHhDvG3?q`wiG=+ zi;paBuusMVWqV~dLCF81c97;y%+$kojTG6ksytJ3EBPw{jh5v$XZgj7zzw}YAace_ z$-F8RBA)ZIp6hv#yRJOqcZiQq=4;BO2c(8i;vZd@U^+W5P}b`M*d(cH+F%9R_gNcJ z>yh~itO)1J-{=ZbGt4eA$ddq=Tk%0khFeTV9_SKMk-Z2rt-K#7cfE+LA=d-!kg{w= zgU#;r={wuEol~ccADX0Dt}BWr8p195nF872w;m$a2g0?uk>oo>j&tEOS9 z8nJ`A1#3_dPwT(Pfx|p6c|F&Vu@ck5O5g5Coy;x*Tvv^!XYIFE_n;G7QG=X6+Jh2? z1f`1vJv}zEPO#r9gfGY%srxUfy{dC&4S4r6>_2W@j>+oVkn#rbfmNi#{(@-X3%3&P z2VkZvBt@r&x50)td?sUZ-)J8QttRW`Q$5R9HXII!)s9<{y$3!3{0O_3d=VKg+0RNh zmJMa_oJ$n}P;1Io>G1CLX1S@b1Rl~&x+ocYTBWokAsGHT(5jIwIcYI*0gwOG_$Yld z0UBIutgTC(I)KmtS!9712t6T9!#RY)63l{g_`Rt^ycix(E7MCnE$eoazfb=HpC3mnjRtyAy)#$DDYIqVKrmh_*+a&G*o`nkzLdcP3 zs)Aj86xLmWK|0-I^IUk^E7L2 zLCWt)C^bm(2DP8Ccp8s|3buaE5eXLapQ>2F{%R7yQN#v@NCSgYIIQCR)&d%CQVH-M z*n=~VCCd*ZhNqDV-Dgd`mLjbFR(P?Vex7tSwwYzCVY*pN-f-bk2$j-{o#t9eiaYCM zTmV0$P&Tm;Yl0ML#9q`7D>v_L|9L^e5tq54`<(i2?xv^y|NA@*^K0|R2d@0=y3dXk zfv(4|ckjNuw0Nh*n>~Ise|sGImc@ln78v-;>*24LY}aA!fBYKF1lc6_0M7>u+;++mShTpEuh)b_1BpRg6vw!55_<>xdfS8A^EpyZeVWj|x5j~uR{pz1AVtbq> zHFkj^(P;#b;RJusqxo|e{D8b80?e2zRqs&r6hu=0Tp=Xjf<7ToTxKLl)Zld`vEz2F z39-2VaAxHkEIO-NUF(Pv3b75DL1KF2i-Gs=Eztp*9xRfHNi4zQbi!+uU~#=el> zvx+S3bXAanu7F=qkw9$T!&)EC$Ro~m$YGUysA0bsIW~j7iq*P2CQ1jx6aFL~$K2vgLcyx+!74&V(z_+kwA z{W%C5SUoNzG~2jQmhJ->D_~6e5cQ)&7G4sFnWivD;g&xO(MBvR+2oPeYcS!hmeDH5 zG*0mVEFqwul$tdBM~#C!0X}gjsNCo%Ze=$K5_4iKJs}ex$A8#s0#| zrr^RJL#%)_Bl7#e_=jYL@>A!!DjAEj$Hg3swENWgzu0~U*}Y>^R?1U2t?{vxboZFS zBOJ?ESX@V)Hs8V)VF~WU@LQbOk+X-H&}c#G8Huu(XX~=mqgcMd0aW702Q-|rW*UL~ zoDIM&hA}B{37L1GgtowS(kL<_0|mNt9i%^jC?1;MpWqJa6UWih9qGvI-G^M6{~$(? zNzB(JZ`J>I2(iNA-GUccgj_eGWZ2L|PK*~9T1Hii=0ro`L<74iE|IqE0NeuYpck-d z_G4foe}mf*Cf^QpqQQBKLp%M!@Lxa>B@c_plYDY+M-w1wgB65EM-^PEgoQn2BlRLMvv+kxj78BOoMQl*ljMns?tVfrJaufipd9 z#olNL=HO}2{xs;(|G|v+&-09c+T?w3)jtJ_9^2t881asCjnLg@yj1b><4u6J~?X$z4J`9UtJ2tE3Q30SG<&w83J z-RYL6A%!-;fC5k{rgZYwZwH^Fd>6h6mL7or3$sbE^|UPOexE~@RD0!+7%P5dlN4+> zNYcksxE3ku1Ipoq#|asS(tqbXJ=+lg92^)d$oculPaP`y>ReG3;oUU>@fljzYxSMSE%jCilmh1wa;*9HBx8z!&Vbk( zA8xCl7#Q?Kll}vF*-u{&jxib@FaRfqAGP1J_{yLaSrCsL=DFD|+e6YiD~@Fpc*dvH zR*B-2y+*ENI3~oppJ6d1KTL4wEalh&Rwypd*WL?jO4aFGpw5X|**?U84AW16JZE@{ za3^EfD*^XQAWQ`;&^+sZ4z-X0?8)o-3>j~0k1XGAO^3jkR4cqwjcP0>k(Z+UE$~ z!1RZ}Ke->Z-_wr^bI3^Q0s4OHCW_58_UIC*dI4t#Kkj6TV~H}D!(p@{TrV%+MUvVe zu<~dwMF$Q4m*&cuDUTq}n$L<8IO%(#Iz4HxCl9*+&AV`B7@`xTV1&%(5$+}|=kq>1 z^tG({*7l_?%66=)_4F(eW2Qs9tco=C%A@VGt4t&**8Ls#TQdOiaZ*6Z4hQkDi?;3C zdXrWfIZ85XQ@{`IDl3ZpaUeetg%#CcWI&M-v!XDMrP&Ir~Qe-3wET$6Ebrz)aUbVl5X&2WXZy7mcQRrGEAr( z$L1WcC6{Y8@KC2pl#~(J6*o6FbhOMinK;%wQ>EIvHYZq?t11|YywoG@a#cKq>_$%Ag{^mH8v=sQ8=>-!Tc|8 z7})__CAa|qkU!kdH+OnKzRwms;OFn!|Al--jr=x>Q_Nhhwtw(y0{>T>!PM%|491tp z%D*EoVd3TGn=>q?M}%cgYIyLP^*bo&oD6=F`3FJL%$DtX>6fUI)0us9p-bzdt`PJ& z_@0O8ZYI}|o!jZBG~yRD&Z=XgD}nqxyO6G6m(OXf0>#~!Tclw~AUVirmPN2eUY|+X zn2Iyy2mQEJ|G=>&*2e)rr@vHrWDVfc5Kb1k)bNR?EAEd)7xD?D%t|^@9lL0{&N*{z z@mj}d0d#PP!eQ!27p(-n1$hkW!7QQTZ5|~r3;~4s&E90@o!u)*j`IUU@z^go2EUkO zZbxq3wf$^t7dTPwlzf{(M)%A&`Hap*SlKpmy!G=s1Sd8xNf&S>(De6y z!9>c45y8UTCdxR zs2rB^$g7NGUcU0P76}+%<2WRFjTNi4k<&R9r9!@O!xkLR2nSr;!V-k6`H?sw4(<^_ z{E)cC9f6O>esCm6L|Wip8DRT+LF8SNUQohskRO)F){2VBN#PeT$g}lWrv|VtvRDr+B0bStF~`YlAS5T~#`Dbt3l7Bz zyl}2=kIytFni!!MXzGK+vl*W(NwGDJJ0Ui)%m#zrwEv+BYdrjVhJLbs!2pAQVdQKq z=MGc;q40P_BnpM!7FZw?&6fV0I3UkTZFy2=>y2eUo+ah_Wjyel6YEWr9;d&9P9t+F z(=<;6W^XS|E*M_153Y{Kmf7$@>6{G@hrzDm@!*&_7t~7ep8YSp z5z=)Onq67(X~nMs>|Lsra~CW)hO;6kGHf`%dZ{c&HVPQkamEEeVD{ctL#DtnE%i-D z8QU_38`0$iW*+$O4`BRTn+(+>2FnimC?z(gxYPF+yiEebZg0=giuqNtzWK*TJMeoY zQ2qRAPn_f0EgT2P9Nt-(X&xV^EIN-Y2F_7+*8&=yX9w^OR^hUB=$JN5!@hhU#v^{h zwA}5!m<43kPmH7ju6}_6DFCZvg%ru-mTkN@j^|J$QI{(3*Q?eX{v|88H#8%Mr;Y=0f!kH;Sy|Njf( WsG!3;Fy5j70000WdKHUX&^B$AWC6wATls8GaxZEIx#jnF*6`7Ff}kROI0=z00007bV*G` z2h#xx6A=kM#*1hG000SaNLh0L01FZT01FZU(%pXi00004XF*Lt006O%3;baP0001Q zP)t-s00015b6Q$^T2gaTV|!ytYf5vBb8CcaYm94qlzXMMrM11az0SSH&c@Ex&b7w1 zy~e%9*2bKzoUOgB*51}*gky}QjEtO&-sj$wrIeJdl;`i~=jZ3%-rhoMLWGoroVA>U zoP_W1@9+2T_xJZXPQr%(0004WQchCtf?L&MZ3@yG;=k zDKZWfk(0J(-~SoEDp0oN#M9He=g-m3W)fSXKwJt1fMd*magDw%r5OBE7gMWgd52Gr zVcbgy*_N7*sd(eFgan(Tr$?m zcK31`(rk`hVLJl1^Rt6Id-*+_&Mtrr4(mI{BOOtWa#&7ptI~(6Jd8=b<~^@f7x-? z?;wIXWOMm6sHPnS^Qu0YB8Cxq!IHU+d_ggx<~?r9vSjlad>HNee2QZdGmB3dyN6P2 zi6uayC_ef(^XkO~GuaP)IhJik%7Ts5GynCU3Lo;tl|-FJf7S081g{pC9R#57RPX6b z9{-|j;_R7jB&FIG2L?7md$U}hb|lQZCRT}fqF`oUGDy=(&E-#$grK7E3M824Xq*-ZY`HW z|7)$N(PZmp65JCW^r1gmyC6-U&pyy$o>RKr|EKQzr@=1X30*Pbt+K%TAOUvUDhzIX z_TyFB(TYnZ_$U@3iw$90h%IU&dN^?oVLH5y&KiLeRxwYNM$2`#CB{I2sW^3topvE*=)6*|N`Yn&1RKQiPRUadd)GM>Eu=!3~yjUM54kQq@wfZg5C0 z29ty#fmL_r)G9HD_VNsv91u9k(e}R5Mh7Y%{)APfVqfk>>WSgvbj4~ z)tkI80`~<1Wiz??mu^gamxpkQd#7a~pn3(X*#>)E)g_o9I68)F{J8q2zE!h830OVQ z|6aR85u8lx5YB2#cQ{j;4uj{L;K3E`#)FyOa2ApjtrP>?71)`C!nvjsTYQWP+AgC8yk zDz!dyY=pQQr(RX%AYTH~Lm$Z@l#}z+p5zFHArygpcox4mU*72za7~B{;0v-wk&NRo zzTt5&jw$U483;i?3`Ox2X^o&s4f}S+0%vu)CrF9}r0Q;^QnTEGQAUz;+G6{~A`lg7 z3iKIp9YCKa_kp1$_w?ftb6BU9_wJ-EtGO7ZKVa?v6-XnTL&3l7hdS(xrzv7yl)991 z=+7?nm|VvmAGMaVr{Hf4y><-_1TdWZn-4%hAIBlOr~wL<<)rQik+Sq~8K4#g=yf4z z7SaRKr5yRZ&+6AH*)-XU;ZDe9a6>5c>XqhPxKdqXd4gKu4(EKJ??-&&U;2F?wA~|F zf!}})VJe4yh3Z0(?6FK-BMVz@;0vp)a)!Fc;?)}nY0*o+6V7nd0PB|(rq*1}SHC;c zL6`HnuXJQK^)x;`7F)=5)vHxUvkzq5L7TxR(k5gj35Dp3#MCYh0}~R2SDslLzXH{O z<&g)Sc||m;4t_~UVYBc7KG0y=3-wUQLdHF>dOZ`->zUz&-&$VE3U~-$A0Fxzc^J7? zB7bqt)25C|J73=G&w$5L{Y6&X&~|&c0&W(kd9WMLPWQ1((hNtOE`N_rpuOB_9OOgZ z%V&jQ_%JoQz5=%OIX;vXwwHli5sHn7@yuiw^ED1(CZf*zH&a^iJB5GhHEbx}bSEm% z%r|cSMvbuPh@l5JDUqVGI15skS#6xGZlQqsy&j&#{A#Wa64W=KGR-Y{nJ zXvHFn?MsYuO_)e8<1Nn(nHy&s^84Frnc|TaK;eMj>zjsLNqe8nJKWE^OPGDXtOw~` z3Hu3*+Ft1`!xiA8DT?b(YS+*c5du)xa1_g0F{xlc5nuY!cneoImme9A$xoLc(nM*{C|7>+#Ns$4pvEs zdGW2a#jn*LOx&1w&F*+ut6G+ff=YP}<}@-fItgEwokx5)Cbgm!O=0Q^hxvW__?UGi z4UJ&JT3@AR;A{G?>NtYp`6@tDHIb$O=p?n}+%LvQ@Fl542U!#x! zWadNG0ShS+UF(aaHsvvayZ{#oJVMGP?!XX-NQzQSN`(a=`J(Usk9?-JAgdL4t4s85 zIF3!fcHCNaV`zL`CaGE)$pE7o$W82HB5S~wr2{zd8i)l7%-gLBTHHNrq#K0kJK4LLaxnD46|-8k>&(Iu2=O2@MX^y6*jw6#WtP z3lkFLT-x7@CRil11x!HOD!>Bl1urCmzy{D(Y2O?m4atLAjSLj16mRWJR`Xa{D=u+(P-7laBI`T{HbhEy<+ z8LGuwU+@j64p+$2S5c<`DhCN!&Akga!O%Gf>;Ohz@Rt#~q zKkBzcAj$|O;AhoDT2X1{C(~^X2R^~klZ`-6AEYFIl+kJz|KML2I}j~AXCulxt9h< zh824iCshX97MB!BED-k{S@zMA4yvfpB31g4svkmIfgZbTc*j!u!#xRV9hEdn9TiMa znh~F3JBW@*apX3tsd(s{1h;}3m!&TY52XSaSsAXJZ`BPGrW?PD3fCGl{Edc_z{tv4 zqOsiXp6yB0b6IP7R=^8sHhy}iywyb&hFupIREvB|3?<3c2XyLK<6{h1pUYL&KX7g0f1;x}0Bq6liYKuCl2NwCHAxL-Hs;8n}o z3Zoe_GAo-*(0dMS0s0^)VayZw%BJMZ?8O14t}IDw7Qn%B74=N=!>&p0ZhP4!LHwbp zz<<r0?Z}r9}1rB+p zOfRbgRHf}qEK5b^DOU%GaIN-8RGT2GlM^x`icYXatbU+PR!WD0o-bIFxbOwO0S5-? zEwZ|Bt5c`RrNeDq620CP>K9-h~bSbyokgrj+MY^O@ec>+Z4mR4tcKeL88JEb!Djp6_(b_GFo5N zi&krl(LWTGSqinamQ|uT6COZ6xQLpm9pA1URQ&F=9UF7^>}f@oV7Cy1LS0kl^@FqK zt)+YKM5&4UY%3QOK-Wsl0#*HEUp3?4~$_BN@E8k4YY&yvf z+41_yCDKl7_gN+FStv_WJKR>O@eu;GaTB|>=0HxnHvY^$inaA<>Lz0f| zf*FOODq<1Gc+U~e^nb)DB`fBVc8rlsDb(&%4xzDKU0 zxRIbrR`#7(UseTW0oTyqkAwri=^Pz1sY)%q)jP3zlkUjRU<}Cxxi~23xmukEQBbTMbW-h z(;3=M$ZxMx22|;jy`a^^P8c=?`nhEuFYJAlPxF%5G~aB34QCpY?ZEcyA0;J<`>?+8 zB?OU;|0zi(gt{`*8ydnauJEuUc8s_BF%36$Skg4;^(*f@Nbi#&)!mn-shdaQBc`&s z4Qx}^?!u1{w%v_=r&4Q~%Ay$1dsS2#!wvP1)BN;s`RCo~aOIyn2X}JQ`{DR`_`DT^ zm+NVFn&*T0?X{mjPpA2GdOx0y@3=niW=5|+-cFzIhtu(Za`g0K{{4DB><;s6=hJ*d zL3xF=1C~C%pKu-L)8X~sR@u+Z(XAtqE$Mf5{qIt5Glmnq#2gb+k~lo_SAV@-R(iC;Eo!yL<@ zRtlr^O!MS9WAsitQAPVKN?iSlY_6&*e5|{4mp)OIaqH&Ag1wyd^NqBSps+(8&_EyJUn9p*Id^2VOy%# z(Ey#Y^%;z@q}eQSDw_po_+hVnPYY*WxX5nFY89&XD03(xTpbT_I#k;=6|ke?8=Zn& zN+g$R}qyqy1Lwasqaa=xTPmblRDQvYUe|C~EJK6q*s_V){rfz5)j1G zO{hz%Xk(GJD?2QeQ@?zvCh+!=eKZ2=YC3CSVFVBUJxpVN$zN7yARHiylHE*4>;5+( z8EL=n0(dW+;sDGSA_Dtb%gxS--J`-9jsGkc);uqqpRs&*m7|-_t(HC+UnpmhB!5RI zH&;SEfrNoAL6P|~;DmtPGKx!wGEs4R_27f84xT97-VmpY(}Jrj@q?X%bIlUwCq@`Pd9QQ2%N@& zG0^^8WI5M*C1_8~YwVe*AqWF&-PB6=R<)3983GJl8F4Tu?sz-``+5z40Ev##AAPtO zX%P6XA3|i_^YKz_Le10~3Fn5!dL8R7>>E>acZHPVEx%;ew zj)=fa>uLYG)v9O}#-kiQEA}c3z~gwSWjH)RhylpgHFtyrNi(2!{xWnvz*jX_Wz`Eu zzvVm5c^1`Q)4awpjT?D`d1FH{!Hs1LvsZ?(o5b*ONJX}Bp zi`1Ze?a=2iFzB^74UB!8;w0Y~_p$a006^5Kr?21c(J^k(Ie~)e(l)MlaL9S ztm=zjTGd`$-JWcL+#s-&sVS=rh~ZGG%Z?{TGLz#6(-3Lg^&#zexM@re!tE*7P`b*N zzZ<##w{8@yOGcp4gLj@UeeG^Ch1E0fQ8uI(yeAWxp4vu80Gj#+@vIwXDNJxg1%?vOge=Chvsl&L$rNuTptt+-VzLTK&Iy;B8mN;Rbulc zfAJ2c5b`IT)zte_6|8U~*%a%RgQjP8zVv(;8+6Kq-%w$RY_^VSkLl|4{7Bp%tb{8O ze$i7P-@GTOAb*p<_DXcCc-#CL!9x(mw=u@{-aW(lPP`FF{yr9YB#C|iXpR2&U8U`X zdR2G;l(kh1KiDA%I?3hk+0!b(+!K%CkbmUz#f3y!>QeM14yvoIR+U=nNDYrd)|p2E zDhjm5%;iIBS`S#C`QFR5b1b9nKlp_e&VVV1m7 zTn0TTr}$8)9j))E#p_sc!%HxbtGy;BQ2X5Vc?fI^mwF9tP`}|m3c7q{aU68P( z=I>1s3D}Tl#vY$&c}3;0=-!pbtm~tsxpcIm9WHGm4`~Um2#i_HzumGcE7>q;YAS% z3*;g+k%tN3bN;7;KX2r`KzfFaj))($I}$K}gNv02ESFO5v+A|hR+MRd`JO(lT^Ev^ z+-?-tB5m-DV8M9eL|auGb7;x}s=5)-pfB3nZ%oE(XGL2p?CiMp*$!f{BSGzZMiZ6P+SPuin#YjPqLJ&DxwOMt4@qo`-|ozZE3TMST1UPL&e4qQ3A$3 z*t}CJ17~8Jb^fZ>WAB5KoG25bUV$%<2Qj>veQ0H+^vYA~9!hk0tJ7<2p8QrVr` z3@}d;`tVnv!7q_@vLFCcGX#IaW zD*CR50I+t~O0;5h&Hbn-EI_{K2ov|L+;1Zj~~xZPcQiSuM@TZ@p^v#e_!Krz5aN4 z`tkJi^xrPI+wFh;+#NW_w + + <@s.head theme="ajax" debug="true" /> + + + + + click + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateCharacterAvailable.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateCharacterAvailable.ftl new file mode 100644 index 000000000..a51909d12 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateCharacterAvailable.ftl @@ -0,0 +1,47 @@ +<#if hangman.gameEnded()> + <@s.set name="winImageName" value="%{'you-win.png'}" /> + <@s.set name="looseImageName" value="%{'you-lose.png'}" /> + <@s.set name="startImageName" value="%{'start.png'}" /> + <@s.url id="winImageUrl" value="%{'/hangman/images/'+#winImageName}" /> + <@s.url id="looseImageUrl" value="%{'/hangman/images/'+#looseImageName}" /> + <@s.url id="startImageUrl" value="%{'/hangman/images/'+#startImageName}" /> + <@s.url id="startHref" action="hangmanAjax" namespace="/hangman" /> + + <#if hangman.isWin()> + " width="341" height="44" /> + <#else> + " width="381" height="44" /> + + <@s.a href="%{#startHref}"> + " width="250" height="43" /> + +<#else> +<@s.iterator id="currentCharacter" value="%{hangman.charactersAvailable}" status="stat"> + <@s.set name="chalkboardImageName" value="%{'Chalkboard_'+#currentCharacter+'.png'}" /> + <@s.url id="chalkboardImageUrl" value="%{'/hangman/images/'+#chalkboardImageName}" /> + <@s.url id="spacerUrl" value="/hangman/images/letter-spacer.png" /> + <@s.url id="blankUrl" value="ajax/blank.action" includeContext="false" /> + + <@s.a theme="ajax" + id="%{#currentCharacter}" + href="%{blankUrl}" + notifyTopics="topicGuessMade" + showErrorTransportText="true"> + " width="36" border="0" /> + + + <#-- + " > + " width="36" border="0" /> + + + + --> + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateGuessLeft.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateGuessLeft.ftl new file mode 100644 index 000000000..8b5ef4ebe --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateGuessLeft.ftl @@ -0,0 +1,7 @@ +<#if (hangman.guessLeft() >= 0)> + <@s.set name="guessLeftImageName" value="%{'Chalkboard_'+hangman.guessLeft()+'.png'}" /> + <@s.url id="url" value="%{'/hangman/images/'+#guessLeftImageName}" /> + No. Guesses Left" width="20" height="20" border="0" /> + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateScaffold.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateScaffold.ftl new file mode 100644 index 000000000..afd11b6e2 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateScaffold.ftl @@ -0,0 +1,3 @@ + <@s.set name="scaffoldImageName" value="%{'scaffold_'+hangman.guessLeft()+'.png'}" /> + <@s.url id="url" value="%{'/hangman/images/'+#scaffoldImageName}" /> + " border="0"/> diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateVocabCharacters.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateVocabCharacters.ftl new file mode 100644 index 000000000..d4b370b97 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/hangman/updateVocabCharacters.ftl @@ -0,0 +1,20 @@ +<#if hangman.gameEnded()> +<@s.iterator id="currentCharacter" value="%{hangman.vocab.inCharacters()}" stat="stat"> + <@s.url id="url" value="%{'/hangman/images/Chalkboard_'+#currentCharacter.toString()+'.png'}" /> + <@s.property value=" + src="<@s.property value="%{#url}" />" width="36" border="0" /> + +<#else> +<@s.iterator id="currentCharacter" value="%{hangman.vocab.inCharacters()}" stat="stat"> + <#if hangman.characterGuessedBefore(currentCharacter)> + <@s.set name="chalkboardImageName" value="%{'Chalkboard_'+#currentCharacter.toString()+'.png'}" /> + <@s.url id="url" value="%{'/hangman/images/'+#chalkboardImageName}" /> + <@s.property value=" + src="<@s.property value="%{#url}" />" width="36" border="0"/> + <#else> + <@s.url id="url" value="/hangman/images/Chalkboard_underscroll.png" /> + _" width="36" border="0"/> + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/help.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/help.jsp new file mode 100644 index 000000000..48f61a676 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/help.jsp @@ -0,0 +1,31 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + Struts ~ Getting Support + + + +
    +

    Getting support

    + + + + + + + + + + + + + + +
    LinkDescription
    User ListUse this mailing list if you encounter problems while developing and using with Struts
    Struts 2The Struts 2 website
    +
    + +
    + Struts Logo +
    + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/images/indicator.gif b/STRUTS_2_0_X/apps/showcase/src/main/webapp/images/indicator.gif new file mode 100644 index 0000000000000000000000000000000000000000..085ccaecaf5fa5c34bc14cd2c2ed5cbbd8e25dcb GIT binary patch literal 1553 zcma)+TTl~c6vwlh>nb99Af5rT)t{mCEg5urg=A(g z{C|6SPb~9Xage|wB`SrZk2FOMYM!buln2sX?5Y+T78iB(Zu9cS7|LZyZ++}u$^oi1 z_j@S}bW9OzU2R+RMy&~OT>X-oZ98$jq#ogNfJ!BM-42wHGZk*6s2KD}U*IA%epmxb zm}|6BK9YoIF;*xSL!+z@<64lB7->LTW2Vi4ostCA(z&2XniwNIv}fFo-`MbG;)u4G z^p@F!)|9HhZprHd_vXjDoxs6WkK-6P0@lfxnGT>*p(QHoUV=u1FAqb@b%*W=a3{`LsH5k^AvQNL>6fPpy#oU(&MuH(*aEX4b35*} zn4n7)`I2U%=+Z=?BVZQ?vjQFW4gD@~XSOO6b{qu81`4&LFuU2(ilxW+1|ZkNMnWe79C$gs zWT?Ele|HR{JGPe)5BTW>0Ey?-Ls6S#GoV0tbt6ku7B&*0 z;i9QM$W1Rj*rRIdceL)rAOSl+sDe3LkB87<%){;ZdHp6|SNlopDXRx< zxBDF9-lTo&v`8$humFygUij@qgT=Qzhj8{ym2-{Xciwqq_Xwk%=O3B-MNAL_6e`3U zyxwmXex4`g0^1RYw~Dth3av3Dl^AAlpO3mG!nLr#&ZZ7c_wUboI+deC+&%TFjK2Lm z!Y&f1h|T_On%RCV&=4bx`!>(YezqGVhl&QpED?N6GV)HmzJ9&rh$x*i?*@o9#6QI< z5ZI_MRX;0+pY8$`j)eF#TlUyG(eE%E7S!rj;mj^M5vhUicPm zVWQ2z+imFyg}SRABmOBY_@osR!>7Ov!ioK`NB6_Rv}7Ud?35ed5Sb@?yND?kv~RCa wqs^a3Sh>&&L4)!LKI?D2&k@))k(LESaga|C278ChSzn3NWVkcuNoY&{0f?~U_5c6? literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/images/struts-gif.zip b/STRUTS_2_0_X/apps/showcase/src/main/webapp/images/struts-gif.zip new file mode 100644 index 0000000000000000000000000000000000000000..f06070c81ed16c6e407afc59324455d113935996 GIT binary patch literal 4765 zcmV;O5@PL8O9KQH00ICA08~pcHGJj>$|n*40B{lj015yA0CRM5b#!wsXK7}&kNH2- zkK@2!uWfeO*k*CrQ5G@8$*AHtLj8V0fKf`hi z>9YU*ds%roCxNrSzx(Ug&&|!v&!0c9tgPhZ4+a8ÐzE{P#qIAMmr8 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
  • svCA0WcPC#f>%D#V?+lz$fU_iAg! zu9$6uL75CDDFCJU5QC?I$Yw|LVG$urzm;tNv~J0khKD9#mq0phCZU|th_?yA}(SWmZ2;|SO&8U;*ykMDP<{PDP}3+Y6-&<$`Zm7%o4=4 zVur<(#e~I}#R!yG#IT66h_DE=2m;UsY0!dZs7Blz?ooyz41*a4abqE(l%a&7n4yTH zfFz*|Aq>F`K^zp+V#;8`V9a0yjL^y;${@lZ%pjNw)F1}XKnYlogTbH;(x3&+h+Bw@ z;SowPrHI=P#zI60C72S#tqT;8#Dro@F@o&@3Ti1L6k&>BJ@5lCp&RUg{Q&|t1Zofi zXrP2r;DEuP4bq^6IOn)D#PBd7h%*xQgRu}{OfUjpVO^krBte)U@DZE_1Aq(4!D!eP ztOP#*6S~0;V1k8VL!bsRfQC-M0uC4q+8~X%6LHm$h8P}#i-D1_AB=?vBktqieAVBZ zOX^R^*{r_`SF1Ogb6xKp*Q&RJJA!^gPDu~V-9*p93G1cdbAT&>d9agyl>STn-+%0< zEyCjxHj7eKdlE$<(r_7C2sDWMcOcVg#51)CZLYa|&~&z2^tI-nuN)FMI%Mz@J1<+M zH-<(})R~7ATLvU$1ivo0tPu00r~C`WCo42x7glwTOS=!c2Hejevjoyg-`Pt0c?Kic z$3A{&NY$5JU2)5ef1=hzASzNI`y1(2?dHeiQq#Jr=LL4v{I@k?C%h=EbaN5^dfD~? z(U6hj9*uOA+i`_A_*L-p?-DP`2aMT;+>RsEG9rRu~ zCg-8&zGH2gh~I?jv#RsSis@Zns+N5*HM){lw|LZZbbNBldY(u{dv4t;g zHuBZOF@7yajeWC>a-6Jpy>J~V%Ru*(gP7+VGAAcH^U%8F*flV%?p z{B3wB`qAu`b_KjjW{g5zBumCwu!70~QQ;igSHRC+p2^ zlNtqP^?g?(^F7Z_#iUO+ILz4~`-wleb&I@1D9Jy0)6lNLX2lgdSvz_*QnZIJ6 zppH;O_2Ge%&Uay(l!g3S)%Us=DuL>c1Lx+iD&W_29ClWuxR$RCZyZW|SSUGMH__@9 zd%iAh{??0s=0yeV$$RYkZ=a=(>9P*UX&t&+4!9W~iE%T27Aj+(KT0u#X)*OSEl~64}

    a1+>C+=E}g~yqGRj0%yfM+92a`l?u zqbXi)U8Nb6FPI!3YO2>=lMS}+-6$Ij{4~(RFJAlkS2?yW&r+Ku+B+KE>iwCr;rs_j z-|Li(&8dC#k=|&#H-S!7tONL zLSqMdj~hCC)L0cSu-)nEJmLM^*Esvwt7{})7(H&%K4$wEWnJ%4T$)^@Nl@)$g}osj i->jUKVkC}vXd1Hcsk_Ov^jjj=nWP5!`xzM`@BaX)9*BDY literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/images/struts.gif b/STRUTS_2_0_X/apps/showcase/src/main/webapp/images/struts.gif new file mode 100644 index 0000000000000000000000000000000000000000..42e7d33d56f043994b4c9d6f7aa1e68d9c2bb021 GIT binary patch literal 4720 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 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/integration/modelDriven.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/integration/modelDriven.jsp new file mode 100644 index 000000000..ce7938b59 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/integration/modelDriven.jsp @@ -0,0 +1,31 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Struts 1 Integration Example + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/integration/modelDrivenResult.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/integration/modelDrivenResult.jsp new file mode 100644 index 000000000..550c55815 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/integration/modelDrivenResult.jsp @@ -0,0 +1,24 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Struts 1 Integration Example + + + + +
    +
    +
    +
    + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/jsf/employee/edit.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/jsf/employee/edit.jsp new file mode 100644 index 000000000..717c82536 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/jsf/employee/edit.jsp @@ -0,0 +1,106 @@ +<%-- + + Copyright 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$ + +--%> + +<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> +<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> + + + + + + + JSF Integration Examples + + + + +

    Modify Employee

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

    + + + +
    + + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/jsf/employee/list.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/jsf/employee/list.jsp new file mode 100644 index 000000000..cad7d1c81 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/jsf/employee/list.jsp @@ -0,0 +1,69 @@ +<%-- + + Copyright 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$ + +--%> + +<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> +<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> + + + + +Available Employees + + +

    Available Employees

    + + + + + + + + + + + + + + + + + + + + + + + + + +

    + + + +

    + + + + + + + + +
    \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/jsf/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/jsf/index.jsp new file mode 100644 index 000000000..e54666876 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/jsf/index.jsp @@ -0,0 +1,24 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - JSF Integration + + +

    JavaServer Faces Integration

    + +

    +The following pages show how Struts and JSF components can work together, +each doing what they do best. +

    + +

    +

      +
    • List available Employees
    • +
    • Create/Edit Employee
    • +
    +

    + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/modelDriven/modelDriven.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/modelDriven/modelDriven.jsp new file mode 100644 index 000000000..346ffcece --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/modelDriven/modelDriven.jsp @@ -0,0 +1,31 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Model Driven Example + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/modelDriven/modelDrivenResult.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/modelDriven/modelDrivenResult.jsp new file mode 100644 index 000000000..5b96cca6e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/modelDriven/modelDrivenResult.jsp @@ -0,0 +1,24 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Model Driven Example + + + + +
    +
    +
    +
    + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/person/editPerson.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/person/editPerson.jsp new file mode 100644 index 000000000..1925f8f44 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/person/editPerson.jsp @@ -0,0 +1,41 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + Edit Persons (batch-edit) + + + + + + + + + + + + + + + + + + +
    IDFirst NameLast Name
    + + + + + +
    + + +
    + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/person/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/person/index.jsp new file mode 100644 index 000000000..48afafe75 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/person/index.jsp @@ -0,0 +1,12 @@ + + + Acme Corp + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/person/listPeople.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/person/listPeople.ftl new file mode 100644 index 000000000..b2b854f65 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/person/listPeople.ftl @@ -0,0 +1,28 @@ + + + All People + + + + +There are ${peopleCount} people... + + + + + +<#list people as person> + + + + + + +
    IDName
    ${person.id}${person.name}${person.lastName}
    + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/person/newPerson.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/person/newPerson.ftl new file mode 100644 index 000000000..142eb07e1 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/person/newPerson.ftl @@ -0,0 +1,19 @@ + + + New Person + + + +<@s.form action="newPerson"> + <@s.textfield label="First Name" name="person.name"/> + <@s.textfield label="Last Name" name="person.lastName"/> + <@s.submit value="Create person"/> + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/showcase.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/showcase.jsp new file mode 100644 index 000000000..459792648 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/showcase.jsp @@ -0,0 +1,58 @@ +<%-- + showcase.jsp + + @version $Date$ $Id$ +--%> + +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Showcase + + + + +
    +

    + The Struts Showcase demonstrates a variety of use cases and tag usages. + Essentially, the application exercises various framework features in isolation. + The Showcase is not meant as a "best practices" example. +

    + +
    +

    + <%-- THIS LIST IS MAINTAINED IN WEB-INF/decorators/main.jsp TO CREATE THE MENU BAR -- EDIT THERE AND COPY HERE --%> +

    +

    + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/forms.css b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/forms.css new file mode 100644 index 000000000..4cc218818 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/forms.css @@ -0,0 +1,102 @@ +/* A CSS Framework by Mike Stenhouse of Content with Style */ + +/* FORM ELEMENTS */ + form { + margin:0; + padding:0; + } + form div, + form p { + font-size: 1em; + margin: 0 0 1em 0; + padding: 0; + } + label { + font-weight: bold; + } + fieldset { + border: 1px solid #eee; + padding: 5px 10px; + margin: 0 0 1.5em 0; + } + fieldset legend { + color: #666; + font-size: 1.1em; + font-weight: bold; + margin: 0 0 0 0px; + padding: 0; + background-color: #ECF1F9; + } + * html fieldset legend { + margin: 0 0 10px -10px; + } + fieldset ul { + list-style: none; + margin: 0 0 1.5em 0; + padding: 0; + } + fieldset ul li { + list-style: none; + margin: 0 0 0.5em 0; + padding: 0; + } + + + input, select, textarea { + font-size:1em; + font-family: arial, helvetica, verdana, sans-serif; + + margin: 0; + padding: 2px; + } + + input, select { + vertical-align:middle; + } + + textarea { + width: 200px; + height: 8em; + } + + input.check { + border: none; + width: auto; + height: auto; + margin: 0; + } + input.radio { + border: none; + width: auto; + height: auto; + margin: 0; + } + input.file { + height: auto; + width: 250px; + } + input.readonly { + background-color: transparent; + border: none; + } + input.button { + width: 10em; + border:1px solid black; + background-color: #ddd; + } + input.image { + border: none; + width: auto; + height: auto; + } + + form div.submit { + margin: 1em 0; + } + form div.submit input { + height: 2em; + width: 15em; + } + +/* END FORM ELEMENTS */ + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/layout-navtop-1col.css b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/layout-navtop-1col.css new file mode 100644 index 000000000..595123f4c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/layout-navtop-1col.css @@ -0,0 +1,33 @@ +/* A CSS Framework by Mike Stenhouse of Content with Style */ + +@import url("nav-horizontal.css"); + +/* NAV BAR AT THE TOP AND ONE COLUMN OF CONTENT */ + div#content { + position: relative; + width: 98%; + + margin: 0 auto 20px auto; + padding: 0; + + text-align: left; + } + div#main { + width: 100%; + } + div#local { + width: 100%; + display: none; + } + div#sub { + width: 100%; + } + div#nav { + position: absolute; + top: -15px; + left: 0; + width: 100%; + + text-align: left; + } +/* END CONTENT */ diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/layout-navtop-localleft.css b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/layout-navtop-localleft.css new file mode 100644 index 000000000..a12210c08 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/layout-navtop-localleft.css @@ -0,0 +1,36 @@ +/* A CSS Framework by Mike Stenhouse of Content with Style */ + +@import url("nav-horizontal.css"); + +/* NAV BAR AT THE TOP, LOCAL NAVIGATION ON THE LEFT AND ONE COLUMN OF CONTENT */ + div#content { + position: relative; + width: 98%; + + margin: 5em auto 20px auto; + padding: 0; + + text-align: left; + } + div#main { + float: right; + width: auto; + display: inline; + } + div#local { + float: left; + width: 275px; + display: inline; + } + div#sub { + display: none; + } + div#nav { + position: absolute; + top: -15px; + left: 0; + width: 100%; + + text-align: left; + } +/* END CONTENT */ diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/layout.css b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/layout.css new file mode 100644 index 000000000..5a7aec1dd --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/layout.css @@ -0,0 +1,136 @@ +/* A CSS Framework by Mike Stenhouse of Content with Style */ + +/* SITE SPECIFIC LAYOUT */ + body { + margin: 0; + padding: 0; + + background: white; + + text-align: center; + } + div#page { + width: 98%; + + margin: 0 auto; + padding: 0; + + text-align: center; + } + + /* HEADER */ + div#header { + margin: 0; + padding: 5px 0px 0 0; + + color: white; + background: #818EBD; + + text-align: left; + } + div#branding { + float: left; + width: 40%; + + margin: 0; + padding: 5px 0 5px 10px; + + text-align: left; + } + div#search { + float: right; + width: 49%; + + margin: 0; + padding: 8px 10px 0 0; + + text-align: right; + } + div#header_spacer { + display: block; + height: 5em; + background-color: transparent; + } + /* END HEADER */ + + + /* CONTENT */ + + /* END HEADER */ + + + /* CONTENT */ + div#content { + + } + + /* MAIN */ + div#main { + + } + /* END MAIN */ + + /* SUB */ + div#sub { + + } + /* END SUB */ + + /* END CONTENT */ + + + /* FOOTER */ + div#footer { + color: white; + background-color: #818EBD; + border-width:0; + margin-bottom: 4px; + } + div#footer p { + font-size: 0.8em; + + margin: 0; + padding: 5px; + } + /* END FOOTER */ +/* END LAYOUT */ + + + + +/* UL.SUBNAV */ + ul.subnav { + margin: 0; + padding: 0; + + font-size: 0.8em; + list-style: none; + } + ul.subnav li { + margin: 0 0 1em 0; + padding: 0; + list-style: none; + } + ul.subnav li a, + ul.subnav li a:link, + ul.subnav li a:visited, + ul.subnav li a:active { + text-decoration: none; + font-weight: bold; + color: black; + } + ul.subnav li a:hover { + text-decoration: underline; + } + ul.subnav li strong { + padding: 0 0 0 12px; + background: url("../i/subnav-highlight.gif") left top no-repeat transparent; + } + ul.subnav li strong a, + ul.subnav li strong a:link, + ul.subnav li strong a:visited, + ul.subnav li strong a:active { + color: white; + background-color: #818EBD; + } +/* END UL.SUBNAV */ diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/main.css b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/main.css new file mode 100644 index 000000000..3085ed369 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/main.css @@ -0,0 +1,5 @@ +@import url(layout-navtop-localleft.css); +@import url(layout.css); +@import url(forms.css); +@import url(typo.css); +@import url(tools.css); diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/nav-horizontal.css b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/nav-horizontal.css new file mode 100644 index 000000000..8e94d2238 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/nav-horizontal.css @@ -0,0 +1,80 @@ +/* A CSS Framework by Mike Stenhouse of Content with Style */ + +/* NAV */ + div#nav { + font-size: 0.8em; + } + * html div#nav { + /* hide ie/mac \*/ + height: 1%; + /* end hide */ + } + div#nav div.wrapper { + position: absolute; + left: 0; + bottom: 0; + width: 100%; + } + div#nav ul { + width: auto; + width: 100%; + + margin: 0; + padding: 0; + + line-height: 1em; + list-style: none; + } + div#nav li { + float: left; + display: inline; + + list-style: none; + + margin: 0; + padding: 0; + + line-height: 1em; + border-right: 1px solid #aaa; + } + div#nav li.last { + border-right: none; + } + div#nav a, + div#nav a:link, + div#nav a:active, + div#nav a:visited { + display: inline-block; + /* hide from ie/mac \*/ + display: block; + /* end hide */ + font-weight: bold; + text-decoration: none; + + margin: 0; + padding: 5px 10px 5px 10px; + + color: black; + background: #ddd; + } + div#nav a:hover { + text-decoration: underline; + } + div#nav strong { + display: inline-block; + /* hide from ie/mac \*/ + display: block; + /* end hide */ + + color: white; + background: #818EBD; + } + div#nav strong a, + div#nav strong a:link, + div#nav strong a:active, + div#nav strong a:visited, + div#nav strong a:hover { + color: white; + background-color: #818EBD; + } +/* END NAV */ diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/tools.css b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/tools.css new file mode 100644 index 000000000..351b10334 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/tools.css @@ -0,0 +1,68 @@ +/* A CSS Framework by Mike Stenhouse of Content with Style */ + +/* clearing */ + .stretch, + .clear { + clear:both; + height:1px; + margin:0; + padding:0; + font-size: 15px; + line-height: 1px; + } + .clearfix:after { + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; + } + * html>body .clearfix { + display: inline-block; + width: 100%; + } + + * html .clearfix { + /* Hides from IE-mac \*/ + height: 1%; + /* End hide from IE-mac */ + } +/* end clearing */ + + +/* replace */ + .replace { + display:block; + + background-repeat: no-repeat; + background-position: left top; + background-color:transparent; + } + /* tidy these up */ + .replace * { + text-indent: -10000px; + display:block; + + background-repeat: no-repeat; + background-position: left top; + background-color:transparent; + } + .replace a { + text-indent:0; + } + .replace a span { + text-indent:-10000px; + } +/* end replace */ + + +/* accessibility */ + span.accesskey { + text-decoration:none; + } + .accessibility { + position: absolute; + top: -999em; + left: -999em; + } +/* end accessibility */ diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/typo.css b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/typo.css new file mode 100644 index 000000000..d7db9d498 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/styles/typo.css @@ -0,0 +1,195 @@ +/* A CSS Framework by Mike Stenhouse of Content with Style */ + +/* TYPOGRAPHY */ + body { + text-align: left; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; + font-size: 76%; + line-height: 1em; + color: #333; + background: White; + } + div { + font-size: 1em; + } + img { + border: 0; + } + +/* LINKS */ + a, + a:link + a:active { + color: blue; + text-decoration: underline; + } + a:visited { + color: purple; + } + a:hover { + color: red; + text-decoration: none; + } +/* END LINKS */ + +/* HEADINGS */ + h1 { + font-size: 2em; + line-height: 1.5em; + margin: 0 0 0.5em 0; + padding: 0; + color: black; + } + + h1.title { + font-style: italic; + font-weight: bold; + color: white; + } + + h2 { + font-size: 1.5em; + line-height: 1.5em; + margin: 0 0 0.5em 0; + padding: 0; + color: black; + } + h3 { + font-size: 1.3em; + line-height: 1.3em; + margin: 0 0 0.5em 0; + padding:0; + color: black; + } + h4 { + font-size: 1.2em; + line-height: 1.3em; + margin: 0 0 0.25em 0; + padding: 0; + color: black; + } + h5 { + font-size: 1.1em; + line-height: 1.3em; + margin: 0 0 0.25em 0; + padding: 0; + color: black; + } + h6 { + font-size: 1em; + line-height: 1.3em; + margin: 0 0 0.25em 0; + padding: 0; + color: black; + } +/* END HEADINGS */ + +/* TEXT */ + p { + font-size: 1em; + margin: 0 0 1.5em 0; + padding: 0; + line-height:1.4em; + } + + blockquote { + margin-left:10px; + margin-right:10px; + margin-top:0px; + margin-bottom:0px; + display: block; + font: italic large Verdana, Geneva, Arial, Helvetica, sans-serif; + color: #A9A9A9; + background-color:#CDFFAA; + } + + blockquote p { + padding:5px; + margin: 0; + } + + pre { + font-family: monospace; + font-size: 1.0em; + } + strong, b { + font-weight: bold; + } + em, i { + font-style:italic; + } + code { + font-family: "Courier New", Courier, monospace; + font-size: 1em; + white-space: pre; + } +/* END TEXT */ + +/* LISTS */ + ul { + line-height:1.4em; + margin: 0 0 1.5em 0; + padding: 0; + } + ul li { + margin: 0 0 0.25em 30px; + padding: 0; + } + ol { + font-size: 1.0em; + line-height: 1.4em; + margin: 0 0 1.5em 0; + padding: 0; + } + ol li { + font-size: 1.0em; + margin: 0 0 0.25em 30px; + padding: 0; + } + dl { + margin: 0 0 1.5em 0; + padding: 0; + line-height: 1.4em; + } + dl dt { + font-weight: bold; + margin: 0.25em 0 0.25em 0; + padding: 0; + } + dl dd { + margin: 0 0 0 30px; + padding: 0; + } +/* END LISTS */ + + +/* TABLE */ + table { + font-size: 1em; + margin: 0 0 0 0; + padding: 0; + } + table caption { + font-weight: bold; + margin: 0 0 0 0; + padding: 0 0 0 0; + } + th { + font-weight: bold; + text-align: left; + } + td { + font-size: 1em; + } +/* END TABLE */ + + hr { + display: none; + } + div.hr { + height: 1px; + margin: 1.5em 10px; + border-bottom: 1px dotted black; + } + +/* END TYPOGRAPHY */ diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/index.jsp new file mode 100644 index 000000000..88fa036d8 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/index.jsp @@ -0,0 +1,16 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Tags + + +

    Tags

    + +
      +
    • Non UI Tags Examples
    • +
    • UI Tags Example
    • +
    + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/actionPrefix.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/actionPrefix.ftl new file mode 100644 index 000000000..70b8161f9 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/actionPrefix.ftl @@ -0,0 +1,19 @@ + + + + + Showcase - Tags - Non UI - Action Prefix (freemarker) + + + + You have come to this page because you used an 'action' prefix.

    + + The text you've enter is ${text?default('')}

    + + <@s.url id="url" action="actionPrefixExampleUsingFreemarker" namespace="/tags/non-ui/actionPrefix" /> + <@s.a href="%{#url}">Back + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/actionPrefixExample.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/actionPrefixExample.ftl new file mode 100644 index 000000000..857aa05d6 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/actionPrefixExample.ftl @@ -0,0 +1,48 @@ + + + + Showcase - Tags - Non UI - Action Prefix (Freemarker) + + + Action Prefix
    + By clicking on 'action prefix' button, the request will go to the action alias 'actionPrefix' + instead of the normal 'submit' action alias.

    + + Method Prefix
    + By clicking on the 'method prefix' button, the request will cause Struts to invoke 'submit' + action alias's 'alternateMethod' method instead of the default 'execute' method.

    + + Redirect Prefix
    + By clicking on the 'redirect prefix' button, the request will get redirected to www.google.com + instead

    + + Redirect Action Prefix
    + By clicking on the 'redirect-action prefix' button, the request will get redirected to + an action alias of 'redirectActionPrefix' instead of 'submit' action alias. Since this is a + redirect (a new request is issue from the client), the text entered will be lost.

    + + + <@s.url id="url" action="viewSource" namespace="/tags/non-ui/actionPrefix" /> + The JSP code can be read <@s.a href="%{#url}">here. + + + <@s.form action="submit" namespace="/tags/non-ui/actionPrefix" method="POST"> + + <@s.textfield label="Enter Some Text" name="text" /> + + <@s.submit name="action:actionPrefix" value="%{'action prefix'}" /> + + <@s.submit name="method:alternateMethod" value="%{'method prefix'}" /> + + <@s.submit name="redirect:http://www.google.com" value="%{'redirect prefix'}" /> + + <@s.submit name="redirect-action:redirectActionPrefix" value="%{'redirect-action prefix'}" /> + + <@s.submit value="Normal Submit" /> + + <@s.submit name="action:redirectActionPrefixAction" value="%{'redirect-action without prefix'}" /> + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/index.jsp new file mode 100644 index 000000000..e134c715c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/index.jsp @@ -0,0 +1,13 @@ + +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Tags - Non-Ui - Action Prefix + + +

      + Action Prefix Example (Freemarker)
    + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/methodPrefix.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/methodPrefix.ftl new file mode 100644 index 000000000..fe9ac75b9 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/methodPrefix.ftl @@ -0,0 +1,19 @@ + + + + + Showcase - Tags - Non UI - Action Prefix (freemarker) + + + + You have come to this page because you used an 'method' prefix.

    + + The text you've enter is ${text?default('')}

    + + <@s.url id="url" action="actionPrefixExampleUsingFreemarker" namespace="/tags/non-ui/actionPrefix" /> + <@s.a href="%{#url}">Back + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/normalSubmit.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/normalSubmit.ftl new file mode 100644 index 000000000..c183d9726 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/normalSubmit.ftl @@ -0,0 +1,17 @@ + + + + Showcase - Tags - Non UI - Action Prefix (freemarker) + + + + You have come to this page because you did a normal submit.

    + + The text you've enter is %{text}

    + + <@s.url id="url" action="actionPrefixExampleUsingFreemarker" namespace="/tags/non-ui/prefix" /> + <@s.a href="%{#url}">Back + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/redirectActionPrefix.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/redirectActionPrefix.ftl new file mode 100644 index 000000000..c991ee31b --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionPrefix/redirectActionPrefix.ftl @@ -0,0 +1,22 @@ + + + + + Showcase - Tags - Non UI - Action Prefix (freemarker) + + + + You have come to this page because you used an 'redirect-action' prefix.

    + + Because this is a 'redirect-action', the text will be lost, due to a redirection + implies a new request being issued from the client.

    + + The text you've enter is ${text?default('')}

    + + <@s.url id="url" action="actionPrefixExampleUsingFreemarker" namespace="/tags/non-ui/actionPrefix" /> + <@s.a href="%{#url}">Back + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/includedPage.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/includedPage.jsp new file mode 100644 index 000000000..bf84a3704 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/includedPage.jsp @@ -0,0 +1 @@ +

    This is INCLUDED by the action tag

    diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/includedPage2.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/includedPage2.jsp new file mode 100644 index 000000000..2b73ee077 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/includedPage2.jsp @@ -0,0 +1,2 @@ + +

    This is INCLUDED by the action tag (Page2)

    diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/includedPage3.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/includedPage3.jsp new file mode 100644 index 000000000..cddd14d8c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/includedPage3.jsp @@ -0,0 +1,2 @@ + +

    This is INCLUDED by the action tag (Page3)

    diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/showActionTagDemo.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/showActionTagDemo.jsp new file mode 100644 index 000000000..c0340a94d --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/actionTag/showActionTagDemo.jsp @@ -0,0 +1,43 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Non-Ui Tag - Action Tag + + + +
    +

    This is Not - Included by the Action Tag

    +
    + + + +
    + + + +
    + + + +
    + + + +
    + + + +
    + + + +
    + + + +Source + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/date.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/date.jsp new file mode 100644 index 000000000..9303e7018 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/date.jsp @@ -0,0 +1,104 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + UI Tags Example: Date + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameFormatOutput
    Before datetoString()
    Past datetoString()
    Now datetoString()
    Future datetoString()
    After datetoString()
    Current dateyyyy/MM/dd hh:mm:ss
    Current datedd.MM.yyyy hh:mm:ss
    Current time (24h)HH:mm:ss
    Before dateMMM, dd yyyy
    Before datenice
    After datedd.MM.yyyy
    After datenice
    Past datedd/MM/yyyy hh:mm
    Future dateMM-dd-yy
    Future date (fallback)fallback
    Past datenice
    Future datenice
    + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/debug.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/debug.jsp new file mode 100644 index 000000000..88de057b0 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/debug.jsp @@ -0,0 +1,20 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Non-UI Tags Example: Debug + + + + +

    Debug Tag Usage

    + +

    + This page shows a simple example of using the debug tag.
    + Just add <s:debug /> to your JSP page + and you will see the debug link. +

    + Just click on the Debug label to see the Struts ValueStack Debug information. +

    + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/ifTag/testIf.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/ifTag/testIf.ftl new file mode 100644 index 000000000..8d5f7de04 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/ifTag/testIf.ftl @@ -0,0 +1,611 @@ + + + TEST IF + + +

    +This is a simple freemarker template to test the If Tag (using freemarker directive). +There's quite a few combination being tested. The characters in bold and non-bold should be the same. +

    + + +1 - Foo - +<@s.if test="true"> + Foo + +<@s.else> + Bar + +
    +2 - Bar - +<@s.if test="false"> + Foo + +<@s.else> + Bar + +
    +3 - FooFooFoo - +<@s.if test="true"> + Foo + <@s.if test="true"> + FooFoo + + <@s.else> + BarBar + + +<@s.else> + Bar + +
    +4 - FooBarBar - +<@s.if test="true"> + Foo + <@s.if test="false"> + FooFoo + + <@s.else> + BarBar + + +
    +5 - BarFooFoo - +<@s.if test="false"> + Foo + +<@s.else> + Bar + <@s.if test="true"> + FooFoo + + <@s.else> + BarBar + + +
    +6 - BarBarBar - +<@s.if test="false"> + Foo + +<@s.else> + Bar + <@s.if test="false"> + FooFoo + + <@s.else> + BarBar + + +
    +7 - Foo - +<@s.if test="true"> + Foo + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + +
    +8 - Moo - +<@s.if test="false"> + Foo + +<@s.elseif test="true"> + Moo + +<@s.else> + Bar + +
    +9 - Bar - +<@s.if test="false"> + Foo + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + +
    +10 - FooFooFoo - +<@s.if test="true"> + Foo + <@s.if test="true"> + FooFoo + + <@s.elseif test="false"> + MooMoo + + <@s.else> + BarBar + + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + +
    +11 - FooMooMoo - +<@s.if test="true"> + Foo + <@s.if test="false"> + FooFoo + + <@s.elseif test="true"> + MooMoo + + <@s.else> + BarBar + + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + +
    +12 - FooBarBar - +<@s.if test="true"> + Foo + <@s.if test="false"> + FooFoo + + <@s.elseif test="false"> + MooMoo + + <@s.else> + BarBar + + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + +
    +13 - MooFooFoo - +<@s.if test="false"> + Foo + +<@s.elseif test="true"> + Moo + <@s.if test="true"> + FooFoo + + <@s.elseif test="false"> + MooMoo + + <@s.else> + BarBar + + +<@s.else> + Bar + +
    +14 - MooMooMoo - +<@s.if test="false"> + Foo + +<@s.elseif test="true"> + Moo + <@s.if test="false"> + FooFoo + + <@s.elseif test="true"> + MooMoo + + <@s.else> + BarBar + + +<@s.else> + Bar + +
    +15 - MooBarBar - +<@s.if test="false"> + Foo + +<@s.elseif test="true"> + Moo + <@s.if test="false"> + FooFoo + + <@s.elseif test="false"> + MooMoo + + <@s.else> + BarBar + + +<@s.else> + Bar + +
    +16 - BarFooFoo - +<@s.if test="false"> + Foo + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + <@s.if test="true"> + FooFoo + + <@s.elseif test="false"> + MooMoo + + <@s.else> + BarBar + + +
    +17 - BarMooMoo - +<@s.if test="false"> + Foo + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + <@s.if test="false"> + FooFoo + + <@s.elseif test="true"> + MooMoo + + <@s.else> + BarBar + + +
    +18 - BarBarBar - +<@s.if test="false"> + Foo + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + <@s.if test="false"> + FooFoo + + <@s.elseif test="false"> + MooMoo + + <@s.else> + BarBar + + + +
    +19 - Foo - +<@s.if test="true"> + Foo + + +
    +20 - ** should not display anything ** - +<@s.if test="false"> + Foo + + +
    +21 FooFooFoo - +<@s.if test="true"> + Foo + <@s.if test="true"> + FooFoo + + +<@s.else> + Bar + + +
    +22 - Foo - +<@s.if test="true"> + Foo + <@s.if test="false"> + FooFoo + + +<@s.else> + Bar + + +
    +23 - BarFooFoo - +<@s.if test="false"> + Foo + +<@s.else> + Bar + <@s.if test="true"> + FooFoo + + + +
    +24 - Bar - +<@s.if test="false"> + Foo + +<@s.else> + Bar + <@s.if test="false"> + FooFoo + + + +
    +25 - FooFooFoo +<@s.if test="true"> + Foo + <@s.if test="true"> + FooFoo + + <@s.elseif test="false"> + MooMoo + + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + + +
    +26 - FooMooMoo +<@s.if test="true"> + Foo + <@s.if test="false"> + FooFoo + + <@s.elseif test="true"> + MooMoo + + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + + +
    +27 - Foo - +<@s.if test="true"> + Foo + <@s.if test="false"> + FooFoo + + <@s.elseif test="false"> + MooMoo + + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + + +
    +28 - MooFooFoo +<@s.if test="false"> + Foo + +<@s.elseif test="true"> + Moo + <@s.if test="true"> + FooFoo + + <@s.elseif test="false"> + MooMoo + + +<@s.else> + Bar + + +
    +29 - MooMooMoo +<@s.if test="false"> + Foo + +<@s.elseif test="true"> + Moo + <@s.if test="false"> + FooFoo + + <@s.elseif test="true"> + MooMoo + + +<@s.else> + Bar + + +
    +30 - Moo - +<@s.if test="false"> + Foo + +<@s.elseif test="true"> + Moo + <@s.if test="false"> + FooFoo + + <@s.elseif test="false"> + MooMoo + + +<@s.else> + Bar + + +
    +31 - BarFooFoo - +<@s.if test="false"> + Foo + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + <@s.if test="true"> + FooFoo + + <@s.elseif test="false"> + MooMoo + + + +
    +32 - BarMooMoo - +<@s.if test="false"> + Foo + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + <@s.if test="false"> + FooFoo + + <@s.elseif test="true"> + MooMoo + + + +
    +33 - Bar - +<@s.if test="false"> + Foo + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + <@s.if test="false"> + FooFoo + + <@s.elseif test="false"> + MooMoo + + + +
    +34 - FooFooFoo - +<@s.if test="true"> + Foo + <@s.if test="true"> + FooFoo + + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + + +
    +35 - Foo - +<@s.if test="true"> + Foo + <@s.if test="false"> + FooFoo + + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + + +
    +36 - MooFooFoo - +<@s.if test="false"> + Foo + +<@s.elseif test="true"> + Moo + <@s.if test="true"> + FooFoo + + +<@s.else> + Bar + + +
    +37 - Moo - +<@s.if test="false"> + Foo + +<@s.elseif test="true"> + Moo + <@s.if test="false"> + FooFoo + + +<@s.else> + Bar + + +
    +38 - BarFooFoo - +<@s.if test="false"> + Foo + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + <@s.if test="true"> + FooFoo + + + +
    +39 - Bar - +<@s.if test="false"> + Foo + +<@s.elseif test="false"> + Moo + +<@s.else> + Bar + <@s.if test="false"> + FooFoo + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/ifTag/testIf.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/ifTag/testIf.jsp new file mode 100644 index 000000000..a872d0582 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/ifTag/testIf.jsp @@ -0,0 +1,616 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> + +<%@taglib prefix="s" uri="/struts-tags" %> + + + + + +Test If Tag + + +

    +This is a simple jsp to test the If Tag. There's quite a few combination being tested. +The characters in bold an non-bold should be the same. +

    + + +1 - Foo - + + Foo + + + Bar + +
    +2 - Bar - + + Foo + + + Bar + +
    +3 - FooFooFoo - + + Foo + + FooFoo + + + BarBar + + + + Bar + +
    +4 - FooBarBar - + + Foo + + FooFoo + + + BarBar + + +
    +5 - BarFooFoo - + + Foo + + + Bar + + FooFoo + + + BarBar + + +
    +6 - BarBarBar - + + Foo + + + Bar + + FooFoo + + + BarBar + + +
    +7 - Foo - + + Foo + + + Moo + + + Bar + +
    +8 - Moo - + + Foo + + + Moo + + + Bar + +
    +9 - Bar - + + Foo + + + Moo + + + Bar + +
    +10 - FooFooFoo - + + Foo + + FooFoo + + + MooMoo + + + BarBar + + + + Moo + + + Bar + +
    +11 - FooMooMoo - + + Foo + + FooFoo + + + MooMoo + + + BarBar + + + + Moo + + + Bar + +
    +12 - FooBarBar - + + Foo + + FooFoo + + + MooMoo + + + BarBar + + + + Moo + + + Bar + +
    +13 - MooFooFoo - + + Foo + + + Moo + + FooFoo + + + MooMoo + + + BarBar + + + + Bar + +
    +14 - MooMooMoo - + + Foo + + + Moo + + FooFoo + + + MooMoo + + + BarBar + + + + Bar + +
    +15 - MooBarBar - + + Foo + + + Moo + + FooFoo + + + MooMoo + + + BarBar + + + + Bar + +
    +16 - BarFooFoo - + + Foo + + + Moo + + + Bar + + FooFoo + + + MooMoo + + + BarBar + + +
    +17 - BarMooMoo - + + Foo + + + Moo + + + Bar + + FooFoo + + + MooMoo + + + BarBar + + +
    +18 - BarBarBar - + + Foo + + + Moo + + + Bar + + FooFoo + + + MooMoo + + + BarBar + + + +
    +19 - Foo - + + Foo + + +
    +20 - ** should not display anything ** - + + Foo + + +
    +21 FooFooFoo - + + Foo + + FooFoo + + + + Bar + + +
    +22 - Foo - + + Foo + + FooFoo + + + + Bar + + +
    +23 - BarFooFoo - + + Foo + + + Bar + + FooFoo + + + +
    +24 - Bar - + + Foo + + + Bar + + FooFoo + + + +
    +25 - FooFooFoo + + Foo + + FooFoo + + + MooMoo + + + + Moo + + + Bar + + +
    +26 - FooMooMoo + + Foo + + FooFoo + + + MooMoo + + + + Moo + + + Bar + + +
    +27 - Foo - + + Foo + + FooFoo + + + MooMoo + + + + Moo + + + Bar + + +
    +28 - MooFooFoo + + Foo + + + Moo + + FooFoo + + + MooMoo + + + + Bar + + +
    +29 - MooMooMoo + + Foo + + + Moo + + FooFoo + + + MooMoo + + + + Bar + + +
    +30 - Moo - + + Foo + + + Moo + + FooFoo + + + MooMoo + + + + Bar + + +
    +31 - BarFooFoo - + + Foo + + + Moo + + + Bar + + FooFoo + + + MooMoo + + + +
    +32 - BarMooMoo - + + Foo + + + Moo + + + Bar + + FooFoo + + + MooMoo + + + +
    +33 - Bar - + + Foo + + + Moo + + + Bar + + FooFoo + + + MooMoo + + + + +
    +34 - FooFooFoo - + + Foo + + FooFoo + + + + Moo + + + Bar + + +
    +35 - Foo - + + Foo + + FooFoo + + + + Moo + + + Bar + + +
    +36 - MooFooFoo - + + Foo + + + Moo + + FooFoo + + + + Bar + + +
    +37 - Moo - + + Foo + + + Moo + + FooFoo + + + + Bar + + +
    +38 - BarFooFoo - + + Foo + + + Moo + + + Bar + + FooFoo + + + +
    +39 - Bar - + + Foo + + + Moo + + + Bar + + FooFoo + + + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/index.jsp new file mode 100644 index 000000000..2fc1a7bd4 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/index.jsp @@ -0,0 +1,24 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Tags - Non UI Tags + + +

    Non UI Tags

    + +
      +
    • Action Tag
    • +
    • Date Tag
    • +
    • Debug Tag
    • +
    • Iterator Generator Tag
    • +
    • Append Iterator Tag +
    • Merge Iterator Demo +
    • Subset Tag +
    • Action Prefix Example
    • +
    • If Tag (JSP)
    • +
    • If Tag (Freemarker)
    • +
    + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/appendIteratorTagDemoResult.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/appendIteratorTagDemoResult.jsp new file mode 100644 index 000000000..2e398de80 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/appendIteratorTagDemoResult.jsp @@ -0,0 +1,25 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Tag - Non UI Tag - AppendIterator Tag + + + + + + + + + + + + +
    +
    + + Back To Non-UI Demo + Back To Showcase + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/iteratorGeneratorTagDemoResult.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/iteratorGeneratorTagDemoResult.jsp new file mode 100644 index 000000000..efb582cdf --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/iteratorGeneratorTagDemoResult.jsp @@ -0,0 +1,19 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Tag - Non Ui Tag - Iterator Generator Tag Demo + + + + + +
    +
    +
    + + Back To Non-UI Demo + Back To Showcase + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/mergeIteratorTagDemoResult.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/mergeIteratorTagDemoResult.jsp new file mode 100644 index 000000000..03b340d38 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/mergeIteratorTagDemoResult.jsp @@ -0,0 +1,25 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Tags - Non UI Tag - MergeIterator Tag + + + + + + + + + + + + +
    +
    + + Back To Non-UI Demo + Back To Showcase + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/showAppendIteratorTagDemo.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/showAppendIteratorTagDemo.jsp new file mode 100644 index 000000000..838a9a128 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/showAppendIteratorTagDemo.jsp @@ -0,0 +1,19 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Tag - Non UI Tag - AppendIterator Tag + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/showIteratorGeneratorTagDemo.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/showIteratorGeneratorTagDemo.jsp new file mode 100644 index 000000000..f076828c5 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/showIteratorGeneratorTagDemo.jsp @@ -0,0 +1,21 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Tag - Non Ui Tag - Iterator Generator Tag Demo + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/showMergeIteratorTagDemo.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/showMergeIteratorTagDemo.jsp new file mode 100644 index 000000000..032e27d46 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/showMergeIteratorTagDemo.jsp @@ -0,0 +1,17 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Tags - Non UI Tag - MergeIterator Tag + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/subsetIteratorTagDemo.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/subsetIteratorTagDemo.jsp new file mode 100644 index 000000000..84f62495b --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/subsetIteratorTagDemo.jsp @@ -0,0 +1,20 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Tags - Non UI Tags - SubsetTag Demo + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/subsetIteratorTagDemoResult.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/subsetIteratorTagDemoResult.jsp new file mode 100644 index 000000000..b34631b25 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/non-ui/iteratorTag/subsetIteratorTagDemoResult.jsp @@ -0,0 +1,21 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Tags - Non UI Tags - Subset Tag + + + + + + + +
    +
    +
    + + Back To Non-UI Demo + Back To Showcase + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/componentTagExample.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/componentTagExample.jsp new file mode 100644 index 000000000..2eb3df2bf --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/componentTagExample.jsp @@ -0,0 +1,62 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Tags - UI Tags - Component Tag + + + +This example tries to demonstrates the usage of <s:component ... > tag. +

    + +To have a look at the source of this jsp page click + +here +

    + +Example 1: +This example load the template from the webapp context path using +the default (ftl) as its template. + + + +

    + +Example 2: +This example load the template from the webapp context path using +jsp as its template (notice the *.jsp extension to the template). + + + +

    + +Example 3 +This example load the template from the webapp context path, +using the default template directory and theme (default to +'template' and 'xhtml' respectively) + + + +

    + + +Example 4 +This example load the template from the webapp classpath using +a custom themplate directory and theme. + + + +

    + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/datepicker/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/datepicker/index.jsp new file mode 100644 index 000000000..1cb08c6d0 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/datepicker/index.jsp @@ -0,0 +1,23 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + UI Tags Example + + + + + + + + + + + + + + + +
    + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/dynamicTreeSelect.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/dynamicTreeSelect.jsp new file mode 100644 index 000000000..2c1cd2e07 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/dynamicTreeSelect.jsp @@ -0,0 +1,6 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + +Id:
    +Name:
    + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/example.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/example.jsp new file mode 100644 index 000000000..5552d8beb --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/example.jsp @@ -0,0 +1,126 @@ +<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + UI Tags Example + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/example.vm b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/example.vm new file mode 100644 index 000000000..5e28b03cf --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/example.vm @@ -0,0 +1,32 @@ + + + UI Tags Example + #shead() + + + + +#surl ("id=url" "value=index.jsp") +Back to index.jsp! + + +#sform ("action=exampleSubmitVelocity" "method=post" "enctype=multipart/form-data") + #stextfield ("label=Name" "name=name") + #sdatetimepicker ("label=Birthday" "name=birthday") + #stextarea ("label=Biography" "name=bio" "cols=20" "rows=3") + #sselect ("label=Favourite Color" "list={'Red', 'Blue', 'Green'}" "name=favouriteColor" "emptyOption=true" "headerKey=None" "headerValue=None") + #sselect ("label=Favourite Language" "list=favouriteLanguages" "name=favouriteLanguage" "listKey=key" "listValue=description" "emptyOption=true" "headerKey=None" "headerValue=None") + #scheckboxlist ("label=Friends" "list={'Patrick', 'Jason', 'Jay', 'Toby', 'Rene'}" "name=friends") + #scheckbox ("label=Age 18+" "name=legalAge") + #sdoubleselect ("label=State" "name=region" "list={'North', 'South'}" "value='North'" "doubleValue='Florida'" "doubleList=top == 'North' ? {'Oregon', 'Washington'} : {'Texas', 'Florida'}" "doubleName=state" "headerKey=-1" "headerValue=---------- Please Select ----------" "emptyOption=true" ) + #sdoubleselect ("label=Favourite Vehical" "name=favouriteVehicalType" "list=vehicalTypeList" "listKey=key" "listValue=description" "value='MotorcycleKey'" "doubleValue='YamahaKey'" "doubleList=vehicalSpecificList" "doubleListKey=key" "doubleListValue=description" "doubleName=favouriteVehicalSpecific" "headerKey=-1" "headerValue=---------- Please Select ----------" "emptyOption=true" ) + #sfile ("label=Picture" "name=picture") + #soptiontransferselect ("label=Favourite Cartoons Characters" "name=leftSideCartoonCharacters" "leftTitle=Left Title" "rightTitle=Right Title" "list={'Popeye', 'He-Man', 'Spiderman'}" "multiple=true" "headerKey=headerKey" "headerValue=--- Please Select ---" "emptyOption=true" "doubleList={'Superman', 'Mickey Mouse', 'Donald Duck'}" "doubleName=rightSideCartoonCharacters" "doubleHeaderKey=doubleHeaderKey" "doubleHeaderValue=--- Please Select ---" "doubleEmptyOption=true" "doubleMultiple=true" ) + #ssubmit() + #sreset() +#end + +#sa("href=${url}")Back to index.jsp#end + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/exampleSubmited.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/exampleSubmited.jsp new file mode 100644 index 000000000..9fe707628 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/exampleSubmited.jsp @@ -0,0 +1,43 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Non-UI Tag - Example Submited + + + +

    Example Submitted

    + + + + + + + + + + + + + + + + + + + + + + + +
    + + .  + +
    + + .  + +
    + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/exampleSubmited.vm b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/exampleSubmited.vm new file mode 100644 index 000000000..e33f55229 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/exampleSubmited.vm @@ -0,0 +1,47 @@ + + +Showcase - Non-UI Tag - Example Submited + + + +

    Example Submitted

    + + #slabel ("label=Name" "name=name") + #slabel ("label=Birthday" "name=birthday") + #slabel ("label=Biography" "name=bio") + #slabel ("label=Favourite Color" "name=favouriteColor") + #slabel ("label=Friends" "name=friends") + #slabel ("label=Legal Age" "name=legalAge") + #slabel ("label=Region" "name=region") + #slabel ("label=State" "name=state") + #slabel ("label=Picture" "name=picture") + #slabel ("label=Favourite Language" "name=favouriteLanguage") + #slabel ("label=Favourite Vehical Type" "name=favouriteVehicalType") + #slabel ("label=Favourite Vehical Specific" "name=favouriteVehicalSpecific") + + + + + + + + +
    Favourite Cartoon Characters (Left): + #set ( $startCount = 1) + #foreach( $item in $leftSideCartoonCharacters) + $startCount.${item}  + #set ( $startCount = $startCount + 1) + #end +
    Favourite Cartoon Characters (Right): + #set ( $startCount = 1) + #foreach( $item in $rightSideCartoonCharacters) + $startCount.${item}  + #set ( $startCount = $startCount + 1) + #end +
    + +#surl ("id=url" "value=index.jsp") +#sa("href=${url}")Back to index.jsp#end + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/images/backgroundImage.jpg b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/images/backgroundImage.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0f9cb92533767e2bc8bec90c19f2045b9cdb18f7 GIT binary patch literal 13192 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 literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/images/leopard.jpg b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/images/leopard.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f67f96b75bd1bec4372e7993ec09e1dbb364f1e1 GIT binary patch literal 3850 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 js( + + + + Showcase - Tags - UI Tags + + +

    UI Tags

    + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselect.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselect.jsp new file mode 100644 index 000000000..d267ce583 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselect.jsp @@ -0,0 +1,93 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Show Case - Tags - UI Tags - Optiontransferselect + + + + + + + +
    + + + +
    + + + +
    + + + +
    + + +
    + + +
    + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselectSubmit.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselectSubmit.jsp new file mode 100644 index 000000000..04d915b18 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/lotsOfOptiontransferselectSubmit.jsp @@ -0,0 +1,94 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Tags - UI Tags - Optiontransferoption Result + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Favourite Cartoons: + + .  + +
    Non Favourite Cartoons: + + .  + +
    Favourite Cars: + + .  + +
    Non Favourite Cars: + + .  + +
    Favourite Motorcycles: + + .  + +
    Non Favourite Motorcycles: + + .  + +
    Favourite Countries: + + .  + +
    Non Favourite Countries: + + .  + +
    Favourite Sports: + + .  + +
    Non Favourite Sports: + + .  + +
    + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/moreSelects.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/moreSelects.jsp new file mode 100644 index 000000000..6b00b3466 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/moreSelects.jsp @@ -0,0 +1,61 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Show Case - Tags - UI Tags - Optiontransferselect + + + + + + + + +
    + + + +
    + + + +
    + + + + + + + +
    + +
    + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/moreSelectsSubmit.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/moreSelectsSubmit.jsp new file mode 100644 index 000000000..7b79c86c3 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/moreSelectsSubmit.jsp @@ -0,0 +1,53 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - Tags - UI Tags - Select Boxes Result + + + + + + + + + + + + + + + + + + + + + + + + +
    Prioritised Favourite Cartoon Characters: + + .  + +
    Prioritised Favourite Cars: + + .  + +
    Prioritised Favourite Countries + + .  + +
    Favourite Cities + + .  + +
    Favourite Numbers + + .  + +
    + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/staticTreeSelect.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/staticTreeSelect.jsp new file mode 100644 index 000000000..c08ed8a4e --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/staticTreeSelect.jsp @@ -0,0 +1,28 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + +<% + request.setAttribute("decorator", "none"); + response.setHeader("Cache-Control","no-cache"); //HTTP 1.1 + response.setHeader("Pragma","no-cache"); //HTTP 1.0 + response.setDateHeader ("Expires", 0); //prevents caching at the proxy server +%> + + +<%-- + +--%> + +<%=request.getParameter("nodeId") %> diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/timepicker/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/timepicker/index.jsp new file mode 100644 index 000000000..58595df0c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/timepicker/index.jsp @@ -0,0 +1,20 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + UI Tags Example + + + + + + + + + + + + +
    + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/treeExampleDynamic.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/treeExampleDynamic.jsp new file mode 100644 index 000000000..26929da2f --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/treeExampleDynamic.jsp @@ -0,0 +1,47 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - UI Tag Example - Tree Example (Dynamic) + + + + + + + + + + +
    + + +
    + +
    +Please click on any of the tree nodes. +
    + + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/treeExampleStatic.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/treeExampleStatic.jsp new file mode 100644 index 000000000..b9cf834ae --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tags/ui/treeExampleStatic.jsp @@ -0,0 +1,53 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + +Showcase - UI Tag Example - Tree Example (Static) + + + + + + + + + +
    + + + + + + + + + + + + + + +
    + + +
    +Please click on any node on the tree. +
    + + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/template/xhtml/mytemplate.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/template/xhtml/mytemplate.jsp new file mode 100644 index 000000000..7ebb96781 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/template/xhtml/mytemplate.jsp @@ -0,0 +1,9 @@ + +<%@taglib prefix="s" uri="/struts-tags" %> + +
    +

    +JSP Custom Template - +parameter 'paramName' - +

    +
    diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/body.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/body.ftl new file mode 100644 index 000000000..9baa1b4c0 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/body.ftl @@ -0,0 +1,10 @@ +
    +

    This example illustrates the freemarker support in the Struts/Tiles Plugin.

    + +

    Tiles 2 is an effort to extract the Tiles library from Struts. It is currently housed + in the Sandbox area of the Apache Struts Subversion repository.

    + + <@s.form> + <@s.textfield name="Textfield" value="Textfield"/> + +
    \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/body.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/body.jsp new file mode 100644 index 000000000..da89efdbf --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/body.jsp @@ -0,0 +1,18 @@ +<%@taglib prefix="s" uri="/struts-tags" %> +
    +

    This example illustrates the Struts/Tiles Plugin.

    + +

    Tiles 2 is an effort to extract the Tiles library from Struts. It is currently housed + in the Sandbox area of the Apache Struts Subversion repository.

    + +

    Features

    + + +
    \ No newline at end of file diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/header.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/header.jsp new file mode 100644 index 000000000..38912df9c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/header.jsp @@ -0,0 +1 @@ +

    ${title}

    diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/layout.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/layout.ftl new file mode 100644 index 000000000..010d56012 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/layout.ftl @@ -0,0 +1,12 @@ +<#assign tiles=JspTaglibs["http://tiles.apache.org/tags-tiles"]> +<@tiles.importAttribute name="title" scope="request"/> + + <@tiles.getAsString name="title"/> + + <@tiles.insertAttribute name="header"/> +

    + <@tiles.insertAttribute name="body"/> +

    +

    Notice that this is a layout made in FreeMarker

    + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/layout.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/layout.jsp new file mode 100644 index 000000000..9caca1183 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/tiles/layout.jsp @@ -0,0 +1,17 @@ +<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + +<%-- Show usage; Used in Header --%> + + + <tiles:getAsString name="title"/> + + + +

    + +

    + +

    Notice that this is a layout made in JSP

    + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/doublePost.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/doublePost.jsp new file mode 100644 index 000000000..6aa82231f --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/doublePost.jsp @@ -0,0 +1,15 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + + +

    + Double post. Struts intercepted this request and prevents the action from executing again. +

    + +

    + Click here to return. + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example1.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example1.jsp new file mode 100644 index 000000000..99aa5b809 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example1.jsp @@ -0,0 +1,24 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + Token Examples + + +

    Token Example 1

    + + Example 1: This example illustrates a situation where you can transfer money from + one account to another. We use the token to prevent double posts so the transfer only + happens once. +

    + +
    Balance of source account: +
    Balance of destination account: +

    + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example2.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example2.jsp new file mode 100644 index 000000000..c3d99c4a0 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example2.jsp @@ -0,0 +1,24 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + Token Examples + + +

    Token Example 2

    + + Example 2: This example illustrates a situation where you can transfer money from + one account to another. We use the token to prevent double posts so the transfer only + happens once. This action will redirect after you have submitted the form. +

    + +
    Balance of source account: +
    Balance of destination account: +

    + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example3.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example3.jsp new file mode 100644 index 000000000..c624ad6b7 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example3.jsp @@ -0,0 +1,24 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + Token Examples + + +

    Token Example 3

    + + Example 3: This example illustrates a situation where you can transfer money from + one account to another. We use the token to prevent double posts so the transfer only + happens once. This example uses the token session based interceptor and redirect after post. +

    + +
    Balance of source account: +
    Balance of destination account: +

    + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example4.ftl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example4.ftl new file mode 100644 index 000000000..f890ba30c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/example4.ftl @@ -0,0 +1,26 @@ + + Token Examples + + +

    Token Example 4

    + + Example 4: This example illustrates a situation where you can transfer money from + one account to another. We use the token to prevent double posts so the transfer only + happens once. This page is rendered using freemarker. See the xwork-token.xml where + we must also use the createSession interceptor to be sure that a HttpSession exists + when freemarker renders this webpage, otherwise the @s.token tag causes an exception + while rendering the page. +

    + +
    Balance of source account: <@s.property value="#session.balanceSource"/> +
    Balance of destination account: <@s.property value="#session.balanceDestination"/> +

    + + <@s.form action="transfer4"> + <@s.token/> + <@s.textfield label="Amount" name="amount" required="true" value="400"/> + <@s.submit value="Transfer money"/> + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/index.jsp new file mode 100644 index 000000000..12908101b --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/index.jsp @@ -0,0 +1,33 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + Token Examples (double post) + + +

    Token Examples

    + + These examples illustrate Struts build in support of using tokens to prevent double post. +

    + You have a web page where user can input data and press a button to submit. + There could be a problem that the user submit the data many times, by either clicking the + button many times, or use the browser back button and then submit the form again. +
    A good solution is to use a hidden token in the form. The token is autogenerated and unique + from time to time. This token is then validated with the HttpSession that it is the first time + it is submitted, if not we have a double post and therefore can prevent the second submit action. +

    + For more information check out javadoc for org.apache.struts2.interceptor.TokenInterceptor + and org.apache.struts2.interceptor.TokenSessionStoreInterceptor. + +
    +
    Example 1 (token based .jsp example) + +
    +
    Example 2 (as example 1 with redirect after post) + +
    +
    Example 3 (token-session based .jsp example) + +
    +
    Example 4 (token based freemarker example) + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/transferDone.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/transferDone.jsp new file mode 100644 index 000000000..f296e7c47 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/token/transferDone.jsp @@ -0,0 +1,25 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + Token Examples (double post) + + +

    Token Examples

    + + The transfer is done at + +
    New balance of source account: +
    New balance of destination account: + +

    + Try using the browser back button and submit the form again. This should result in a double post + that Struts should intercept and handle accordingly. +

    + For example 3 (session token) you should notice that the date/time stays the same. This interceptor + catches that this is a double post but doens't display the double post page, but just renders the + web page result from the first post. + +

    + Click here to return. + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/clientSideValidationExample.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/clientSideValidationExample.jsp new file mode 100644 index 000000000..2c19f01d1 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/clientSideValidationExample.jsp @@ -0,0 +1,55 @@ +<%-- + fieldValidatorExample.jsp + + @author tm_jee + @version $Date$ $Id$ +--%> + +<%@taglib prefix="s" uri="/struts-tags" %> + + + + Showcase - Validation - Field Validators Example + + + + + + + + +

    All Field Errors Will Appear Here

    + +
    + +

    Field Error due to 'Required String Validator Field' Will Appear Here

    + + + +
    + +

    Field Error due to 'String Length Validator Field' Will Appear Here

    + + stringLengthValidatorField + +
    + + + + + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/fieldValidatorsExample.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/fieldValidatorsExample.jsp new file mode 100644 index 000000000..8938fe12c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/fieldValidatorsExample.jsp @@ -0,0 +1,55 @@ +<%-- + fieldValidatorExample.jsp + + @author tm_jee + @version $Date$ $Id$ +--%> + +<%@taglib prefix="s" uri="/struts-tags" %> + + + + Showcase - Validation - Field Validators Example + + + + + + + + +

    All Field Errors Will Appear Here

    + +
    + +

    Field Error due to 'Required String Validator Field' Will Appear Here

    + + + +
    + +

    Field Error due to 'String Length Validator Field' Will Appear Here

    + + stringLengthValidatorField + +
    + + + + + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/footer.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/footer.jsp new file mode 100644 index 000000000..11828c8fb --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/footer.jsp @@ -0,0 +1,9 @@ + <%@taglib prefix="s" uri="/struts-tags" %> + +
    + + + + +Back To Validation Examples  +Back To Showcase diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/index.jsp new file mode 100644 index 000000000..36f92b90f --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/index.jsp @@ -0,0 +1,42 @@ +<%-- + index.jsp + + @author tm_jee + @version $Date$ $Id$ +--%> + +<%@taglib prefix="s" uri="/struts-tags" %> + + + + Showcase - Validation + + +

    Validation Examples

    + + + + + + + + + + + + +
      +
    • Field Validators
    • +
    • Field Validators with client-side JavaScript
    • +
    • Non Field Validator
    • +
    • Store across request using MessageStoreInterceptor (Example)
    • +
    • Validation (ajax)
    • +
    • Validation (basic)
    • +
    • Validation (client)
    • +
    • Validation (client using css_xhtml theme)
    • +
    • Visitor Validator
    • +
    • Back To Showcase +
    + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/nonFieldValidatorsExample.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/nonFieldValidatorsExample.jsp new file mode 100644 index 000000000..04800872d --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/nonFieldValidatorsExample.jsp @@ -0,0 +1,38 @@ +<%-- + nonFieldValidatorsExample.jsp + + @author tm_jee + @version $Date$ $Id$ +--%> + + +<%@taglib prefix="s" uri="/struts-tags" %> + + + + Showcase - Validation - Non Field Validator Example + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-ajax.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-ajax.jsp new file mode 100644 index 000000000..22840de97 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-ajax.jsp @@ -0,0 +1,23 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + + + Validation - Basic + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-basic.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-basic.jsp new file mode 100644 index 000000000..6d75c51d6 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-basic.jsp @@ -0,0 +1,27 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + + + Validation - Basic + + + + + +What is your favorite color? +

    + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-client-css.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-client-css.jsp new file mode 100644 index 000000000..ac62bb2b7 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-client-css.jsp @@ -0,0 +1,24 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + + + Validation - Basic + + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-client.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-client.jsp new file mode 100644 index 000000000..0517e0569 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-client.jsp @@ -0,0 +1,24 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + + + + Validation - Basic + + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-success.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-success.jsp new file mode 100644 index 000000000..738097a6c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/quiz-success.jsp @@ -0,0 +1,14 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Quiz submitted! + + + + +Thank you, . Your answer has been submitted as: + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/storeErrorsAcrossRequestCancel.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/storeErrorsAcrossRequestCancel.jsp new file mode 100644 index 000000000..b997a7817 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/storeErrorsAcrossRequestCancel.jsp @@ -0,0 +1,21 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> + +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Insert title here + + + + + + + +

    Application Canceled

    + + Try Again + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/storeErrorsAcrossRequestExample.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/storeErrorsAcrossRequestExample.jsp new file mode 100644 index 000000000..96d81aa3c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/storeErrorsAcrossRequestExample.jsp @@ -0,0 +1,44 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<%@taglib prefix="s" uri="/struts-tags" %> + + + + +Showcase - Validation - Store Errors Across Request Example + + +

    + This is an example demonstrating the use of MessageStoreInterceptor. + When this form is submited a redirect is issue both when there's a validation + error or not. Normally, when a redirect is issue the action messages / errors and + field errors stored in the action will be lost (due to an action lives + only as long as a request). With a MessageStoreInterceptor in place and + configured, the action errors / messages / field errors will be store and + remains retrieveable even after a redirect. +

    + + + + +
    ActionMessages:
    ActionErrors:
    + +

    + + + + + + +

    +

    + Try submitting with an invalid age value, + and note that the browser location changes, + but validation messages are retained. + Because of the redirect, + the input values are not retained. +

    + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/storeErrorsAcrossRequestOk.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/storeErrorsAcrossRequestOk.jsp new file mode 100644 index 000000000..69eee5caf --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/storeErrorsAcrossRequestOk.jsp @@ -0,0 +1,23 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<%@taglib prefix="s" uri="/struts-tags" %> + + + + +Showcase - Validation - Store Errors Across Request Example + + + + + + + +

    Ok !

    + + + Try Again + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successClientSideValidationExample.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successClientSideValidationExample.jsp new file mode 100644 index 000000000..77f111c2d --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successClientSideValidationExample.jsp @@ -0,0 +1,53 @@ +<%-- + successFieldValidatorsExample.jsp + + @author tm_jee + @version $Date$ $Id$ +--%> + +<%@taglib prefix="s" uri="/struts-tags" %> + + + Showcase - Validation - SuccessFieldValidatorsExample + +

    Success !

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Required Validator Field:
    Required String Validator Field:
    Integer Validator Field:
    Date Validator Field:
    Email Validator Field:
    URL Validator Field:
    String Length Validator Field:
    Regex Validator Field: Field Expression Validator Field:
    + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successFieldValidatorsExample.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successFieldValidatorsExample.jsp new file mode 100644 index 000000000..5e83be49c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successFieldValidatorsExample.jsp @@ -0,0 +1,48 @@ +<%-- + successFieldValidatorsExample.jsp + + @author tm_jee + @version $Date$ $Id$ +--%> + +<%@taglib prefix="s" uri="/struts-tags" %> + + + Showcase - Validation - SuccessFieldValidatorsExample + +

    Success !

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Required Validator Field:
    Required String Validator Field:
    Integer Validator Field:
    Date Validator Field:
    Email Validator Field:
    String Length Validator Field:
    Regex Validator Field: Field Expression Validator Field:
    + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successNonFieldValidatorsExample.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successNonFieldValidatorsExample.jsp new file mode 100644 index 000000000..bc22e4fa9 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successNonFieldValidatorsExample.jsp @@ -0,0 +1,33 @@ +<%-- + successNonFieldValidatorsExample.jsp + + @author tm_jee + @version $Date$ $Id$ +--%> + + +<%@taglib prefix="s" uri="/struts-tags" %> + + + Showcase - Validation - SuccessNonFieldValidatorsExample + +

    Success !

    + + + + + + + + + + + + + +
    Some Text:
    Some Text Retyped:
    Some Text Retyped Again:
    + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successVisitorValidatorsExample.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successVisitorValidatorsExample.jsp new file mode 100644 index 000000000..90e2b42ad --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/successVisitorValidatorsExample.jsp @@ -0,0 +1,35 @@ +<%-- + successVisitorValidatorsExample.jsp + + @author tm_jee + @version $Date$ $Id$ +--%> + + + +<%@taglib prefix="s" uri="/struts-tags" %> + + + Showcase - Validation - SuccessVisitorValidatorsExameple + +

    Success !

    + + + + + + + + + + + + + +
    User Name:
    User Age:
    User Birthday:
    + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/validationExamplesStyles.css b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/validationExamplesStyles.css new file mode 100644 index 000000000..961be7c2b --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/validationExamplesStyles.css @@ -0,0 +1,11 @@ +@CHARSET "UTF-8"; + +@CHARSET "UTF-8"; + +.errorMessage { + color: red; +} + +/*.errorLabel { + color: red; +}*/ diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/visitorValidatorsExample.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/visitorValidatorsExample.jsp new file mode 100644 index 000000000..0300a4fd6 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/validation/visitorValidatorsExample.jsp @@ -0,0 +1,36 @@ +<%-- + visitorValidatorsExample.jsp + + @author tm_jee + @version $Date$ $Id$ +--%> + + +<%@taglib prefix="s" uri="/struts-tags" %> + + +Showcase - Validation - VisitorValidatorsExample + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/viewSource.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/viewSource.jsp new file mode 100644 index 000000000..9c5267ec4 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/viewSource.jsp @@ -0,0 +1,53 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + View Sources + + + "> + "> + " media="print"> + + + + +

    View Sources

    + + + +

    ${empty page ? "Unknown page" : page}

    +
    +
    +${row.count}: 
    +
    +
    + +

    ${empty config ? "Unknown configuration" : config}

    +
    +
    +
    +${configLine - padding + row.count - 1}: 
    +${configLine - padding + row.count - 1}: 
    +
    +
    + +

    ${empty className ? "Unknown or unavailable Action class" : className}

    +
    +
    +${row.count}: 
    +
    +
    + +
    + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/complete.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/complete.jsp new file mode 100644 index 000000000..f124310ec --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/complete.jsp @@ -0,0 +1,13 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + Execute and Wait Examples + + +

    The process is complete

    + + We have processed your request. +

    + Click here to return. + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/example1.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/example1.jsp new file mode 100644 index 000000000..d3c1d835f --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/example1.jsp @@ -0,0 +1,16 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + Execute and Wait Examples + + +

    Execute and Wait Example 1

    + + Example 1: In the form below enter how long time to simulate the process should take. + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/example2.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/example2.jsp new file mode 100644 index 000000000..484636c03 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/example2.jsp @@ -0,0 +1,17 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + Execute and Wait Examples + + +

    Execute and Wait Example 2

    + + Example 2: As example 1 but uses a delay of 2000 millis before the wait page is shown. Try simulating with + a value of 500 millis to see that no wait page is shown at all. + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/example3.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/example3.jsp new file mode 100644 index 000000000..3fe65044c --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/example3.jsp @@ -0,0 +1,18 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + Execute and Wait Examples + + +

    Execute and Wait Example 3

    + + Example 3: As example 1 but uses a delay of 3000 millis before the wait page is shown. + While waiting for the wait page it will check every 1000 millis if the background process is already + done. Try simulating with a value of 700 millis to see that the wait page is shown soon thereafter. + + + + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/index.jsp new file mode 100644 index 000000000..566bc55b4 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/index.jsp @@ -0,0 +1,19 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + Execute and Wait Examples + + +

    Execute and Wait Examples

    + + These examples illustrate Struts build in support for execute and wait. +

    + When you have a process that takes a long time your users can be impatient and starts to submit/click again. +
    A good solution is to show the user a progress page (wait page) while the process takes it time. + +
    +
    Example 1 (no delay) +
    Example 2 (with delay) +
    Example 2 (with longer check delay) + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/wait.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/wait.jsp new file mode 100644 index 000000000..7913943e7 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/wait/wait.jsp @@ -0,0 +1,16 @@ +<%@ taglib prefix="s" uri="/struts-tags" %> + + + "/> + + + +

    + We are processing your request. Please wait. +

    + +

    + You can click this link to ">refresh. + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/xslt/environment.xsl b/STRUTS_2_0_X/apps/showcase/src/main/webapp/xslt/environment.xsl new file mode 100644 index 000000000..87ae897e2 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/xslt/environment.xsl @@ -0,0 +1,25 @@ + + + + + + JVM Info + + +

    JVM Info

    + + + + + + + + + +
    System PropertyValue
    + + + + + diff --git a/STRUTS_2_0_X/apps/showcase/src/main/webapp/xslt/index.jsp b/STRUTS_2_0_X/apps/showcase/src/main/webapp/xslt/index.jsp new file mode 100644 index 000000000..619bb6059 --- /dev/null +++ b/STRUTS_2_0_X/apps/showcase/src/main/webapp/xslt/index.jsp @@ -0,0 +1,26 @@ +<%@taglib prefix="s" uri="/struts-tags" %> + + + +Showcase - XSLT + + +

    XSLT Result Showcase

    + +

    + The XSLT result can be used to generate xml from the action. By default, each of the action's + properties will be converted into a DOM and rendered. These results can be transformed via + xslt. Additionally, the result's exposedValue parameter can be used to define an ognl expression + which can be used to manipulate the object which will be converted to xml. + +

      +
    • Render the exposed portion of the action as html
    • +
    • Render the exposed portion of the action as xml
    • +
    • Render the action as xml
    • +
    • Render an ognl property
    • +
    +

    + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/assembly/pom.xml b/STRUTS_2_0_X/assembly/pom.xml new file mode 100644 index 000000000..308142846 --- /dev/null +++ b/STRUTS_2_0_X/assembly/pom.xml @@ -0,0 +1,438 @@ + + 4.0.0 + org.apache.struts + struts2-assembly + pom + Struts 2 Assembly + + Struts 2 Assembly + + + + org.apache.struts + struts2-parent + 2.0.14 + + + + scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/assembly + scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/assembly + http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_0_14/assembly + + + + + + org.codehaus.mojo + dependency-maven-plugin + + + copy-war + package + + copy + + + + + org.apache.struts + struts2-blank + ${version} + war + + + org.apache.struts + struts2-mailreader + ${version} + war + + + org.apache.struts + struts2-portlet + ${version} + war + + + org.apache.struts + struts2-showcase + ${version} + war + + + org.apache.struts + struts2-mailreader + ${version} + war + + + ${project.build.directory}/apps + + + + xwork-javadoc + package + + unpack + + + + + com.opensymphony + xwork + javadoc + 2.0.7 + + + ${project.build.directory}/xwork-apidocs + + + + + + maven-antrun-plugin + + + cwiki-docs + process-resources + + + + + + + + + run + + + + + + maven-assembly-plugin + 2.2-beta-1 + + + make-assembly + package + + attached + + + + + + src/main/assembly/all.xml + src/main/assembly/lib.xml + + src/main/assembly/apps.xml + src/main/assembly/src.xml + src/main/assembly/docs.xml + + struts-${version} + target/assembly/out + target/assembly/work + + + + + + + + + org.apache.struts + struts2-core + ${version} + + + + org.apache.struts + struts2-codebehind-plugin + ${version} + + + + org.apache.struts + struts2-config-browser-plugin + ${version} + + + + org.apache.struts + struts2-jasperreports-plugin + ${version} + + + + org.apache.struts + struts2-jfreechart-plugin + ${version} + + + + org.apache.struts + struts2-jsf-plugin + ${version} + + + + org.apache.struts + struts2-pell-multipart-plugin + ${version} + + + + org.apache.struts + struts2-plexus-plugin + ${version} + + + + org.apache.struts + struts2-spring-plugin + ${version} + + + + org.apache.struts + struts2-sitegraph-plugin + ${version} + + + + org.apache.struts + struts2-sitemesh-plugin + ${version} + + + + org.apache.struts + struts2-struts1-plugin + ${version} + + + + org.apache.struts + struts2-tiles-plugin + ${version} + + + + org.apache.tiles + tiles-jsp + 2.0.4 + runtime + + + + + javax.servlet + jsp-api + 2.0 + provided + + + + commons-lang + commons-lang + 2.0 + provided + + + + + uk.ltd.getahead + dwr + 1.1-beta-3 + provided + + + + + velocity + velocity + 1.4 + provided + + + + velocity-tools + velocity-tools + 1.1 + provided + + + + + commons-fileupload + commons-fileupload + 1.1.1 + provided + + + + + opensymphony + sitemesh + 2.2.1 + provided + + + + + jetty + org.mortbay.jetty + 5.1.4 + provided + + + + eclipse + jdtcore + 3.1.0 + provided + + + + ant + ant + 1.6.5 + provided + + + + tomcat + jasper-compiler + 5.5.12 + provided + + + + tomcat + jasper-runtime + 5.5.12 + provided + + + + tomcat + jasper-compiler-jdt + 5.5.12 + provided + + + + commons-el + commons-el + 1.0 + provided + + + + commons-io + commons-io + 1.0 + provided + + + + commons-lang + commons-lang + 2.1 + provided + + + + + xstream + xstream + 1.1.2 + provided + + + + commons-digester + commons-digester + 1.7 + provided + + + + + portlet-api + portlet-api + 1.0 + provided + + + + org.apache.pluto + pluto + 1.0.1-rc4 + provided + + + + + org.codehaus.plexus + plexus-container-default + 1.0-alpha-10 + provided + + + + + org.springframework + spring-beans + 1.2.8 + provided + + + + org.springframework + spring-core + 1.2.8 + provided + + + + org.springframework + spring-context + 1.2.8 + provided + + + + org.springframework + spring-web + 1.2.8 + provided + + + + org.springframework + spring-mock + 1.2.8 + provided + + + + + myfaces + myfaces-jsf-api + 1.0.9 + provided + + + + + javax.servlet + servlet-api + 2.4 + provided + + + + + \ No newline at end of file diff --git a/STRUTS_2_0_X/assembly/src/main/assembly/all.xml b/STRUTS_2_0_X/assembly/src/main/assembly/all.xml new file mode 100644 index 000000000..b5769baf5 --- /dev/null +++ b/STRUTS_2_0_X/assembly/src/main/assembly/all.xml @@ -0,0 +1,212 @@ + + + + all + + zip + + + + lib + runtime + + net.sf.retrotranslator:retrotranslator-runtime + backport-util-concurrent:backport-util-concurrent + junit:junit + *:jdk14 + + + + + + src/main/resources + + + README* + LICENSE* + NOTICE* + + + + target/apps + apps + + *.war + + + + + + target/xwork-apidocs + docs/xwork-apidocs + + + + + ../target/site + docs + + + + ../core/target/site + docs/struts2-core + + + + + target/cwiki + docs + + + + + + ../plugins/codebehind/target/site + docs/struts2-plugins/struts2-codebehind-plugin + + + ../plugins/config-browser/target/site + docs/struts2-plugins/struts2-config-browser-plugin + + + ../plugins/jasperreports/target/site + docs/struts2-plugins/struts2-jasperreports-plugin + + + ../plugins/jfreechart/target/site + docs/struts2-plugins/struts2-jfreechart-plugin + + + ../plugins/jsf/target/site + docs/struts2-plugins/struts2-jsf-plugin + + + ../plugins/pell-multipart/target/site + docs/struts2-plugins/struts2-pell-multipart-plugin + + + ../plugins/plexus/target/site + docs/struts2-plugins/struts2-plexus-plugin + + + ../plugins/struts1/target/site + docs/struts2-plugins/struts2-struts1-plugin + + + ../plugins/sitegraph/target/site + docs/struts2-plugins/struts2-sitegraph-plugin + + + ../plugins/spring/target/site + docs/struts2-plugins/struts2-spring-plugin + + + ../plugins/sitemesh/target/site + docs/struts2-plugins/struts2-sitemesh-plugin + + + ../plugins/tiles/target/site + docs/struts2-plugins/struts2-tiles-plugin + + + + + ../ + src/ + + pom.xml + src/ + + + + + ../apps + src/apps + + pom.xml + src/ + + + + ../apps/blank + src/apps/blank + + pom.xml + src/ + + + + ../apps/portlet + src/apps/portlet + + pom.xml + src/ + + + + ../apps/showcase + src/apps/showcase + + pom.xml + src/ + + + + ../assembly + src/assembly + + pom.xml + src/ + + + + ../core + src/core + + pom.xml + src/ + + + + ../plugins + src/plugins + + */target/** + target/** + + + + diff --git a/STRUTS_2_0_X/assembly/src/main/assembly/apps.xml b/STRUTS_2_0_X/assembly/src/main/assembly/apps.xml new file mode 100644 index 000000000..28d77c100 --- /dev/null +++ b/STRUTS_2_0_X/assembly/src/main/assembly/apps.xml @@ -0,0 +1,43 @@ + + + apps + + zip + + + + src/main/resources + + + README* + LICENSE* + NOTICE* + + + + target/apps + apps + + *.war + + + + diff --git a/STRUTS_2_0_X/assembly/src/main/assembly/docs.xml b/STRUTS_2_0_X/assembly/src/main/assembly/docs.xml new file mode 100644 index 000000000..acf2a635d --- /dev/null +++ b/STRUTS_2_0_X/assembly/src/main/assembly/docs.xml @@ -0,0 +1,116 @@ + + + + docs + + zip + + + + + + target/xwork-apidocs + docs/xwork-apidocs + + + + + ../target/site + docs + + + ../api/target/site + docs/struts2-api + + + ../core/target/site + docs/struts2-core + + + + + target/cwiki + docs + + + + + ../plugins/codebehind/target/site + docs/struts2-plugins/struts2-codebehind-plugin + + + ../plugins/config-browser/target/site + docs/struts2-plugins/struts2-config-browser-plugin + + + ../plugins/jasperreports/target/site + docs/struts2-plugins/struts2-jasperreports-plugin + + + ../plugins/jfreechart/target/site + docs/struts2-plugins/struts2-jfreechart-plugin + + + ../plugins/jsf/target/site + docs/struts2-plugins/struts2-jsf-plugin + + + ../plugins/jsf/target/site + docs/struts2-plugins/struts2-junit-plugin + + + ../plugins/pell-multipart/target/site + docs/struts2-plugins/struts2-pell-multipart-plugin + + + ../plugins/plexus/target/site + docs/struts2-plugins/struts2-plexus-plugin + + + ../plugins/sitegraph/target/site + docs/struts2-plugins/struts2-sitegraph-plugin + + + ../plugins/sitemesh/target/site + docs/struts2-plugins/struts2-sitemesh-plugin + + + ../plugins/spring/target/site + docs/struts2-plugins/struts2-spring-plugin + + + ../plugins/struts1/target/site + docs/struts2-plugins/struts2-struts1-plugin + + + ../plugins/tiles/target/site + docs/struts2-plugins/struts2-testng-plugin + + + ../plugins/tiles/target/site + docs/struts2-plugins/struts2-tiles-plugin + + + + diff --git a/STRUTS_2_0_X/assembly/src/main/assembly/lib-jdk14.xml b/STRUTS_2_0_X/assembly/src/main/assembly/lib-jdk14.xml new file mode 100644 index 000000000..5efca3cc2 --- /dev/null +++ b/STRUTS_2_0_X/assembly/src/main/assembly/lib-jdk14.xml @@ -0,0 +1,58 @@ + + + + lib-jdk14 + + zip + + + + jdk14 + ${artifactId}-${version}.${extension} + + net.sf.retrotranslator:retrotranslator-runtime + backport-util-concurrent:backport-util-concurrent + + + + true + jdk14 + ${artifactId}-${version}-jdk14.${extension} + + org.apache.struts:*:jar:jdk14 + com.opensymphony:xwork:jar:jdk14 + + + + + + src/main/resources/backport + + + *LICENSE* + NOTICE* + + + + diff --git a/STRUTS_2_0_X/assembly/src/main/assembly/lib.xml b/STRUTS_2_0_X/assembly/src/main/assembly/lib.xml new file mode 100644 index 000000000..2f0f94bbe --- /dev/null +++ b/STRUTS_2_0_X/assembly/src/main/assembly/lib.xml @@ -0,0 +1,49 @@ + + + + lib + + zip + + + + lib + runtime + + net.sf.retrotranslator:retrotranslator-runtime + backport-util-concurrent:backport-util-concurrent + junit:junit + *:jdk14 + + + + + + src/main/resources + + + README* + LICENSE* + NOTICE* + + + + diff --git a/STRUTS_2_0_X/assembly/src/main/assembly/src.xml b/STRUTS_2_0_X/assembly/src/main/assembly/src.xml new file mode 100644 index 000000000..fc32152cb --- /dev/null +++ b/STRUTS_2_0_X/assembly/src/main/assembly/src.xml @@ -0,0 +1,120 @@ + + + + src + + zip + + true + + + lib + optional + + + lib + compile + + + lib + provided + + + + + + src/main/resources + + + README* + LICENSE* + NOTICE* + + + + + + ../ + src/ + + pom.xml + src/ + + + + + ../apps + src/apps + + pom.xml + src/ + + + + ../apps/blank + src/apps/blank + + pom.xml + src/ + + + + ../apps/portlet + src/apps/portlet + + pom.xml + src/ + + + + ../apps/showcase + src/apps/showcase + + pom.xml + src/ + + + + ../assembly + src/assembly + + pom.xml + src/ + + + + ../core + src/core + + pom.xml + src/ + + + + + diff --git a/STRUTS_2_0_X/assembly/src/main/resources/LICENSE.txt b/STRUTS_2_0_X/assembly/src/main/resources/LICENSE.txt new file mode 100644 index 000000000..dd5b3a58a --- /dev/null +++ b/STRUTS_2_0_X/assembly/src/main/resources/LICENSE.txt @@ -0,0 +1,174 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/STRUTS_2_0_X/assembly/src/main/resources/NOTICE.txt b/STRUTS_2_0_X/assembly/src/main/resources/NOTICE.txt new file mode 100644 index 000000000..439eb83b2 --- /dev/null +++ b/STRUTS_2_0_X/assembly/src/main/resources/NOTICE.txt @@ -0,0 +1,3 @@ +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + diff --git a/STRUTS_2_0_X/assembly/src/main/resources/backport/NOTICE.txt b/STRUTS_2_0_X/assembly/src/main/resources/backport/NOTICE.txt new file mode 100644 index 000000000..f7abb2147 --- /dev/null +++ b/STRUTS_2_0_X/assembly/src/main/resources/backport/NOTICE.txt @@ -0,0 +1,7 @@ +Apache Struts +Copyright 2000-2007 The Apache Software Foundation + +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). +Retrotranslator (http://retrotranslator.sourceforge.net/). + diff --git a/STRUTS_2_0_X/assembly/src/main/resources/backport/RETROTRANSLATOR-LICENSE.txt b/STRUTS_2_0_X/assembly/src/main/resources/backport/RETROTRANSLATOR-LICENSE.txt new file mode 100644 index 000000000..c2a85598d --- /dev/null +++ b/STRUTS_2_0_X/assembly/src/main/resources/backport/RETROTRANSLATOR-LICENSE.txt @@ -0,0 +1,29 @@ + Retrotranslator: a Java bytecode transformer that translates Java classes + compiled with JDK 5.0 into classes that can be run on JVM 1.4. + + Copyright (c) 2005, 2006 Taras Puchko + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. diff --git a/STRUTS_2_0_X/assembly/src/main/resources/build.xml b/STRUTS_2_0_X/assembly/src/main/resources/build.xml new file mode 100644 index 000000000..d93200b75 --- /dev/null +++ b/STRUTS_2_0_X/assembly/src/main/resources/build.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/STRUTS_2_0_X/backport/ASM-LICENSE.txt b/STRUTS_2_0_X/backport/ASM-LICENSE.txt new file mode 100755 index 000000000..9496b1785 --- /dev/null +++ b/STRUTS_2_0_X/backport/ASM-LICENSE.txt @@ -0,0 +1,28 @@ + + ASM: a very small and fast Java bytecode manipulation framework + Copyright (c) 2000-2005 INRIA, France Telecom + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. diff --git a/STRUTS_2_0_X/backport/LICENSE.txt b/STRUTS_2_0_X/backport/LICENSE.txt new file mode 100644 index 000000000..2f07ce8fc --- /dev/null +++ b/STRUTS_2_0_X/backport/LICENSE.txt @@ -0,0 +1,29 @@ + Retrotranslator: a Java bytecode transformer that translates Java classes + compiled with JDK 5.0 into classes that can be run on JVM 1.4. + + Copyright (c) 2005 - 2007 Taras Puchko + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. diff --git a/STRUTS_2_0_X/backport/RETROTRANSLATOR-LICENSE.txt b/STRUTS_2_0_X/backport/RETROTRANSLATOR-LICENSE.txt new file mode 100755 index 000000000..28c9615e4 --- /dev/null +++ b/STRUTS_2_0_X/backport/RETROTRANSLATOR-LICENSE.txt @@ -0,0 +1,29 @@ + Retrotranslator: a Java bytecode transformer that translates Java classes + compiled with JDK 5.0 into classes that can be run on JVM 1.4. + + Copyright (c) 2005, 2006 Taras Puchko + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + THE POSSIBILITY OF SUCH DAMAGE. diff --git a/STRUTS_2_0_X/backport/S2-FOR-J4-README.txt b/STRUTS_2_0_X/backport/S2-FOR-J4-README.txt new file mode 100755 index 000000000..7d845dc11 --- /dev/null +++ b/STRUTS_2_0_X/backport/S2-FOR-J4-README.txt @@ -0,0 +1,22 @@ +STRUTS 2 FOR JAVA 4 + +Struts 2 is targeted for Java 5, but a "backported" version to Java 4 is being made available, +using the RetroTranslator tool. + +To use Struts 2 with Java 4 (preferably Java 1.4.2), place the enclosed Struts, XWork, +RetroTranslator, and backport-util-concurrent JARs on your classpath. For complete details on +using RetroTranslator JARs, see the RetroTranslator site. + +* http://retrotranslator.sourceforge.net/ + +NOTE: The Struts 2 and XWork 2 JARs are complete replacements for the corresponding standard +Java 5 JARs. Do not use both sets of JARs in the same environment! + +If you discover any issues using the Struts 2 for Java 4 JAR, please report them to the Struts +Dev list or JIRA ticket ww-1391. + +* http://struts.apache.org/mail.html + +* https://issues.apache.org/struts/browse/WW-1391 + +Cheers! diff --git a/STRUTS_2_0_X/backport/STRUTS-LICENSE.txt b/STRUTS_2_0_X/backport/STRUTS-LICENSE.txt new file mode 100755 index 000000000..c6055ec8f --- /dev/null +++ b/STRUTS_2_0_X/backport/STRUTS-LICENSE.txt @@ -0,0 +1,174 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. diff --git a/STRUTS_2_0_X/backport/XWORK-LICENSE.txt b/STRUTS_2_0_X/backport/XWORK-LICENSE.txt new file mode 100755 index 000000000..ccae16959 --- /dev/null +++ b/STRUTS_2_0_X/backport/XWORK-LICENSE.txt @@ -0,0 +1,50 @@ +/* ==================================================================== + * The OpenSymphony Software License, Version 1.1 + * + * (this license is derived and fully compatible with the Apache Software + * License - see http://www.apache.org/LICENSE.txt) + * + * Copyright (c) 2001-2004 The OpenSymphony Group. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * OpenSymphony Group (http://www.opensymphony.com/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "OpenSymphony" and "The OpenSymphony Group" + * must not be used to endorse or promote products derived from this + * software without prior written permission. For written + * permission, please contact license@opensymphony.com . + * + * 5. Products derived from this software may not be called "OpenSymphony" + * or "XWork", nor may "OpenSymphony" or "XWork" appear in their + * name, without prior written permission of the OpenSymphony Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + */ \ No newline at end of file diff --git a/STRUTS_2_0_X/backport/backport-util-concurrent-3.0.jar b/STRUTS_2_0_X/backport/backport-util-concurrent-3.0.jar new file mode 100755 index 0000000000000000000000000000000000000000..99f9b9c6a3e655702a827bea183e327589ba0912 GIT binary patch literal 327810 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

    oj}8*<66_PVBdL7 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 + + + Retrotranslator + + + + + + + + +

    Retrotranslator

    SourceForge.net Logo +
    + +

    Contents

    +
      +
    1. What is Retrotranslator?
    2. +
    3. What Java 5 features are supported?
    4. +
    5. How to use Retrotranslator from a command line?
    6. +
    7. How to use Retrotranslator from Apache Ant or Maven?
    8. +
    9. How to use Retrotranslator from IntelliJ IDEA?
    10. +
    11. How to use Just-in-Time Retrotranslator?
    12. +
    13. What Java 5 classes and methods are supported?
    14. +
    15. How to write an extension for Retrotranslator?
    16. +
    17. What are the limitations?
    18. +
    19. Alternative tools
    20. +
    21. Contact
    22. +
    23. License
    24. +
    + +

    What is Retrotranslator?

    +Retrotranslator is a Java bytecode transformer +that translates Java classes compiled with JDK 5.0 into classes that can be run on JVM 1.4. +It is a free, open-source tool based on the ASM bytecode manipulation framework +and concurrency utilities +backported to Java 1.4. + +

    What Java 5 features are supported?

    +
      +
    • Generics (generic types)
    • +
    • Annotations (metadata)
    • +
    • Reflection on generics and annotations
    • +
    • Typesafe enums (enumerated types)
    • +
    • Autoboxing/unboxing
    • +
    • Enhanced for loop (for-each loop)
    • +
    • Varargs (variable arguments)
    • +
    • Covariant return types
    • +
    • Formatted output
    • +
    • Static import
    • +
    • Concurrency utilities
    • +
    • Collections framework enhancements
    • +
    + +

    How to use Retrotranslator from a command line?

    +
      +
    1. Download + and unzip the binary distribution file Retrotranslator-n.n.n-bin.zip, + where n.n.n is the latest Retrotranslator release number. +
    2. +
    3. + Compile your classes with JDK 5.0 and put them into some directory, e.g. myclasses. +
    4. +
    5. + Go to the unzipped directory and execute:
      + java -jar retrotranslator-transformer-n.n.n.jar -srcdir myclasses +
    6. +
    7. + If you use Java 5 API put retrotranslator-runtime-n.n.n.jar and + backport-util-concurrent-n.n.jar into the classpath of your application. +
    8. +
    9. + Run or debug the application as usual on J2SE 1.4.x, preferably 1.4.2. +
    10. +
    + +

    The full command line syntax:
    + java -jar retrotranslator-transformer-n.n.n.jar <options> +
    or
    + java -cp retrotranslator-transformer-n.n.n.jar net.sf.retrotranslator.transformer.Retrotranslator <options>

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    OptionDescriptionDefault
    -srcdirThe directory with classes that should be translated (may be specified several times).-
    -srcjarThe directory with classes that should be translated (may be specified several times).-
    -destdirThe directory to place translated classes.Location of sources
    -destjarThe JAR file to place translated classes.Location of sources
    -advancedWhether to use alternative implementations of Java 1.4 classes and methods for better Java 5 compatibility.Off
    -verifyAsks the translator to examine translated bytecode for references to classes, methods, or fields + that cannot be found in the provided classpath.Off
    -classpathThe classpath for verification including rt.jar, jce.jar, + jsse.jar (from JRE 1.4), retrotranslator-runtime-n.n.n.jar, + and backport-util-concurrent-n.n.jar.Current classpath
    -srcmaskThe wildcard pattern specifying files that should be translated (either bytecode or UTF-8 text), + e.g. "*.class;*.tld". There are three special characters: "*?;". + *.class
    -embedPackage name for a private copy of retrotranslator-runtime-n.n.n.jar and + backport-util-concurrent-n.n.jar to be put into -destdir or -destjar. + This makes your application independent of other versions of Retrotranslator present in the classpath. + -
    -backportInforms the translator about user-defined backport packages. + Package names should be separated by semicolons.-
    -targetTo make Java 6 classes compatible with Java 5 set this option to 1.5 and supply + user-defined backport packages via the backport option.1.4
    -lazyAsks the translator to only transform classes compiled with a target greater than the current one.Off
    -stripsignAsks the translator to strip signature (generics) information.Off
    -verboseAsks the translator for verbose output.Off
    -retainapiAsks the translator to modify classes for JVM 1.4 compatibility but keep use of Java 5 API. + References introduced by a compiler will also remain unchanged, + like the use of java.lang.StringBuilder for string concatenation + or the implicit valueOf method call for autoboxing.Off
    -retainflagsAsks the translator to keep Java 5 specific access modifiers.Off
    +

    + For example, if you have a Java 5 application myapplication5.jar you can use the following command + to produce myapplication4.jar that will run on J2SE 1.4 and is independent of Retrotranslator, + since required classes are added to the translated application with a different package name: +

    +

    + java -jar retrotranslator-transformer-n.n.n.jar + -srcjar myapplication5.jar -destjar myapplication4.jar -embed com.mycompany.internal
    +

    + +

    How to use Retrotranslator from Apache Ant or Maven?

    + +

    The distribution contains an integrated Apache Ant task + net.sf.retrotranslator.transformer.RetrotranslatorTask. It has the following syntax:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    AttributeDescriptionDefault
    srcdirThe directory with classes that should be translated.-
    srcjarThe directory with classes that should be translated.-
    destdirThe directory to place translated classes.Location of sources
    destjarThe JAR file to place translated classes.Location of sources
    advancedWhether to use alternative implementations of Java 1.4 classes and methods for better Java 5 compatibility.Off
    verifyAsks the translator to examine translated bytecode for references to classes, methods, or fields + that cannot be found in the provided classpath.Off
    classpathThe classpath for the verification, including rt.jar, jce.jar, + jsse.jar (from JRE 1.4), retrotranslator-runtime-n.n.n.jar, + and backport-util-concurrent-n.n.jar. + Current classpath
    classpathrefThe classpath for the verification, given as a reference to a path defined elsewhere. + Current classpath
    srcmaskThe wildcard pattern specifying files that should be translated (either bytecode or UTF-8 text), + e.g. "*.class;*.tld". There are three special characters: "*?;". + *.class
    embedPackage name for a private copy of retrotranslator-runtime-n.n.n.jar and + backport-util-concurrent-n.n.jar to be put into -destdir or -destjar. + This makes your application independent of other versions of Retrotranslator present in the classpath. + -
    backportInforms the translator about user-defined backport packages. + Package names should be separated by semicolons.-
    targetSet this option to 1.5 and supply user-defined backport packages via + the backport option to make Java 6 classes compatible with Java 5.1.4
    lazyAsks the translator to only transform classes compiled with a target greater than the current one.Off
    stripsignAsks the translator to strip signature (generics) information.Off
    verboseAsks the translator for verbose output.Off
    retainapiAsks the translator to modify classes for JVM 1.4 compatibility but keep use of Java 5 API. + References introduced by a compiler will also remain unchanged, + like the use of java.lang.StringBuilder for string concatenation + or the implicit valueOf method call for autoboxing.Off
    retainflagsAsks the translator to keep Java 5 specific access modifiers.Off
    failonwarningIndicates whether the build will fail when there are verification warnings.On
    +

    + You may use nested fileset, jarfileset, and dirset elements to specify + source files and classpath elements to specify classpath. For example: +

    +
    +    <path id="classpath">
    +        <fileset dir="lib" includes="**/*.jar"/>
    +    </path>
    +    <taskdef name="retrotranslator" classpathref="classpath"
    +             classname="net.sf.retrotranslator.transformer.RetrotranslatorTask" />
    +    <retrotranslator destdir="build/classes14" verify="true">
    +        <fileset dir="build/classes15" includes="**/*.class">
    +        <jarfileset dir="build/lib15" includes="**/*.jar">
    +        <classpath location="${java14_home}/jre/lib/rt.jar"/>
    +        <classpath refid="classpath"/>
    +    </retrotranslator>
    +
    +

    + For Maven there is a + Retrotranslator plugin + from the Mojo Project. +

    +

    How to use Retrotranslator from IntelliJ IDEA?

    +

    + There is a plugin to automatically translate and verify + classes compiled by IntelliJ IDEA, so you can develop in Java 5 but + run and debug on JRE 1.4. +

    + +

    How to use Just-in-Time Retrotranslator?

    + +

    + JIT Retrotranslator is able to translate at runtime Java classes loaded with any classloader. + It works on J2SE 1.4 from most JVM vendors like Sun, IBM, BEA, and Apple, but does nothing on J2SE 5.0. + However translation at runtime consumes additional memory and processing resources and it will not + work if your classes make use of Java 5 API but were compiled with "-target 1.4". +

    +
      +
    • + If you want to run a JAR file with the JIT, execute:
      + java -cp retrotranslator-transformer-n.n.n.jar + net.sf.retrotranslator.transformer.JITRetrotranslator <options> -jar <jarfile> [<args...>] +
    • +
    • + When the first option does not work or if you just want to run a class from your classpath, execute:
      + java -cp retrotranslator-transformer-n.n.n.jar:<classpath> + net.sf.retrotranslator.transformer.JITRetrotranslator <options> <class> [<args...>] +
    • +
    • + Alternatively you may simply call JITRetrotranslator.run() from some JVM 1.4 compatible class + before Java 5 classes are loaded. +
    • +
    +

    + JIT Retrotranslator can accept the advanced + and backport options. +

    + +

    What Java 5 classes and methods are supported?

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    PackageClassMethods and fieldsCompatibility notes
    java.lang.annotation* (all classes)* (all methods) 
    java.lang.instrument* (all classes)* (all methods) + Bytecode instrumentation is not implemented.
    java.util.concurrent,
    java.util.concurrent.atomic,
    java.util.concurrent.locks
    almost all classes1almost all methodsThe LockSupport class may be unusable due to poor efficiency. + The Condition.awaitNanos(long) method has + + little accuracy guarantees.
    java.ioCloseable2 + * 
    Flushable2* 
    PrintStream + * (11 new methods and constructors) +  
    PrintWriter + * (11 new methods and constructors) + + The PrintWriter.format and PrintWriter.printf methods always flush the output buffer. +
    Readerread(CharBuffer) 
    Writer + append(CharSequence),
    + append(CharSequence, int, int),
    + append(char)
    +
     
    java.langAppendable2* +  
    BooleanparseBoolean(String),
    + compareTo(Boolean)
     
    BytevalueOf(byte) 
    CharactervalueOf(char) 
    Class* (21 new methods) + Class.getMethod(String, Class...) and Class.getDeclaredMethod(String, Class...) + are intercepted to better support generics and covariant return types + on several platforms3. +
    Deprecated* 
    DoublevalueOf(double) 
    Enum* 
    FloatvalueOf(float) 
    IllegalArgumentExceptionIllegalArgumentException(String, Throwable),
    + IllegalArgumentException(Throwable)
     
    IllegalStateExceptionIllegalStateException(String, Throwable),
    + IllegalStateException(Throwable)
     
    IntegervalueOf(int), signum(int) 
    Iterable2* 
    LongvalueOf(long), signum(long) 
    Package* (4 new methods) 
    Readable2* 
    ShortvalueOf(short) 
    Stringcontains(CharSequence),
    + contentEquals(CharSequence),
    + format(Locale, String, Object...),
    + format(String, Object...),
    + replace(CharSequence, CharSequence),
    + isEmpty()4 +
     
    StringBuffer + StringBuffer(CharSequence),
    + append(CharSequence),
    + append(CharSequence, int, int),
    + insert(int, CharSequence),
    + insert(int, CharSequence, int, int) +
     
    StringBuilder + All methods supported in StringBuffer + StringBuilder is replaced with StringBuffer.
    SuppressWarnings* 
    SystemnanoTime()1,
    clearProperty(String)
    + The System.nanoTime() method precision + + may vary on different platforms. +
    ThreadgetStackTrace(),
    getId() +
    The Thread.getStackTrace() + method returns non-empty stack trace only for the current thread.
    + The Thread.getId() method does not reflect the order in which threads are created.
    Thread.State* 
    ThreadLocalremove()3ThreadLocal and InheritableThreadLocal + are replaced by corresponding classes from the runtime library.3.
    TypeNotPresentException* 
    java.lang.refSoftReference* + SoftReference(Object,ReferenceQueue) + supports null for the second parameter + on all platforms3. +
    WeakReference* + WeakReference(Object,ReferenceQueue) + supports null for the second parameter + on all platforms3. +
    java.lang.reflectAccessibleObject* 
    AnnotatedElement2* 
    Constructor* (11 new methods) 
    Field* (8 new methods) 
    GenericArrayType* 
    GenericDeclaration2* 
    GenericSignatureFormatError* 
    MalformedParameterizedTypeException* 
    Method* (14 new methods) 
    ParameterizedType* 
    Type2* 
    TypeVariable* 
    WildcardType* 
    java.mathBigDecimal + BigDecimal(int),
    BigDecimal(long),
    ZERO, ONE, TEN,
    divideAndRemainder(BigDecimal),
    + divideToIntegralValue(BigDecimal),
    pow(int),
    remainder(BigDecimal),
    + toPlainString(),
    valueOf(double),
    + valueOf(long)
    The BigDecimal.setScale(int, int) + method supports negative scales3.
    java.netURLopenConnection(Proxy),
    + toURI() +
    The Proxy is ignored by the openConnection(Proxy) method.
    Proxy* 
    ProxySelector* 
    java.rmi.serverRemoteObjectInvocationHandler* 
    java.textDecimalFormatisParseBigDecimal()3,
    + setParseBigDecimal(boolean)3
    + BigDecimal parsing and formatting precision is limited by + java.lang.Double or java.lang.Long precision. +
    java.util.nioCharBuffer + append(CharSequence),
    append(CharSequence, int, int),
    append(char),
    read(CharBuffer)
    +
     
    java.utilAbstractQueue1* 
    Arrays* (21 new methods) 
    Collections1* (13 new methods)
    + newSetFromMap(Map)4 + +
     
    EnumMap* 
    EnumSet* 
    Formatter* 
    LinkedList* (5 new methods) 
    PriorityQueue1* 
    Queue1,2* 
    UUID* 
    java.util.regexMatcher + quoteReplacement(String),
    toMatchResult()
     
    MatchResult2* 
    Patternquote(String) 
    +

    + 1 Supported via the + Backport of JSR 166.
    + 2 In most cases this type is being replaced with it's base type.
    + 3 Supported only in advanced mode, i.e. when + the advanced option is specified.
    + 4 Introduced in Java 6, but available only for 1.4 target.
    +

    + +

    How to write an extension for Retrotranslator?

    + +

    + Since most backported classes are discovered by Retrotranslator at translation time, + you may write an extension and simply put it into the Retrotranslator classpath to make it work. + For example, all references to + java.util.EnumSet + are replaced with references to + + net.sf.retrotranslator.runtime.java.util.EnumSet_ (optional trailing underscore) if the latter can be found. + But if you replace a whole class that exists in J2SE 1.4 you may encounter interoperability issues with other libraries. + So, for example, support for Java 5 fields, methods, and constructors of + java.math.BigDecimal is placed into + + + net.sf.retrotranslator.runtime.java.math._BigDecimal (leading underscore): +

    +
      +
    • For a static field there is a public static field with the same name and type.
    • +
    • For a static method there is a public static method with the same signature.
    • +
    • For an instance method there is a public static method with the same signature + but with an additional first parameter representing the instance.
    • +
    • For a constructor there is a public static convertConstructorArguments method that + accepts constructor's arguments an returns an argument for a Java 1.4 constuctor.
    • +
    +

    + Another approach for constructor backporting is used by + + net.sf.retrotranslator.runtime.java.io._PrintStream. There is a public static + createInstanceBuilder method that accepts constructor's arguments an returns an object with public + argument1...argumentN methods and optional public void initialize method. + All argumentX methods provide arguments for a Java 1.4 constuctor and should not have any parameters. + The initialize method has a single parameter for the created instance and may be used for postprocessing. + +

    +

    + However, if the backported methods require access + to non-public methods or fields of the instance, they cannot be fully handled by Retrotranslator. + While you can use reflection to access any data, translated code generally should not depend on security settings. + For example, it is impossible to write an implementation for methods getSource() + and setSource() of java.beans.PropertyEditorSupport that will work in any environment. + Also this approach cannot be used to replace instance field references. +

    +

    + You can put your extensions into packages other than net.sf.retrotranslator.runtime. + For example, specify the following at the command line to make Retrotranslator use + com.mycompany.internal.java.lang._String and to rewrite all references to + com.sun.org.apache.xerces.internal.* with org.apache.xerces.*:
    + -backport com.mycompany.internal;com.sun.org.apache.xerces.internal:org.apache.xerces +

    +

    + If you have written an extension that does not contain copyrighted code, you may send + a patch + under the Retrotranslator license. +

    + +

    What are the limitations?

    + +

    + Basically, only classes, methods, and fields listed above should work, and other features, + like formatted input, are not supported. Known issues: +

    +
      +
    • Reflection-based tools may be unable to discover additional classes and methods introduced in Java 5 when running on JRE 1.4.
    • +
    • Some applications enable all features only if they detect Java 5, so you may need to override system properties:
      +  java -Djava.version=1.5.0 -Djava.specification.version=1.5 -Djava.class.version=49.0 ...
    • +
    • Translated code running on JRE 5.0 may be incompatible with other Java 5 code when Java 5 API is used.
    • +
    • Reflection on generics and metadata may return incomplete information for dynamically generated classes.
    • +
    • Constants inlined by a compiler and access modifiers are ignored during the verification.
    • +
    • Inherited methods introduced in Java 5 may not work, however upcasting may help in some cases:
      +  ((Writer) new FileWriter("file.tmp")).append("Hello").close();
    • +
    • Serialized objects produced by translated code may be incompatible with JRE 5.0.
    • +
    + +

    Alternative tools

    +
      +
    • Retroweaver + - a Java bytecode weaver that enables you to take advantage + of the new 1.5 language features in your source code, + while still retaining compatibility with 1.4 virtual machines.
    • +
    • Declawer + - a customized Java compiler which reduces 1.5 Generics to equivalent 1.4 syntax.
    • +
    + +

    Contact

    + + +

    License

    +
    +    Retrotranslator: a Java bytecode transformer that translates Java classes
    +    compiled with JDK 5.0 into classes that can be run on JVM 1.4.
    +
    +    Copyright (c) 2005 - 2007 Taras Puchko
    +    All rights reserved.
    +
    +    Redistribution and use in source and binary forms, with or without
    +    modification, are permitted provided that the following conditions
    +    are met:
    +    1. Redistributions of source code must retain the above copyright
    +       notice, this list of conditions and the following disclaimer.
    +    2. Redistributions in binary form must reproduce the above copyright
    +       notice, this list of conditions and the following disclaimer in the
    +       documentation and/or other materials provided with the distribution.
    +    3. Neither the name of the copyright holders nor the names of its
    +       contributors may be used to endorse or promote products derived from
    +       this software without specific prior written permission.
    +
    +    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    +    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    +    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    +    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    +    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    +    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    +    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    +    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    +    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    +    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
    +    THE POSSIBILITY OF SUCH DAMAGE.
    +
    + + diff --git a/STRUTS_2_0_X/backport/retrotranslator-runtime-1.2.2.jar b/STRUTS_2_0_X/backport/retrotranslator-runtime-1.2.2.jar new file mode 100644 index 0000000000000000000000000000000000000000..0dd542f04b3c9d806f06df78bf0d9f23f2ab8439 GIT binary patch literal 260721 zcmb@t1#l!wk}WD`W>$-txy8)P%*-WbmRhV9Gcz+Yvs%ndEoP?QGk zmHZI}rKt%?`6D{<=S2H+{!3I=P)<@zR9S^yR?IY}4km~ZP4r3NlgOBxR0Ni;byW_5 zzS)^h-lrM(j(E)J`l=!;*e=BhaYGxl4H)%|V)y_Aoti~0BHpzyGxsf5YgJ3H`4s~h z%gaZX{mbTj!VE_cF|KvQ)%R>E`<|g}z=vG5gFdv8R4hkDG>c10@x@XkcChy>%9oR% zP5~YOhZishg_mz-W^{Zbzx^>KOCN%!|DTEg0Tur@ox%PnVrS~i@PC$o{0|8yvwsu% zhdut>|JQ-}XY>!4KSBUgXMnvkz|hXg#?aXw@Nbj;`*#!mpCd}gw;<{NjA3c(VDoPZ{a+wh8M+$& z1p>wY%;BF1miB)ELiIO6Yz*zp{{n{fe*@?!kE zT>hXKTNnbI{!4KCzvTq5wfqbFF#JtU|3Gmv1-P32dsO`Il>V;IoK4;TU%1}I+48S~ z%HLh$|AaBNw=;GD0RH-+`TjSJ_1_U~?2WCR{vSBupSS>1b5r+!fkFK(KAa`lZ^X=7{9z{*rrI6k}r$(!Ke>T zNVFPCwhPcX4{|bRtGV0brp}>-`bbR$C?nf_$$zw=at4jAZbx3bBiSn9&1YoB`Cv4v zbt9SeEPPMjc(WQq&ErL|pExS6qj9N`UL083}n|1_e8wX@11`sZ{PM;jvo zIapvcDbnD$NjxJ@0SI(lcpWrw1(8Ugh8;P_Snq+{cb45 zuT(&h*D<|HBXS|}S$V-(QiICS6OzM~Dm=(i_grNbvH11zym?JAsPdX+78{nbBFe7) z!APUqb{CC8OcN(Cx=Y=gF@-X}K_==0*U@CfUY0~+1a? z=CV4JdL_ha>cB;U1Y(RIR`3(op_aRqzp-MsuJKZNp?*Y2H*V$LrbmlP7GbDpI7EBfEc#tBSPM{Qk4ZLwJ=Om{*~BELJFUKPcepnF(CE zL};MR_nApnYRES;nuluYhGaWQ>LWF#q0pJ&L&ilsVIwdLPyvnsmd<=!%$4-xyDm+} zaCTu5KrsilPQbv>HGoNx+~E6Tb#n9r=8aC4*-$+M|G46=Fj5jok|y}Dh=hTZy?%Kc zcXqD0Gzh$@X6RDvkjCErhxTi<^+7yKUFI(F=N?&SRzN6=Ko1h8PJiG1yF#VlVqW{Uj#Ar|{A-3SEg`r(QN@e#pY zaqB!8M+H;H6aXnDW05BBR5orMO=xjsPff~b(L5+gC}(hus_s=2CVz%IR-f<`vS*ONJhzySz2DJuJ5_i z%y!k}*lllR5>+;)|Hz^1#;!2>r3r9eEHO3Xi;HQN!3{DcR?iJHO?z0SL8oZ=C?_fG7%idG zD@ms@eTGQ?8p$vBb~K;j3Avm8B_iGyrDQ_!S^8za%;k`$I?X2V&ZSCV@Khq}NoAfk zj1IUgO?C2nTGZ-FHF1;hh3iT}7Tw95(d;~iA(PXQJG*AT0P}Qeu6ZYK4+H6oG}33x zn|Ltqw8Z`R`W-u*N`JHtQ0?hb5-!l3oI$3OJL{;5<7C2`j_PhA>C{8c%6C=s;V^`d zef(3qK@v5agrpx@lN7jgNh-JL`7vF2H6@#J?l}5RoeaozX9Y|dXVy0At-$B%FeWqo zX6gy>;3FWbZKXebB604z9NRq^imj435=$NJV2k9!Zc zFBYzLHn6I^ejMdOIZlc)%yvh@>V$I9WhQ|BuIif#g2Gx4MS?=eFC=8)oIEsl^}vCh z*I3fJVK09@0a|>Ke97OVQz>(!(Sp1u?$%qB_d7V#x_T&QT`E-M_yJ*B=p$I*@m(VSxXOPo77*IiIm{CDvP~d&82No$&R;wpf31T%JXnwaYYRqU6h9Yh;6iU77N*k zEmHS3D}k0VbD}uTd?}TDHFn{wy#-#wIZy^ zPHXVql(U0cn{R3hIG`%aZ~j)ON;zKp6_>gKR;$$9KzG< z>!89WMw}?ME~y4h%B~LCeDHNvc)I`VfqFp|=d z%IL-debL9G6A9#_8+5i>v<-yo)%F;@urbKRvCnANC;2FEzpLgQwSLX9Avek$JeEv_ z=oY@Z!Z0eK;sm!(P)G2@O#B253pt3e!SLwB;}1Dx$TL{VLo2tF%NZ`bCmhpb-f#_# zz``6G!ElrMj3eIYbe*aeIMM{}9ysfvq#bU&M&>THKF$Z8i$aQ=+~u+}C9MEW1>5gIB3gsDlP-~RWp; zr)K^}KB^8rLtd1by1U=oY|%pqYY3lT2^(T#SL2NA;o*B$b`Qb9(litKWR=OucJDeQ-@pXpMK9)I9UbKz||3#jJhKpzOgDQnYgoBMMSY? z(=bP@yx=h~7eaefF>2h6YktW$CSy+6(u`{wj*i_;bfwAv9ze3}oTEP62h5EaXOv|B z^f~MMHZW+H75xioGd>`k8q#I%Tm=E=oj@=>ew~MHjtL4soiWwW$sj`KIW^-JEJK(H zovc6XZcvjF)mLS17dEY-T$Hch=sUeBy$uS>bEG%9pY4oMD#Ud;X8I4z^a3%tYn7*F ztFB_wQ4nPvJX+0LJ{cb%WvU`afc67lR@0#}b_l9qash`n@46gLY3iwJ8#8m!8(^qq z_%`9Tf1|R$RLzGJb&^Kqm`gngB5Ukjib2OvPnARGq4B5T)DR$av8f>FnM$tgn((3D zelHHD-79&`J%Z?nxwZ)Iln0^#4VZ~gdgw)CY_La6r`Ld9pbN?%i*f)0S)_qdJfpOC zF&|}KBO&QV0gu_}k=^XTi}+H?QtEN%3RS-^q=0Y$+A0Wts0 z!qeFqU}@yyZ2BK%yPCF>vMSoAYkYRXu&_N2s{pP@qopTwpg{sgoEQxxtSCs8f{NVS zJbN7Z!3<|0gH|VrOptJcc-)nfGoV1v)u99Xd_BAxW;LdTpIXWi=NjmtL1Fqwb@% z@4*5inrDGY)S8Dc3nrhHx(+U2;A=buL>}}=fRvea5M5N+J3PAaI}#8&%u1!`uz)ls zoaBqh>fT?$grso!(HIk=ZaD(1j^;7lQ~?J0_T&Bm%}_!X9Jzw_qCiq2$ZzqBf| zDRXGllgG!O69v5L(yJ!d^l;WD*Dr&UTBI8ZW$vdcA&crM`s0kX8$j&Imi80rG#5{q zzOPLGu$(rLB`kY=cchS9MIu7afDfLfmOL>7eGgbb#zgV}MVx@ruDc*i_^Dmp{+J(g zVe$)rXWgd2)k7QC*`@k$g3a_LY&t&88@dHWAR6eTP_oQqg8bOp z32<5u;u+wRoj9UZHoN8PH`O#sA?`6oHO`f$?Uzte6vo2LVpc!>;2ura@rdS8HkuCM z!}Z&pInb~X^{Vnv3xc^`dm!#9EOD{}7UI!Jq5M%YJLUa)gEF{|EDdB=^vr0w3Fdgk zIRZ5)kjw)e6HKZ54DN2vl!iyuZJrgW&j+BiI+-k_TQg6p?j4dAcJ)qtCJVZ3vEW6G29r!)i}1(YGh1F)et_r2Knv1i|A3Zz#C#L9| z*J}qZbC8Nlh$RzCjCrCu0Q0Oo1q`md@B!Fk1l*N^RO*Xsx;Gy9?si z*ET=Y$~#Vpk3u$CO+LwLPegU>3wkf!a`Z;g^2fNm6f?1xc$=(8H1m?4*oOE8=nr-y z1c#LDfM2Ez$%0vlXLTlEvX_hp*j82Yb=Oam9RRi_gA?yLUFf9N!gax#0t~VZ&~yXNmDFmK-f+S_@Yio3*gD1Gd+k~3C-Hhh zcN5fqPFpZVw|c2DX<=5^82QOqgYcFfeY*sX-lxJ-5ZK2Ot^mP#@*nQ6yfe;MoU8nTqbcmjsN5%1fFLPl|7A_jXoYrF;z z_b|fh>IC0*LW%wXx;d-RXbMlER@)=Y?Ifm!tR~jsd}gL%4^q*>c2Sq~xFY3cQ^eam zN1%NIp)JTRg^_#Xhgn=&(b6RDvP+ZgHz==jGde!dXNh zd{FWNr$lC~aT8oz5L{4ni175^?T*dp?HC<$c*ut%ok8t`gW8=A;UCBN3L^ass7$AX z=xq5GQBOPY1>w-o-rHQfG){w)1wyy^^z%Y zQnTs9Kv`rISo+@D*A?B5&42W7NEaqVmZ^lPzkpi)Xao{?dPq^&1 zu<}@oP>xLD!urX5uV{lz`8$8;(Wcn>&JvmOljFOT6t|`%W`cCDHKd0JH99_uhK`Hz z-50c2HK8!5Wy5wabHICP<672+*hHRAcO^`zJ-&IFD!Cg;I?ONsLy@%ele}$EH8HIR zBu6omUWwFo_0srRt@sSt6OVdsoNYAOp?qD(2H|cE^NYIRHoMxM37J(IaNPKyGCLcZ;FH>r4<$74TZ^Wt3qybZW;^Ao!DrI2VOD1owZ}1B%QI!TdW?(z$?;?x zLt!goClN<{atPQ~mBp-n|h{Va`0K`01B8jClG(cnB)8O-iwD z9l;dIk~`7qSIv((bgHQZ;Oygb@YC)eO2s-zH41yGA`WrDyuoaoQPJ-3%lj@Ev&h94 zxGNzAa32}&P$TZsJnKjI`VK&RqtGhZ{x$^DzWtka{zvDakJZ{wxab|IxTUgC?jIL%&WNoDNC4TpCowXHFQ2F_qqja^m4%eY7k1)T> zPcAoSoBaD)i1^NA3?>Nz?;!DuS+(5}qZqhK^rp`4WJXP#A!=?#tZ5r7N0q#4HrP*-@;VAF)LYy=>*I^p5{NWc2b@=9ka_@AmyM?W|$Ah4p^7^OYL#OIqKh#{4 ze!%%TG-`umKb*EGsNly*Tivm-hE=O8?Kc(uP>w`qmlS4Ofm)aDZa*YpH=G8S?oALS zDrQV9%EwAFqV9*2%zpo}5l)DfR`aN;R(L4eOP^guf+Fxo9uO*HfqPa*`3{;h4rAs}${*gwBh7J{>*{U;nq(8^C zpkE;O>kIh5ra7If_xdwXARy{L?Q6Ebm*#~3(e4*CF?9G>+qz2C)(J-yix(5a!T>sN z#mc6!sw%m2ZcSyqxH#I<*pkw*GRXKN7j~m~Jz#V4GX62>HN#nKqz~~E$S-lfEd}G0Yliojhv8}W%J1_Xw%5g*O5w&t1zKMP1RLBJjZ<&Mk(j>}jF$n>QNI_w zIqo_FJy6x`gf#XIl!)yoh)sQMP4Bf0&WXqwq1@ zo;6EN=wXYix-z~Gy>7H_e^&dRJa5Sva8?W4<9G3kq)aX4v-f=N_A2!)sRzY<{Me&A$q(5a*p>;F1opXoc%}0J^aEzs^ zq;3HwMNFPY|HlDka0nl@KD=ql&oXxEQ#tL~tfdjP@5#Bc?Y|5~v=(ZGv{yM@oC1{YnWN>h>3iaxx)9U)i@`&8ScLTt#U|njZZ^9wLKOV{quK03p z&%2(gulZS?F6~hESf0P$Z(q(YC)3iLrZZo%SPZ z?IY=UvNI<0Vy7Ry4gl6$-5P=9lZY?!<-1-l0w(S3_GV(Ls`ySN)KE<s$DZrqT8D`R%)*rA8rHu@x|2FEl10$3PI#JR}BbBM;o=MCyZ|dtyO%DxOM8=#X zw_<~D8Cp~EA}!;_Ji=y#Jd*Cm%2>RKUxc1MAN7Uet(W>5-8igOC|44+qNl3SR#H;N zz7Z4=vVlTM7GbSVCr{hNZX8Xbh>^~fLeTSsn(Yrwg@sBr3h6f&GzW{(QzlFk1uiO1 z9u&(P2Awbj@9!1HIR%M8=|+cth-WQtZuW-nSKt=It4DbFWgviGDKeVo28H1?U{&^t z^D!DL@bR-|fuSsVfv&8q`o3@b(26!p*;~OPMUKRtf)K_94Iv~dt1)%<_V6dRwHlIw z^Wldm)K)}r6(ZRR7qGv#z2N{cc9JxyGIo9>X`>BYxfP65fr+RRsZzI&Xe9kjD3!6g zx`^6>`l5)g15w}ur14R7@}=L;!Tlj-2QZTprFhDqhSgoHd~=tBL#WL)WpNH#EmA?( zB4FIy4nQpW;vu?8o}DHcKKBTD>$ty6Yxkg0c$B(yAX( z^%Z&?+7Q)VBaDFq|7`Ui}`#MWrZ8(;N8ac)Uj$2 zF73Jop+o6cB%jGVRbAR5R2s$SikIO!;4A_$jOg~2yh)0SHyvth+G{T8OUaJ{AxT+I zk^y(bBUZc&+&NfkYrv8hyoh~0aPCM1d?!v|!L89&Z4 z$^q@wbc>I82_MxE+(*S6MMWWvHaH|Z_beo4_O;p#c>6gWse)OFsyTY0?z?6@DQr~_ zA7MJnTl$ySs&1R zCZULV9UR?N!7zE`cv9E>Wbsz|GoTtTPmVokU0aGDA@XQ zq28s!DZR@C?jYTH@GnS$2Z2|VH;HPb<{2_CBl;7|-z8qiR{Z=4yRLcPMKaP+41@ep z77+6FM(}(C^vS}up(r8-(9#{M5;6&9sp#?VHW49zFnB}{Z~%V`HvYcD-QqNXeT;Ia zNXUGk6#tD-Ay>wks>bfeFV@frytf+1lG3Q}?NIE$i!+zAB|#p7zN62f2oMkC2I!Sl zGnl0Y8&5cY)?n*Ec-$M;o8WyrrX}L2Vu)R$fo)|%<93n&K$;^^=)Kg^qyx$~DN(34 zhgC((EyKRQ)MPV%{}Gk6 zYNimCRMw6A_A7ILRWl3sZFZQaqO-Zvl}Yt?R9S3wRk@A~e#41G2GDrwX#Q>JsVBz~ zu}O1unX={mEtH4y*-AJl@@q34lUeEqKG@NX+uTgt}P6KAA9d;kEiUwn=0gewE(Ur=F~mV`L|>%5K%<~cCfTw zV>q@`am<5ZQD==-3^IjMb9)K(-L8=i@sJv}1`(nR5t*ylMSA@0YXn(Ag*A0DQRUTw znt?g}7X>f(T1XvEigbm@AyHd#erGzdRuWItWSqX8j^K{1bV)+}yco9A?O?fu31Hwh z#c%?=(&bfMv}~Oq zmOE4=`IHBB_MeNV&6V6r7(gmwI&APZi^5_#&;gs_1o7+DuZo zWl0l%ViIvQ!@xw*JBgXCmN`LHpilrT5}gQR#x1vYO^9fNZ6q zk!eVkTv!;_o->`@PtfW}(?IIQS`S@B@v&lDqtRO9l+ETTJL{;bNM~kkg_amsXQ~sk zPEmxmqRa``IjVH{6$*;)LqWdn?tN7O~ ze5YW^!wO6BZOa0Cwy$l1>?3yX)nj2;qZ2Q|a{=C5x+2Ny}u(EKxtLxj7F@ z*l4INND8r)j~Je+GpB1nK-AqltH};$$E~m@8?CqnZVy$N?-$lb$9TbJ3QRRIG=(33 zsed0~R0kiTdUzMDDc3|-H7Y+}XR8|56ha9=WOPlg()r3Jp>#- zC@2bMnqbXA)E(;+Xi_y)?ZzM00pi=!wX%5N6PLelc-N;IOyj_im5&$P=G(l$ye6Hh z4@uc@(W%VlnKQD=hvV)kIQ&Q~yOb#2sC&z&dZZ>Bf@W_K@rlxEA{e*k9(_b2 zcSYOzd{zA7c-IXL`e=kWG=WQT@&ypkjfo@i4KJY54u9RFkRq?_LKZ7NjytD&=j+xx zF||yBh*vGsLpTA(j4M?cfmgWbMC6}AJjsK_Ru&bSCF z6pP}oA#W<&G)18}Lggx$fzOW09i*iA1>4^a)ghBY)!Z*y4~yN(o|3p%YAMcoas+-u6fokCb8^9>ZW8VxMJ)na{(d2%xhSM?3@MFenRA9G6PBj zkg=t>FS+CSzrcXMc?!@9)k8EC5p^DW?qlPa; z3Dc`Zy)7gCF)*bdKn4%9>-jQ??ri#7)S%2BI8ssw-8rm?)e0NV-wLN8(^D)D%gW-G zMxsQk6=*3=jH0jT+N~8tE+E>0S_i&lK-K}`9d$aG{28)Qp$5`&gFpjPzHjInL`R4j zLhxtTk8|m{l&C1TIi>p^^^8IcTaz^(#zKuBwPse9+KzczdI@KVgpV47Kg&I28EHrE zf6Yj|&SH!Tp+?ySUnFOwXBgO^;%!1{8#n1PmO&S@_mhR+kf5t;3a|l+=H0|l@jBE< zyhV(Hbscn2X%!kR3+42cX{gz0jT!E(c|C|}Vyt9pI?YNm)x|a?vQ2a8@}+4`B23!c zdX1zvdWdE4=?rm1xee3an>I|9wmzqn0!J~E4C&k;GfQnMXWf#^RN4E=jh*P~Q02xi zVEm-H%~#vA9IWit+Py3FVrIz(Y9I`j)^4YEwN`k^N`FCszq>AJ)A{pJY-plsy=P3FPck;_#G?r4HJK|9L= zyVID=K9R?}qt8}{(mTKx_M82NT#lF1Ho$t|#BQEl5d#^la=_gHo&sC++M#!cy9}j( zuD?>c0BuF=4t?9@b_ene_RE7nEWjlYWH>KM;|s;$iAlQ#LkKc=z~c!kx@MjZP`8w; zF+_Vb1l0-h3*wOI;BZ9k4AI`P?L^<|yBO3JtA!l}xC)rC;-VwD^^r~0e)@qAPVC&W z1K+SPA0My8N(H7?D@WBhV9k&jOAV)Sbr=q0nysYbjv}J5_OZ!2=>GP6wF(^8b>N=r z>KdGE9h6y-gI&|wLu>?nUy#Zt(l>J;CHNK&$fy`yg_Z0u+|2x?J5{?MkV)QptoJ0s zM@+%N_VlUJkIKcd4pOGF4x_7l<$@WhV+Wnx4ogrsIJj|9W(g~%u#Zs-xI(;*#b~^m zb;mC|pbeJ&D26$wL6e5BbB|xzdilPk4%o1%b;={G|uJzo(JQczNZV2BVVF>J$ zseYw!$)7&M@|gB=cwnoEfCKTY*v_TEw4u_D{KA@GsM@9~tZLB`)GOzaEl5Mc@l`7* z?bVDjzkQ1GT+3R)U=1$05J?kay$%*5IJ&7CG#Zjmt787C;VWmLj`PRRW?d^JhPK8A zYNYZS^B~KfGMq-huSnVJak1YDG?#`g%K9q1n3Bpzra9kA4F#v;Z8`xm@O?#C3lC9JyXa?LBtxlojG49Oi|3!8lN z#IQsgXSC+qS^Il4d1!L2n1*Ph6$u_y>t=2*fO`%b+Ao9c>GU0!gObBBEWXOxxai9> zB$Kycw2Bw2zUNEWd8I030 z9d5w|Ar2=lMhYBC`IoE1sn{v)VHb@@qo|zN3Wyd!sdgEcdamcA&xj~&&30S>-q=^z zB|jQeV;Q&*OKuz(2rgxrM@^r zgqFha1^2;M>1gCa=FuMXB&WiO$Q=@i*3@!2a;{|ro zP$6SUf1O6B7~k$E>O~_ZC-!p|xslvA&6*Z}Au6PuAS6HX+k0{-mTP5hQ5HljuOiNm zy|o3$BvrEyIH%crWljB>Sg^eO06Un|c7PJ39~fT=a;l69W9&qxZ)7GIbZ{(AY6Fd3 z2^er{?vq?dvJ$roLg(2Sk=lkWu8iF}_(r=?f-Dv%BDw)0D&*Rp6Ym?!QwQ@DlJUY zfNlP#%4*)R2}bA|q!};_M@86V##__di}nalDT_#&U6MXp(c81VATwhKl#5xNm%SiR>eP$hinA(NlCFB>>+Zh~Onvx;A?iBCj@O?Nm6yau9~z*A_%j6b}x zt4y7bniyZg=|rYzIhAz0jPjg%m{N@c--K@amef!%w5y9dl653rd1NjMV<6J5I#a9 zxfz<>trRHpt_Mw_F%^N^@j zO${|0;LxdmR_w63FhMi)sqE` z?59-yp^cRB{w%4ySVCvt;{`F{CUy2??!E!LPfVeF{r6fBj#BTR9|6|q88qyXe9i<1 zx2MX!?3~_u4a}3B81Imv*czPa9s$?zarNw1iZmoh?01a`7^xnwRCMk{6u}P~8Bf5o zQ_ap?@fS%^2Vnb(Wu@Q@$v~hrF>7Z>Iv1T;UjM-3~#7MAKCTiYhsSh$G^J zE+!i_Q$eS^!D%aU!D~o+21-6+u;EO@jPsZRnUu_su(M#Sne! z3#XMDHA}K+So+QOAm`2Rj4!f3eM0eUIM6I@am6qY6-7FDRH^~Mq}u#X!1Eb1;Vp&b0Xqb0$WxS@>m4L&f1`$+S9s_kt6RWGou-&CVyhr!|}bMP=x29PbUakmL`ci4m(#k zt)i6>%UhlrY({*uMgzk|Y~dBCA_}6B%vCGloAv@5Ap`P) zfH_F~FgIPOY*xHl0-izTZ+Z?aTrAabEPML~2ABhfH#{GlG3XYoxsZRyE~6LN74*k7Uq0ELrNP?A;7A=ZF(0wV*fDTqBVK@+T}|s9rw9mc;}T1fRi#Lv)nm zk~E`8xHd}RS(q`Qc4!3%XR<%$oGwG3k~dm*7+>|K1NmiNSKLW9l08KU1fhsS>k>dO7T96$~c(`+%Ve$!%Rb%>3)L>&JM0j zRYcB}1=h(g*Ivr7M=ZETOUW0e3m^VIkrKAxecOu<{W@0f7z@ykp87b?g@ha%#+aFX zScN#eA?q8_YXL(5s9kT$4|YmMV1nV4GJQn@h{m0s@QIyXz)E0^f~AB3yiVv>-rTQ3 zTkpDbZ9OIY9ti!UJ17Ep@l_l!!cfL;u_D2~vt1i+B`c&(e7RvCrJx;pPDNg9N~p_F z%FmQ%bcnFtn&vbqqD9@=ATt8q z8B!lShVp*iVNxF-S9hw-Aw2s$o7cMO+R0D2K2+T$OZ#3vOuNj`fIwcy#;UHz)>W4YuZp~+=B+m{xR$phNSqq-voSl-myr-w=7RRC>2CIE3 zz0qNM=duHx-=R3yEblsc2Pm?77l2>FY^Qu${``$t1R-|L#F8VMlshnAFlIbt z)qsyXa(67|KB7DH%R&*Y|CuI?-tgQFK+Rvhw!i^2BN%tJt~ESqU)2U%Z(zC~cg4e< zqywy_ZsNwwl_b00ZfJcas5OW;fO}PXrC)EzYvt|v+Z!ICQO{lv=gz=JbgTmd-#BP% z*wbJa4?N+%xWb2ocUq=e!xseq{@aaHM7X}<`@0s{HSR2U5Blacx8W`#8k-*)=rzU9 zF#br!Phzp%8Y7rb@}r%re3Yk1N&=(`>>n&x5wO^(>dbO48Axu-vgc;)?ul)K4U;5% zX23V#un||967Q2TQ$hTeW0hgaV@gd#w94Fp53^!*-D_w|@)>=v)_1Ew7huUns`WN> zy@QatGVU~#d6l?o7t&cpod0m5IRyFk` zO)V>mYvMMEkNCJ%pfs~wxCLi6m6wM5&V<}r@@D%FNHmMG?1EQ)F|*1mCSCj)`Q{B} zo_ra_gww@m0~%?1e_qY^S7dx}GKyx*Mo!Ufn!6LHX3ti2K2+G{`D3S+8O%pcv{!Ck z>CVA?AhmP1XT~2!R)juG)$)3Vs2>nDMZVJM=KPEzb))DUJv5RkXta-{3>T|EX-{!R z)mp{sRjW~&*VqE89A(WYI?U?Jsy)tGmqA?Ht&zFsU5K^M%FWH&GN+7 z&q35lIu=}T*U#7bs$DM3v~|2zU8;{))t05tJ(nxaA(l&QGR`2Ee!r$|9xScU*>Q9% z+SaXamYpNG+2=nPyLC9N@Lmeqw0L24Ec3?m9?%(P8q#mQZAQ!Lld=cwYHe%~jHfQS8Hy9eeTDOgA+P2N# zHgf8|+ItLZI{ZxS-Lbqz_KmMR+v}frx>nw@X&(b9QhW}m3<$mY&y{DO9*fNJ-o{zN zeJ;|bx^HaEx4kaS_}$Z2r9qd|L8R4pN zH`^wDPi>0v+hJ*Lm>=Al6#RgULgq1vI@XOcc2_Tm${2?3?5In9VoU~1XbgGbP~4#H zt7Kbcj?72FdNAw*w$@u?ETTJe93ijl8?R~ik+W^j54naLc$Qa2AaSm4z4t-&47|r- zqZyvR?VIbFybnWqffMe*UxV0l@J(9Z>~5*>t*vLIxU;-y*z@yEXADVqwRz`rmpH>g0e`eij($fcN%Dd&Y5W{5$>Od%r{n81ck{kf2-QPZmcA{QHiR!(@xq@V zcf6iJf8a*0JLIOYRX2~=xq7wR@y@rkCx6uOvH9HP8@YWvbBy>3c@y?d_Ky6;`B~bN zc=f=r6Z=Nx>c6~we!K^n1o@@f+{VVg-Nhy}lC3=ZV=e@# zN1XLl{MNkjVkY(INWTrqHH=t<^6URyE0O);{AsKT5*}sNGcHUX zMgyNz#q!f%((Ca!AM{BR?NbFjD4IaW03odda<;E@O1dnP(h3JNbi|~g16(*LmL}9# zwrHNxn$fs8chu?O09g#U+o~n;z7n3+wF%Rk-efPIShE7nbUeOk3MzTO5^~+jb<)mU zp=}3_!Da7uj@ z)~zyw%xftiOXkQ^94qC%;!tmgiSuX>r!z%C@lTue9NYoT_uOJ`$K_m5QFGjLqKvnv z>Tf(3i^e^PpMf?cX=xHlDku<+H64VZ^?6uotgM&hySItc`2-j_ocyqC3;``0s?l zQqB&TF{7nf_wQWmb&la&j59Vhf%~V;A>r7(ouSFWG@79nZ{F^UOwF0!xpn38RviMV z91Yu%0@zCSp`~E-)N&J&bvr)RhUr1;RO}x-+s)CYL*cb6crxvHGEspk6`@Dvl%fN; zYj(JO^V+h{6i|xZu(Srdc}?_U8X?_c6`XlMP?#FO8^1WR5!}z!ldVsktqZ=y317ba z8@DXmfBx!vxBAG=x!8xgOc+~TVptDr9p2G*fZC6HdS+=7S`0p0)KYQm2SaLzz4z6P zm^l)B|KW=Pi>DtPQ2u9I9MHla|JbljwJQr(o!6&TSF>cG|K686ZNs{ninXb)n@m0g z`P`hij+ldj`<{ZAiAD&UJF8(|*R!PI-%-a}(u{o}AJY{)e10biX>L=Jys3A^kj6&O z@!`tN$IaXs7S<63S``Ml9=#1dB5Tjemw=@wvBUg=4k_DW(tzELWO0^I2~s8&_y9}0 zDv-$WE5g>8UxQdw9MK!|x$ajb6r2E1jY;qt(v1@jRzp6Tr0)lhjIm)#-TgidFv<+nzA`dW{#0`G301HWUIT2!oS^u@`fkFCx<4zHuAonPF$M6@t zTqOP7g?(usIiFbjX!{%fTY5jL?h(czL>HvbKL`N9IpRCa6f(bJ&_nx1-%q(eCW82A zfwps48zqj-x~TtH+tlxG^DuU)wGy7^ zh51A-#vv^z2#Z_~jGL}}_>w8DF>z?w z`RmipA(vHyPrqz=Fhsr%=9umlvsx*O7Q0U7NcqWOtvvX-?xHm|vj!GzD>nFW< z!16k7>Q?>PI_cNapVXAa21v^18(j)1wNalL`0B#VNdv4*hD~soP~q+yJ@V zOCR4h=KbDs%BQI!rea>oIO&YkEVv2|rTG-ua#xIub(k+kan(Li%Jk%1E2#nz(T3-5 zWKR$|623GM;y_W#E`uk%O6-yLvX}DfU-|c}q3c+zbAGqx7q6N+Zi$IPiec_jG%#8* zFP_ZXY`*-4KGp9w$uaLPm9^$`;yaU*xK_lMsoUGd!#L!b=cpCb^7&>y!*!j*VV}`a zW(T3&^;Nb7mC+n)LN`nvS9E|UN$pQ%>FcdX?f74@g@EFU8QGq>F0~KPI*Y)W7gLE3 z`731bXzAIwHR6&N^#!?rkFsJYp%Wey?BWsN;*qdk(&r)`epD13BAEfVXgq_H3@F$> z=c=IPy;~eO-34@)WO98zwbtT=HZ-=@vWcg`w$~}zut78TO-cPVDJ}CW%M!aP;0G8ohLoAez6oC>PPVosIR<4@wa>(K-WCxb0aC$o05N-On8EBER-h+ zTpp8OrjfrD(SKyWMI-TA zM;gzn5lFtlc>f!nRZF0FrJLfnAE@4?wpPe>e#H~0iG`qWQ(Uc*d9B#W9^4irD$1xES7N?(#%W zbFa7>j_`ha_SR<^+Ts^s^mE)C!RZEe6$d{3_etyGA{7Z~U?8A{pIM3jn>mU9^hin^lNVQXtu0myn(S7F- zU!%YMK5~H@fQpBbhL#~3F9TgAT-6!_QY|vHsAJ_%ffaA|k7ZYp?SXX1Ch1qmauOpK zY-?8Smj%smdkkNGm(LZKfG`!qKK0)6ZKvKjj>XYLWTxrS*R_(l#9!?jqO6KKB0O$Q zg}NF`-_JIT@nP~T)4MP6js%uPo%eh)otnHYS1;`HETwL#QxqI%ecb8M-xOIq=?Xhx z#R)k{g7O0T_hWi76`DFLn0=soYnt~hPkt>4nPn1B>x}}En43_aXc^lnNFWoc8HEjrRk4;W`p-*~cC>UXLr<2eq++NtP>gPp zs#t1Y@h$6UPIjN}+VNq9E|Y!fdJfY+zB>7uX*aZq&yf2>o@M0Zm@@W#OVoh6VfECIIS6^~?1Oy6Q_|A|&Ie z0z{S>*8&RFOWM+q38x4cS0h3N=JHksqfb*;S%uTQtfsvi2iO;f82r47QEyX$!n+N! z&D>5_H+YQ{=^t$L`6LIi(`&gEt@67InE1f{IvKW@!WC@=T~%2Hjdhy!leVX$h-az* zuC1n~ijJD)(<<`3$qY%u#4jouY3a#kfLoE9lQ53!i_g*+Hp8%rN>z_5|03M82DS%BYvdb~-FE$KP4Jn%F^NX^i$~mn2U$VJ0O>bd5Z%?Y6H%a3e zBs7oX8Ry(k%kvrFL&?8K6m?Zpn^oo(G1-!G#fmaXpipVOy~kaFzoUdqc!F$oiBRCf zL>e`j8cAvcp_)Sns*0Gp@>M&TF*GD-FwB%NlmP6CVD`rLDQ^}m^iG3nVjy$Ld&}s9 z59hsNA&$NpRSQvL zgtJwd3NIqW1)NQsA84V%duf7Vkok6*Xr)^AwB&=a-EJ?-6 zKX9R_81fIYk>S9NStV<^rHARs`VQ&x=fS1>uEBsOEPs}SbveP#)Uxb^R%}LjI=dfq zw(Ed2MI`K(TOA0m#+#o^JsBWeB7}KysCV7~zpnFhz;Ej#T$g!?1R2t*YAc=lwJ3DJ zhBh}(gHTj?H^7U_-Qr-Ug9sfibwVaj&kZ($X3rHod`DGa6Q`-UeVb5}*1Oz9t^U9> z5E*Zv*==ahPK_mPUt8h95RS(03RBvIM(a4>WKH|%PDcIN3{5h?f2R#O$IGo@IeR^i z+)jToWB1C2JuY8|XSgX_pV3tSzHfCyr4}gL?KN%@###imLy1EZ?`l*p^5hTr zm%bs@^k@r~!jSDmP0nApDqgc2#Jelkjojn(E4dxHr^I`m?y}r8wEizB*(r|FOa$@P zf;V`lxmr0ot+yl=nS1jKJnn`UBOK2Fm&+aX)^!k$=ml^;j+&XCK5_&HIT2+QM}H^5 zDC1djYobcbYV`D+T&Y423m)-QPS(Li$0A{%xaN8M+z>CqwQ=wcvCZ{;tnR#cns3&X zGR0c}DnWQK!{5+XAC4Y#cfwU9=RUyZEf?QW5D)tUB!ay}(S+vO;GOHkk-q$ueztBu zSz^sOda2~fIM;c8V2cLxjg>yMe#miI2?$|7Ih1U&dYJuL1TXMmUG-THcXqX(wX;xk zvqsYSOC0KUnEM*?tM&${Zfp}XvtbHq{#42Vy0d(B`Lm;%(rlL`gt9R!uFvG(?_9Di z&{VOkXGBULkle(12o5&z^;Nw&)jH|5lu$0Sn9wynG*ObTSUie2z$=DmbnFnr3re?H z#aApWMjy5h?U&?nJ~>haq8-dAPy*d|&mOP9bfJ&9<@81bg9b<}8!r2{HiE)EY7yR| zVy*<^KZ}!?6&dV*66wWF>_}FTRW8WT?IBeX>BeHdEPtprkYGc&?(0cSV?f8-%@EyW zR-i~qmx}|NCGy4yVHM0FjsW8EcgwgUb;*GmwPSIVvsp#JErsD+jId2Lb;cMcW7N0Z z_~CVzMUOc=t|qX_t}+az+@whLF^2jUx`?P^eVR91N4Z8{&HXMK#GS$7s|EUPP%5C%GUr+mu(3uLHvN;k8-x}}_N=a%_u#Gf&F3g9wO^B&Tp8GZG|c2uXF`=!(moP4 zvu@}|B3TR7^R!--e^7JmpIJJLa>8uh$DynqPLQ%cR7sKa)Hj(Av(}{e!@yDo7p`S9 z8on*nbeMzApc8(Py&8wBVmFBDIT6)u(*`|rOwZ}=c|!-^0%)q=!?**dHQ{fwErXpI zxX<=r_)2(Wuho-1j+K6|zg7D{w)ZhijZMz2--}1LT>4kC;Cs6|te3hg?@^QcbcGyv zkB6&g*2=C#jHx$G(*s{arRulLL4L27E)Ceh~aOoSXAsQON2%%-D-oo9l+H3K0I_eHRU7e zcQvRhl-MxtU=@OIf9&4X+zj;o+(|IB#!9_^sP+M_IH2#QZLywmt?7Zw*qL4Zo33(L z$Ai+j2iE_Q(8>R-(eH8)_ts8{Q&_&uoBLCBR-gKF$m_L!EPNDENp>#ncDI+Jexn2$ z!-t`=-zw!36hUKRMpcUq>EL0H%b4*A7;(>!vT`UqQUey%`ZW3Z56%YWmLD3S@otZ* zJc5mo?n|rFH6+rVv)57gVzttfJk#mUM8nm9@STS|OH8T66iJ|kH!ZUbF&}`U;X*J6 zXrD=7fbV0jwv?uU=L!-&7sii5mV$2?4m`8&Ou$~GUb#;IT;-Z^)>O9d-O z4R$!=wN6!_f=dQ$B)5sdP}C1t-=sv(5d7gzvwL{XplyDXv-LpMiE-YaJ!C8q9nx5l zJs9H~f5(jS3Bg_EFZuOt;&ZYaH6m+UDnZGFqhAE!t)t&$k~I2}Ka;7H$maMETS&SO zh#d8M%gimT8=HP2Lgjr80wA1+Pa&+wMeV|xzyKZ?hE7g=T24x z8Y_3yaipWciCi__Z(9FQt>mZIMMf4hv49AZsyBPeWVs4x0(a@2o=+Ogb&+V4ptoe%MTKf8oMF zmM*PRAW7;W#gxiRl&j4`L9jsF9Dt(WzLrq47UiTZJN|Al7H{RQgDS1tS(TPHLMnMH zNbv@*r&C|{Eea49^M`zSDy@r@Whc*1mps)bJvmtArp*)ly8J_ZskkUWUCf`cZmhI! zT;}T}#T&kUptP=+2mzgOE<)6UJAJ$5AbT2SZN#YqXuoA|%iJt+0c=oj9db1NJh~p- zFEX5feE@<#z)J$&URk%O%!Tsl%=_syr#arD^E6V(#WZQ8`+5jR>o=)Ru#R*JAFxfq zCjq9#bJdCOP=2#1rm>34{XUw@*rxn!qfUX$-Lt(dP}2!VMuj>cvGsh)DM9`;1x{dR zmr5F9S>{UC7^CKpwVn-)au)63lu>;T{2HzUFi;XC9Bp_*&>yVrK4l&tl`r0sllDl_ z!Qd~DHxTxel@I6mwc{O#TA1$r83<6`XZ!qM*1SaLQvqr2jK81t8{g^?G~}I^=dexOEVI%xt!K=lLnUT6*vtQ~N= z5y)R4R1Pu~;_W2~{48!}B^J~D+Bq}96E9*1;=9`L9VFd>&L{$0UZ5=z#@96|0s>8l zg}8cYvJxofd+Bx9PD&lh)}dG>G~6;Ujh~u58+dnNYB&WE)Lnbo2|j@y?!EZE@Z8*b zANAsoh*lf7cJnf_91BOhfXqB9-|a&z^=NnuQd57oU;HwM+^m#sFkNqTW%c;mnvO$Y zU1G~pRk>z0uqD1DbEhPZg)>UBDco*i%toQk?1`wbtWg+RnLJRH_>N`yST#w!bgVQ* zVvT+SyPw*YE2f4xs8Ab0=MZIsMHbeF#Ed5viOi%L6S8K6Hi=Bx=fjLMjbdy7pRD*t zgG%3<0;v3>Fqx3)`Mo- z*yO||V0)TMAwjKwLV{%!<(2~t=gM|t44`8UHoFcFkKKA+Fw`ikWW%bOPW?Bs*Mjp& zzYZDC_;mjInj+^>AT+ZLoKBD}_oe{JCo8o89PTzCwC2n;=e$~Y%{-Sw!d<~OrzT}W zWj#|10#HioCmgG^I0SOq)nwsoALLJwjY|V}Qv?eZWsbohPau^t{F%lCVTP0%)VYa- zDR`vxnBFZ8IvxAw0!RnMx%5W+WXHL*uzkw1eeTs1C63QOoFo@yJXPca%E{Xq`z9c^ zPApMQ#l4r*!03l0QsWJ;*Jiq%Ol> z4?wzbV<#t{L=*Y?LlLI0UneB7KJ`%^Pm{&m^XxTTb(p99XY`(!P${{`&p%_5(KdNk zyQrIx0)*Wq>;E=OX?h^|`a|nu!&1((=vh3@v%k8@w=69itLf9J`&X%HUy~V@0-rW) zilnXR(x#$Yv6kJ{fMmnpB~;;<0VKsV)K2G~3#ew@34PTw#heuxYwJY`>X(F-D;*nW z(Ju5F(KU|Hnuk}e16=C6wL`afq410JD|K2*-Ab^t-3bHo7t^Pfx>k3ZZ8V8v+hgbA z22m(o5!iTYutI{H$sj7(64J3G+(F^tO3#~rad||0&reY|gkd!_w^3dNl{vjZoeG=( zl{9x-3A8cZO$JREGT3snL(&O#Yi0JKa(z+2lUErajolk48wj7;1H|l+LK?KXn2PUn zxvjC`Mju9CvJ>xf*=Z7U4s@Cl>wo@}o20Gv{uj(77>AlpOM~H=c1P3RXLW@(rGYx4 zOs>Cxr^!o1zwoE~@-)Q~A)bFB|5&du3itI&8mFVRMAq4iC)paG&f9+4CGI4!O75=0 z-uvGGT!rB&+?r`TKW*HCZ0Ku1bM0SA=&G>?jiVy$lJOg|%wLfY6cd11?DGby<7&<@ zdwIB0SM2UBEDGHWi_<@*Lu{p4XKJjh*(E*}9#Nqir8qboVsdzYDb^=F@ujHV;r7Fp zO-IMlp}&6v08yMQs<(@S#JZGHTbVhF{Opz%?p6%|<2Bt83DDAsuf4FjCo+|}dKu`0 zrbWFn;2JXa0JcTa)OeZo4-o=yJag(#m0(J8NJL5qN#3939!?v@XP;6|O;b21t^(+T zX-hqj#SEcWRtL#!N(5k~O&`t|OABBcbl%Vo7k>o@dI?PD8|Z~Yx8rjA*7mAwMG8bI zRVkGEMxf(0?*;FJWQlLD#}P)pj-G`C$KrKET|kYSHa>F*J8{2e(e8pdlEa~IP$Ru# zA4XOf2DOHP)LV~vUk3=+p^gu_Dv;U*@HmpvVF-q^4l!uZ*acxY!iEf1)vA4f811Ll zYHmVcMr`Z}J3{JEUxj4vGqg&6;Mk$N57^Z~UST}Nc;;G{|(7U%(JI@3)D&c z)VDJfeDh}&Q9m+VF+zNngg~^z18!^IJ&l}TWN#lR4h_;Viz@_m2*4%E7uqniz@?5i zjB^XO94WZ3bW7J9al%BFGt#sVWryrP3_AqtQRac{9?`RJyKma5-YHe@37?BnbHKX~ zpE#ZQQsx2MgKiJo;vo))ejQb}&(9n>zAyx7)cm556dgavcU$)tGdH4Pu#|*I0JUQ1 zq(Ih(m?Ppx-5FZhN4bq{751UE!~90^9_$%H-T$%w^IVL^i9(dX{3<@nDA8<$n<|f; z`?vmkDj(g_a^0w^r&-F`T9ICNqX2%fc`hbftHiC8<9CPpy#=DRNYhCZ-6g+m+7qH} z>r=K{f!%`G`Dc@&SBhJrfEI4yiIwr=LK7a(7EPsEoU}t)<^6a6v@e?Vn8b-dP?KXN zrL76; z-?pkK5Z2E5%S~{(a-A+*8L25>R22Xv!(Z%cl8NaMMm4By6aZ7)T76L8e% z;d=3+oTnt_nm1mPtHr_>ClE+Rl(sjI$10p z_gdL9R4)0{{;CMLZ}fD?SA$NqQgujHgI}>^Pg-8;$6xnZEnNCls)iVE0q>xo4J2;~ zyGL&e4ctcPZ#?)bRBZGzF9GxUatP9YiGJNJjX9GPyc;g6ap}RA-iA{`SH26cAsJA- zQFKBwe2Xl{&gr^;T}~A-ZR{`gYwj0J^|jWZBroJnMT)~im(&#RZ}YWC`4iW^e3m9B zRB>+6B0N#^UXu?{G~D!chdBQx_=FPM5I9>@xVh;t=5@2Q{A^Is^)|L|DO5|Cg(8Zb znZ|Xx(6ij2UHv961FwdSltZtEzDJMabz5agY=I5XolJnw^=plcd4G{{T8Vf5B^iAC zk4Ma7LgAK>mNRLRRmW-3cSz*nIk52fFAsX#wxP?>;zbqWEnx|62yQ4qmtDAwugdm% zq(3(X{gi-8o^pwV2e*pkpKK|2E7{2=Gb?Rth}R~u1VJnqGD0sHLhp!pZ-ZJlMia~D zUpdXG9;X2?Re-B$*uw%eLPk`~51je5vTL9YURzF$O*w=rL+O%YTy-=yX7%(GJx9|= zugb|}c278GQ?(_F`o;ep$Mmr;>UXm|M+K@ci4T2+dn#ik?CDFE;dwnzWN=G41ruLv zF$-Tn;OmBWb2Giz>kTd@j0Zb#YN;sT7?y&Jx1wX@-Rr@f@9Dd5|0k#&s53q|#+raJ zu`+dSE$(c(qtJ}I{U*1HZH^2u!j*Qs-8(LBY*2S><_+cE<_-Iqc|NFDn`Ve~-?JWG zV6lpQC6}*h)5?5Bur?g30v*Ex>q1)isN?L5jk0>Ns6qHW=09KTat%|`n51`oS^mM@ zW4#w#7_87IRBIC}xAb9cA+WkYqMaqd-TCt}8EhMLLP@4k4&MfYO`iLJQiKLTTJEBT zI@Ul}uV>2dl3BnSPk;NRJs0;bCeoB3QlwELO%j7GfEGUFGilBQDL>i-N%@6;7X|@8 zQh=W0K{zS{Ij*Lh+R7P4>e$0XP$(DR!C@dK@SvBoT`&tH}90fv>`QO9EH30Cc> z*50&<$$-(!wAIch%n-bxmN8D(-l8m1WF}k{2948G#%Oq_Pby!uqbHE`JkXEtASJ$GC@8-6`d)z6ESoBvJW?WV2k&CV4aucl8}m zY3Jw-;TBqrN$mjcx8r+4L_#p5dyS6w<9=AF0qStbV01kxp9CE)9*{;{r-g)8Pv-Eo zxcbT@W_7pNo^5sLh*r~?t3`Kso_lt_Mg{EWP-yCo-Fk$JH#r& z@<0`^XL8_Qny4+%>TD3bFAF2 zADs{hk5X1dB)_;f8#d@Epe?wSC?SD_3+?f$NZL^nZ_Ev8Up*^<>jsD*R70FEFU8Hg zlb5$cut$FfXxfp=!Dv+anT+0Z!=oamBFVn8vFf&+qD+V0K803_7;M=3vD~D1Qc3{L zn#MOu!vN{cJb!4@Q?+~Ykrz6mG0VELmu|;Ey&9&R0n96GyR+8?kY1ZB{+7CK z;ZKf~D~BlpR|m)s*L}L1S!dSaloqf~MM5 zvgpv>DMp$=27$bTyR9C*A3tL@3M7jnaLtK1XJ=CL6;*|HBAVqQ*z z9QXqWLQuaE&YZnSsa$>BAU)5Cs-_-_$8)1TOgF$G*j$r>Q-Ao^jZtL z=uVqq?o9}=FIrmR>^iX)P<}ef1W63g6ah^j`P2*3Jms-C)uOia%X>U2*+$@3-nv)s zY+&T7p%?5SwNgsB>=u6kD$zo{EO7|%Pj;w37Pjs%Rg&<`gCdPCg<-W7OV#g8e9Yw4s{D!H{H6%QH zEAkZ?ST;6b*3!p4hc;cW5#-U?=~T)Bt@WNo6o;O+DiPg2(Xyusu4`)q&p2&wbgqX# zgdc^qZ-Cp}fWp{$*WOAp<*3^vjQkboDj|idC0m^-7I>4|p?RMgr;2G3W(aVlv4t*7 z_+)7@Xtnl;DD?q27wHMB(Ag$ZWW?qDbF76@xEX-ztTTxIR+uq8gzZMGq`?M)Z;D>h zm~OHvt3e9-9?=_{dkRTtR6AKm|Wf9Ll##Rb%-pgnAw`#y{rR;T)-dyAA zkf_9z9FBKl*^22Xt8##t(BYOOb*z_pBApqJ6@9QWelF1a#OwLEQuIXc z7!s{BhZf>F`Uw^%ciDo~*?f52-+jh0f(l^7p-i?FRQZ7Br$9BLA*tr~{ z(n8*BK0%umFuyR+ZhQW3E3aCtynCiG#L#=|_=-KlfQGuhoK$YXi-Zpj0&%0ET_J23t!(Ax-e7Egch zjnF`qFJ%=RjVNe zO3*sRVS>c%aPHF;y;t+A8x;5qp{2ZtjC=tlDlt-(nkGgUPDbgm=p!mBpYTg6-G{C15@xM`hyNuvo9L$r{-`k##^Z_O zt|c4Iv_c>&+M}TUq)&8IcTbvU&$uj=6&7g{j1i+iNbn?I7)A^WZqK+=;XK#C`v}rd zspmU(BkPs6g*#@B5Q@B!pn$lx`@w*on75_88WWzmkg=!CC`4THTdkNXk4_9l44S9# zD=h64}d=Z>MwW3Mp&twTDZ%rhv`L!2ai_;6+K zc*Ol)9MiRgjMj!bXfzgi9HeV93_|}`0}1cDYR;&LpZFk;FqN2%_@;LUo08P z#ky4ECekd~;Cj`EkG(9_ik*dtD|m{XQ#7yc__$t@Q7y1%^*hdC!md?VbxIe=FXo&<5sl-XE&2c2$7kIoQc zA6QGD%p1SZ*)Igc4_&^PYh<*V`Q_)eB2yoD!J?;ls#hHUZ!EzP`5PWTF~U+P&!y0E z^EL2(g-)vIMOnC&YHN?HePMSW{9kf<{ro&+hrZgMc7;}Q@1kY=va}n@ttzs&0x(q; zR89RIXLL$*9pdol)F}tsHZ_3*u(isiqyY7d-xDraP^Nw?%=ljqhA;UUj;wV>n=uOBV#xh=+Q+$+y+>nnGadrdd`vM6b!=(3n3Hodvq(=PnomxbN>(U zkN@SYDPd@5V)OsGYR1ORNP#jV4fix|RWDmvfBN5(SRfzh-jYQ07lcb)uWi-IN;V|Q ziV{u$cKaZ2@(0J-cbfv!cbL*&yI;RvKR_JfKm+s187C;uMmzd>O{EKc_KLJMYEH;h zxl>!lkHd7}h-Y)lFv(-jl3Gsa@ zqgWiNn1KWz?l>N1H>2j*zP6a7Ai3*kd6`x$m{y+CYUcTtRXwTy^YUT2Du|y#(82;c zDr3N25tZxf98JQeEmgHTWhM*ME1=(EJf?1IU%*C(O`VJ72oYh^fVNOaChbhls9@*S zs8}8H8iIe|f<+JrX&Xp3;Ygdi0oA_NVXM`y3aNwISQ^(eMd1<8dafut#r)6GDFr5= z+~Efe+z$0WuGl4AOl|)cMkQ87+d@YbO_!2&jBKGUcA>| zH=0T&vlMg2k93`Bz=~&mMm-is(c!&Go_kM;ohRXm^Jd8|`0I-l?AH#C6~U9$q1s0f zGGX9TE)j4=Llx>wi$Jm zEgf~2w**E2#5|qUEwi$IZSbAb6v0kZ#znwy&}}%mQ-LX+?LpZIS!4YgEQ*n=kO7QK zcLL{AEbdW++R*gacyO|hUqsz$wThEg+1_9%nOaP0C(hbqWf z!SA!0xrj7~4X@Af(wuC!X%7TAJ3A+yne?pOiUp$Mb&8GF%(cjN!(XV5x>`(3 z%%-U4+b*_L_;w5nt^_sVfX{O&oR+o(Hpev!+(WN3%$E(=!B>$*vBT{RE8#9{A1!^ zcm^qGBqA;=^OSAsgNjyNz%A=^(On{^)DqA$D~KqYTY|PjH`%cyHnExI!UsD=}R4vco-;*es^lB%T~4 z`P-QXjP^+>tH(zc%9}FeE4uCEEB>k-uw5U(vHJu{WiQdSywf2%i4;)E9KhTLkb z=V~WXs1-+^*_9W2CL6HE|IyAlh`> zFx*laW3SRR67W&|B{F@^TX7u=yE`LR@_|8E5#Py5m9{OyJ`Q;Oi z?1Km@xQpd?xQ*XBp)7Ps9=1E>rl>vl%vT-ZnOYbBQC{4y{N=+t0yRPuelT*fay+7G zL=Kh66|ZoE4+e^fb!w7#U+m2Ohm3SA)tb~&Y`$hutR3sDJw&(Z3r>q`!YO5`!P z$Z-i_E%$&r5HPZYZ6c22)9`USt{08#3j z^J`F$&#`8>^2fd8|4`ch3j+nCz=3pP9JJ{8$g#{I73Uvg*6NvMSzp z*5g+49QqZT@@d$|{dtU>>q zYGE(QKcnE7wy8?)p|$W%$L?7fAA{{^uA-D*$$!vl^(6cwzcD6R#V;!r+5V zCu8zpl&G1vs|Fca`4-Ft@6Bi;wfEgnX_LB?`f+qBPJ#^iSMSzjW+h13seQ9|A2^;7 zdI2FJ=EjDdp`SHX3QLNyz-K=ILg>fF5)gc{2@`h zc>W;riS5Xf&eLHAEhDY#awD8B)(Rc|hTbm3%9dWzft1if8n@PlNIlrnKhikV3=GAW zw`mQmb)_oO=+_`i7famo_@l_;oxC_xYb;R-<{CIwULMF;R>yZdu!V;kp(1*4QAehZ zoCwM`?5PJlwx0KePiMqxbFhYXSd38OjPpzu8Y+L;yQQbh+f9CrleRN%gQG*wosx-k z^}c>{o%Fx{MFi!dvcoU z+qS47NKV`XWqdU+B7})D_&=`J94NEi4Ch8MOY;9jt~6XkTA% zId$c07S=`eR3u1oR;UmWwp34=g-i&dRkzo9}*xpK zjpe#EcD#1SbAdMyfusZMVwt=$v2=&qX`w@1$CjRBtSwBVwfOHkG6C5q@%t!P`?>cq z6ONY|ESz#}lgj3mQfauk6#npi5+9(2Ym3H2)0&*GoBWM8X#Sb)fG~nHcIxGi);;Rl zM-1spsLPXqeI1!wuu+7W%tpaetuM&L06eOOc{C4N_}_DS9aLzVxCVq}9M_aB-Kcw6 zG8{B>nsc?yC36SpWS5-oX9SKGDh6*WWA>};C@(a5_HA!m;4x*sujW6_pQ&{(0&PhW z-ivaFnwZL)e$TWgZ;=X{!q&KLgmv-1w^;Yv3tA;!CL)~%ytkr!F6!l?2?8&F%1v2x4lbuqt5~Sq0_l zfb>kIZy=N%{w(eKszp<)g)^?P_zavohDU;zU{-`oA&g5Ms(OP42P^$ z%mZcxavDaOOugv{(3tAljFl#C3I8)M$jHMqv;8ov5>bGFIR0mOLDtm8!rtUR=pIdK z7tW}vXo8&aVa?h>^k}ttyR5!p;(fx%)S*&D^aj#Rd`Y(Twk@)52WAV9RH`?DK`+4O z4~2fq*p7pJFMWc&g5$UD*IQdQ3lsn@rtGWjP3NoYtb5-0uJ4ccm7U*>@!h74Gqe9Z z{3z@!n@!hKtPWYrZM7UL3|76=qAOl)d{i1vCLa{Erq(jhiH9vFI@|vavz9aC3JUVq z6#s()zv#G6>gAHCE9fLr20gh*~=pe)C^3GK#Quh|`F2@2h%tMK8 zMN%9oyjUSS@=jD%w& z-jD+wF&mCWC=6v;ek(HxrC`8dXa?(QqOpA7ihY@+H*`rf+uxy+AU z$J8EV-HD>3^g`V1GSl#boIK(p!2%u% zpr4YiS`$ze&^#0Q(|uN9_AKY+_yLN5+T0{cZ)=*|#LIh^z>V(HV~TXSF{?I3r1CN6;MYe z!!qhQF!_;D_jPFa}KosSx(u)PFjSwtxU*XrVCX&+I;~tG^@Qt z_^0T~T{DZn=A6sC9)d&IqM9=-M)$+8umLCt*cPF;(~5to1L0t>cDcf7mdV{!_+E)=&Ks3B&a&xS4V0ypBpzI)6NFixr^*S`9Nl0emRtjF_ z4mxq$!xiU(b&0ES2)WV~^%6K8SS2;h(T8!JWe6;owetejBHu*y*q6TE)eGt&?$qY8 z6Q8*v=|Z~$c9+bD+!SV9pam%rO@oR+=R|%;=L)9meu|4U44*aI^ZH{1Ok>`-#yTsL z%|wH3i&9UvUATINA>-H^*ktp>Lb&b4K|T(Cct~Q>iv6+)(`x66X6f(Rf)LRv9f0bg z-#`89j}8LYvAiOrk_*?Vh)!++C;|YcD^RsJ{FC6H>@N-l?01W*)nLE79BaC zRbs@BQVIK|D0h~0!RNZvP!hyqfjSs>B# zmX$$9L$YB$6s`|jd=KK~8GQF_vRX{(;Q|c5ld)u$$9Jiw->`MSf~6Do`jzv&x6AZO z@MiT(IB&Wm@pU3-faKI5eK40!Av;5#Y1~R^R*sX;=McT-^yw?6Hfr4=S#oTv}!o)H#3!5G!dxOKyj?V8z5^FlMpbx-^n@4zfNtQ=N>c55JRuFEiTNQz0j zX#?wtBkN9@updy%enA4&AaP^y)Iov;95aX0H_c%rzG%1U{G_UU4YmanX&P<%01lzC zX=_xu(7`BPbc_n^i0;0V@tNK?aIA{tj@yOv$?d1}I)&xfo}e}Hgsn22i(K`Qul|9r zdOGVK(067NcUs@&?&_n4C$QWmL1J$rHq!qNnX0yWC!_@d0vi3vMgLcM=s$$JCY33t z1tuiDCd-ACFXW7(j}(8rJl8hnLo}Fd=GM@3ChnyFhp}^t?j&m3{Un)K6Wg|}iEZ1q zZQHhO+fF97ZSxH=nuY| zkA9fUBtrlmn$LSUS>xLK*|h#Nqr2n#tB-Z{cMGVZi-VbDiBT0Xiny3EwRJkwFpwuT(f-)iZZ^HHvVO+jD}h}VRKYy^lyn>d17VcdVJsK1 z1vvya^X5&&;mE11R%yK>cp2aun%1~Q<%Gz>=YGD2TB2`JO7kJ)#KK^$NkDFL%CvaW z@twjjL|2`JJS@_BHLkxq@me@YHlH;Lt|+mF{jdY$iox|nH&Y7J{5yoC;RPZyXWgtboX4or?V znSZSzoXUhFWJ9)rsTS?352m{mT&qv4k2u8C-ghhEZ02mV;#s3MZi70oqMZMwxeCOT z0LtG3>?tDJK9nJ0H36*`VFiVc*eE-!T=b;OZZNJR0)?L3_ zrwsakyP`ifMS4lX>$gk~|E4-2B^$6-`x1V~VKzYKW8fp3^9SamXCO03HU#O3*)<|4 z2`!f884L#y;upyG3o?h3Pn6~WJCvI8Y^+VH|EqEJfCA*29&c?CJG_8@e?wpY>r%{d z_egi;@p_#5{6!!3IfdU!i9BAdo`3}>Jg^jRS65NOh+YnN5@K0Nh%zbI-k)*Qt|%B^ zykzV+h!QWi3O3T$NbM#=-^!?_oWtdP*C1y;1Qyw!=MtEqD6ijrq>QURfuH~5-$04}!xXqJnyr|h zjSv%dUK+9(f{G1?#Ygo5%15ZGpcF)C4$Xi(5fN~dLtGMqu@?F{zA`;{t*AH`i;IcA z6HrO}bO<(oK>d*UTQT5|9~du&zTtlb9Ars_x*{SVByR4E!8qB>-DY7ztmc7w|EE)U zskmR_cd8m@R1$6Uy)54p6m88A?AjH_X_B6@da+0o$OPp+H{+?A`0dH>K{zATM~q_3 ztACuX!ei+!t=NWfTI%vB87iG#_T(LW47>r{6wYq>1Nj*d4?oPbScoJQI$eKaS=gEi z0v-Yl({pv#B&U=5CRS`XWnt3Y{ITe&=UH`RE$j**N+h%e($H7~lf4h%Ap<92Wnm-g zK$i4TOXlESmf+_o>es8;4C%Y%Nz8p2r>b4Hm9Ipzjx_z zo3CCW8uSUF48(=oNDZfJpm|67=bLy&^DZodP30uw|SD37zt`mDt+yiJnTB z>M8}OOlLB<1N`Y8T9x4YK1=!S2?a9FLWmnJTd)$OZELW&cZ;{V*_>FrL2Yi+*O)fr zptQ?eNh!&53L)(UXMbs3h7i!FmCX4&QNat3giczf7H%&_)lyQyUyuplTGt3fYshOhG6!jC@IxpKtl6O3kdAi}I_WR!{51b| z#YzoNK>`;Y$%TfrCyHhh^sGtN=fkFeMo*%$)R-n`Ym;`gTJOSQ7xF zXI-(5?)mlU&`A2QRl++9A=WT5JR$qj-`Uhc!h(1#j^@tjpbW%~b=rCw_!l9ZZAn#+ zjBHMU%!nhLj0Bg}{#2WBHX}6xg9MySL?@9m{k8aDPc<1W82$7kCWls%gprJ~dyzhL z$u?tt*FmGOFmJ6O!0z5yHbYfq!Rd4OlrO7>>E4|M6hMEKY(g{<_efU{LvX>$H|RO5 z!tQ@HLJ-}W4Gm?LYhz-<*B`n!#+ru0Zph70T96v(+1S&1+yHD=;ao`vaOwtO+wFk! zJ=w<5JYD;EY);Kbt_y#Ix)PFLzK3%TW%}qV!%ip~S#;xCV9$ftpzCXG1=^sSj9`v6 zGUpZK2_%HH@97t6c+LSS*V3y8ZUCMAO->IE7OENI2@K6c%R4#v@ygWa%YNX4%j&mr zn~&lSURA37u@P%Hol8SXE5z`rI!7^MUFJv6!VVmWz=7qT|tO-$|1@>f#_MNb`zC@apmolf$}pOIzHk zOujF{)+H+e!1elD?x?J8mW;*ANQ76|M@1-!-h_v>SfJOoN$e>iU9w24tDna7CwS-D zEB5y_TuSnE)l#yw^D6AOA07F!Z+OD+VPnTVHq?S{CjBR@`-=rPoOV7|577tJo+ojG z0vesoYkY`IfG?qV*(;2|)jf0dMB@Rh&BHkK$8SExm^)h|8xn+&_B0d8c=s`LG)(!F zHvKs9$c*wXXpsOV3u!y15q8AUx`<|+fAr`+AHPv))BJ4W#7q7dn}~k?l~*rE(5qyg zP5LJylhmibhsGemcdRzKUOQ6-;#kPr7?Wg_A8XH)tdP2M@5A$CEz?2ot9G7v!t zzV`bvSP*#{-H8=0GNLk_imL7(qvUZRv^C%R2FmOHL}WNIhb`Mhg*Mj%(eotLSfYWr z(7vVsWd6K_e?6-m_O89Aw6k>^a`7b-Vnq#arHioTd`w{7zyYyz778bt{I$U*9%&28 zL20l`418$di3rGmt#$^SPC=Cc$F&s0Jwz^7e1uLZx|ObrMcu2ey8Gpy7Iq~ac@!%B zEi1og8tO=eK<;zn&iq=q3oCq;rYpKlYgY1j*b)tSgMMrgX^e1V4rr(rovmZX%}JG#P3 zOpiSX>q#*cEY>mBpe805GL0SA&WLZ^uOb_p#!aA4If+pRRxyaXgRKyJh~kqr9{(65d^ zs^pzcTf=IY5^HImZ_bk#6&x8Nw&%@G4^)8}QWY{sAZnm-g>G6&D$i{%4F4%!Ts}B0 z$Zmg-qqO&D53DRd=h^OX><bwNN;&$ojW_H==a=Lla? z|22({j%1RfiK31fp_J6IdV~rl**BdiKsAs*uScwOY@oVpGKBkp929hvk@2VIuYUXL zQWJ;A=$XL^`?#%m<(wxd)wnr_f9HpKbK`T}FNpR+1dRF!PUsNz=o(YakrYBa;f~7$(`d71b_gFK)D%V*_++1F8*?uHFOon#w7i%&jw%qqNpK zoJ(3Mf-DI!a0DR?H zPDi#a=8u{yPq9E;qdMk?7j50|8bPenSrN)-a$y-tXw}*@WqDjE*&3LX#6dM3ZI${W zLZO%+M}X>_Y|H(WrL}ezC8Ij;HWD#lnra5^l*Z#} za=S({iqY($I+>>s`9KrZxs5QnbjRF6G5s-p?&%x?QI}t_CC1eyrX6bp&(zX*BGH1N z{Z%Ay1B3P)7hA+}NzPHS<@0e!2 z0k@A(-$YUiGcvT(Wa}?;u|xwqQdBA0G;YX#=^UwBgs~!Vi2f-q-?l@xQcm=FnYT9d zl&o+j=MLWX0> zyeAwe9j8y){k0o5aU~m0rPF@b9anozJbS;lo*kB7T>f1gGfhL_2Bp^vf*g7gPt2jDwF7_khDKdrL%Azz}-JtS5AC6bzyunodc|8e?A zTY_+G0QSlEEHwoP6HU$BPl~9Ws)Fk^>0a#syQ{A<4-`~YfvG*J84x9@xzpxG=ClOj zWg_NM?W*#w#F3I`>zo)oP2(8@E=3>!m(ui`bk73{?m9VCTL&7AkV@H=9Fr#&LB?VB zBnDkw2o(roEVwu&L={*B4WVYHmA9Ud7DBKR<*0!DfX?{dlT%y;SSp-scX3PD1)h1V z8c*>ugp_N2f4>Y7o_WM_&+wKAM|Dr_U_gW%mjCEu_K$)e~Ec`FMs_! z_5aBFBe|2IPjU@XY=SSiQBLh^?@Dc>q}cIQ?QZF@$Ocx{b?3N-YP!L zvbW6W#NsuBI@N%9{d3wEy1zMW7Y+h250Y9$&SXRx4r z&up3WBrmG8&qrx_0!Ai2S|}@S5b}I8z;kc;Gj=dTWc4(aIfpgKtT0CRUsb5prOns$ z`n1Q@@#*?>(=y#b7J8+-w{R4aYTs2^veZi$nbuFB*0hN|2<3&UmAMnL$li~^-M zx>^Uw01379AY7B+$?3x5dTgI@-$Z3=NEAiRpUIchz0Mi4B>|z-@iZu%3$09{zGF2w`OwP()>-H4)H2;$~!v zk(cGB04;WoIbb>-70ZE-O&DTM0ihtgvmgdoiS6m1j?CfRX%M@UNE~o4&OYoZ^AsQXoUHdhyf<3nTY zWMz=J2jPVWNjQ7!IPa^0|I>+9sEc~p&$ckt642~^@BQvFVV?&=EryT{X*!{jmFrrj5V^oz?HMwXZ#%P8d+XXjV z7=w7-<23i$*bcmCJ`OEsr2l(j%-~U6&@c*S|HSW_X4rP26NnGo*_Mm(E^qKQ)ey#) zW8^kWQ7zF{+ord#_+x6 z6Afp<%TCLf;_jI5VrdLLoygEAhM86>aV=Ymp3je%H0@oKwAk$Wunr!J`Q;V#?KJgXY2EwnSJ>_e{|ECfnRYG+eQMY(#Y|CkT-bDywce!1 zp8{g|Oh9kClY7iQ^-5!*Z>REZQ8Ae(w&6v*M_f)J`&D9yF{C=LICtRhxq=)#tl|yg@4yBDlpU#n;XWK{U@gu=demZo?fb71^)u0oY|Qj?SWnU z&`z7$8Ki#&qMQho`^P5&3iy5gYFZcV3;A+itH<^YhH~gBMdj1Sv>j#d-Iz#-D^Tr5 zJQ2u^Q9MMJxtr~EqzZehpJPqTv|_pgrIX!!w3fE4PxwM`z1<1hVbQX7-^G|)y_}SX zuJyD&*MjcEC^*QMdW`3Db2lzcAF#UvRX*xxJN1MxaDZe)KJTRfp1$oht#avz71PKgVXp#X#9aWiYj#8dNCWO7!=9HP}lB&eMa?Wugvct4mRS2 z)MAfvfvIjA1_e?%Hb(6&1bDC$Sn5nsVbP3`T%!kFg1x#RX@yL~4;_QOs;0ZraCU@o zY+4REjI}KbIL0u&R$*Y53?Bq{-UP*%7YJ!lPn`1?hew)c9COo73~BtDC|Mw59}Q<@ zF42wR&p6#Q!ED}5T?WG9Ku)H6#s(PNs7j?rscJ+C%#^nRw3zEB*Q~j$=9u7!kVfd$SVYsms8Y@bE34U3*UlUVq&+*1gcgUxUFP> z@@YWtl{tewXqfJ&i|&>k__Y@H#PLcqB}_7CUC*l+0U@gUF(O0?>Bn17S?c{6b0}Ma zMf#D@wZ!vpcv)#kRhF7-sB<@Hrp2lki&;W^EF+#8(*%AktH)U@6Lv3&oj_@2_aWj) zPudZ_dnkg`6_tbC?XAI1U93adSnyb6!lipU`N@35&i!^iNvyYKv%tA?`bQt%>KYO= zZc>-Xlvb3hz^E~5IFZGKQ`l0+7#Ujd#BjgTh`bC58u!bxx!!?1$o{bex2o;E$pXJW z!f#Xql1!~~R&6GbU>P*dwwiygHduU_M9yp}zh4JRvU)Oay#t%JZh4UNLc&PlMD6Q2 zY_MW2L@;|{{g|TcZQ519q2pwLi-2IO(WMivOXhqpm~-)rY{2y!mbrrb7yOY|G2O{$HjQK1iz#Z)# z2_(ju?*5+l)cQ&YdOi5-)93JvHqGEFaZfPC7 zv);N1SF|R#&x4~&_Xi{$@(yzYy>ag|RR0l_Oy)%huD;K-e+xP7?tl5(g>n+S_wnz0 z#Qi|ei*N#v^%-(SuESXXA8q`8_!o1UAEQ;R#`sg^LWm5lQrV!hPlI~_0W<*(sgHNs zs>HLK0sgo{)T)&}E`)hQxSWHp z`?q6NDuG!y@MN_rLsJh}sz&V~%QDt!)lN`nRcjv5d#r{n(ZYLOPt4OYVGQx3pT2j4 zzPCp@5>&kH4EqXx@rcw0YN*nv$T-wc4HIyc?i8Zp7?0Ww0VG}liVv{*^3L7u7xh9s zF9%aYmor!}k^?5b7nRc_LNs-pAe#;{4Pi7j8C59)Au_y!usG4=)+pGFXBzByst<;l z5!suu3lY{{Do39Ayl&#!INVCj z5*pF3n?r2;l}RXggRZdca0W&K7s~oGrHlt?Dc#xOHM zQ1BwdV;jR_8_j4p>f&FuvqZ96mRX2Jw*Ihg+^q{TlW_ZN5IfXcVf>~rfGCR0kE00b z*RvfdeV8G3BSy?<3|BR zRahCqY;_h=5gpYjfB|iO_87=vRTiTim={KqF9DL6HdmFEU85VERcn|UtWY^Tu_pHX zhTdAUQcIS0{S*!;AbE`7kNRtKBp5*MXT*TP8L608Ngjl|uXIWlp%?e#C1}7Ig*;3z zGZh5P039);l}2(bC`TRSU=OAgE?fppQl~*30xe9j7|z%<`$vl;rO(-b;=XI&b@L&- zQBFv5_5>^b$tCI3gh3-}T%z^>M%vUW#I%nUJuX@1lewL8kjXR?ZX%nhOhtAqOc$tX zD|wG%9qj8=Wu~k;?>w`&*02hf)W{9hD)0;QUswI2Y@hPe^iIpKh3*)Z6~Pr$B1q>b z!#jaL8LCYa)0_iGRv7D~XP49KZ(-+H&B=^ey+AZyz(NlKr{v25WcCQJ z!^2}wob2LSPzyigcFn3lPy-%^4=6R-ngGXPu)}8-yW%#~b}t?)WURX=-=V5&124kL z>((D)_^jP>6Sh)A0(KO%>3IamQ)@g;2`*STpxRNg0;!;5LAKX|5aFp%ckk2^aIJAu zh059rss#-F%N~4vD?5(B<*%+in%gNF4jA5r_oCV%crQqGrw5YLE%{}Zb^~;;zd`kr z8sX;)eP#BAeYA^1B28VQmnm5bV)w}=vup&D&OZOjm_uqxQWPn;*RT1h2FGc}j4X-C zM<;!&w~yDKwS%42o8PO0ofGy6JdbaBWdXDFFakx-tobxQb5*0;X%5vpGb)bO1z*0P zb4(ACsS8&vkRV%yxlWR+esb9j%yz{X?pjTh>pZO>ID6GY>r_e$BR9`FhkwHffoBlf z@*tA6Y4r*N4X>A!x98TcCu+F=!fZC*Bwzinzln1cJRAC@`N}yu-tuUPZB#wvGFyG- z^kc~CW6A4())5f;HK`qw66?=5qu#;H=y&0@w8xD+wEopJ-ov~WgI0HZ{K5-2NACwu z_Bsx*vuD&eR#5_L8%T3UNwLfgfpzy^UQH5}=#A_v4pJLS^T=&@+GIynS*aqPMME*} zk4Kfx!{!keg?5M;1Gr9Q@C8iPeR*rYyN7g`gGKRGxuF0Ccp3MG=t6j+C+&DRCrENs zIYG_)6s!0-B1k@9Ed~(lByjzL`|2#c4$*B=`5a;FL(B}iH2vn4XXKT3 z==rPBr3KZ4x-nTa%_fGnLy6Q6!dFi-vUxRbcAXX{R z%3R8Ihsz_N(O35R4CcZX9p`Cg@G`w+cq9yK1MQ*NA63l3Gg_grp{DG#oR;u_+?;!D z{~lhmAacN+SIpkMRKNYEW-D0L%CNkFeUUFi@(!_;Eq(cwz>RPle(H_7HzVq?X|0W} zJa{;u;MEX(FkcvaH#hKVX7AO+&MM(!;nx%K)yrPNjS<$VBq2t!WDlfaAk+}`2acV~ z{vVL>u*mg7r6bPxk&S=&s#Kn)ew7S}&r+X^)4l#>Oqi?aaHpX;lQZd&;U6Cr$uu{; zHZdoz?tOIAi^8mG+d=hpHp)LQ-*9gku?<2NY)T?8dh{R_1(jHYdY8)GDc6IvI2p|#L0h=Jp0N%ivDtU;EN$?JrZc>M4qBg zx)ao!alM+=1wlDuyV~d*fGyNU_ZNZf+l%$Wi{{ybMEuiP^I)}*Gduu8(QeO&#kSU) z8@JSuE$DxO95O_TH+iJR%*RF&aKuIo3oR?lsbTdve~d1viE%`iZq>xcZO2x-h_8mn zaE$q96ES0BXTmmOY8yFY19NFCJ#tyt*g9&;#?{C*EqSEoM8MI~kztT4*h3qGaxv|h zp31Mn?xG#s!;}#;PW((ydLi}le7++hmfnXuN8#)5mcoPCO{6~~2wQU=^}s6@R~|>* zDPVgRO1%a|&sN;0LiVY?yBc)Z-IDC^(IIEGaRwTa`Q6ly}FdU4iZO)B)-);-KJF@Vv{4Y+xQ0)M z*7!_PkjrRK<1o&{^J;7a>6|(FE z>0N-AS{E%I!p(%}u&P7uYpItOcKo}sDB!n+WZF_%+WB=LLo?FIawU#vJRKvhK|L5ZMIv7HGWr@++#$?-3bD` z*wc=~`I^8JSby)VztK)jmrj2#F5i%fGep^m+jZy9x97(i=&*YuwCHEBlvXlt15@a$(fXMh3?LAvFQy^ z22dM+#TN3$UNwOASxsLpL1*up%e{P|2G}l+^CcY(3OU|Rmb;O9;35rJeKh07| z1mVud?^K+qV7I6G1ZqvfLIfg*bsr|WOIVi7XNZSxnW}Kyz}V$JjOk2)p|S_QZIuY4TnP6&rHhk@UnEnKqJEZfqXpT$NTVuh?jud=n#hVKyj80-+Lj9V~MEw|T%HYi#0exNii(&6*B5TV42QqkTeUP6&k@gY~)(rb|j)vf@)RN>j_N#~ay6)Y)45dO3j=#9bkq7&s{SC(sY3b^mqq+glkxjT^q7)sFcGa6WuaedH4LAWhtlZ zcr8(Bj8<;xdE6q|JECKNR%vBbaZ&oY+#*rC=(?%2Li?Gyc_pVNr^&ReceS+K^)mgO z$us2*^X0=Vx5lUWWNkjjw(}Cy#ndxD+c2s|1Ic%JgpPBXF2rjcayD1C z7t-i1mEn09;`xu~G7#4=P^JfU9a~dyCT3vf8&(_EpKE9aCrO;PcKJ5#13R7^Wy{8S zBk{+-UUJ|5aht3D?Y$hgsNA>C&moSx*eB7wWK=XieM9dpYEIhE4s~l?ZV!V$JYWU5 z@3hZ9hP^6lTz$qnpySV5ZvSaO|HGKs#qQ?J&4|}YIT5P<+|al3NRfrxgwrk?Z%d?Y z1zx2ZAGFKO(Ld%?O!OgZo5r?TSz(ub6Z(16(cJ_<*5j#2EydtE-6$U1*S~Z>{5);c zvYlR#rFD1)d{wi(@D1M(^FEk!zF;1!-~@Vj0rJoKX+egHmnY2PwVcGkQ?~E~G@7GR zi>p|d@?_7o<;!I@Kt@I& z?RnGvvR!DzBA$8ulX$k8_uh!RzNvh7&vcgN`e^j-H17DE1Ye~X(=cd8HQO1P6-J^t)338_Km&X_6?n?ZLA)S4UNzUT7w*Dt_M^H7G8vmXwn!~xo3j4z&63cM_HLc zFWX>ZW|=i-M6*y)s8jc1T1qr`FWXQbuxd^(7p&q;vmfoV>rmQjV!N_lC^74h+IwQt zrM3;KF6e%Yv|5P96lFxQaLItiC&p$45SJ2*rVw#O#AcaPoh49o z^jwJ>=p>M2J4KWPnyk%Pn^Gv1Mmk2{Aa)I)Z7*(q)(6uIehO zdvjB!$e^ryFFAdZ7T?kHDT#Lf4WZQFap=$elWZ85kTE`)U}wZ5U>mm35V~b>$hwHduBLJY&tH~iTV52Sm8KVr?CQHg zoMu*O#7iP>dh7x9;rNm2&I}T7s`0peEhM;wE3uZA@f!EFiK%gKnycy z23z&oInOD)=bWq2Qm3bM^m(lz~w4nySwm@ zr#Q8xHbeNz#F#iY`O}ev%)YZi?vUV5Tom($vx#}j3a1tq{wJ02Mzl?MBi^Qd0&S(d zt6L)rvMXW1=Lw1q<{6w2m;K~^zJAB|AD92m#7g{!Tpog7T z5GwIiYP_?@$Io<}ABXct;!Z8$78AmG-p;5KO10;XY0(e(2~db1FUercb3HWkGElTh zOEfgCf_zl1ihMYi^c?Bj`ys z<&`-h?mL`>*>JW~n93#!+2x4(wG7go`gMO+M*w-;tIlRgvaxr~3jquc&ZEyIPJFa= z+2)0ayS6i4-|-n}e}x3aG!Hp6GF*931C9p#IB@d4zIvVlFCm`qgs8E<1OR-Vsx3JFZ9%h3WG{-Mvr^RF+wSEtJ@d2U4#3|xeiCI8UOB! zS77y7!1hFP3(}k82K_?F$H~acK+hJ$4h|N_qo)Be4yeBkRNVhKNNj7tswT(1luW*K zOy4enfm0un>44gQQ+&j!dtqAsm4`ZQv77L<<6X9)@$jLs_;`>jW1{^aht0S6 z?l{~+I`Fpmc(ArpUcQ-(J3GfyFKk(WuNI@8UW9w{u4FG5ZV}v2va!Tl*8BQf`@@4h zq@P(8vUu4LS%O@sToGOz-as!>FI0flEB1Z+t^47_9`qR609rg<2pxegl&(k*c29s8 zi5CjM;uZ70`PTXHVh?MKZGbJ_HpG@-2Wm&82d5{{i_8lRVDpN5-+k+S_`U}|20s8F zj~9YRzz4-A;)CrI@Im~63^0GixNp35JUrP$8>1Vbi#PUNlkvgu3I3q`zyvtI9vrgm zvW?sJ=i>V!`ec4kye=Hh^yQNH!hLZApl{K}bpv{(zMwvo?^kwf6MKPt6F+EPHx6(5 zc1V2TzkE!30YHGz+t@L_5MO~WiVvpynLXV&U&!x>56f4!!<~U%qHo+U5J2p0?wD`L zx4;+G2iyJ5o^RYY+W|6>pfWq0bBp{A;qnd1N5eZNUuSeE`u5!>=PB( zMRC5*uwFOwVl8@AYRDT(;M2TZuR+}o#p+B4R_!t&z z(?D;p4|(*?Wns4A1wX^rptm!-;JfJD3A*syecce;88$_9fLjx}c8d>X+%ViZq&~y? zeQe6`7*=OspNPQT+w*;fuz~R;bbvMvv9rj~^g^|Q%D?Hi>Lhg_6?^r$)83#D1{Y=1 z5T!l?A@>+L0;motHzltF-^VTW&e34rKm|Vo_pgV4k4CJ_GW7`tx+@7wOO+ zp+nw41AY4Cdi7Y<@A0k?*Aemlhr-Fl$Nr; za}v|1q|*AP%?5~q2nk7Qyvv@pYMOg0DmQGlS~})$ZZ`y*?UUD9|dQV#Eh%9(?(dAsE{W@VZR%5>DAZ5Ao2 z)upmSwu6O`-&@_JhJp&L-`t z3l%E0H5yb=vALKPs?_BSk@sa;nQ69HH}dl|EyPH<#EypwAvGHCQ^Ja=II5dks?u#G zCo?`F3`KCY$X^b$+`MLAyYL7y-+)U?It_S~ikn)BOIlQpQwyYevTsCZbDo4likUJ{ z1yLv^E@Z%(8L}ftI8Sn8a;x$ydCKyV&y1v1iItNjgj>SjjA>YWsD}!;l?o*EMJSTr zFFRiu@L1dzv(i~Or`aM4d92IT*vP1Uhg{Uw;crxAxD}P2G(}-D8P$U~H&HA%Qle}i zN{-S-W~fy?8~`sK>4U0JB4=qSWQvJ$6;i-snswlu1n8f?+7qa}*Fi=5WJQZ3rbe1= zjhj!8t961~dbO#QB&{kg!>*TcrbmeqLBcP;+l5cPW${=J;`1+U%vWuP!DAUus6QvU z1T!@#8B`Hko6ofmhRUR~t>vI$9Y&4NmQ;dgdWTJBQ9Nf25jMPiN$;f%6Z z7EP(3qg>JGD#@&`kPD?8lk`qg8c)VyjbKrt*0P*p)gnUn}_G9G4daYCh8)_ z!WE?ols!8AvEjQ;j=nw_7vvX-_W&FDZA2X8s4e1kyU$PAG8Y0w_x9QmU3@vruYjfg zqJv%F=~-meeOh{6|2w?UYlQ&ibeJd$U6z!y`&AXJaci*#Z4@~oq;y{b^DG0a$SWDcQxXE6aMg} z`4%i&`HWDdtZ63x@~i0yBIz;BWGI$zUG({TolHR5LDH3RPwjLxRNRd0>)Z;oSk^}ji*)?KhTS3#o zj2heEJ8Q-3Z;u|UHCDX~V}7znax=OAFcv$p|9SY(_&RquYIKJR2%zTu`xQm~C3PRH z?u7uTSMNGy;*HGxTf-iiE0!aTe0Dcanr`2~lyelNn004mnspv^!hXQa1Xgsz%DASU z$#8m0z=WDuaMJ#eeuz0{9%C3FO3$R`h29uYGnn=n*A9Ym-#Ydc^$=y3|BuB2ExmeZ z2^{cFpY0hY!(|mTV;`g|{BPQRKzwg+Fb#{EBg(yhp#OcU#nj|EUGK(_oIwanLTa2L z3H^XkLrO2tf3$4a-r^3#;!ZH+Sk!6k;Bd{DW8JHtVF~S0)cK!0_1UD=H5(S74tdfI z9y!1LczQvk&q1`0D#mXbS*{lgD*$}XiH;k5Zd25unm{wCYcZ}`pap}G(kPXH4YGYW zPMkn7L<$-}B4~5L6?Wy_U-&v9uf?M@JpD?k!bQ0(sBq%`wgrH({A8O4XCts!>O5fQ$Amwe{by3ux9K{a=`-<6PGjB!pB~u{SyiZCH zX1r?j<4XTTt7WNBn6gtd_#|Ud6*6>HtM!1;>oet^D|ZYTRY(`gz{T+r8cc9R{|mXQ%|b29t$V;meaH=mqu zSo1uQu<-{XHAun)XPA%WdWxg|dkB0lu>`dJXXe$$p#gxs8D)#HKzgvz7F-f-pmI}! z@n#fKiP*M89Ho#um~O!+!JboHBA2bngwYc)Ps|TOYLTC(yd2A=T^*>fRde!pBpuMg zG|lUf#Xr5vdn9s=D|$_BL0s9D)ESEkJ1tRL{XIS)|3DF$YCx80V|V#MuEzcD6Vtn| zI9)p2_UDx`H#7T%jlGb2<*uC}l5gpunYzPutkv4fMN(UWUjiV`B5@_Y2B(yXoL5Px z#$E5+vebaaYx4MoZfqw;RWkh0$!JwJbr&?sq+{K=$HtM7$;h*vY%2b z&HmcT?jnLNTO-gN{mV}?cvOMPwFufpQZpp8@84nTuZeAWCoqUjSC`Wcn}(y4#;Iq*sJqCbV7V#$Pj z{-x}N`k-zC1+6x2ijq6h_woh|{{)JA4UPSCok4#{>h8|<^u4?Te=om~$J7?v@Li4` zh~6G>$~PM9XV(e%lfB$k6~(czL}#w!m#9A`l4 zML<5$YqR|jyP)F~)OCdWRnKd53}-qLd0LEzSOXP!eE4K%TV-%OTAj)?h)Z9}e?gEaAbP$drH?`HvTL;B?Bn-Ym_S>=@ zoV_w$t4iOnXbYqCGjr3RfVa&paQbv?8rxGu+Z{WWy&aHu+a8aIkAITQ3sg=U>{RD&$HpGFIv%$|Z3Wl(q;Yo5Zp9)wIR*x|Ek||TXdb=q(M~46 za&0|aNC{YVBV^wm@h-?8rP(r!_JOVDxXoGsNl6Gb>9Nj``~ z88HQT!W_6WOs`leOsq3chD|P`~wxeXa0BgBm&2vUjIfFG{$a<@| z?Q!B5Y1j;wpl((px$~1bsJk7E6y+{ca94Vz;cz-dsc}7LH~`9|n897hfnV#o zZ@%w2!q`BCVLiUF3hv^V&wGLUyBTzKhr+w#9oX~PuK2Vn;SKWofIpx6 zZvOFDr)0avYVH}P4?TqJ;6ZOkvt99@MH+>|3GGI?$^yzCaW91z8t{G^#X`#J^e2CP zGOWYr;G4mH;r^4b*~w9Z_&UouqN8}a9V!vFxAjj0agAV94OQ|980tqy)o{tr7ucF}bI96=#VVcT*S456#pw_Fl!8bpQCS zc<0dn29@-*1!4ZWmUG9{1<~jTu5*C%%$LRVw49|XaT%}Psg`~~qjQA(m-Bcv!ATe- zcN8jtPKY(iyv?YL;4vm6WzonFm+1iL&7=E$E)y9+-#j&e}HehL12d0kExX0`^- zE{-O2O8@;&(Zs;`zhi)lRjjO)OwfI|pBlH?89DRl$(7*yYN(LmA#IJED)WZw`dCBg z>9{VYn*%S;xOuYU_~}7AgM?7y5>PONS zT4*;+&8k%Y3E8buVOc68dI4nXPsRcE%Bvp;By8P^li&A8sxe%pkH*LNw9JrSVNOmG z26yDHfkqD+?)_$7$}dsjH66al&I*QNS`!nTdyDdA%1#60opd!qJ*J1hPJIM*r3Eoe zR)9M;%;En4POW$(@6hywh~cLuZKSl1?6pNPnQ|_bxd>VV?5cCcr5?1|eX~Y#2%5#ihdBhK+ zG~gSwfE)GHM7V;`vg=P>Rem24(G981d~M32Uzj8R;Ae)$v$*>;S%AREDjo+gQTbNYGJo1(+;#byQmN7>~XgUnE znRW4KNj^ZOT2&QHhX~(-)lfUS0xrBnO>B-?(N%IzludbJh4RCu%Uumc z;x^yBV#FI+$$=xDPN3t({yS4y#$uYdBVA=Vrh_JV?qD30CI6o& zeCWd`Nev6V<^B{lCy-42kyTRec02^w&+L8_ykr0>jmf}2?$D#WyeXo(+Efc+o5l#P zM5evJ<8OEg$V`E=k~#2^3&A`1v6oe7?FvG?;I?Hha{vf}naU`c1P|{CxGkPYF${0% z;!rF9i5NC-Xv-P-xcezLBpckN5V=vUC9)L6wSKUNbC0mMr`OLc8~z2kL+*ZB<~zU0{oUB@7QR+9G{`p9&O6CiTo#{p9+6row{vWHC@kJvlKd#v+H~eVXzhgLAr5XO-oHur zC;Ku_PgdRqQ3_YB1O3=f;i3zstPkyHwGPk*U4jC9a|euVz#5hbTwvab5_tNtoua{f z11>+t2_YM!ObDc8Y^zMd-?KvNh))wg6yY{1Xz$u|1ue{N=g6Bk;zYtZd}c!+?WW-W zh~9!b@TZVb?2qs7`pKsdPUrQ&&xqcG{Q8yyBuJr5X`+^LGQyEEL8amVds>khjnRRA zE2dR|9U_g8&&1)HV!5r!ti82#tty&*(zV@XNxDB3M5yl7wIa>P@Cq1|zDb!(#}C$b zSvKy$F|*IsAXoPZGRHY?q9dEl1q zpRVHYfJ>e& z(3mEwW`aD%nILFAGUpTreli#(4%B?{A%0GdXt`u`H9**GccB*~BjUmC{&5V_)^E)I zW2b91DDWwdi_!qG~DFM9edwx3yg0g^}GVvIxyrHvBzt93}%J z5PAtkSu9dY^BlR!Bbp_K-j3{o>Mm;iQAy`0#V_Hrm)JQy=1WLHFsYuT(vLJGe-kTf zTC-}UtqBA#%Ha&QAihtUrKGQQ>dxSk71s(vgUC2(I$QS#aVcutyO7plRsgLYmd9nhPlPr2PW(XN1Vz_V!!F68cry%yf#5 zO!IxBIXqPvZxY(MR?KL=vT)K~(hPK#uSU^t;sZA`+faWBEMq_YtA`w?p6je@U#HgB z>zN+JIR(xsb3wK0Mh$VS3X>$7zzfrOEfXReWfv)`atqs(`I6=;r%KDRGwn;8zFF!e za6}_yog*u5ox?ZBx4-)p87%>eqo;>`_9rY#LYi?I=q^`=QV@iq(UD7lg*ks&ZKfHS zeK?e8kd=+H6x@R|nM?`?BT0##01HvAvkpM%%K7_rq1aL?NmN=KQD=GrvNS}ekbc6S z6Mx5&9iv3ZGfM+l8ZGMNl8NIOoENbM3p$^|v&gd*{%$G&@MZMk$|&&9VaX3z=-*6^ zIA5MFqq@5A(q6aHSt%3&I8%wZwl}UqRS}OCWd92|4p!b= zSla|Bn$dF01G{(wtEN-XDi~R8ypUzrOa(bVQvI^Ge8Qv2(88o`&Ct%YwVbmD2;LW0 zgu2{xdzO+M2Q|}l(exxd%fr^(yRK|mGJ_G?cZg%NohD037OE-2k$dZ+Vs99O;?za* z4P#4|bBp)5xH1^SB#6xR8C5W~abGb9D~|W@l)#q2I5~S`BoyoU9c-FIgsGoHPB8!M zF5xoEF$c}caFQcJxIUvMr#uDK0dHECU9ASw!$p*;f;ng#5IFTN9{Olp$%*rT=(0QGAZUmqIm&jP=(-j z{VV~-_~%|+G)ISAG)IUFlR??pz?vbPtlHkQYO}Ult2TNbVK}J?4);I%MxHQSv8|{* z;{ZQ90i|ZJq0yOs6-Qw$BoJQLAnz(Jhx7KZvhCz27W2`F8ZE-6F$C zwlhleSO{t-x1QA^-ihyA;;%g0e*D-@mXSH@HVtuhPu7II`zcPEDM(0( z-KP@h@KUb6~Z_ByiISgUnP4x!oD5dwHa zGHFkAA7CF?Azxq|8t=k4|I$h^3v~n+en7SSXPX+||2MFj+Bw=7IMWH48#o#mIh!~N z+1a|9I67I_+5W?wmaVLygr$P~MN0r_`Sscl5IuN^{?gGvc?CKbY6q$NOch7Ty?bv(+u)Cr(bWBlj6o4)iJfM^JH^b_ zuJ6**COG=QDOJdIBqT!?FQDyVPMZNEc4m`~)+9qv<6dWkQ5gBDFq%+l*{Vv2akEXo zgrJ=}MoFXEpafU|Kd>Kp!hlD}Eh`|=slh2rrOH(#3Ehd)L`syhu!#@Z>_lGoLkUiU z^pPcn#-P=)=)#fGbdvNAMtzpRqTv(E;K6?8f))%bWfR?JySG>X8_y6Fh^ zY0A@H{DE7rZW{M#>SXuud^xU4SQBa|hbg+1V87c|+E2UU*TyKx4oPO>GGlZXgn z1Ei^aGOGd=p%4w#gyoLeX@Sga#AsP-2nfi%IKzXIkXESvZT`?Tlp=acS<5$5A-;yp zYD~NXwk~USmjzBxhm;EqAx-HW!5qUgDLU8YF?>NsN2Ae(jP5>1?77WR3_g{dbcurz zHAQRq5j^_o4oRoz&Jnw!Sj+)Z6*>BFHT(^9BX@Catt;6Q|GP454}V~@?y-qJhGoM6 zPhJs9hc*F$#F!?}g!5gAU8YFrP6E^vyH$sGd9&`J??OS9JIl_##l{|bLG;h_?L;aa zx1-#4`+ zc(OLNWaHi3G~!z3F9r0HRU~??7dH%OtCz5haKkI61d1A_6hZqUk|lt7LLphWJ{))+ z0buw7^3T*Oeuvxu=_lV-_QwJ8Z)Dv5cfa_THc_qiDy00=Ca!)>XO8@4yfTmo1`LQP zrvNPpu;vVa*h{d8-2;dXc|M)O65g<`8+x*C(9yDHaH2piwQjkyyD|HYI`4>OFx9V6 zc=P9Y=6c?|&T^Y+JJF^6a=7CDJ=98GySkXI-$-SC5o5#AY${5WVYDW|Wy&d$B|-~)`lY5w4pHJ(g$ueG zCLFI=v_#-LMbb`rV8=}j|B^{U%UPMNWx_(*NGocp0xMI;vNk}fn)vBRZvOy>EWpPV zOua(XONrxL!noWDB=b(yJJk`^$t&Zxa_I&2>fYl?Y-TOfQe4)zM)Ab6)2;Gu&3@T) z*(vz4boM`J4eCNhqae*+a0qPYftrS_YkK*;4~)k`aQ zPR<*vm2S-;FxipqQTFxMSiq_>qoHUbfFj>V;&~>9diAy+&0CX!46-z}Hij{XEZM#- z$56;$k^cOuxyv)>5XBG4l>QP+Ar|Z{3we!ITd|JHWuwD_{??@SCEK#Q=Eqos3lGjt{76TO32^;l+ z4r0U0Wt(wzzaA>EM)9ck0_9Mma8GjdYUH(`Ev+(Lk-#dLx%|BF0?|HD6kqD3&6dhZ z8Kx#4NLB@A%GIiZ-lkZ}*2DspK2($iZ58!C*9c7zE?`yDRurC$>R^wIL@B@02pw9Z zQb67EN~S{1=NTQ=s)7ZQMr7ymw6hp66m(=Ql+8-Rn96yS8~t!jkWb3v_6k}M1(czy zR;|8YB7p${C?qwKO7?t1njmnd-g2amJMDeG6G>)VEZdX_j2X8UC}G9h$Dx@DI6Sc&7>63X0dLA;D^}wnB`1cR z8TfKWpeS<&BCGUux)U@_yu?|GB0}g6^0)#26m{0J9}QV)Th%rin*%Z_F0+z65WD~6 zmfmu18^dAnT@P&lZsXFdPx|gQFJAg~Mm{^s9GB8=r~?Ep^R)Ab3(=>Dji6$ae+|IyB<7HN1X%9 zN){*?p_W)M9iaM>p!rVOxKzcr)#c{gT#aC4B{vU5HOmNONwor9)|0&6UXJ2sohT6} znIf&WI6cIN-ag1@tT3POh%)e$N|7lkX12mr)uLLgSPNZ*o!Z=q>84cuJyzEXwIyS= ztVB5|FJ~jZVN36{vm(-Dt`KX8T>Yqjl>>@CI_(qHxyte3OMPln|QSN)v1>)69=j z!J%m4CmVM*>PSSBWQ;PPo*7JYgcc{Kp7Xo#7G*B2q|BlGs4RtOFJ_s+H1>ja7jc;= zb!EVqd7rZ?G@zXdk1obO2h~s(8)joV@0K|QWEo7*;U%0kM?`8jhTjSsMA!zg39NaT zA=*4s*bU?=#t3bW2hk;rofEf`b!XYi$ z89O{VU&b+RH>&4ZWe^58Q&_AH5s zAv68ymNhH-g5qRfbW>PEnj^M8s2;hy=hr{O46IB`O4AP=Mg7ry`2THMDs13vqHJMf z^1oOqF~k4lr7~Q$f&%dOH)97#6wZyvi`33xDZt@?#lNAbV*zkAO^et32Z~1l9LWa} z$DQkpwVJ74Po5rO^rL7ENUdovv+FIG9}@yv%4F#bm(sU*&(|`&o`*BDP84dY$|D%F zknsht5C3d~(1AU-@iP{jECWQ^<}HF|P;peR!#Rk# zX-7852FpbxgO(Qpl3Sb`*Azm!{0oDu!PQf=dAw+~^)FKsce`e-;-7T+!=K5C{C{#J zLMA@}g^nKo>yZ9&MAb@La!3O3-!^=$j#-Kozwt!s3YwK$2@CjNXR`>(SqFiM89G}V zr8t~6(=So?a&P<4a(w^_hV6{@@l3L8Dp{7n6uS;hUCm7Wde+j{>~{3JK;i~yLOQzT zU0oJZ1jqO#uGDyH04*jm{%qP9*nv7`QoX~f874o;?p}jyxB&SLB6L@bb)^jbGD^Eb zp5ae3sNLfIO1riX>1O2&S&MPXrPrr-o@(o^L`CmEo6HEdO(P{dH3%!CX&INN{_5F3 z48IC@_G$WYUf?0Pm)C#`hwCKIR53g#2RXKqeK4j%KXU?8o@cDH9C<#;)piE+5=#f! z2N29%vCYc45V}^#w#QMZqYqLb0kO+;m4|w5{#gYvECY|=oq$*BizuK{Lw`FHuR~d) zM>>L^P8Z+j7W$C;;}7MmgTk(*y`7S9ZLvSuZnQ@zDqUnBPLQGNhMC<_Kw}Xy277Lx zpOls(sTTg;sf}uqZRgdTaY{KXZOkCMNHQL2O5Auwk6sLlIG`*BGY1~+Z=eqnGF13u z_$ibLKWCjs4|R2dcKQYsVQ~wn&kH99CAq40IJ<+9tFr8y)pGW!)85#IueUhUUAtdO zk+%)+(}u9DCr;76tcC2RD>}ISSyj#;{VI~zLtlNm<&VpBX+2LcKQ{-YPG^B2m{TNT z%D9gnlbBQ3Q)%lVgx?j$2FF*J4VpcLyKiiaXSQ!*$BV(1OC)kPM-cMt;Nd}yJ;O8F zEqcDU3c&bYtCvTXS;cjUdO%J9GZ#2&5THmrN!p^TGeFFsi9X^Yt#q4XWDhAU(W34bpxjLatjS3j6W>PP$W4gAI6wD9Z4#wVw)rfw_S}h zsvX1B3{rNL>X=E1&p2kslT0+z{MnoBMK6JaEF~D6ZQ0@L?rUKeI@z{_)|^|f=T>8^ z75TYFPt+|^3prUcSFOl0j zgpS{BE}-Tzmlfg*mw@+8^|y}%jX4O40f1(7W+_fb8w z*Tc82*A10+N2ObINe+gn5HDzB4Xp&Gi4?-Bi|4%Z#jxO7x>ay$65 zkqWk!p5FE_Wfzj5&(KU8BPJnw`AnqE-5R4X0MJ_yRE_{=LI(H0VIQ!04T*I{IH9mUgSNOguGraQoA1{(9CS; z3Hl(^;BA8I5z0|#epHKke+T}G*<3&yKOAb=2IS|z*!UG^YwC!9H1y1$w}}4{oX8tE z{|G_0|7Y>o$YHA>`_fW#{jKd>4~T3u6lw2tiD=SHr6i<*)FDTS2%vLW?W$UsoQ_-T z06}8G+=(t1<-LXasH&4PMAG9;e<_Tb$<}eDh@69G8q4;Y;W^=$@wjSxp6T)Z0_pWQ z1U}|2uj&s$5l4BUtnCW0qT;I!C@9V9Y-Ihwx1+jn1?{mG|A*w)AZ7)xjd>OL1EXm70eTPweXVyU2qkE z3}f*>H5qYQyayypd;}1p0*oHZPiEJgwImE^W`|}Tnf(pxALcni0baE5ovT~4>H{3h zB0~VGM8+#Io!M9cLz(#z+h*2}cTe6{-Cs|OO*G3dh@X;3d1+>y3Ya4fn>>b^e4uG^ zA&ecHHzQ0Z3*n5t&2m%5KQL8%{>qL1iatF!8#@BxIiQohr0IB?N^P-w<1lAnAQ( zt<`ROul`+_EjuK62o@>oEo7`Qm3@+SV}nL|v=N4b%q8jLSOUmB_A$w9R{6uP4ho$e zj0bwgqe>$CTXnVM{?_D)<`je zVE#{y2V=p8zB-^Nk!^=)fl*lw4}`oI9^TwK9rAG?+Y6w);k&DOdPDZZViDh>@-l-Q zHBKx-UPRx=H@NGeVpsY1p|flQb(wxwc~Ecwd(uP@#vFD~g@DK8@M^(nWRz)@D3ec= z$M!os&MUv)CpJ`epCD^Q~PyE#Z|4J*z4IJJW!Nw_P& zXDng?E*aV)bKYxJn^ue=7QE8tyrzV+-(9HZl=}rK$F;XQ%q4`yq|_xv#Fz&qs~2U? z4eK`5ZZR|HgJCNgLdb2EZC=l#ij_&$`Yzl9gIV`zw+Ar_9_v4>+#|O?7e7$9OC!K$>OV8m z+%O(ty1IWnm%dz+v;z?twFpoC;2l(u_jdox`Ed#B8#sQXXxbksTJ1kU^Z&X6XxiDD z$eEftnfyfL|FcA0t*oPjB!SG6{RhG*j)5wS%D1Y3lu-7=5TxJ=Q=|}~xOR03%mqK2 zzGDEIsa7|C z)b3J@pTtt1FhB2{7?k~6f;_!XXaM4B3`xUklWzQg^mHEN1E{rZ6hU23;r|RptWujo zI6J|#9v9{SkAVahhf>S?h>1>!vaF_ZKc%a$GQe)QPjBr%knY+_=g3phhKsbCvG#iu z0>@r)*Bva?bk}VAt7}%}u3d?CqQ2&Z37F!Zd{{aQkW04pBLZ-E6Em!LECw@#5@gDk zbkTb2aXevar6(R0@RnqxQYvSvCCQeI!v4t$>)A;zP2`;S$SHbr2I8;>B%(_Ld|Yt> z`WV}87(&NvIg#xFe^$xSheJazE!n`T)auRu&vCKi3Gn1u9`5uQgc_Hk$WE$3pOYnv z#sKbJq`-GU*6lZlca`>9Bf|PiK1va;6QV%4QN+fkFdOTF?oq1w)rU+Ru6p%h3ow&; zSH6mMlPBg2L)QS;CnA>}sambsE<(cc4dec@JWybwCr4fi0v3As<8W1{S@KDfPG?7i zkdcFtSEs+W2k~6y3)FILveC319MW~lP8SB|a`ypD6my*3iF>$NYTU3z76DhidEHV& z!%HxBhXYv8JXRlm;Y>b%H^-qvju%5sed})s)$$82eudv7lOFx2rBPnPVJB&VKs^iF z!<1ixP{Yo9ga|I5h1^8zh}ZL+b=@o?e6!(&VH41w>ce9tWC2!F3^5mt7Sj(jB<@@i zK3b}GJpWv+MFc=eu0KL>9PF=Oy#GP9{^RmloT?>{WQIKQtruphqX<0crKR*|5A!A> zj~tYqzrTyTF+!@IxX(B+69%%&%IeRPVRce-^ONM|(zJ7cQns${dV2RmHIvV!lHS|u zO7qFa6z$yXT>eC_@B90-+w|+tZ|&%$r{@)wpQVOzk+S|+BF0@=LkTH^l42~ah(tLy zL$T3Z`zeZev9-t}gIMOO(9BK{BX!A`IiI~3z2e&1<*9-@B)M(9LbTW+Jl{5d+q%j@ zpFwCNV8zQsM5-KVEe8@>gd;8AtB>{NKwmJPOH4GOKE;MI*I>zSim{P))es*uQY3LL z1ri<7uK1hGRwtoktRlgtAZ$M+5Cio(oKm6MpI}C3{aP3zC9>8CBv2<(IMMm(E0|MZ zMjn0|7Q=$dG4;(u)U)fMaDZ9c6ih(~BUtVmK| zJqPFl9s59$S|n7I?DWah`rI)^y$k8tpbH$0m44Nm7a$WorK3UEi-n~k=pwq-8bJY? zE!cv(Si#41!UZ;VT%ejaHR+g;Y+QbtO-(?Q2mwF^I?7sYAv&iSF?s~Vy3~u2LZ1xd z@8ufV+&n3MyvyXBcZ=@wa*198 zK<_jBEg=E`xCD)M9251!`=#3(Y$Nyw101+{`atw>bUE4x$uLtO06Fr*JxdA@VcRlB z__D)wLTIZ|7&MO)$YAXf%$1@Ed$Xj?FexMGi4Tr&iM96Cu;d&-H`FE6Pf>=YL!~67 z&z70+~qAE+Aa9R~u(N_SD{JRJq07}|Yjt#`b{txrc4|7HIlY24>=)N#) zZeMcDc|uuf^a)aoyK-@?C3{L)ndJOI9=m1UD6!U;!o^Zs88$FnvsG?6fuv(o(m!nr zggLz!^<(}cQti_X zEJU3u4Lf79++$Opkhe=!os`(@cu|r@m_Kpm1vs3@qBY&>Sx^%P6elA#tItEoC3pwL zxG_vmHv^XQlP2+WI@k~rUdu_v8}$nKVMh*mzd~IPVksTPD0!(XF$kYX6)k^6iaRi~ z%7W1fw&4p>3pa(Dwa4M%cdRb(z8i|@=DDq5i#2LhUlAZI-ohT)er;zI)rC)|Hxw5J zHi|X@7+aWSOvt<6L*B#7emKw2ll$9G^@2Mr)}1l?{`*r62G0>Y99V>o3*3CW>p9cCTuI46V^dZkX|$*_!E<2FXsirs1Lbi2O*Po8W$`o z!>pg*8jf2lKPoInO`K^yD#$~cK)q;IkQc0sG=^%)sIV$XLmHt;ZeDOe+U}_&3fT-h z2tQ+dsA1W{&jG9~&#GDw;fuK^fcKe-APPfThjK#RM`y&I1a%FB)^*&fMgeV5Cg1z=r0FwTgKY zOTpA~sOz1S0HKm>DU-=Dt(*`Q-Dcb{1tyPhPb>(fub_a(5DRzu@B$P3I5;nxnggw_ zq_Upq(Cys4yMH5Xp(0Nxnnc942hSzyDKVCga{LxKKb*vaA<3mD&s!Zx=%wqI?Hth) zqVDv|BbCL8?_*Lt+1DMOy)PzJ%>m%ipp}2b-L(U6G@Ds%wrNR8yqrEIeW1*Py9H)t z0|;I5tt}?r4NTGPts9CH*&=^-9`I{xfLvHoqKHvrYA3U(vEB~KH8p^bTGW%l#N^$l z%ADse_!M0H_lS6IkPG^-DX;~ta4C6WH$sGGkZR0)1)cMIN)nl~}1Q}NG@SQPTtFOh#A(M*giYz(X=Y@JQa91X1h zm2DQQN+}_mA@krxK{w*?3*&mA1BSy+_L2wSlY@gpV)%#oi!=Xheljxudq&E`1MWdf zjkabcMCrA>2Cb}^JVL4Rs!*Qw=S0LkOr)&f-SK_TFd2+~0qN ziZN40YDN05Tn%!oyY*!bi_rjlS-Zu02^*n2#<}*QLU3NluL=;r?TT~+^vF*+*a2=L zJR*8@&nZi#uV@kOwlf$vT1ag!5kvSUz>_Fx(e~{srfb9k!JL zI2rPkSz?8rz5@JGRpWyVBur=3=jPL;O~_l6WQ7M)o$o*U4Jgi{+bCT7NjHY&&7{Mz zo1nQ+vLpYD1+i5f;AkuFT|+LW5 zA+$Ph;+P?~On_UI@t5-JyuJjhj1+4dFiwy+K%F4cGr*BG+y2OSQYt%CD z1%!8s0)Cbzq(rkx4s6@26Z$XDN}tTZ$ZPT}(g(zX0KZxt_S7cFaG|=%ikY{?l}uCA zq8hG4;u)DQ|AqD!^|?PUHn@TPGD5> z*IF~QaJvnm%IWEYMS=T$=xjUlXkb)#YH#Vcjxn-6tmMKR&n~-Z#HSrsIbq;|#)2fJ zFU?4wp%!UYk#gY~F|^g3y$q4YaY0RNL$+d1lN6YEe)Slvv%-m&m@7kb;PI$l8I0JIJzFT8o4gFLQ%@>JQ@$br4ZY$rH!oqVX=g7G zHN9kA)=?@Vc%n*B{8pI=945IU)AwgvSmj3~9)K?l>D)-yLhMNE^orT<1^O@=+s{<= z{%7=IxYl5ssQPmgJth*Ds=SnC6x)pfLIFJC(&SkS5a)5v-^GBOQ+7-2maPdYM{|Nl zHm(&B&;IuKp>k$^Ly2M?FV^INgF+}m8 z>ZBot`5}gX8CcU-L=bY1knSzVucCGnlYmr@&1CK0cX&I-=000UG7W6neV&_r{for| zNqJ6Y;YU@M{bBdU|8^e~wYD>Gwy-smx3jSQ-|pPRLUuOxE3VxAv$uGNbH)0qw)|JAFg#uf~Cs`a!CtN#ie|=xy&X|5vk<)WKw=sXT6SN}d zAeUTll{^Fy0IIFa*e>$SF&8V?b1SXas61J#9rL*Tn8}_t*E&}=p@`9*m~=O4*0ZwC zT_0}*p`#2w{}>L!8>D>dYYs^@Navq8HQ~yhF!I zezzcU6wHR`tIK>^)XKw$9m<)|>KLeVhZsQ*Kx;PjRmwreSiEw|R{T8>r#~&Zb|Pru zb`cyBKT>fKWhj{*3BS+D|^QO_fs8IQE1*cKsVONet?!&pxg@G0)r3c=bRhE=Yq6|Zc{qsWtQgi#(W zRzSeTjg3!>KG5||=n`*`_C7Ik?zDXXo#@AGirz+*%>0bOI5ZyvhgOJ-9mT+2LSqy{ z_K1|@67Bh9g>H-Xoy_APY&b~Opt^3L&LNr~2?6?N4mBEW#(1I8M|#~sj_4U{8{C8H zDgJuEO#EC*=Kk+{n&|QX{4`^0G%wb`dEMf|Bggh?hl^Jf0Kw&MzI8EI=3mhol1bB+ z2C|0~(pJAl=K>bI6NkQO$9Mui<+ezVkU90VOHeqF0qZ(dDx9s+5fp0o)~L!w`nA*t zsUD_*a3^-V&?8h<* z;5JX;g)4iSS6%WPO`$cHa$&zD~{*c8?Y)yVx^ZyeV?65@8d652eJi2D4#Raj;_|N`w73>JsC6_^3 zZuDS|Pn$Nke%nB8(oNZc>TMa`L` zjx3HHlj9S;o^OO+31)OvqWmn?t$4vPbqU-i!5YJ}QP-k?68rNyYsVw%5C%1Y!_)(O z#Ub`}#Cnv$xd#>mh_QhPH1PUAV7hu{0SuGhWbQ~5A!9sAWLI}I)AomUfE9Z67^6Wa&Q!1ux4Qc@y>~I58w4=#&-s zZLmm!XD!y8S${KzN&S0ODe)#`E0`k!y~S{hzOv<5gcBJFf@Pa1quKsnj?g75!6xht zf9TOup3%NFC014mBnH~BU(|xom_5>pOjgk>%eOY+>!~F+t65Rjnr?rlI(6I=^l7c3 z+;`bnK?eIA^%i$t&}W?&mKzq_c6;c$`sizy+}2Pbx88d*o!W*M zP#k7Ppbe;y?iOU)GyQ`QA%T=N4PWZk zNpXUtVle7%ZXPOD4MMl^xSwHa_o-agjoQEAWfZ|VoW!zt9?(_2?@b+eg3@jmnVJu4 z5w`WP0rliFmv%Kc0!d{oFb)t{HcHLgv7H56SFPR+>+Df5`a!X|OsJI6C0;B5owJe) zz53aFvt%E)C@h(Hg&I(D)QPv*QV|5giBx}M^56nWWUJMcKx`I-#01I39-!*LG>d9| zk!z(-eQg=j4#>|J7c9?|DnwZwvS~-0g{ZVazlf5nKJYIW<0Ec?dm>gMwiJ`00(I4G zg>7#emhCj4mV`wDd`kJBx#ft)y24HYF_)U*_P5JL0xX(0N=OT07ogyu`r*fW3mzCi zKV?lAXBTjAZS*BJtQp~Ovj|Ou^G>S+=3MTbE+I%Kw1{HMg8N7wnAP5Jgxr8sk2o}j zenDm1&3DSiDGjsga$8~ZZ3Fm}avG0&`@fR!_z*W$>R#>WZ=}ZN#kKt;SCD1C{ z^|3GTLPo0-sCP!37Y?{ZIqM;vVk>%2@%-l69QL{ULuOXIw_r`;!8Xc!kM++Wcvmf^ z`25p1NRa=nSA74|Jp6xQmj4iro7CR@kkwGWb?g67Lj}#^OCgG9HrulL7lQ!8%%URB z+hPHdh)Y`gk6ryWJvC*^&V~VKYD&@6dntQF$cs?!=%!Ig6>n->(yUUg{!`Ht?&tsg z`;CVwQDzkA1zv_Xz0K*m?ZkWLHOJ{{O6!~V8}c{HOGkf7mF>`7d0M%a=`>@LHE*E? z2a_pkeF{U_h$4rRe1lX>8$15&RWu|5cnZaq2oQ~~Qsk|2mKybDb({?^tlmHFWnsIUezQqFM z`-y284;#C3E&67mr=zKw5G0IRqT-DWYki1Ish~)ag&laLJW3E)BntQP?|8M=N-J4* zwz>Yev2tV~tTt7hr$|X^pTYIT6%q@CgGqkt%y?I!wsMO<{lgavwqj9~6Bm3+NjwQjh>`TM8NdPn{0oE&O zlcZ&h&!6Ihc#YRs=45!(2zptSYNMp7bH+|BXp~9}E82k?w_{*$ZMY70^h8B|F%_DO zBEc3zUi_g#LI%|25UDIp9G2)H_X;sroT!z0zBtCdtDy_RIZdg(GDhWS>mpl8o+xR- zKn=eY=FGT)+5`BT0)4HZ&JJJ!*7bbg6C)o=zl1fY%UxD`rO93!=%(+O^FR?)ZrLmy zwwI5;9UF?G9NHi4ifw9}cwn&h$aksbaK;M-x#lf6aVpV*SZZRM#W~+D(fKJZeoR`r z989$b2F0X*lqH$59ygA{@rx*o8J6L!q{f!2NU?wnX)ur3SI>~2sYO#zytAAq2s@-G z4euy|mAS|)yohz4cPpYWwE3=9Sj8VJ%G*p-Dzd^=B4GeMo|C;lIVwj+3y8p*-_o6h zw@f~r?%_m-E=6?z_9tHlIyUkp6h+hYoJbAu5dq+_h&gXfnUAD`Z~W@-%UWqB2kG_t zS%`Ku(<#NqJ324z;|)Z~TE;J4k=REuC{0qnVt^Po1<;d)m#Ee6s(_X0X!sn5w~Z4V z%KyRIJ4aW-f9al;RGd_7r-F)YR4TS@+qRPv+qP||V%xTDV@`MfX5HzxXRYZwx7W%_ z{y+Jg{oQ(=y(^ES6SMl9M{i5I=jN%FfoJqrFZzswaXA}hEHd`DOFW6`_=M;$3oRn+ z-=PZpvknmfTDW^g*ZUcxy7m<&-@REZ?Ik_Yib<<<3}#JMTxbkZ4)Rs+5(UVf*pso* zj&5B;wKhStpw4SQz=`8ghms}$!Q%I^xtfdC`AXdS_E^rL7Y7u@p>48Xyc>BkZQ!8K ze%EfImnLV1_i_BgVzYMj8}-H~jz@1*q|>~;(WKL)L1-#Tj|P%@(0Ain=QF{~3b;+t zW~?!Ht{frR+r|6j@x-LFMyZ;Bxo&4OG65{{RCWF+i6aL+Z%r}o^m&nCWpD0KoGOT{ zdz^|~!74&rH>oZ&TJ+RPyeVfW$XjZ>5yGGYlnc{WKYOIVag<)+C6Eq%ZC)UoRt1pM z9Kpt0k2oDPYu;mhIUSV}GHOKcn`&;s+P{XXVK(1=W8<>cvm{RAW{`(F)67im=SKrv zDrt$!xn8y>!9482nQ~pQZ;`@GUVLOcgvX8^I*R?)-3fU?K5teLf_NPolCIo5J@Sua zy^;dlo?)|zq#ckYY`$UnSl8yaK%z-lWejhgUkGvvG@vx<%1Pg@K6t-Iz3DGXF(LIp7^-+hJXw+)^Giq*|1lb3e5_@aq8KeBlUWy*%__!?m4C3*#c=*>8#?C)YsVmChcHG~#N`kO#wNdpIc#ZLe9a|Uf50?uy?LNb%Q6MQ?pJe-r(8LW?8|jBXBCRS4Xb@r$<&(wv>BZvP18ykk9@(`M23vikO}J{IiE=XJ5uo2Rvv^gO*alYmW*EF8#ioXXuo?Kc^_qsH$wW8jgnYn6H zrrw$xWwBqufsTBBvYx0mdJWc-Xfni0tKxJHiNx;q|7ca5R;MA&js zW0&!`D}9hp4LaSk+C0Tr^F+Bp`jW}rEG!iYS(@GL`!`8ez<61jCi zCJ9d}DH9_T4VRVlpmh0a<`K{w!YPOIn9+x@ftD+d>M=A&gji`3xJKCr0?{585(S_d zvZX!Gzb@EU9ex-^_BKXAg?gj3q{t;F%olqvSpI%&mzphMm*5S+9GlvU|iI=mFTZj&VLZ9~~Pq!AN+7E1w zGZQ~DQwFgjNAW_}Evdf!JE*aHEW;9)80>oXv9t3t%-%IkujHo!pKgCIHHYwLLOF>_ zn#yH)6%Pm{xnBy=6AA-g?^Lh5MowJOD|fJY=)B3RC3?}D+ZlCoDr-M>=s&Raeh?T( z5)?M-FnZuxa5gSK5EyySlQqw0k{~$kKQ9SUM=d5^x5K<_ZzCk9Cp}(^aGp0r@UB37 zl;oGwwb1mLO-0*1+C_buUp>Zw>2f^1y`bsR3z`4kf_>Hw8T|tN&v}*4+TgVxPz&FI z`RyCWf4?UCcP%Hdhu~=B>iDl6a1}S8Julj)HeaiM8>wJo8oF$9*<%Ca0Sh8hjFiBh%EyivVh_G_?$Y`4WzzeS`(d-W3j@kc#zkyfl}Wk|X+xA{<{=ugY#8CRhW zCVdS&V<8LXO}%9_C37fY;-=P#N4~k3zcb7Fih+@$8Uwe7k;WnIE7-z6er6CcW51W5 zvdy#6YIJlIY4;^yJIO^+QBK4x=mlnSJ*;u1jO|9U!}as&7nWvItkh zGh=8rn=WI4iyqXd2tnGqyo|(>M2&Fn=d`L1>bD4u4UtP!9*g)jAcy$iydKtoq~Fp? zgWklSbYXwj1c+pX+21g4T)r?w43FpQ4HGu4l4Y(Nh~Ns(a8vHD!!RYMo=~i}Yy_Oo z)-7<7>BbS@OD^sV)o>f?g+WAbSR?JOr_I^cE-!@)j6z4UHYOUXbPN-yqT?!G<4#nz2ZWiXBc~fx`ozv@D9!+#fl| z4Ri1hx!L(10V9rVjzKpeEd<|$bK~ydP>cmVQ-a0NJl@KzGUWE0LvXbFPNb{(li+Y# zzcR_7<+QGm^H8sgz=4mz9i<7WIT5YQNz+%T?r+Mb3cx&P!%0!UEIW;Qh5;sDs2J9* zng;(O!i+t?fqG7xv&=4*zD;!qi#&m9tY2f{SB@5KgOedP(=PNKn0KKol^mTv^D*XL zN-BO~Cfy9fB44igUPk-_XIREcuv3JKG~ELI-8?8=3Y-f;8Vj5SQz}rqm6@AsPJSZI zkOzsWaD$%W9oU^SW*5bhq2sPzN;I4 zckFqa_F!&J$g0pGIDb>tSq&v7M0SJU_xXb3G!13k|Bz2byfccu0CSZcg4d+s^okpI zHHlQ1ag;uT2wNqmwcz4Pn{XX9#%Hrwr_74D=y6(?iF^H&_clIRt&49&z~l5p_RU_P zf7vkedd^Us4E0_QNq5|5f3nWiENfIv7IPzD8itc-3K~z@i(H+JAKdZ%y|7cWvWUP7 z*8W5BA@7TTjlg>D#?F%;`PunbA$qG8eP>t;sq#=}i^T8~yEYskGLU(kufaUN;Ava? zgw>+qM~vH4v=)n}Tr0JUh!HQT_>YMLe<8ksh;(pSZ}e_D|7YdX?!8j1RP6EM za689`U0OZ~hRBC2Xs~0(K|`F)-OEg>d#Yj*AhztJf>~%e#(e}%fy)V)%8tZ6R*t*z2iIl9`Q9lbzR|j?h=*%Sx*oWFlP8joVPM# zsC)bzdS8R-P1$g|I5iSAV>o!RT7m-QRBTBpBGsCRNso$G-sV%*<4y5<)KPXCdPnEw z2HTtFLURY>K0IE&r%Z;#=C=bWQV@mUc0TBqO~n^^gY|VgJ#^}D5&>xj-9vD=J}f7hg$im zQwMSN&ev`WV1l#|_9&sshJsGRM|q`p)@g2vI-Ai!{p8h63WV0khX{IcN>+i$RC~RP zS&jgvNw8U~cXZY{x3+|2))72(api~9S(3613|)D3X{1&YYpuSW!`n~dH6cw7WM>N znKX8VnRNqpHI(X`7HXK5RJ@<0aW`!7yHI<3rl9DXIrkb~aak>@QNcXoAC4Dfh4Oux zo=u#T#mE!Cb8E$66Xi$$?**fB~{Y~~z0 zmO=!|P6kr3Lt`(vHaWu{sI5Yqw5}p7&IWj)_OGF7E!PipthTXZLTnM;e3)LQu=l$0 z*HP5RoLvDW3B-KUAQsd)*~+>^mg+MS8rma11ev439`Wd_W5K3GPKhh%tD>GxC{44U zE2HKZGbY>VTVtsN7<2h71*(HF9>Bn?hx~|oPHL-x5d#A5X6hhA|I4wl5OtY^&c>$ zQ|-k6DjK=$DW1jJ=YT1ur+@B*2-k!_t0L59G!_4QKG9-%`*uP^XT$zt6uvb@LO10^ zhcSGx(eMotLcm*^Gv6Oh81G#>{0tD2=ei|UxIBLK(9+Y1tEW1A&>g5njszjXklHtC zfQiN)h=XHPj=|<)P<(#L<*NaSm{9;rB0%Xo#WaywfFoc?e+*z~5oV|ed%4=Sga`)E z(Np7|ztBD&3oLI87jy;qdAT5TEr-9&E?{Qn4l2Fh3T@YM4mI*s)tvM#&03|T+xbBL z^~`K}N^Y?unN(%Vg+#ajOwEDIJbsw1qLVbzbn`j3uX0jX?3?CL@5bk!-D}bwWaHSK*@9okCqT{^l;?964(c*u()G}TYO|`2HT?)lG$@aNm7DS;-&GWwsho(4w zm*UhGrf7W9HFRsDCg&9h)R-z}%Zn?pC5^I$*{q&yTeiL=p05`pAG5L?@OwYuan-{p z*LS1Sj+>&=!mJW*jE7gq2&9nqi>3YXi85;77~TE7z$-?}k)UY%n@wj%AdA*AwEU}J zZPE*hS@NIH1pIefk;R*;JsbFM(nO`%0M9{|>p+tGKvdIT#_iB+eac%>a<8Hv`pCD) z81}eKA4Bb!S%DvF2-+9=yY{c;=@H45=w%#dxH{=&Du&b+lYCFcla=QME zzs|-ikT=c>*zb4QL}vBE;^>8*tr$!3TzG_!hekeKM*3mfLbZ+|AmWdl^#0~z_>78X z^(O4wVdCc-W$mwI2OBQ$(|ZbFvOerq7k6KqF?s?_Y{;-!+u({hK}ZLF`4lk@sDjsu z5N_I|d|qK8DkuGIHQ(d-&;q9V5irlt%>w7?(^9#hJoJqIBk?b?n#K0Y@Icl-)wIL&zUSqkattw+`#%$d# zt7P-*ACgbPrx5iGpaK>GxRvzZ*SGy^rt-grgCzVmHkL+u|5c(RFJ&|L2hl6N#pw(H zNJ9P%+kk4j>I)0yhZ+bL8wTTtA7;PZ1RX!0SRcN47V@{3?l@I~4>zX8c3XtVSSy_H z!2c(;oAJ}dcsg7C+uah-4Xp_Y=A5!lZZ#TCEx$6BQmSBqj4`$DCMK_oRlqF&s9<=w zpl~5X65FEjM)EAM0Gs%CV0RzIiDv@1Im&gW07o3C1j+!IF~JaJlML9XUZ;Xzbn7?# zLvU^n#9~mowXe#0G8L{+bXU|*;w$OPl>S-BwF(!oOPSc?e99Vn!nb+2IwA_?8sx<_ zYihZl3xum@`0`V%RI0u9zH{t-bJ*GFmCx){+tG$`GuqilxLqIVc~JUM4(tRu0NC{_ z4-~4gTDqb$7x~=w0*MyfoIoY?IWA~aS9-L+-5Kvpu?HjO?{Mm`c&$tu@nRxrs?I3x zdl7#c@u=K0f3zFIkSs5yp3F#}vnFZ{*yJS+GZ&&-R4fO)i6dTS)^<*|hj@j4j31hS zW#8`oXhH*E^@CRX;=E5C4qG)9*Qk;Zau)G3o5#PLii=oKhP2TU6E!J4M+qpx>2P312a~N6(~l^ubxzBG}L1TcmycWBkl$ zZN_sBB#8n@lH`B8Lj12JiRw9+{x7ipRW$w!qxk4HC#h9H(e$lSj_(~`WFRFBpJ<7^ zXxX>myo{B=$h}du{D-1b-raFhLU_&CXStAC6eL0nRJ{?V&F1>6iQiLC1VDYHtFITo zfY{!Emy85(-W(Jrp!f6QB$ly9*8M{iA?QY1l(Z2l`ll0_6Rx0nHN|d^rI{a8H2QvB z45{Tr&s*`XBqEFtB~nrr1SS0xlv?w;ovz-BFg#UY1{N4Y?#d^xOIiJVL4xh^C$Sl^ zl%)QCYiTl9U@$ChLyfTNL!n#M$BZoHrS2R}Gm1cmEcuql22Uc7f=i8GUZj&INyS&E zMXsPKeu0boFNJn>c-o!1NE%BNR%1x@ic<-z9hkAS5{fCA2>1jUpxA56=@8J9DPG_hFD`SgPje9(QZx8?bx!?1FzMXdDk@2ofE#8CRG7=}^ zhHRG@s9q%=`HMO8xj2u|dAwlXTP$g#b5MlXf0;ub^pz=c8xo?ZKop8GRR9mR>XQ^Z7aqWJ|5_3O8G*1<`W^Qc-j zgY^UTstiUl9T(eVw_EZZe9bCxMHsUMqWtLE$X^kQ@&N8jho(7WhxM^hng85(*f~Ob z{5Ptufb(GK{{yNN9PNRdL;sblHEUpa;z=)HaryzBE7c;9i&_j45r`-XA_z^1Ayhe^ zr?_jiXBkH`sjgoAeXCdJS{@O>^BX}>N+U6N?7xH6Zel#C>FoXa`uV-vYu(7TG7vhB zFDGcGc1DvFiLDmiu`B{NTo>_-fvtxsH}Fu7OBp2>1*?2QAiofM@*8Bt&Wyh$d>C9K z$MYsbwk=?Es}(aTTa~3p2Dg;dhN6Hij-M2RRby_YoVs8Q%`sAIxG!7Gu zcs5jzr0oj;2gOS$eTi1bj@<)1{fvEh-|SOU)KavK>iHq^^WB!@&3IpLBP!1yyYEys z1&>E^h+po)!aLt!2uo1&N5IEsEtJ$)pPOdQB?iUJc-mBVj}e4PZ@%I=0%p_u%QG*< z9bsNam<4UsHm3kb`Ntm;Lzu{8ri!;aq(=~&ZQyc6JTk!T4h{hWo3-)}*X3M7Stk3w zT(X5(@gpsPRx5GhvcwQiZgGeQW-%vf`>ZzbzR+VX-VF&7G^=b*VVw@h_$8)Twl&BJ z=t<#4we4TSLkO{GUC>(bU%Kg^2XJoUx6G500nx+lqHUYpJ*y^)Vhiacv|fFK(AE>j z=4w%|36oh(w&|kOb}Z#*919Hsj~M%JaUJPu=g5~a&h^+5ioK)%P=eK)d(h(pmt`)2 z(TeB)KUe<|o-z}(Z06`u0Xo$iZGajl8XN=9iW-DjXX*eLBE@ZgaU+2RG6uz}7F&hp z2~oWLmY}}_Qhb`%-+}RIuVQv|bRa?Wv39C9`|fpl^op0)2Za4k;!Y~+YGhj#vU-rZ z9TvD|@TihN>4%?fdoH%^MHiAhIsUu=2QuZYKq`mg_>WXFvu7l2*MtI+6}yi@5QBu>lbNViy$JEFMI_lfclZ63 ziJZ|;m>V+;g>${?jv#YlEZv+HUw5q6%aV!ON3IL~N>GqUCLF%6jH$h^WNkozxGy(w z^F8^O4Mk1@UsD483$XJ-Wr3mGeL>IdDZjIZ{noaHi}M|J^yyeT;E7@9ufm zNec>PeG}i&h_Zq%Zx^5umWR$;u#e9NjW50@HGKlxx*$WkE!Hppu%YT zVMFZj>SV(u86Z-P$Dm-sY-5#Iqvj5xv5iId$ONv~bkz-Xs`2-VFi5 zE>f+z+Jawq4UL`B6j^poLHKn)rtm0?$h2;B!4w_pWFT*+g+jwz)zR=zo$U|x!r#=k zN|Uy4nYa{_D6SR-7K*b;HTRyh46JUwqU~Np6@2Z?SBTT6tH8fzSTI#aF%iFHj+IBQ zL-67B@D|He!+#VMZl}1hQPsSSnqnn{RQEklD(^t}EjU35BvsbGN>%)(8sPNJMPwz; z%R|vh_QiJzB`wa;_>&sDXwbiarKWa2z^#}$EP$(_*dId}0*N=r0*@n9Hd_^o1SO*E zF1pR8SH5qZ{s*VDYHI9rr9sXXDEc0LwL#nqqHQfo6je`(ovS1bOA7YzWp~L@Ib0w4 zIj4jS?yQOQ1j^@S#;LA6+b>Yvz6V|fu(nhB_2bCr_@0Mo-M_PLt{LW8D_!Fky?x;f z?NXojI$0lrt$8Ot{wxy~F-q^Jc{Tv7pU|Um{jN!#)q))+j#7C4B3DV|Gla)n!K_WF zRU<%)m?&a52lpKnQil#Tg4<+I-FgFtdLcy65z1vaC-_7c{mep~GHP2o)GV*92%`$G z6#qmVV2g2?RJh(pQ~Vm!hmP9mw+kxkMRys$`2-2!zU>8;X3A!Lcx${Ud4`-CAvhi{ zIws0JU7^k+a(?QsV%0LOwr{AV5Ft-@kaHDi8ym(=f&GB;VV#@eVR?MPJqaw{Muu`n}9OZ3w`DcCS6nB%5O zYk}r3LbCC(957MWmI2$qAZ}9ah$pY_;+HyC@lSrjT`wo|iP}L(hAv;d^ zg~g7=Tj}M7OMjqj^rg)Yp^H`1s2BO0M>e%-AJ<$((*BOYNP34SYooF-shRzbA2-?O ze}g!WAeuODu$DTGDjidr?KIQiF+Yqv<&o!-8@h;#X9Y-(bqhDm9@XYvk0o=cy@bg7 zPbqo6=Ii9%z`~SYV|)T!#|27S!lwSZ)7~1Q_z1ML9lqmXcjUM@t4z;U3Q?M#E$ZJk z`}5*PeBfCeO|Rp<;VdfG*nzMmAsy)*;YPYGtMT2tT{%jfdoVi zjSCm)#bIMoTntVGA`bq(*F&fz>8=EW5QHiTPm*K(n~u(4t)1axwev>8_l6HAkKM<* ziNs|(v}913g34o*m2`Xvex5EuP8rk#13w?z;HKH=`m!VDg<14>d~4tBia%!6IIH}2 zuwoGXNHkmU>5dJv^^IyhOMkyMvx`+{uiR$uv<1Cd_uUk0NsuMU+Y#Pe6J}3j%@dY= z5hq0X`cHLT>q#UBE-aOe-p>lt+&fHI$irG=2P)u+!Jz!cCZ0K*n7G<+4lc3_O;mb8 zKC23;b5obfYXKK!8&%49y;(a9I)|<{gtP(R8q$e7HWbSA4$PZ}uvDo%zMZfM zMt^U>8Dx)ZiDr|EvPo267e%G$=x&+df*dUiqotH6#03TG@79H8kzT7V~N~ zLGvN34W!#*e7LWP&@3s!9-@KBf|Na&qNz3juGQiH1sm(l&y+r>g_ z%MN^dcgqdgmxjt8F0KWdqL=CpqqIwlf`q-33naAl;(-r7qSii&#bNYc>Npo$$l_x8 zI0pD~;PvDv#vh@R&{wNp3$7BM^reIy;#DP$D(px%?<39FTD{>Gh{V)L=t^1jcW;lf zPak3tiS%2HWr3$chuwBE!P*Av8HP4UNsOr`Tz@f3B3OFGmsQg!m_)fuT95PsxdMYg z-oBfNXxzyKs%oiqR_3Ay{YO()?a6|6c$QR-sKLbTq z-6-C=ptWYgUuoq*c}7{hAU8jK)# z6e@oMlDhWlkCPpKU$m^M3nJI!|Lo2OJzTVm8Ln{aQA!(H%`z2Uzgn^J83uXe`mSMC z8B;Bl$bSze6Qo18J1zgS$&ax~R!D(y3ifiH?muTvqPaem$3QO7fGNB7f13+w8|!~1 zPXARuNAmwjtNvLUHpWf>OGDJ4seZA{wjwD3>`w|mP-~p(g~@Qp0R3q(-e=3zSHN84tvC)R1tp?i9YRwZpOKtdr$1B6ha7HniB` zGXGL!d2K69)+nh%^o_!n7I=+pgSG$qtvS!5SUW1)Xu@dV%KNPIH)pH{3-%2lV!x;o zi+j)nSE=g~lZ;EIIj}R0U8*0a{Al82NzYvITRAl%F$CRZUfotTtb)$qd!;^x3f5vp zkv=*yfrhEOY3_t<`mNzl%w-}wWdu5sWmxpb`6D$~!acX(UPp=grqKdgYo_^;r;dGZ z=<_|=CZ6>k9)Po(xO;L|RLS(=pJ-S6-pKvpP}g)BIGpdL{WByyXhk8e0z3@FH{yqo zf2$MdI|EHpho||1v^l@ZbYJ@B-hHKsD$&#}Jal%vilo4~nBP!~2p3Huxq;)*=m_Y) z{tuwu>fO@yHz&xa?|$O^Y%|o;M+MHesB2rcR?y8D1E{uL?NK;^)K>C!t)Uu0Qq47X z+058F)2){KSvakRj$i&WBJ$j6XBMuK6?~l)_`^n0EV$Om@mZ)y^7y9DL1tUW5Ys(8r*9DNSzegyOHLNP% z`er47bPa4ja}~3+l(>@{q~==E8IIbne|=fGU@jWyMZ1#l-Yb&yjmPAkT;10*1_YL~ zW2zD>Ny;~=3}6dvoT4O-s)m}r_SftXP?IQ|)OIP?hM&PvDIY0G3b9z`?Bs@`3mEmr z*XD3T3aaz8#OW_(ljWe(`Fmj1-{VmyV*EDVTCLh{&V@fWGbOYgT$$z76oUATGq1Og2qY#@HiTs1( zZB%z<+{{a~+4m9oB5{N6`u9w3pq07>5U#2jXjj26d3-mCXBcJJXEhM6$k!o``Iqlr zBFCKA;IIDk(n8qMi*!=#IIaF(x9a%MP2S&@ zGJVKp{x)GFSy#tPNZoL--*nk}a?5(+Il6x0{re8F4b_Dts@{e}7cqpl;bgfqQ{i9Q z+Jxc~mSiD$dSkbiI=}9^+GOv(m@+?}aB%7-!sKCTA?^YLumUFnIG>HS z0Dt_{dG2d&q>$P^t^dB^Bb~iCx>yKx3J!E^h1T?hR|~GYy!DI(O;@Idna>8w(k{?T zl-7jN$d@tsze$0Dxb%`k-NXOpN}w&e*#JX6Re(5uf`G7lFl#QiQrv##{0*m{{)e0^ z*W^l*!TvJPAAO_-YYm*$BFO);#mr-w$R1j;M|x|OGKX6IO^QZ_V;;YBinfFNq8%eZ z+<=d-|I4zv8_;o?<#c<_7H-*GY86lyy<22_uqTkZ=Dv6#UxV;g_%;SArDS10xDdcj zKAo~-smK)Grjl6T&nhS&iCU=n%Dk21-Oi-(~!<6$kG5Z$i#5 z1Zk>kd=W1?e>)No)r+aLonp}RQXMX92>r8lThRC>fxpVvKV+Z=N9Q`m4)f+XdE1)05-)=bT{a`r+)Swc`x>#a_S z{x&J=PECRWVllxQZpnzn8Y)9aCwFKu=^4>_w51uW|C@__Ps>yl3WZ-A#ozB|q+PoO zpjxa}bgEbCG<|b6L%W|^E8H+-x}r;K=Qd0DYJ+rTpCUt*LaY4+U_*?}6(49jSV5;m z%thN)>~)^~&8ajFa${I?6jUaLg@34~GQ_if78z!FjMvYmQAb6O;jt1=`8e-+b@U1N z=871TF*S{Fzs=X$%a%HHEb*Rr-Hb^~-r#R0xBS*U^B6+4*@%!9M99`)QK@{MZqEvo za_$jvB?NaJPHJos&@>Qt?peNVqB**OSNB>^DLUkFmQI#-R%Q}m8JcD+@)qlIb%)1J zx~!+J4irAmi(h#A@gg9mmUMZaa!W=5_EQqy_uXQ9vIiJ+)d42K}D)>2AbqMk#5Y0BL`dM=RZplL&nbcEm2j5O}J9E2Uy(2 z2F>ij@(eNZO)pG$l{fwS?!ye&zGAuk^N+V16Y@g(*!|$7d%G!EZ6U`pyO%nGx`ck= z?=XAsAIKBibk&`2<>T{3g{rD1ng?m4K|-8Z{W)YZMf-0ne+7-NFg9gE@5b{lbj>v_<5rm7-aj=fk7@R~WU zUGW|C`Nw?qS|$Zy446z*L;vsenWdeqfO6*lB4N%{9J5CeLFKXH5l#XpA7n&7)EoXT z))W)kqiYBiWf%aG9^5?$Q(ZeB7d*@~YAUE3D_#~y`Dlr(kVst;)(Mqv36`j66f1=O zl4yAgPE;(y2+x2ynm_9})w%JM{8Wv zv?@KSmRx~!OnW|a-qA~LRhY;i)um92iCQ555!17M;%nmo=~x@%d>ikhigufTMY4~B zVmoxeg#TIqwm00@cS()j9F+Ko4Vsk(akgB^4E-c6xvAUnykj)A?AVwi(ZRBh+DDTv zu^?01MCK@+Ok~qRUQLZ2{b4jPo!rI8ZnJED_6E!E`m5P&c{Gf2mYNIJS}2|<@J1SO zZJMISWG@E04XkZ+mcvTpfinNVP^np|(z-+vYGWBm5R9kbZXw8YdE|Yf4BXuy_4$kv zUJt_=aweRoAe7^7wy92d#g_lr!gys!GzfeH-=RdvQvSdPzEcbWqLMKtzI?V^MY#|^wDX|WOn9$U zj$(Gj^^;VoUfHYbCkq_(bHr-H@5++xJj5tncHoyu+{_eSS5Vg!1&gJ|KWfUVFBaoL zUk(XT%}0E$j7fUi5HbIG`0HTHmH^peo{Z96&2N-k7RzuU&d%@gQ>?xK`^@`WF*vA& zPW7|Sfku3#d2(~PL9aivy+vU zO14wI1&|I42VUSsHgkr(-REYP1UgNUfAfq85FqC z=(+U2eRrRC>DRbdAs|W+Wks~oy{bq%M?gS-Bi@Ag-SQ#3(sdJ-c=WfLly^J_KY~GR zT!<@*9hvsg?%tpqoH2?7zHN9&t&ebtDuxRhMH6MW%u6#i=ZfTSJ-gr@h#C-I&; zyEL9Fz(C?y)DhoiJK<@>k2b>V4QfX4r{q0~1e9ZznqT$ZdD)ZZ7>CeiR77`ONtv?TI9N5;?n@)R?E zbT(-A?#!{jc`la}#?f!?$%r~a$f2+EmRFXHxGH@x08=s6;@SoCrrE`<1}D;9ud2#` zrr$<5&)<7WY;yeGEq`(!zsiR~SPOdnSf?giuvosrTKuWr|Ana~r;`A4>GCjFvZWJR zLiYj}1Tk7*AT>TF_<`oG$-v^-!_?KC8fW$b&O1g=USwpV4)++-ikXU&=Yoo1+Bv*Ms!9B|G-3o&-|rYnet7-OjeGwY z&-$8u-Ozb%;QS5aKbQ6c=ctjsz_RN*u;ugLpT@}=*&6@{A^)u0Gv&s_1sD){3>FsM z8`T@TvI!f|JN!e$2O_u2N^<6%IwD!!(?zW*Ka+64F}!^VNTsb|VXO=M+-%8?42^GJ z9zH>IA#nn|XtYw+0m_^f8EBlLK}@U-co&KqfabxbAXvJB$O7kI!n|VX9pb`7E;7T>L}6b&!#hmDDEeb{N+R6FH_N8M)eY>OoOhYTIp&&> z_^B#oGeqY%LSqK$6jZUFm0V01%EF^AsJgu}D%~VR1dWFGwv}mBXu4&vGAO1@!N_d1 z_ymR4$i|~ie~akRUuioWl~3B!bmnjmc?|qwBHL_`A79gAF}(EC;$$n*Mf-o~B?6D% zB)SChYniz%nr(@$3EUiO(%q~6t`}4vlP>~j+N8gYOHx^ZgkuWf z7UrlbM2)trL!e(I&c3^V8{&UJ6KYB|w|hhj=VdHZY@d$5SwT)pJqHgr<28Cj+ph_- zQ*5ovvJdY1#{;-q%qm3>{MY&chpmkN-$jp^m8~TmpP{p!wSkf0f0Q?cackn=84v+q z_YF9QOybavJDT@ zB^e2_ZLYr2%9*e)8M?iW{!oioC3Y+el!9ZEusX&@jSvA#k^Eom9n-JhsCJ**%(spAr5F46_l&ejjyed!~xo<-_ zLv|*kA#xG+wub+H78b951!nCDu2342$1$^I18Vcv*>abCu=OXxj6_1j5_C^!4$*jANxg`Y;qfjnC8V{vYI)D7uLumX**X-R;-$n=c*$V+@j>7-l z&)?eG#u0evz);B2$O`xk6Et!#us5>>Hdg=dV+WOqS~By0Pyt&jMjFmE{w2?TFr#5_ zeyFGcVR^nOF%|B9JA<%Hjv|<|nQ`}S1VLQW zRx$4ZF<|fF+=iT`t6d?!)-Kiv^OeWJGr-0Uuris@YKw_mPrJ7ZR;YFs!75O}B`?M_ zRwH|gs;qr89qEaW3Dv3+(Jz!Ur3L`{PYiZLg-c=OfPwo`9&=KnOtU%hP?Q3P|Q$m2!o`0+p&b8N`Dsu zvx=@plskxssZQYns+&Yns{b0Q}6g*H?= zHb+s*Vti>S+@LJicD8Fp3x5BVJLFGNi`bpZm6K>M(7r=UsRV|pniOolO`3tq4K7?* zz|zIjh?}pBd{Ott!#;Dgbs)GR=I9*aEZmo;rtwMk@wWw|5?iKWubjeM+&70`N*SVO z!#r1j*(O%ZtjzMB`c#jKVtI+?k!hPLm`8%xxyW`p!iXIyyFHV2=xI)bf2VyswP#(HteiHfc z=9iLR?sALisi_6wHsS$vVW>?V@C9K;BoMqPqDKkThQskCeA@3;4VxQaNdPEY;@213IB znLx<+uijh2mCW29+`()dgT@V8U-+9}B`8Cz%DoznTFy{_ht+}tmK%ZYzMR0k;gzLQ4abU8QDbJC}k zPaly@S6xyOxA!J)WL^DMq@-UDSxlm9<4+a&dEam@r{z5XYM{#Tqi}NTf~92(1Dy;L z{S&_O{90>L7EdNE2vuOz(J&?2b8#rY66GvQaaIv)6Ll~s(;RpPTnk|A)f(HwvCN7* zOurBFKu)l9RCe*(<`U{Er?j(PJitJ9`IXB znYfznONp0p3ZY=^&xbwVhRXf(ts1`B4l=YgtU_|^wx%BmE-ZV%Sj(<1z6!kQlUr+SlNoFTq1i}{rl5vf%5G1-aqonx484jQ@{&7Q0?127gTDh~2-orDkXLD1b zh&bZjw0O}!DdZG1`t3&*sm<%IkfYx4Vj=R>>qgP^ji|Z8m~uMjr1SI=@FsY$lg8*> zfNa^Lf*vPdIMJOTMXtqf1OX)d*anglmmzvQFQIvKL_8EnPSLp!#s}8jGRN9`EQNtv z3`w7YHLx(p%>1Mx`hb<4S!UYppOJ|r*+0L@77pxl0TxVYdriW#>6NgzSASc>*`DMp;$EElKC`Tg7cM zY{Td43LxY0{v*!Ksvjev0ts~k_K5!no@%Cl1-OKNcWeS|Q52q8W0;k1H|Ho*)3gb8 zl;`;)N|kB%U?x`|R%czwtbXEl*kpc(pIf z5pZ$BFwte&msAlxP@=Red)|wj4}FlOG+V^lEOM{~wakNI*4p1$9o9|KtC|f#7=~>* zb*d}M z#F5a_93+KAucDWfSRlXz6xuCd4YhuKL940S+A(Z02H?OI+NpY<`*zp3HGr0<4hE z__HCUfCz%?vwhN!vlbv%Lv$uh=cld%k}lw#GBRy*ylQDsHj-`w=;O-n@7bcTK`Ju`&v8tWJ6GOK%reO;F3IbZjq)e=w=$U2!)y z1m2}c@ZT{z_#Ix#@``+``3W9>g>;ToIpEs<3LUfxQsw;&`)`P85~IF-R}z<9g0@9f zdW#zPzRnHJ60IR3I}p1tI(%)9%oR!5sMdxCZ$9rJnl6U=&x4Eo1W<&$K<)zmXSiej z2X`k+vvs0El>`gujrzPXl?7}Nr2GTR1*hPFIMqoPssKxqk#pZ9ox)Ik{k)r10wZn( z3pDDYX)))?@fC-xyUCRi@2{H|Dql);EPRQo%DmX6{$Wb{D`EYm_L6apH zgeKeet*5X ziHEB?xCQ-EH|$&qR05B{s>dR0z)~fImxO#H{83|HMa+;amjnv{dSt7D{JX;8*rh10IM|d!U!=D2%tkI^))VDnHP&L1%2^-z85P;5R=Xdm)UWI&_G{rXFPrrd0 z_jmcs(r)32L^;v4(JWRS;W1$-J4|~$?f#t*weBP1>>_7Cm#tvG?6O^NSYSLZ2lE4` zg!j-omZlGGFTIyzRmD^(zXWPUvGo?|tTgwBG|8s+2 z9K-NL7-;EZ&-Cq^;Qw(7_#c3FYW$lL{ekya>WBncG$JxGmNScfoETI)J2fZ>Ng5al z687{d{aqZKwDInE;DmX3k-0{5S*5=dMWfV4tPygAC9Q0wQ?vO-qq@p^BdQ(Qad%PwNgqSD!16r>^T|pUW*V!M$f4Nv03=mY?&gNb|itf7p+2gFUNk z3009S?}9sN)PtG}7gQM5t`GvX^d^|5iW^NouQh4*;oUW6WQdHhlfxq1XexIaB|3}5q~^#ve-%n9n*IU)mNzAg zcha87dxa?C7%N90l37>Sad=6m)C9=dbZ-$8G@D2nVCTScS%@iVDSh+~NTR@#)+2}# zlJp%oTjV05s4yIOFgH)3&2!g=PBXHSwk}jTS(JC?(igeh&y9bx+l=9^-gF% z8z}oU>W$t5jMHmsQB@MD6-s?!jFMnFOznauK@z4(Ps4@yXnJ==eh&2(0XAkH)RufQJr5luod|1bcpIo zu$bqB=T1l*qxmAt9-k1~(N*Z7OjSM82$GrUyzTWf&z73_D?wCu&s*Hi;xVs0WJ!yc zm~BticjK-Cvg}c;%BD+o|1{HWFDaHGVJIok{6yY1z3WL0k~Oqu1f}G{eWn7V91koJ zPZiAwUm)ob<;k?p=Tz@aD0TsG7+{)k=03+XEfh;(lAl@Mzw+$%kXGd^HTD*hx>nKR z-oK{94>|Ew&OjDY?FNMfLAC~9^Edoolzn5DrBRkQb4abu?a@5^S3E(LpCL4Mo=~AD z2Gx{KCf_VKe8F*RBa20@(@pF6K08=q{&w_EhJQrpbK~+-BiLz#4}L>yryG)o{v>ISwA6OGJ)bW z#gtYLkZlTuk|zq{)~c8l<;~OTnuoBK{N3ZK=N7$n(UKAxe<{mm!K*C*cVB&3x=pt* znwKb^F* z>gTtg;1umEE(qsJ-;fk60Q>1DvcwOIJkO%!UxZE%bXsQCPFC zU8$a8w5j;q`zUp{)hg@}Y^s2jAag@r7(cdh_=cPXea8Q$e>7KekHJB(##K3Wt~J28 z97Gu#0h=R4f*jOoZGfE?*M^~NaV$rE`dR5K8g~s_MbBmvYjeXuT&!2kAo?*{Lv!6B zWyVO$&dsl=75Tx*GiSwQ2`^%40?qp^AZXaq&&Qc;9G_Mj6rt*o$Tm<;BxEm;`NyyR zo)QMWVjwh|i!CXdqkOPH;TEl?mzFmE7){fKblY$DN?X`MSL2sAvgc75Zj;HXVbvi?GTqYzbP0E$wS+MXFW3a!#BU#= z|56Tp!3?2*&=u`SBz{SMlRAG!$0!)rW!SUw$-2<*?}g^q^a**T%rC8!03$c8tWX5Q zCX9w<3^p`bcq!2v2a9#y3KW%Q46=;uT9K(Ii~{C3v*|g?yWy3$7fSLIo-> z0UGm04=jSsIK$0lo$o30Q02LuB){YXW!aack>&Nef zGW?PaBXDL-67qZ=XRbF6#e2!Tc%--7qdizKZ_ltPcn%`zX06^2}@dJHK!BZbNn z9iEq3OGiCyr271rF1b^3(WDDmHo=&Z9J(P_rmKs>d8gn)#Z$k0bla%P5j}hjvCJAK zEzf|F7}iz}TWDE8f_FG7rDL8UErtiNH4{yFhPj?mI>e|#?x7k0$#Y%Rk7CKOPm3&9 zhmmy$AYLRqbe)%B3=v7nyFbGSKdWtafS>uJ}1_jcH8nJWFwPwPsz_?u^osCt^LG}Ah&4v#jX``D!E64-us+xu!^U%5n3npt-Er*e`6Ho&EZR!pm!{t^U**w~%-D8R%U942P-V$zZH6~Am0H6CjUYjYVzB1zIE>WBIhF;18 zy7BVsy2g(6n(Km5=Wleujm^HJj4rjoCBM>qM=-7ggoeWip$`-vX1^r@j)Xhj<`8SB|}_46;F~XmG5uQO__>lr|pYoc^Gem@)qOgkW0R> z?5jN73F`#OVV~%t_Pr1!Va=C)xLCoPwVcNMpc}MIy#z@M$%l8Xad?qZHf%<>R6LeZ%Pb1DcrJ9 zbjkwV@!pmT`~r#b9}9WG+&Grw@WPhU1F)jQzC2`F%E&?3Gxqa^W42iVJ{PZbj3NH4 zDrphOUxh2)jvVG(0yaHSoE*IVk&r-i{Qg9K%_jq+ikt~;A5~Xuaxi&AlJqqm5W&z; z(M#QF;J8=6HvfGQ6`i_(mKp(0OFiuwGO=m-}_v3{-A0gyZjrjDJU z0gjf1xW%G{U6JKTHvl~%)yjPxp+g%YwOH6R#cC>sS}ts6P6q&*%y^i8^ybALa=e&| zZ;ik->Fp7ULvi>8{XtOiL76U`$~MmsmpuLSLOSX);G)w%&2r8(ifo-+4^93Itu}K? zJb!ZmA=lx2Z5|lPm>yXI-+=A{ae*2_U!GH@04^|B2IqqMTxuQ}3j#Tm2}qf6i+Q&d zoiI)BG4W(wq+IF{AjV|SY2^kwZzD~5b75}hq~P9S5bhBE&Cbo1c!rtdk?sv#yF}9f zOjS>2o_B1LWDke6`eRe(hDS+!O3VZaE!8 zTS@GLsJhYyz>>j*8`?Wz1RJicO)=-hs;WTP1DU(BGzlKm zT-0+YiV(n4A~6gIK#)m27m>z4bCMil4!*g<53HH*(S^e&#)#yEPAF|y7&^W@s(FtT zJ+Brwr^-yoS0=Ae1{R*xr+4#GkaQ8A{GyK?AvI~!>@Sfwcpqzw1Y9ewW#-L&@UV{aUXD~H)Prx% zY}8SiDA6N9JcpYFObKh$FcWb49;C3*H)QR^eZy?j&f`2|Cpi_)=e|*Z(}|)lEt>^a zhkKV=Lt?NHE-{NXb{ew^R}(d+R>yXCUN~1!WMndfHk+b?7k2q|hx!Jf(3eM}DQX%V zZe?F{HkSwHGM2->GDPtuz3cit_)MY2_fRSG0*zt>y8Ym(cqgqKX?3xUM4@W@2FM(J z6%TCE2dSP2QW&`w4P8_P!%H~Ly(9H_z*zmKT$u7PAW2<{E_xiTCoEb1di66T9GNI~ z#5E6*SyLc;&o~dAs2J9M8y>L{EQSXt5vvkBYartALh__Ht;ko~Q993p$u=^Ac*Udo zO`!|Pxv4vCr#te>h9XGQ4jS-!&gUvRF`WA<3;6aP5Ir0G!;TJ4{qox2Yyg)Jz;e;1umnN)qXLcG? ziWSD%8(8|=&MrlXg@cMh@hCe4@m89!JtS-q+AU19qLibv6AQ)abTap56@&Sd8A%0IT} zd*z%kT0ZPmvFt4OPSEdUw&omhjsextH$g$vp4ck(^X_A{7dfZUr^Zg$N=D4Km{g;p z3+#+U=&SIH%}fdS0U)c?nH{y^-!18BhF2P(`;`TQo}4j>;HsH@F2ADHcY13*Nw2K_ z#K59;L7F%dv_Ii>a)mwEcVS+~9<+$jmd}|n!R~mx=-_n*P$LQSn&dK=bitkujJYvI zu->DL&1h?fABa4lPP_n>T#F~@$?{*#r#zw$4AqxdWs$OW{=(J`aHi$2PUg3*#)Iw( z6LXEk$ytu=*~F4eRp_*@CvhTVS3b5MB((>75X+*~ON zusyk+k))7Y2nI*Ae5u_5$&Eo@GKfXA2(PoKKa=&S6v^+Afx>3uKTko30}@jKfES>N z%BymDvPa72FX3xX7-^40R`?VFAWYkE(PxJ0bjx@N5pqo(;_3x>rcHFNju|8U5(v`J zO|^4*ur$ zWL^0355>6)r<3WfjEk*%2Ip3P$uoaAZjRL(oXsm(y;p=$3$D`>>B&90);+q(C)WL6 z-_$N4;|Juk!0Oo0E|L6(!oR6Sa8 zc@EG@PKq#b-lX1XYM_TAky(}nH!CDQpa7q(F>mPJHWHa&sqT*p(yc3ccc`I@W-12E zV}fMy-4Qm5!)N{StPs#vx%KU%b3V}LC>n$&VcWh5fb=Jm+hb5_eJ*XkD>;r$&N?H! z%iJdEt6PT-|4rTf;6d`e^|ML`_z9T(4{S33#di4@+rr$|hTq;^-|b(^$;<@He+0t^ zZ7XU>B-__EJXY-hug%qw<>z|vg$Nj7QLZ^pe;)6Fui4dCuXGjtt0 z&L{b8@H|{Nn@qh=Or+L(e|^0{>!FMTI7FSEHezowb2p#01}WA&Fm* zi!}HZ3kJ|a1oyzBnV>_al>>et>MUJ-Qj98D7)^qT`8i(v zBm53#?rRx4i?CP6i{&sGekZHiAHu8JB`LRy2pg4(sxu;CnC_R+4R9)9%I16w>zNxZ z{aPl7pUy0dM95D=8TwS@oJUD6<}B1lAYW2vu_X3|Pjos~0^-S%zG#@|aTd8h?xOID zZOzK(REn$82dO{K<|~{`Xi$MY;DYGjfN`ibVBUh=%8!{3I(?S>D3(9mC_OL@_QkUT~0bD_^!;2 zrtdK;^39b(B-DhC_~N_3wEj(H7s(Lk6@fo>jQADQ3Ob^|-oKui&+A)IU3^deD3E#` zg8dK@(Dq}^Yn*g$taZz3TjGdL&1&ksr}FEXBQ%22YGFCXw%Hu<%o@N2jo67fFx%7@ z@?mq3TlXFD6rX2bp*?i8(yGeWk(Mz3<(7qT%VgjbQ+3U5&WHwkjbJ|+jd`-D!Hn}k zQll<3wbBX@mW7CAx$h9h-F1|OcJ+w(uMUvl0r!Jj}65BU6LqjX<6)9!}yuc!Tk&p z$7eLgmf9J8-*TL>?RJpu?d<`a1851g3G*Cz5w>f$?eKTnv99T~J!|(6Yg@vhU&7SN zaK=t+`+<5HoiWom-Gc(H|5VvwlF4db979pEoNKonj82P2fxF89aW#b9(q=EmJtkKL zLZb@)ILml#N%bghQn>`m$@pn4kV>#oU2meol&wGYHm^~CeZu4&O~8cZ$|EV>sDxbq z*nFT`i}4a`njvG%!J*3-6VW6{%?bQgxNxP$JCJTe?#i< zEFBH?wt?7~kQjtIR#%=6xg5BQ$suz*fBSn8tyJ>IV!CJZZ(({1F~g>$vU5o39!o3r z!=~eqQ_DW&J;z(%P%xSv+DrBX3NBTXpm-6gGE`h}S30QBa1EbK?}*o;_#*ytW9w-N z8u5j(s8ppKV8cYRNIj|0Z3KSNF5!k@iWla!fs9{XBltyLwo5jNtI71PT~PV(X@w`E zv_(n}(qKy761sD;8yKun_@E;fpH_iuQ11Oo6wMG;HtC>R8Zz8~1pbPlI2h034V(i$ zRB#S`2G`6X1rI4IS!FN*dz-Q&)!r<)=Wh%v>|yhx(+}gII05B^oZFGuep3w7)?^3CKA z$^=9%X~7TO%J@aO8|DggI0%v8K~Q+5O2;L+kKmhKBER_8XoZ^XXx;`>X=F!25q2oo?_={mv{fhO2~ZY>A?? z$pPOia00)M1!3mH-L%vUd7`kcu0>L@IGKBedS25Z-!=@O+4QYCK1qGYWQGOw z=35omM!A~!^vlBiQ%F7Yh#HiY%ku^x?YP>fU0O-OD*%46vmcq9l0s-=sJ1%v$$R>0 zPA*4{)O0fnbHp0bf)|R3RbP&FYl&jS@?Jx}YgRuK{KM^!Ky3soW;ZV0a_6c7UkmvE$i?G?`gC0jN`y zIDX&hnWo}JXLJQh={D%~xyeriK_SM5I+Hc#paR6|^|suqI||_SVn@a1V)V9m+G^|- zBd{k}t08#NU_TZj^tLoG$qr{eGJQvKF?{r3KQ*M^1^Xd*6kQAj6Ff7aZk~rI*hGKB z$R_5>6UN}SmM?(S&Dy+ss+9r}P%Xxfsz%2#1W&{+&;_%jL2#vJk1aCqNIlW2OLK7n1q5Yc!jH5wK&n?tl$y+z#-ZZB zRi9;}XEZyeydW^1si3r1p@iuCPE zsDCUN)t<16H0?HCSYi?S$jDO=Na+T!#aX!(5JWaWuYfLQ8>UpB4sw*7TWd$DGq2Is zMD+)>bJN!}Iy>^!t3+2z7AmzbJ8jIEZhyDIo_yuFNMO0Nkt^;2I+2F1*V|G^Fy<4cWKsuXOyWTA5iBF9K*EZy?gtQT?SHwparTgiuG z>XrC2SG4_n|AD&TpF_ETo1?Lzt&y>ky}pgZKT?AJd%~~|qlW3@Lkc)foWn(mBlOX? zd--w70ct5L?1*Do*RK0ZylVjl(~}EU(L-;*@OtFYi7WdH^B|zoSY9xnE8JzT5jz6q zI1#t9fxEn^8$)>`(9-3|@CEbO=u51nc5W*8J=D~)uQWS-L!0ZLf8-_THzz%O5 zF3(oi-JLF`+q+qpo1DP+Z41dqA?VoVSM~e5Ct~S2B=9()X-`5M5*6st!$XxV*i8t? zC2$FW6Eh{mYH_u+HqflkgF%-%mMdYJvoXR5T}TNz^InzKZ7omSrLI2$FIt+=7h-ByH3l zOe_P|gi%49`Ax{UEP@hY%)-5A47hAt$TBO|<^+Ec6W9)FENIe3e9%+n(kgIZG-Goc z$dR|8{yL}chb^XnWHnmUo2ZL=Ifd@FVR<>xbaM<=(+q0@afYpx%Po*EE~U&NMMQs?nvhoQ(eoI0txCbpqzbjbe7WT6gmv!BB1JP?J%mY3L2dG&`W)HCx%D zAcJ0jMJws2z*RA5^gXAqMj!^0b2C4`=CqGSuImJYpa2_Z{`?@ygMy`>2_eD7s0k{Y zdOb0A&DXe$j*J}6Q(3s;<*`9mD|g-qaVi*z?o=UQfrnLJM~omJ$3k2Hy#t&)tT2j- zl3kfnu;2EH3|k^`cOWu>A#X(1Dh=3*P$70q0+^TVXi*QO`ss(Z@^7nQ)_%g~WSvpu zj7nQsN5!fS(L;vMKXh1?^!x*C9!HFywg=5p_NY@~86;yEa(45R)+q zp?ZQl8teqZfABKE?giKRg)P962$-dsYeoB+#)9(frDZPWagawVsL0rbTuP+XoPQsJ zHEAK9DlW(hHfZU(pBUG9J}6% z2=;VE+{*JTmelvg^krB8VnzO?LG;kPj}7t0DQ+QEI>wqXm-8Ffq?FCQS?`vX{7vTr zB;IL>IrgKDdhr z6E@Lh>}wFCyU!Df2(fXEp|)oi+Q9a{N?B6_ zp>i0^=Ou;3^kdo+0h>L9%diw(T18$xe-a{0@Ib6=1LcVlKen80oFx^2TjTgXW4?nV zQ+~?mr>RrS+`*Q<*i_K!VW+dxXt=&_7jI4g$EMV?4LO0HGIVUR%g#k>=KZ;~Hz@4P zavE(zd+^goo4z6TdJTv6oyx*%^E|~#&&5;xUj^Sb44{n%eQ9H7NmS2q)wjn_krCnD z1Czft^V>fztoEIiLCSWOzdlU4Hi;-FKT+YW<_j|S{5<*R!-xI2cWLQzm zCCVyqoc#Ni>`3mn&!h98(=Z@kzj<$Wi(f=FN`7I|ez8NUnV74GoFn;oBQkXs0T!Zu zU-f&JNOaVmyqJ`#zLvk%aGbf`>Rtd=yjRWySUW{%VYa z**PFBN3aWWDU6B5FaU1%WS7S-#~?62mnoe|{$6iw7T@AUV~~6XHz*m@vVXS(S+o{$ z#N=++j$jm?@m61H_$YN)(yyMl6>mJNqlhX@sJncm%;9)G^Q~g8C+a&gBa>w0BEeQ9 z#p0LEsb}2w9Gt+S(0ly-+)(IvJ!}jTN5!D0*My;c&9rx=-G7_$)y>x?y@ah!G46_z ze8`1{Z094X9m8B~Berp$yAd-FUi_yXF^MC)B0>2AFpPr)Whah{>5MVIgFhCsrVOWk z4_y0|Qqf~U?GUT@;-wEg)XwX7Cj(kT>k~cWfHt5F4W1}HAT>zh%f z{eiuM=SCO|Jvgc{fhi|+qYg`qpOq2W3jJ|9KI<-}g*{^?jkB&&rWp4bTmn)VBZf5i zB8OluN21bV>%2~DV4m8uOiJv4augpZ^eW9I&ngM_PY~qka;>kM+$m4&!}`Sd@#V6OTy-oXkY)I6QW-otur`RN zJ)bHL&b{N7@gHE0L`~Q+e&t6Pc5&54a*OI7iYebZbmUc*BHLx?R>doY57>IuRB*v0 zDpt;xQhMs(vu7Y`;Vf{4Z!0}9u^=QOCpzZfASiVCWL(}vc|oB^aAJE{S z$!(*9gGH2NPUoLj+WX)kDOYUWe<}4w+n0D(gx#uwQ|v0L3Sqq~K`&lYOw4Y(BF$g7 zrW9}AZ*D_wu)dppnsAnHdr{3@558&V+T4wrV$F0X8GUF-(I91ZUmsS><|KIgq!-uP z-%xGUJQJOPR_kr~&K=7$1RjxB;Bp1Nxg{#Ll$P%@MCkSZyl1bUb`G}89ic#`4VHz$ z#483lh|31pb!768&3bI8Rj>os{AH>%WOHo?b@&i6x_vEuoOw7GKG^_PLP;+ABDFfB z&X*l3OV&A1FTl&>eK+}wHhax42=_isXVP(=KryHEa&8$^vIek|b9&cM@g*~>2r{}nyXsSuTe{Nts}2%#T$0t@vV-}M zv}RmaWnX(;W4C%{>cgYZQj_vCk@VJRZZunl{WbphX2LLK|M`XT6FG`zo1fg@TF;gqKE@s`Z+FD>$i8%8lg^NjCLezqPNndzIM zR)Nh@4yL!?IMZ|_Q~)KG+bzDuxcW1k#)gw^@lu8pEMq{1(}LPqZubZ;g%Bm!j_hb< zKpJl-Dx0cAGmkIrECG&ntcn4^XSE-Wn(+Mc+>2z)4n;Z`X~;90`POi3BpA^}3nZ@;NhfohMVI?m!jF~0w$VXG&C6mNZrNVNw^S^G z`uh;Bv18rcYHfl`qFle)Fd=u$4L&b&=t7nH5{cCc3DsYtInTd&zEODXPOTmI7vr|Z zqe>vQ#}!|SC0~-Y;4SZG{sv5Y4-x{GbjB4ujUj#AV|`t(E#MsAd%Sr4R)3GL>v|hE z`c#jqkiB_zkZOBaYCrJ|%Ze)366)d-B3Ontf z-#L|LO@7(Po+SW+X_Pgw%q=K~A_i?O7aXWC9^#VcQ91=V{pZjW+%xV6D`EW;S1wbl zlu5D@XrBrB8oyDg!U|N)OBn7iZF-~JeGI|aMP;5AhYT}uX0FbD@|=;lh*ZR*z4OGT zsR)NjG*Uq1esEkOOWtX6sEb%Mw}kvI-k&x)yq1M=AX8Ihct9JSF~7igj9#X-7KuX zKz4Nci2B+w;P~mb^hF!`Q8&iSO7V$dj0+&ZRSf_yZ3fcH@Ha_3*%9#zOGz^N!r@Y}P_?sXmA3ZsgMt4t zd0op)wq-`6=+**4qdI6Q+cu}%&{|yofBj;4+++IM1V9Bzma6TZ&Y>=C;f%XCt_(Wo ztpk&##(x8}=TovZ2Q0ovM%SMz`+7X1cg)444<@zrP^_?YN=mVYvrqj5Zg-8`HlrJF z?)^vz*xS+0Z~wk#56y}r9xG*>XPK{%BD*8|_W*PhbOhhjAHnPV z50c379|9u(e84NY{W1Pu>eftoZAnaiByK~4r2 zHih-I^?gJdEi3lv7{vsm%1pB#eBnf=nX(7DNwG{*fQBWJgQ+_jDe&K1Xyf?OkWjtb z8)kmi%u%3vmQZpHTg{YBnNNdF&u?%qQp^6lDG--SA=fOU&_tzP=PA# z*ZBb5egr7!7>wb6EeG9>_H#A(p~HDl``0g)|L_kNw*KSj_G9>M{v*r(*Se-rRoxa- z8Hs1PHlCz_e6vsCsnSN{3}tLC2qiAYN0F6U8Z1U&Jd#_y2z@#w)eeQsc-wrH7{_(T z7Zk^p3;{s_mjWLj|27|PyVHe5HiCgM7nY~1i}9Fq{Bw$Z+56k!5d$7O=Nb*0j=A|@ zBGGEHk$U;4$nei{ouu=;<71o3+&OeUlZI_e`FvaczBnqq2y51{WQWlohb~9^rw$dT z_7Z=2b8M=s1xZ2>myBO!F;eDI%Mltm3yodN0;d5-G-|mjtoefA4M9@#_O0cbCOK|^ z`T5{X*nhVUZ046F;=d?-Rwm3WnL^)%ztEg`a?{&9BIHHwrX6WF#WX$0WY^ISH-R_x zALNKHPoWqns6vVJLk(KBz^BdU8l4=x=tief8#O(O(4DBwoBRjp42)l<%9SU5F z&_(`^r9m#J5A>ht(ZknN;}MQHd>A$GW)|UEtTOp?;f$sX*Zs*~MfF|d!1>Oj zA}Dpb5uMLMHc-Q(kh2|*xYlpUbw300@IO&_sxT^rGYrJd^4T+YUri3t?FuaijZZ98BJ|V8ywMGh_%?MGuQ0Ejt zv&U*LRN;ybme~U$S2_GV{!KHKmI*0RpZsi=8j!m`DBDV7$#{S2bs+m_l?%n zXJ+QKj;)W?EFw9gORzkAz0<&oHoe~qZ|ZRy8CxoB*p;8TFD$=h$xilMlaHzvx@h=A zJ5coP$a`m$OD{49x8|2_zwU*E)QD;cT6g}Q{v(XlyB(ny5qNP8IW0u~9Ox#G=_U5H zDRUX5Civv3=yamLviS#umHJ$ya?HAby87s~DakKW!OIr>yl?$f{u^}2Q82%qJeXG! z_^d#BL9lZnxVr%~G}K!@Mt4^ge4E`96~wFfvfCgwzZ&18Hd1B*!4FQw z$O+aF`9kpph2{{XY9M0*xP?8m_rQYo($ek@?!bRe+4l*I2fI?{$-^c5`_kOh-&J!*&IbKN={+0CjcXM$`w~AE08-j<++A{@=yn$K# z;=@qVAXj6vkJj8n?rE30}3nf_%AZxpvlfHnB0hx9Lq z<2X7_9bru2o1#RTZlenHj}Rq&lT@<2nP0^&l8Bh;3GiqjcV zc>>PmffTl=1?-oh&3ruh9QAqf&{b!6K+6l$qM+hmIxe{Q+)4<~4@A@D*U4d>Z-`6cZ9)cErs)9kD&~PopD_6@9b! zxtm+;<++m{v)yQJeSk@)6HMkftw4_#fF&J;Ix(ViVUUQjDd6TM_&c>If;U+VQ#WFyCRMAi%eGY*t zdDo+skWhnFcZbGoXOi662k!hOpmzdp2p$cVemsOhVbJ{AgCaQ?p!q)Reb5}66K;b; zly{Lw32946hsR=V;w_Q@Z6vQ0a8656!kNqw`jiaKB+z{%sm*eH>1@gsli9mUhDz~~ zs7To;M>0kU8R?q&N=&D4RkX;--zc~UHlh^=|K>i%;;MRV`ollc{qg1fPf>djb7L!` z{|7Hq(NtU)LHb%+X;DD}OJ;KtCj*x@7>6T<%K;BS5d&k=ic5);TT{TV4lSW#j60F~ z=KGe=T~9S&&@YO1JBdDfxR9XlqHnPoCOlR1m~!cISgn6MzjpBkXn{=E-`MTCLUv4k zw;6ST980L3qyG{k%@O0F!wcP*BNpYRm^UJPK#*e z%-Wf8(`Pebg{n*L223{$KHRhJeNy0J9CX?e3K9` zkDVxF?3WT1aI3nFUDZ+|Z8JLkC=y zP8daG7=`sr1kHj+L@+m>Vsb(8#%`4{NTTKZ1e z3&^_PVKcu4${B2YsiOzGX^T=#Mu%RF_+R~tH6f4uOfFVuOXd@pz#BlQ*gNgB0X*?t zeal2Fj9=Xa&6+OyN>q=EF`1_m-oZKeamgM5$Cf9P-?%fgfeJcaqzO{}UomNsc&D3` zN&U+(;q4pH+hnbCxt4dr<3}wrjnQ+YatT?EXmLpJqPd=Pr{vj=MYD{*NkCvXw`aN; zI0}{oFVVO)p1}UDEfQ+YibTiEDa;Z=6&PI8mt^j&EzyHS(>eNKYL>3h+gNz(l|)Qj zBdq7WQ@N24nT-G_AY`Q`oRpAIg%vS78TIGe9@*~bQg0z4b zjV$gM>Nd0RQJ4$5Q|&;|6@6*!<&1hswT?(CF;)}XE&64oT22;jbxZ-L`>S&5uqFT$ zmK*FK*{F*K5vgkEl6GLOdofp*8F|PIS|8I@#ZG zzbhrM5$lT8kQXTZ#{7fj;_;)!ns5jedP8!2Ix!-w+rG(E4gQ_oFhfnFYx&c1YJMsh z&wto<{+YUHZun2W@jrG3;yv1%Z`buLe^R)b9 ziuHS9pS-`05@5VqLjha()pcl2@uB~RQdN#2aveD6WAi*jgBa8|BG^)!w<$<>NK^~Au{g}h*{zg zlRQtsU)+>}?lDqF(2--OOSPV;FU>0dQ<|RlI%6fy{uL@f* zJlnA`wbP6-ydBlr87YZ;&XF*XyR8}yl9%rB2>%sVI`OG!({18#fj{cqH{C5rf(fuCb+^|J=~56toZIX(T?F%~j5wE9Qx%MTg& ze>(DiI~5lGgGkT+<5XyFp1ed5qNXIrPx%DUfZXv1J~q6lRtF(w;HB4UJr`>Ailtt$ z;e$dN4k2=A`ipFT)tFoX45fW^;$kA}KI8nNdRy1~*N9%0e(%8#kFl6obxuKn)ml(B zNoqW;^e6FIxX_{?+b&*GUTaTSFu4sOsdeBo4@o&L!kC#ZXjX;I?QeS)YSY|~DH=~C zM^~xsDb)R?dolh9oDybVlrhF-Xw%#3473?>wC+922dtg;ErHGFRsgzegbde)ni_HyTk9JwcCnGUAnQ0$t<6oI{cp=Q zB=_E(>rwwvl}a44!xO%K;vl)ya%Jtgi5XPc16b=$3ahx%RIoQYb|`37v^rB5nf_nK z>jlt)*Sa^z#DVH0FU(r7`f#izAHd}%NhK8f)Q2}YhoSTl=`i~!{pl~azoIm`F}=GT zY=Yqj!36nI7BLPj_IM#CXUy+lWeXP07d&pY_O#y!9;$LWQ%t7Xjm zh!phOB-KH-McZx&Nr~PDj#@)_M6b7I?>w?gKUL0()^;S2Mk9sG51K-i7a{>+RWn0# zIccT7>Qu=8oMr-{7LX;L5_cFZ8pZM=S8dd(Gf}0NefX6_mk+>=raJybh2Csxjl{nz z^!J*D;-0$pT?+n_^(&HYYSt@ki$r|vID<%0cP4Q|aN2b3l}_3rzzAy<@}$ryNMwe4 z6fW8C5o|j2q`2`LGtV}j^JHysaRDaCY~bn7u_ECAA?=-_EZvrM?aHi5+qSJr+qPLb z(zaP?+qP}nwv9^L&Xen3bMODGd2!l2`?NN0MjPYm`+ASwf4?eUXOvcRA9Ru{hW?}&we-U1&h5ej0`-Ibb9!g z!PnVIFY_)rN^B{FJzna)f1CD#RbLRsBDfk(rsoCX;0Tod5Oc=F>#Wd|*UjzYZ#%`A zp>E~;tI72K3n~6jF=79wo${A>sA8%3B_4WN)dB!@0y#OT2sD-p?f9C}xt0r#PfW7*xHemFhak zhF_NrRvdSE7sI9Xq6|uO!AhKX*EJ`Pi?GpHlG5G>EQVa@ysA3Jk7PWXzyO(*%`f)q z!1O8a3L2bA1Et4~8}#0QQ*_wd5Sj4YZ5_1sqtx1+J@kx0X}+MKmLG5ifMNx8{#4B9 zG`Is(>F)SQL>7+l$XM>}Qkt-Bx&2Zlz6Dz!;6e`YH}mC^^1x5*Y_qG7d4@r$4CADRnS zD4B^urrU~*ZJmXyaqhHNW>s{oB5M)|l)Ly5r@fWsm#%5K_z0$Aw~J?vMS2p`N=4x_ zF}uu2Izzbh9#v?KKWEf^N}4qs)-f(Ru=Gsh03EI}~{iO^}|tCE*6Qg{&`Pqq09D;7nO0%MfDU zkM-LVczjxg>5@LWyD#&@x3MrCS0%7)Fd$+z?@W4Ph;gLnn1ZPYmg(|U#bt`J^tQn- zJG^r!4+Obz8Qo>7(tK@&#WYR2WxFpBe|qCYUS1#9}UkRR5%yzBay!q^=E{?tbF zf#~wmJNl`j(~>a8*r2)fPJSOu=sxCi1WeB?KH|HC?6CgkL`sQ!#6>oufG7Wa=t0Zb zdG;+>f$#mN>6h?_eWXi!FqO_Asp^=QgjfQ|AqMdV0s`r}MpSV;y>AStQ8u5-=v6%L%AC^eWb< zY>jK`EEyApjrYA+v~N&uC1@=R7?NNafc9FZ51>!qkMC9GQ|`4e;HLp`BkXOLL$^GK zu3L3o@9%T8zgeqG>32@6m0rt{kLZg7efE~P$jU(rvM+)z3Ta!?;M!x)xm+#U8t7pP zrtP;}kK(z8x-?r`oPJf!r79h{VK9+c1vo8v%fXpLH%WVNJA?>+rVDUPH?)#XZpxnd zncOucX>Y;MQ4$Xgs@4u?Gx;IcLY7=*j+Ilqenyk(&aN!W4M*Y7l0JR0Jn?<7kI&>g zuz$!n9CSk8D0IATfr;-udFyVDVRSOdhN|kt*1Et{Nv;P|bmrhu6hqpZ#VVqg^_OJRW1a^4HPI7X#pPFV zca*%-a|FN2L6ux57aH0Az{$O-??w3KZMDyAv75KmuZbZt^)sm81mZ?4ebIL0a=V>) zsx}_$gil0JBH}WwU&6rH0RwHH4ZCR_;Ej11+sj?ln2i@u2xoEOo_yJFs0H`}ZPqmh z5-?~LP19;(s0L|~&$O%FJ0`MTmc!StWZxGW0tqtivCbXgmm0@QO{lWgL(4dBT&tva zJ1%l{P>1!(uif7Zc-l*Y#gNn~Re+toq@EtnoB9^H^dY_3woV}3A8rDXJcgViZb_^o zt*@0EAHDSW)7VeUN)ff%#=lyAtVI~co5Mv4k2pu~!=cxE30>MdXz~($UNa$Q=BiQ; z;M|c_w+3m@7l0Bexng#g^&`Gn`TY#RE;K>X@Iwzh(aM!&y!EC0#DP{!kH85hy?O_l zeHP3wYPk^*(k&A~(pCHIB`gb7^~ss9{9Rk`i1*uu0nfS~PdG!k=y;m2QL_fQh;S#N zevCJZPD;{!+gZhU&>FI>OAdL(|n~N3HXbbh_yu(!YX7oh$!}@BvQ#m zKTz2r3_WyZS{tfL<}7}?e4k4$x`&M1qnx|~ma)qMTsR(3?}G9KL=3HW_0!0lMI=H( z%?zWJTY8wFId}25F7p*OM`(8GUh7Ul$^T)|^Dv-|vKdC-VytLVq zt$+VpdGh8@I&a38vN`g9p=|yuK>UZY$!(3q5APYrnH9HJ9f1^7^(~kG0i>2cA4TZ_oPV(j}?*0*7Lg1@w%($XOzyW@oA3 z;1#W=Wu-`%99fBx(-T$?mxzRAMg==&cRGiw=Ll}^Yo2}t1V?az5GpowBEiJ`{s)kW z(}eyPZJ7u{55K6cuD0c__ZvR8ANqfcExnohlbTbHYa!@t6r9suao`R@d-ZRZ&>XyA z`SrmG|7lfcNHij^NF>VZR0^D)bg1M>jEkualX`0*KUX_9&+AQ+Lb(y8x!!5;tUvPv z-z5uK;rX-1bNKzi)-CY$_yA(n+v5^+&GA8t9}Mmrp0bp`F?JIdrD3DAk$XhbkzT_A zG?yI_x5y=(V%=+iOsd^9&%j<4+0lDt5pnqL=0JQX=M6?rx~y4-J5+{zL5;JbzLI(P zTjCO?{xA0+P^aE%w_lwIneG;QkpFocNH!NhCw{$Y+b;%cprhI894Uzc z&+xFvU;0{#XfdQBxT}7n%Wox?6IsH*YH(b=BXKsN|2*D<@6Miam45l!{#W_M` z86~h_!%fS2C^&Xijl_^F_7s9SwElC3g0xps8KiQcNv9k$eJ}wI12onVzcn497}j)5 z{81y&_a@?2{p_lULFhYuzFde|q6eJV8m$kwCh_7z+9Lnqu|JXlu|5=1r~O`81kRPM z`>pMOHWUEV$6NDcl>eSP1lN4b5Iq8gU~upo1O1$li%{hulq$wgfjHVjnB;1MJuXxA z$Hyaa1;Z|@Hf2tmeI(1Kt&*-Y7Y`<`^*{V%d8%*p#kVj+f0BuP(T@*#0XsJ-0`^~hh&vF(^WJ2EASW~m6NG_B#D0eR)dCiZ z%}erZvf;5zRw7+HJ%>y@und}>CS1v{~OD@dGvAR-fVH6&G8A%T+6&h`3l~*Je zEFD!7$53UhvMs{mI|{?S4pPzyWPcKlY1K=$5nH4!8Y(9|LH*}q-mRCT(uNKu*8iLM|6fu=M(kfw1I2X18VF_RV;hJYP+}Zxa;_p6dq zDUg-M*T$hB(ilLshO^~KBt>P?4xdwG7$kFx0u>H0jbFz6oZr~-BBl;!7>CVEe0<_D zc5z7jNu7^jmx;O_{Maj`Vd>22o1;L!_(9cB>SsSppD!&L_>59IDt6uXtQ1mBnebB< zqY=_raDLaVnMYN+$*Nvy!pwGvA5{jFLP`+`>O1bG)1$vJVw8A#6GJ3M;I-P1zBs0h ztg7hXc~Q!q@oOn`YMS2ets=}R6q#X%?)sfu`uyMk#oBGaT11=C4rZT$Vsej2WroX0 zu#nja%zC{oP7``zaC(0ICbv*k=4uwtVKX(Dv&~XqfIBpjf+Jxcy|;pXWZF>=tYj_y zikacOz)!~<9#I~4Ip0>W)mEf@BxbJ;?joZxstAN&j-*-n&5)f;2dzFK6|Rc zl3HJV%Ae1DEkWuNAw2zi1N3+;D|B95gpM z;KAT}0gcFo@uA>q@wpI%CIaGUt(b*Tj0VX)tcrw{??|MT>&*i~G0pgu?=T;z_mgrp zrVP4k4x8?ed+YX7ZF85rUAW)H04ZOwD10YD80*VcTh>42tGf0kfPZ3IO`%DW`>`E+wSt9Oxkfzta6MdK{rC(Ys*+ z=Y?OiIoZqC8pZzvVZ0Q3!0i4aK`+!lRH`~}-iGX>M9M)}SFk~n2Nj-kyqIPyP?(77 zOJNpaDC83f&#Bv_BH|Yu{-yGB?s=%5D+)gZ0%R}Q0Q|IpZgRTCncP%B&bse#16nwB zJy)zz;Je{8sjgZZN)q6XS|*|p{AIdodU{L$$jX7qAM!P^Z9rSFNQ1qtzk^M4X*`z{ z+Olu|bknbp)>`e&)X>;3tdyjgI9wrxMWUw?JcF0ztywhDY8BSh#SQ{G24!rw7f<;@ zH@R8tu1P%C{gS8x>WZi0&U}c3W2KF`+siDO zy2C&--!uB#Z)S0+$o2|TJFL}h$$q(c=XReAHi{)d1f4r0GJrVPRQ4yV6cc2VvLZ|u!Ypy0xwRMoA%$+6#)z1*J+NQO zX0P`MX3dO$JRhURU9UrArM)g4!Vz^1i*zVfD!M)=F^l2 zjwRuGw=+fch|GkxlW9^|@H2I}8Gk#^k_8VG@eS>iO?OSE6}Dhns0=pZ=}wf|)6H==Q>K^)Ul2r`K3gc!7}V~#zVc{n(zm&3}L zWf7)6^W%2#G^NA#EsHLuI?6UAsxNg4?sk)^&XjPO^S)@s$9A?d#~Q@0%I>#N>1s>` zwNA>LVYW-aOLPH0PnNnOxiNl73=L@punEwBe(JW|C!CI5V^U^`d^qWnZQZ6vEXYl) zbi$d8Ja`M8YId@0b7Z};F$Q#)gh{4htV}J#OvVv^yQoX{TpHeFFt!_itk}I$`b?S` z1msN|xkc=JuJpj^%#!CudaEcp67De93I_G-H z&BQ+Y*5R2V_keR-LU;7A*DJpMzA#~{6W5Yx6mStMJ1ved?BZvN8Dr$&Ug(uF{&lq46_5vl1^iNFK1|k@j3QGb(gcBXXJ<5{c=f<|&kH)suM;ln> zz)+l#;s%+3$51h+ke!nGSswjmE3~{}XH`E{VF-KNlj2tLJzzn0hOw*sXc=?A@x)EV zl3QaG3~ZuYIUM;em7A9YuoAd{4FnbzH){@pZGl&V)xur*`Fk4>Rc*HB!EHmtm5y+G zhso`*hMz-~L0HWx=q&^ERQJS<&oK?g#Kmw&PMIYHL&_NwA#;jUV~KL6=Fy-ku|^_YG{@n#xkMBL03Tj_W@VvmfX-v zUoC8;B>&ts^7mBs-wWtp+y^aX3~tsn;<%&&@idkV%~s;L{J4vHiUQL)79WQkn1Ome z*Npc1?{O*gOeHk<#e4`tN=ose__@f=jZ%>O#gG-hA;BS)DJa863DbO`at}8j8Bd{@ zFjg`+KA)3btsgx-_ut(w!KTS&kkz(XdoSdgI8FThd~D<%gFM{W;2pqT-vHK8 zI}ZSi^#K zd}K&#o$gxsFs||7H1T0S%eay>rYtb6Ul=TkrxR9+cPHSZD2vN4*XWR zyhiVsC85cl=@1;A@bbnlZ%>#58Ef~lc4^_uCZ&pND8Q8@Wopp;VP|gEWRmP_Dzgu0 z4U`C{6@WF8Bj4C#5QvwlH%$&$v1=6(WEUA>O$vm(t+5hm zvW&}d#t5Hb|EU&{;i6D2Lbjf49x{i8s+O`S(pSB<3*%bQKz!jr9o-BCGRn;_2#0lT zMc-8Dt1ad}XinU~1chRO)e7X`4E?%vp+umZB zS0Ts}*$q7UhuNavG4MqsRmmfgHc{Ryqd( z)(AO1MYxU47T0_JvlquLTGmHmm1bTSVqKls47B}cg62(fd3)2%PKeci`Cg)Y7`B%OL_VOuZ?>9A)?FPgaddq=vG zZ@)rqplut$B0A?tygxAf|h(A%2Pbjt4#r)^3BO; z=Y^FzG|zeeLM^I}Godk6RmI45J}%%*x@FYltIFoIaawrRh_ye+T9- z1qM^U#D!ytfllg)7nDLB(-OX?&nG7T_(cO3RFcYN}*B4h9g(W!6eNqRf<(2k&0(O!N&ZfCWz;hOl zWTWx~A+fJ}0~jhR^RO-LYp0j7JuLwcf<=_TI4jNerOVgZYiZ-@IJ`vw_(uu2PT4;0 zn{(>*sc&mI3Hk#;hwO=5=dZB~%nfUehLe0zv#t8{v4ZbnsaRmR`GF_j)GZ8}7p>~3 z$bxM9LxQfDe3Xay#lUb8)M5>{bQ>XfopXP5={6Lena5dkVh*MaJYL_i_RSNmS*Zm6 zf{>zrK+oiHDsF?GaxJ@yF3p?0EC~oKG6?ZR>|#Oc)o43S2!t@|dx9Pdj{x92Spqxm zW=QlA$GxnWRHbh-yqfX6$*-|IE zfftm?!B+2ki`&LvLDoc~2#WFEH9nquG#0q?HAlh{-S2gdLm>E`K)LU72eo~6X zg4wU-F&m|vCrTQOG)0`OmMc~=ogoL*^=J#ZGQ_*cvJ&fE8i;qNzzFYjgmKg-JehW) zs=O9AG&+?}A$ta$zAiPsTvm4#Cs$lb3`iY%NGC~&Oh;GuT*i9i53AcbA){XsvHtRR zv!!Q$EMmJdKE@Ao@^Q8HM`(#e_sP6AYQ&0@^=ekPmhxuh7x6F|Tg}B-3UdOODpanQ z*mKy0YshoFB-Wqc*_fE(Ed+Z_8Glycs^7==5kyV%CxFAsA0y`(V(*_8iV-=|fDmye z_UG&Apr_3_Q=9U1(iplb$3u z0RPN;zPA?9*Vli@qO;%?-9Ix8@0m)taxDYaKH0PD&U+2S?18Pzpf-QJ@!eXg^P@GH zM7G>Kg}Y?z)qw-BfW7$Q>PM*3npk?VfS0PX2qX_8#(`xg>$8ho(};T2DCv`kl-WX; z&a*9I4yo%mFh@3tu#lUj8$`q{u%QU(9OCzLeYnB2*x1Z#e`o7aUW!Vo40$hhWWLLr zRL)q63Osr1BggY^tK;zgcB_RzZD)Hq>qTu|%tqm>yp*RTQ+_OZ3KVWt%obq(Do=g5 zc(3n=&HA`^$C(eV$CEWCkB^}THTi8mO-ZV_Nj+Jb|4*6{k7|eb{q6jk=u;vc>Xj#g zrjRbgVNx!*H2DByZn_W>wJ46vphx+(6w{&}35y;Ih3X!5Il+Tox=BfA@_el72tIZO z?b3z`dUxYmo}QURKBA)3*V#W&A5%;MSvwD$6A+3#JPv*b80>uAGM3m(z+Dq1OV_B`4@I-9he#KOZv%cvCWu_b zcXxv!6a`Y#>sw4H^aPH*`%Pk>Y6f=K*Py->xt`v0M?lLU=WB$(U^c{ae^}D|qFvEt?<8e#6J*d$UXXb{**5(x+G#g-D_{lIi?f zqj;Ja!CU)kVlC2ev^iuF))P5svVBeD+Lf_ZwU9O3>n%y{wA&{Ece7zfWoUC`bn*&Y zX5yY@B=?v%Z;d4Pk9l8yZY-GtysOI~`4mk{L!CbG7VVLCF3MX($%7OY#$TfuNw!me zv^Ih?w0eqLV=uf>D5fGaHG>?jX02K2HHZ0KyEDM(BY8C@T2z>w*MRmz_Ujx9(*H1f zYzDMha_I|>GfB~+6+MQVKc9*AgH|vH8jU33o^$Yk*-Vp~85KsQzHK+n*d$NSrM0g)R;#RN))!)pN3?1200|3le3kciiTQ z^Y!!3$mMLDh#VZ{(RW(z)o)o{O~Rb0f}DvItN3u&>~B2+ng%(4`VF@!?MdCd*q?|# z`rjGC!Ja&D>D164)dN}#XT8`i`hQs^k+Bl^s>1Fx6u2(9QeOQsmT}QH&D1EJ4BNi+ zb1ACx`gTb>Q8igM*#-7F*@Ln0%s?@|x`vpL3-SqIK|Gll2fjJyeoI;(ny%X#`Yc}2 zy9y=rS9ULABKw`G91PZSNYIECWD88Q@;j*I7C~i0w1r)CUn8|%gH~s|6b~MxhNt`P z$hVjpBvDlGLl$I5?CNL;T`UTzN)B1QSd*RT)}X{(4%vB;6*_qKhXd1Ag2;?y-cf

    ?)t7hY(c!oXpmIfrmzkOMM?wLXvx=SeOE~+DE5JgJ%O?# z>)?#ZgLgDQKDT$*snxKomY<>3o-bUz$U-G69dtBze3aTKz(Ag4P(y@Cooj4GU+IY5 zHwtM16)J;z|D>Lu!H1f(F%76ckcP1EZm;-F9Svbl!NWOqpdNlfua&LmW&@Js@;2Sm zhy7T%F_F&JP$Yf>lrip%GVd(;SV)>TQw$)7VJL?^)II;laI#ZC`qv+ebFdRT>cTOG zXZ!xv_MR2ik}=KsKb8uAc8tO{Fx>=qx*@q0~3n`MJQXUB~ETIxM9Acpoic%}MlK-Ms(MhkmiFi{rh!|K@(~B@X zxbptb;s!Qy;Z^=ux{LWG$Np1?yNsiSg{-54jiZC2gPkG3@~>o9enjFsKXQ3yd8F-@ z^MGXTZt$8gf)X;Q0GAN(t|=nt@@xu32JU@RzhCw?*pvM3DGTk0G~8{Wj$=nDE4TIK zRMj_@>i%jRyYq&V%v}v(4G@4ND2GC3s2~mII#NX8okUH%agEhrYdH!WCdOAMZ`wA? zmC(LpCNcV8>;0+7X!O10pWD9KYluFpYu*-j=wnX=NYC!*VKhp1gPA=-h$MoND&a5! z$0GlO`Ga?X0KmSv_~+Sv=U|$K5CHT$bh$*7?91Dq7zBTAZg}8q$$6| zvKW*Gy)Sk#0H^+jqq$0L5@(1m$3A%wR?7xE0xZ<^5~Rh-6txV>A0VG$ZZePG zMx>}H(ClCDj&D5=9luJkA20U|zrFTBK&4E{!mz|8S5oD;NomLrg)l0iX`CEJDqfoY~ZaGC1$VmeunFH&ah zx|-a2`~+J|*7}qxgTXvu^ee<2WV+EpCQDo}CJ3Hpa&vKEV2TCPLg6vLW;f*Qk|gRN zT&<;X6fh-!Y{BFse)Y9R^_Pm~@b68By+aq8cRe6bad^yqTpcLzmS&)z6U_ElUKYeK8-0O~3 zndzfpqa1y)0Nz}-Tv8O*ud7l!OKQqNTW){zW`3O6#-@T6+OKLf=Azz4a>x#n$0(o( zWKwAGW6mn}yzobAsfa=kjRr9CJMn_j05lII0JCn2hCWFOD8g(y+Gui9$u`J(i3^qd zUXMbtJbx2c+|{Vn->|WhN-pWBWT-S0Ze@ntL=z&z>nFHGVLsOBEaK5ylhC^3Knzb; zWMtc^Gg%q4_ORJty3w)5V04{_+=1yvd|ZJ?pvcUEzY!z}71fZV;4U@|8ZSBjlUOc{ z(C2r@cJFjDOFXw(y&{?gp&}V;(BtoS&_lR6%&1#r1T|5S%LAScAN$#jN8t!mE8EHr zK#~3Hy)nrhlQGF#K~rKEHf*op3B+w)H_i~2KV^M`>UW;?I7{u@9GAs zJlm#hD|meTF^axy+l&7wou6xdhpgRZqMz`3kxc%f{p9K18CUF9Y-}k82v*pSSBY$E z_XV63yA6V@pk_fzn`RT|aaA?>gP6e_uwP+U@}!mzYgdzqLU|JnTJhK8}E_|L%}3ja0;D_L7x*#FgDs|uluynyjR+LpGWjcT_I?4t(H9xL5TXr?64 zZ-8WQ9GkyF0-xJ$z$6aJ+IDbr1*!a-+Xb9)N zBIurV=gt&o5Jx@G+wRHq`MUM#{rRku`8uUo^sT(Vi@02>RD^y5XI@!Q7Na#*iVT^k z0PJ3BcKT&LdvPfXyio(MMu{>ekwBb$z2r>67lLF3$>L(YWDo`e7D9N%gX#wqyWoWM zjM{0TTzQM5yW+;62*f~4$cDV&QY<$!;?0tY_(bz6Op`yxjG8tzcJ0cB`7VUJWuU*W zTs|%4#%43g;xaM}E355csEdGj(MB>!kG#s}fge_Y4x2o2kLjJ6DMT6JXH|mG{;7O~ z8%af=zXJqXe86bk@3i?;@yu$A7zS0}vT`B=0*Y%r+yhB9FWeszt#s&EN2-SL6450Z z9%98bX&2=;x9Uu!WrIOWfE+Y5y%>LH!z$M`2Tso`{TejaX0@kzA<_Wq^qF|8k6c22xFnYv$)b_5<(aYr ziB)lH_!w8SR=H70IUfDdFcnv`0yVOMYju)|VfjP0QE08rtem@lvj$vcX05q4VS&vO zGw!^!JhFJm?;tJ{cqsLj>F7}h(qKRa*ivZ05-ty`IK3_=cBaa{oIx#F>+Pv7{{O(b@WnLr&H)(jzFQc3$h z<*P!`r&1`Ig2e#wq4jKzDw2jKZ;?nJms%&SrNJU?44da+GNck?j$`pn!n-T=ELJY1 zPR-6Q-~Y5mT6dY2psIZWhJ~srrq)Gj&)zg5Px1`#;r=qTJ}|E0;0b}X=HP5glSA4< z8c-sFL}v>DHH9P$v1xk@?VraqH&M@)M52T(n;&bYNV&4SWDPxk+{%a#P;X={r{x~O zVhK?R^QcQ*KdaShu*N5PIj$5J2GEW!_t9n-SSFkSYkGb$OwR_sS;f;kx2BL5g@2*a zl(6LEzB(e~e`55F2HvQw?+#43V8u8}9Y)tARV>zfnsr;i;#m!?fjn>?y+>9sULe|c zgtrY~$J$mUV;QW|9XK-L!rQA2`sr=r@8Rf0j=GS2X=l`k5DlW@LNEhzSdaY+UV@S} zvN$)p2(~B9P81>G9M9QUkB#*1)FYE!0;kNhoQIS%TQPu z^gUd<#Abjz`1Va>etUOd;UOyP4Y{bGy-G7m_vav|!8JJ<)e9vJ?+qS<7#ym>US`$R z5>qF8sK}JHML}5z^0Z@JA_R>xs04^KVW@1Sl$A-SmZi!V-m%H*&y1hHY4CKg?iW8r zxy6#R{8|Zb2`A}k{G|y zYDCX$Q0d>7TjPa01!4MYn`U&_DI;#8eKY9rnxy8!sNF&S0r0pm(OLO9k zWOhW)KTi83^T29nsv3NN?wZQB=au=CBjZ?V&GGzDuX1kB@J+?$b211J9z6c}U78U& zqj~wJ0&NUGi4-{|8C6wrZ8YToBZoMGrL2ohu#jLNMoCM&o}!g>7XgX)Y#t$kOrWqT zZm320I+8P%`5+>7Q?rOfNlOS{=7W2i58|fhmHVT&ip%BceB$Nd+TCc;8Hk3Sq}& zCm5%1G)KQVJ}-5TGLjkFoc)9ylYJ3RTv6VVsI)r548-W_(ax;JSEDjF5!0-sAhBUy zL6nA|e_BjwX_w>TM)$jpb)I)@3_SS~;yV`M5P~ILAyuPAxk)L9^0|Xj+Z%1yExAPL zTcvW@EtTYrsO<*5lf~v~Ea+6HlKT2c6u?2YTXQO##*o|{oC;4^%~!`nX?KY5tRDvY zgKIM%(ZfC^=16cheAz62ct~qEEA-ukr~qQ_KoQgh$l;n)?YEJH72qh%)PibaI;L?v z8giJ<*Cy8J40li(YzHQMcTsRWDyJJ`-3h)9Say$vr>|L2?m<1?)5Btv8}$z^56d5( zFgrZFwA!uQvqODFShe`?Uq1<={vr7K2@rNekC$dQor}FsL_Tya_6iQ0m5I0)=Ykd~ z6>5uxOx%>~_xXyxkmfpjZmhx;dhP=d3=q_lG;J>1PH8h%Vwu)lq{9W54!;89&7;SrLYgv$?5zScK-x}Aj0^lUIw z*#B+>uqNaJY7M4%0`wk;`?-1eUr!1$qweN~SM>cXNdi0jyk1PKGSzphxX&bPkGXD%c#6p+aV`$jh+@_tL(j6qJcvLqO5e zxHHiEI3hUzsqyDE-QD#c7qP1FKqdWDQVK@8DBNQc1oJX$sEdt!(QC<7`d~q{)8m z47;>_9H4HvOe<*g$@cz@mpU1`E4m->{GeYqbWqo?(=U6L3svpmgC*Vpv8$mKu1S8Y z(rQHa$K@-;_H)f_n2>_&dYKVKH(SxU4FCH=zV#@wck|yK-%AnEhtd+RT|x zR*$ZPbayr!iTqkW5K4)z$+dp{5PU4;jm0ff7dWq~GNtyPjk^KMoc<2n0I|p?lBt5E z!_Rgx-u8BLxJZ#>QwWTbg;X1{kqH9@g=$v~(elJE?BCZ?v!#yVHf!=p76Bp0R}&6x z#v(zUW}1>$-{(U-&zVE^mN_kP=efchAa`8Mrz1P$S)w@53RAQir#hOn4B(6WlmRsu z=8D-Vg!HCfQugB9&D_a!)~R`l#jdh#P&Y!5EVlV|I3!^KEBJ`W#|*Mw5Jm~QZ80I| z{9vs1ENn?+9;q0gB84kK8b=&|)*Rme9C;7+OtVBX8Dwcwo?d%Ispv?P&Sf=f% zQQukT{LZiA@NROZ$gT8iQTEKoT6JJs>JzYsjdkZQk8HX-p7-1HSk*U`tAg$gK2z40 zL6`*CHja4yeaQ`&jcPQLsywZ#y300Bu-B8C(A1o!sWxc;?or_z7S7if-K8+DG-gtp zd+OP9)td(7+Mpocl+USL!&W1-L+*y?=fgyID81);LIBxuHl=KvRa=3T)Dp;SH z-w8t? zv_x=NZ&rQgJLFo{zEfq2EdYFusj;O}6q-PpPddX16^X*AY17I;d{(*?$^GE4kt1-+ z&@lLc+gDV1{9w|qmTyo?Jo8@ zO?5*VtV*yN2$?79MRXh4qTyjpE7Rf#f`wq8jpOqeVW%9)UX_?Sp8Kxxu1kVuu@_?& z*ck(uT-X8}1V z=teldw0Q)isU{y17Cc*%!2ocxa`#t7H4JV&x;}c%s>a2pcA|n;KXKamQzPE=2~uNDL5$KRMbWUo_>_E5Wo@iS^aA?RiVvzJ>7c5{etz|008D7))!{kb-=7_jm8g z@$i2oD~=ua%er=jq??TDq9>eET*r_0@kH)>LEgHe7?j|}@}Z-~%iE-@_Tc!fnW)c@ zBWEy%(N@R0@`RixwUGX$xV%D#xlF#&gxMU^{ij4I(z`1!@D)=zzG5ot|HVfAZ<+9~ zyjfma7MKCvGeG%=D&Je@F${dkVBR29NKr&8pBR@@j^2n>l0z882Nhg@zaMWmo?*I` z81%Jo(s5b}YgN@;)n%0Iw?j6)=IPm+yAUi>X}ySPQ(_Cf<`lCsy%A-u5EpBf7`WbG zH4RfpUFd}x7X&UuxBkn%8ti4@8|VfSy)|2OE@_H;->sNRW{Idu^u<1d(jW>!PPGA1 zd>vySiHfv#6^#|FuUJua_1TZ<8R*e5^C<88%QuJy@01)lMsQ#VG!)iyPVlUbuq=tH zgwE3U%`L+q*^&SwxR@>+5kTxtORof6@Mq&EY=OFx#D;+x=#7dnBAG**=vKnlyeM!6 zV@l4D5b03&cy3ykgagjei8=PtiAC&&CJTqGU51;=2%Ixu3_Ck&K^gj>@4XFD`NG%X zW|r|iA@<27F}mc7iD=;zD(JJ@fAud>lpXawN@XkX5e9St7Z*%UB6>pz40*? zn7hZEjWm(77LPSTC7fq-5I|t3NJlsy z!yR(Vgmzu^FjV3WX6Es-L$bMtXd;0D7Kx5`(?v_6c0MQjrP5giqadks=DPjhnqRs) zYWYpMY1$@sUzkvxN!@(c3>hm%zL1^bfN(z{_)cu7jDus&cUu$$p@5|#fdP;m7`fQZ zNO4oCEXksp{CFAF7_3RkL_2 za>sgZSx1OL*&#V{=Rs2=&vt!F2B(OtanH)G7lW!2aWwM4{K-KBY9&5SPjPeXb6P0i z+0aBqx>Ly(%Q-iip;BNdc{@$c7VWWrC4M^@|Id4N>lc=UWA*?^4mUP#i$rFsggYTs zTe6hw5E=T^dS67kiqm-2qe5ZSo|P@6oD-#~J4q@`-@lOLhXf*`>raKdd(M8oXQ~LK zin|=sv(}Nx*~#2n`ihQK)jN|CeY@GAqa~3jhNl%#ZqhOYs)23B%5R-y%_)}<53pNE zZ-@uOmyhhC5D7VK8Fz#5Lu>?I5!*IME`ijJwII!1+%AdKFlyhtgl2%Tkw%sCe~6-_IE%t?)sSYo*8Wrj znsV;~@Uh$@-4GNitb+Lqik2V^m-%wM!#rY?CUf=wp3Z)+U*=`=M|=s6b|B6WhgH1a zi{F99eTf>&e4vtqLw)Bsogkd(VLBN@BuJ$23b3mC)J#*Zm3<@s^S5fpqK4vO`&S5~ z{|aZK|1gxP8UoD44ZiM%rVg%3|Jpdj|MgAM@W1B6%1l54$s>Qj>Id?x4YQ`Fh&qMgLsRbMt3z_4g6524BWh5d zB@s!EbDHrHc3`8dF=)ZFW^-IOBv1`avu56r{6;vh=b9)W-hou7JZ_GLFKhCK?Np1M z^Qdb6ElcjBm~`Ly4E$cj{pFo63w|;#PW_f#L8>^s!H7v|R-=(8+Aqjrm?$2e(0;T^ zn~!7wKK|yLFs}#jf5v)>D{2s?ub`s-RT2{ZA3vb4lAyJf@qa&_0)-W;IXQT4*06K7 zLTN$N#`p?8)M5lgS$z0XJ|Q6xWMm?2Qh_)6Km^b42c(D{W;12-gAs?F88+-GXEb{dGdB#TI zeAvT3@nAeDtI^c!>QQB*8my)I>k&J{UXC3^21BzmVbdVp2@ajF*pOH!auEd8<>l+ZncZQYh*!`jXaSe>5_>K=LmzM?=+V-##I<4V+dkck2; zvV9+{P5+x=j&liDkWm7C5(V5M-s288qnB+Nl+V<^e*n2eWoWS-`x&~?MRmZVVqqia zDV2s+&X?_}`=rMMmkr1qtnMlu-z75%o4bog?;6O-Y9yx0I0D7;BYug6v^#wk<0m58 z9EhQKsN)z8Kbbi@douZhp6D{Y%KiC)Odjn=apU z*Dyg(2XPCt{HDM=!E@#=Ddds?cVv@MlT#!C2zD-rm&W|BpZ|=?Id7R0&2LnOe4|p} ze~rq&KIH#{Nrk`BvQsohX5*X53T4GfV^@l(6)XD%N&(^FlSJg;FESsRoop|baZvpS z{bzQ7e4#N3b2$ldD85l?cNzQ>NmmY~+u?XR&11Taz~}Arlfaj45;D_4EWNM%G~t2k zRKt2lb^cz8$FXP=f5F;{^~kFJN=YS@qTXwwoP!Ztsajsc4=&YIT_gEa^$Np9Evk>j zEXmUzv+x(0t(^-Nj|-iQ`mb%!w5U|z>5K9ne*l0Y1HoT!kXgOG?Z}lht`vm7$^p|F znk^>o0q={{XD*xE6EN!K-!^@IzeUCJmnWt$T@1yBBLxE!d#nu2+EsfrQ;hXIHl^gKo*RY{REA zFVG$Z{e(PY5&e8A!_vuwy)FHBZKlyg3jt^yv|nEO<-Gn%dBS#Csf6|k%Sk=9Rb%;i ze9w+5A1^?0s|7@5T#q25#AjH1=KZ~W=3&;<8&VBoJ6%JR*RYBqkM6-V^IeYPJ{3&& z@PP!kbngM{kZ$lEtx0GD0jYffDMz@O@RVJ)NV>sjp@ys-E?c8qufVVw>vA5G0pE8I z6*Pvb1xRI`d<7>sMQ?WqKeEp{*VZ|CA}TsJo0G5W$#(=k95plA8Gx7D(>KXLT6Qc- zr)R%&+w=kQ3wmba z@kR~!w92s-d3Y1mEe45Gx(x@ILJf^dc3r)p;%FerR*9M=NbWc`mP6l$-67ER{{_G_N?u+)7x{-bz9?4Fg!I&8GrYLAVi~*>{Jz^;6p5LzI z=}wwMO(2A`#IYTrQXp*5EsH_tqven~V1@ot6R2pEn&r#nJnK#^{K*f}F1rsmQ4g6+ z;EXxPXh}yF&=^->k)Jt7hO<-pHlw^EI9gFBd^C?#OK%r$j`P-Zv{WGpn)OAefyh}k zu~OnYe!kV|CTV}_%_^+7Pq;}4uwidSUtqyFIZ0X~ND9+ma)Y6=ZIvnXXdAfY9?~Lu z6C&ogwG6Qb(B#Tu=!04r?I0ebzx9S{6gk_h+VXJEUA{D0jikSvABD$TyyNFgXHHTF zTgVTPrjUO(1F!LvFN?G#?7Fz-725@4->jTlmF+7v=>U5JZN-)Fo|EvQnayh@l-F5{ zF^x4WDhd~n**592*;7-Z7NKf160tmp+po!obMLdxXEaJ}r*K<0_>g(`f*US5cC z1af>SJ({<57dQJ7dinl&$5FonZEb50S$L=37#T_L2@MygAo{3~^s zpdX=8*nqq^?$80PAaO?wHCs+xKePy~B=P&IN^NoP4=!AWG`>$gfl)hs8-u`kQo3L| z_yijIaB?+je7A5Nok5$!)}1W5TYDzyw$z09Y>`aG_u^5D%vMCpX@_hF$9-4wc5<5q zxlS)h$al~3A}JE}a-mNJL4~P(6*z*&AyM!;k2B}J!AtW2?Rn=OW&?`F__;{BDOlGw zb=Eo3oR!}Nkip(M)nB8r3X6HBs-i)$hj0-C^j^J^5wvXTKsXX@4wx`cm(-X2t^c}UlKF*G*hQ(UD9Fl>T``ZAOt zS4F)8)|tY|T`{jm8=VsLPB=rz)YEaKrP7MqHDYNcwGL|%900I}vC&)T@^yRjS|zlG zdZ^34?S$C*EK+vh`PaxLYr?pV!4?V1N4ko2krL>MZFPQZA!iATnY8*Smt@(kmnCVw zJTM2;Xs5VUd2Y}%8C0~}U{Sc$iqYgJ)}2+I?i~@c5P6al1jB&1)u-?@u_{&njsWJ* zzMw)Xn=xw=WK%3V9)hIZsUa#mbm}dW!@;AzNkLbysP6dLUWf2F>7Tw2!95~?4o-;7 z38!OS8PV!APnSJ+slvxcu_h=`G%9Mx48f&e5`Ec82%%UAEE;@9u6f^<)!7FvVW@7Vyy^O}(RG%ivgTu~SW)Ci)J&#-b2 zxY_52+IrW3-7RH6qp6?K>v3_TjG4Kr1K159bFyv{05#{DK)8YbM*A|GM6p0QCk-_9 z(Wf)p6=K1t^#Zzi#j_*bKA0c)6ayc6J>U>JdynWGQr0s`oyys46gcendNT71vRB2F zeQ<}H-JEq=7`KQ{vczsyWK1Ks1z4ihDKf^iU1Z@2REgD!i4~DCTE8;#-hge%Ag^b4 zbs$UjhJ>*lmfxq3fhHH!dx&*_uJ}(W*dX8e>7Ba$^}r>&trDq_+M1aAPlo2!x&*)| zJroB)GDAl>mmdp?_h3ne!T82@u&`!Neq0c0JhGjnc8g=_BTr-Z-vZV>1j(LZZY7r5 z+k4y?UO7p%{3fCod1-?r;;QQ*NaVYa^(i+-L_J!~jizeqBwX=RB=hQ)^Jq;MoR^fc z3Eo0?SYiy#mc7@DS8y>2H9Hcmrb_+7;2L8DoYA;=gp?v^NSkN59Mh<2s)_RUk_C^lWw)Qr*M)rqU+*IR)P-`gog1Nc4C%CtO@lxJnMK-0=|RNxo3pjzec({jvy(0X& zJK&_u84CHV^(^ecr6QP)9Wm*Rfh66SZi3km^I7>_4aRr6Dg^qz;ul*#2oA5~7S|xS zF{mlVxtb54xL;RyvG-aP^r0MRvTP4L50;Fuz6y^~JynJjk;BY{LJ zknT*4zZ1D2a9A$7%Z$G%qKrL_m=MMfZ=t5<15%c zFZuv#->jC2w(?gs@_;z@7;ObL`_ERy4|_CQ;UG~2;82C5+EiOCe}zh}zK)2*p>s}! z+JlB5!t-6Zd=+v{5ZS^%^m}B{>gKER@kD9SXaZkO;K(bs37oMaa}qP3?`_F5R7+|(Jp;k# z1QW~zkk&soxjB%&omW<>R@zbYV6gZmMsA&1<^!*%Wbco)q3ixG?rJl~N^-v?Jx;%6 zt$9*h`k~mh!uUhOm~D9?Lq(@6NT^HJ5ih@qwr|^(wHb#|MmXKR#5^y?WU5$>rRFqW z#gdN9V>!pGnMEVrBhuL}Pd`rGv^_$i1IB-4Dr>>+T0+43`_j(}Y4c2z_vgP1ug;%0 z+KRrr-}&#~zcGh5*K^jRF|(l&u(WY7`fF~b^WRN`P?QuzKP_C)_Jc}A?hcWo!2?wO zPB~;>RiRO0a;j*0xQW9q0B2$<#98mnkq74%r_K|oFK}>RkugbnLG4AQo$}dt9;vLY za$ZUkqN!7mNWmwJ{48@r{WWNG4A*~ZDU<5C-u&{a zd^e;dTyg?mkIRhXT--!tLp}tK#~Wx(icfem6XzD*`R4=X9s8H}zqC*g%^u7DizgSh zbaF8L|9o;d6ip|*)}+S5H3UR4`CChBPTvp&1wL%FEzg*djN|jqAGQ6dwaWc;8Vm%P zbJMm)L@sNz3uM1Dfh}H=8iX4(o&O9Q&1e13%tK@|l~-J1A-TB| zJQ~Q!RS^u>?-w9h{1T=AxIb`u>%y{2FzLp3CkpPh!oKq`A5y3w1OGrQ4&dA2Cz_Ec>&V-8m9nE!7 zO(0`0+EKh|2&jj2gV!%kqhC|Ctl1rT3uwmKZ+HryWh74NjPwq}M8$?@K` zCc4pmtVda@j4tTn$sE+vxpQgx>NxkRw07t!XvxI0w6cby-t!&^zu95)mo$gN!-zDA z$l@i(YUz!t8&R?8C}rXU_0G4QEE$W*(jxYp6K{-2)dx1@=&bjWQTCaqFv+Nqfh^!w z4-8pI7|LZVGV3r%0F#<{nfcrwmdRvcT}0>HSRPzWG9+?ZIQFu%(IBdEL#v)^sSLLb zU}kcv%U2-`PQzNfMc|H+vdETW-Z<>HO%w1@V@X)p^!E7gVEx4# zk8$jgIz-jlpP5z})fTGXd-Y)}{`|({r}JZ~3w|uD3bSaHMq4thF<>^9>l@%M;`jF~ zhRC{Ww0R`B6+eMQdfB$L>)+6=Vgj!H^YCOsUaCQA|6o zx%qp`qFk?ReKr2j)~aL>nKt+nM0!dD*+<9*V$X2PjXuncxsva z>nG+b1(FU`+$e}+@!c-%SbWXWTf+#n+FNh1Ms zbU3Ll!?#3_vY#!>sf}#1drRWkZSd;)2Y|C*E7(bgl*4jWo)n#Q>|=JH zJhnN~^UyhHbN9OK668-`Gis34)>kk3rg-5N& zOuV-GwNZSa0YL~vD6%DIf#9e$pK}$o@I6u1I0O#w($?!xcZnLq15%b7bQERt{XgUt zHRwkohL57y!saq!eH|diXvV@EZ}Uq07^xpmqzv%lMMXkIc=zd^YH7{B({j)=2f5ay6p>$+qpa$`u_Uu z@8AizW^uU%yve$NdivpeR2XRh_P7a+EZ90*;WVh@+i@IzLVfIhVt77K1WN+sFM5&n zzHXG7xs-^9_|=1nZ*)dt3OEM&@6c`CN7&U>+)^)}XlAEar}%BlH6y+3m)5fIxC&Z1 zv7-pp-%m0hCbS%kzo34ARJ6srgaNorR{a>eWS?XAExOHYam<)PhP*>&rd;ZfQTPyf zgX-#=(u$qZ$-6)8OYpC;_{7NUWa4{^S@#V!$^W1*khM3n{@ay3!hiVB@AN%4`ky+X zN?yZ4fe-HU&jF#?UYXfK#j-{PteEJ9GAyy#cQrE zyyp$*g9x%o$^wRz5NSOv1INAB_9Tpl^XE4ez=_jvW$Bx?0mL$&K8TUGpt>?>n_yNE z9FH4j(5KW7yNywF+07&mg&Q?U!+`u$L>53N>1Ip$;Ct;9V>pv6r<;mX#O(|hTxH=% zRWK-vYcnM)N!`OyqH%p(x3#uXe3fT|aa2 zLiV?C1EL;66FI-6P-(6@pRao$W~e6P1l(E-xsmJACyz$49z{P?ecqyTfL`6)`+5eA zUWWJV6G0kP@G9iqbp)78e7B>7xI6w8Sb-o*GUznz;+psb%W5r!)VKaAN!sa{)*bxtG@-TsF3#rGVXOK%X0b*^Nvc^@mi|=)$p*>W z4`7vHPLv8(sOA8$IjXC9m}&$aVbPXQxJzxp#>FTumy~9#Tqw zSCY#Ap10cHtI2-=%6~_wCS@;`bww<1Y9x7jEF@+@bnEuEq{d3}X_n#yr$r}aUD{JP zxP^yi$Y!w=Vl1BIParIpXxv`d!&?^{{`6)t_Go+Qgp7=BudOSI=lh!NuOBx6XHXI- zE)JLK)4SCM9nscJnC%uEY$FYt4Py==uW{K7mm7V-2I^PI=eAvCzI2k~EYO?f$IBEU z8@9+$42AhlE<)e}yMRb7_?IEstEKiLeWU}5K0E^_UJLY_HE6*Lkn8(s0p<995>Vhz zL952CD($}hM!{?Y&C#vxI3bQaUWq8g&yh@%b65 zUUj2X_QQ#$GIQI8W04pw+!IQRUoF7%PFKJL&E1}~!If|s{26BG!yEH#b#3(e!nO$htF3@d4pr8q> z=NFiye^^l@jQ*sXbqgT^RG{{T!Vf1yn8lVoIlP1Zq5P>*m?L zssXYC>rrNnmAkKm{A!mWxUN~nY{EJ?%~5ny>k~Lx=*25;DswbAIt5;R4W?)`Jkd9^ zWym$-h0hw{v=jG<0H94=7Ubiu5y8B9VG(?tm4ZI7Q z#Gn*C`*Yvj>m$}=pYFpp8*+-HQ0=NEz4lgc2=0$y1*JMq{6VKyl5=2))h6AecmNL~ zYH(P**)3Cz+OG6$LGU(GeVJ^Vjp}AS*T@d=OA;E5I*Q93bl2vQRi^|acxaCu?d@ja zxy(bO;1gbZj427)R}_Z8Yyke*AZDxN6U2w2S~4+QRIrS0e72Xb-iz@Ca`gq=XhzQ; z-$*?a8{l6B^~ZQn?Zl;AM0r~{KbW>*A7QFp_>kLktwl2c&665o7q}iF#;4QjC&8_q zewh%ekjs*&Un8^$HSjJaVfj1-hULyFVK7vy@gwNDW;qFfuaEAJtf1blR;{QOds;R@*BQfn) z7X99mNS^Pt5sr%}O1Q0U&_NuRe}cqxC|<{%c>xw^!5?(smKJ+Ta9{v;WNUE_8@I{0 zkOxY|-I~a|g!@*5p8CXGQg5=mmF1F)fc4w+wu&j?-;0U4`s32C;&fwvzQx+e*VC>d zPzt~&V_c@WkJe+Zt$|q*HAy<(BE5B4$K$!vJ0?JF5)xRyBR@C<7GP0N?KUhWa1HU* z_?>WOqRZlgczxB%9(^d;m$NjR8I6 zv2%4K2T>mI@1dLh?l9?@SZ%QQy1(AW1=t84vi*G^U9CL6x=}|pvOKA-=0M3|(ot-n z=xVLQF>4>3w65I@y|7vf9kLFACJ>WJW^rU~ZT8)0MEg4jZ|QDO!S}=Y7^Vi_2j+2c zb#Dc+A|cZeqUld(%NexlJVQY*KoPVX;n=Q^X?*KNXk{f&u5?%jWx(V`7ePij-3zD5 z#JuTv`OfL~<{wUKRI6pa2^=ep)Jg(xLIp&{scgQ&R6r6@h@LkRe=Tb6VCC<)OBll2kt8=qJk z>$f8AQDhfN2y16BwWv2)hM*oxZj#G;{xZ{HFw_W*$&ItGf#leh_c~!p z$h)>giz}fiq(ep~W~0ZiQwt6h9m`kFYvc?C>xPritWa)KGjw$}XH-oGh<(pCuDOGy zW_i>FXGXP`NmcA~fg1Nyc7Bl$+ZC2I{itQC^%w83MSW7-=<_O%1S1CCW^jC`e$`4v zKz9qp9gV`OBXgrVm}~aTHMc$t*ZW+UudSUWhtFbiDIuPk9g}#on<6%$rI0)tlbD*b z4Dq9i6>Y;ym=nLN0y8)Tmcvm{g&TVg%XM@IW7n>~2p3*?{c>}_F36-%ZAWnn-fG%t zVqm9sgp_D@D~nLJqWI<;q03>IG%dySQXo^P8m)wvzKK@l;D!G&fv*9cW51LsyIB6y zej~i`3|lv5Tjp+_5wDqi_fCMDDCtqK+Tj@UBqC~{%GPqg?S&{WHzH{)jTr1KTAQeY zfRm!w=ohi&F<0Opby$`EfDct^(VTag_>%5QM+g}_hPpWp)6xaM)I&d3z`yI%a#nu0 z#*W%TUkz^!wYLCF?9F^?HQR#KWVPsQ7(M%f>aLFAMH%rO3mjWN-}N$V7$B1v z+X8SmSqQX0u|n6xVTJ(F>+uBAc4D3cYQr;eJagiognXcf+mK^DPSNjS$#>_Ya(5;C zcMgW7-A)aR#Hx#uf6!oI=(51~%UuIU5LAW`IUjA6*q+e9F%VsO++D9n!${)_2Rqo^ zLrtb~(_R~4(;s++Y+&vYn8S`2EnwlMa0e+runPcS_xmPpsur{(>uk&?vGHz05bZ82#q88!S?C8m1EZz=(!r0P?6MqbbU zW1Y4J_~It^MS>z1SMl@KBj%Y(C^Qv7%=0G~2Yerga?Gt8C?RG7SKl&%^b}eMT_fb%U~Rn(U{`;+MWpklR!wWi&&G^0N|G?(IO17 zu%Kp)46%^Fw>0M`)c6mJ#1mIZkUo~+C~=|&V#(+il=;sjS=GThJherz<18O<+8M7&;?q%!cw5M@|x znGX2palu23cu5n9w>kdYi%EGsEhAh6H6z?3$V);SzN6Ivs{l$Gby+neeZ;b>2_J~E z<0(vwKEOnlxXA65nh*gPpknQ}8-9&s~Ev0M$Q4e@&H*9PwOA-_l?H zO@y1+Xq-#ayEl2U>fjjY`Zz+RbZH+tf`a8{?$K6jrYUj_waO3)aBv?ihGD)zlTmH* z$H?A85C7BGzT}d6O@IIG304P+b{KPip?Z9$^Un~WH<{_D`ko;ae5b&FW9k3*8vUDd zX=ZKmPx((l%4UHV&TE~}$pDbd3=_iYg_sp)5db3PS8Ql0#u$D`uKkWLmdkp({iS0U z^*d$j&p|)j-WdK#YwoqiDFFPThBUYPqpAC&r<|OgAB(q5W)qVR$qxPrghXuoH@PGk@HTqT=aJKc=2dZbc6ej^9#{V{?A zzC#umF1JRdg&Yt>aez{5!zF~G+4z#1`=wv=dw&jQp!hJF77^}A(9mHU5!*ZQZuB_n zZ0OrtPOf{&`)%l$3wxh627S7Hd6^t9I3#hkew^Md zJ~YTURNKtiWUXPAi7X8De*5>Rln=(VP?uC@ophf>1ZrX-Q+MT64Crd7ntlhTDos>I6l57c?UjpNp^>p9dQ!d0k3i`#RLYRsD?`zAn8Q$SEXs>! z{XE zor#agCnmNrDKHYLlvrwO;g^0cN|IYB=MpudI8#qvYM$v@6Rzr+!O$nWF{y<*Vuk90 zfz-wz)n4g&L-}f|0JKbSe0ciHpV$|I!^DkzV{NVT{ZGO!F4CCO2myB|ci(UvS;97C z1XucbywgVpf~wuo-$=;AwJNWrS?hynG4wZJF(k~Zze=)m@{L@}I~@MeJ^im5?Cm)A zn&caVdfy=YPvX=+!Y@fd!v^8oyf#>(rBc=0qHb-uTuBqf==KkO6fuI7Xeg)dSpcl@ ziuAfwbBCjI^J~Kca1`w451+)_N#{IZ^L)Y!^y$NnOl^Cuz#|wzhqm-d6V-}n-`su^sLt* zIUoJ;ERwyL)?Nh*>CWJg^#~dGk%VN0>NLY#?W70ozGOGk zM-O*LLp_62zf`4*}d4 z1R7f>T(y|Sp7pm)C#!Sbp3E=8m%F=Pzt>*?b3-r$bmDh!(=F)L(WwlvAPN|Ne<#T7 zXK5^8*r1IYJ)}6zFe6b&)X2O~^{HfzyQqlDBAfavfxcK&GX0ar;+l*(&pR@Dzj$g0sLdYk?5BmYRg8~=q7oa+kT&r~nS@`3oB|*)IB`xF zK((+1`XnRE`r_g`h40dq%2qjiS1|vaB&HomIM2S1>FYl|CP5=xdm{rqM$s=LPFm{cDc;KyUH}!~D6CNPk|KT?@>Qfz$-^XykeDf1NqS+Q0>)R`eF=rUSoSU?EDY(34B!AGCna zX_)_})qCeL$H-)&L8mNVugJKcVBmMdPB(S6%z8F@BMSUD!|ZBk%3`yYaLSqO!vOO- zm>X)Y#70_q8Fw+d66>b66Oc}dl(O{thl>t>0j&**8lmp{^gzEWv47*D@PDP*{{otj zwUd?3|CkIV$!b|B(!p`9ZeDF_tDG;te(>RXntGY80q2n8QzJuac$F%8##>r%WH7U+ z#cS$)C3UOH-he(A47TYhRr)j1rtQ)mPiDUS`M6j4vEDjTYo&Csi~U6Ij@nh*7ka|^ z)D+b&|E}7Jx&g*<=+RugwY5Fgi-z+VQdE()Ta(1PN`r)F_bDzJIX-JVnlPx9F$G%3V{W73^J57Q}{7to+?GPT84P6fnQ@ zPL>{qk(*bOA0Kxj)Ft}K1ahXa;l5lepH^0Okt}#VRCrSJi(#NsAEPm5RDUGOXmn;` zQJ}lLwFV|(QB}qz#Zj0>E!8DVNo%tlORyNKqFYpGFD?nb0M~o6w$v%gNwiNZ)I^Z^ zz2sGNDb6_VU8tF9&N{p2>YqZ;ciL3l5fJdp0-Q582OKq#ofPV}3L}?nUka*?BSPqXM0Di&L;Y@ zc%C}gS?(XX98~Sc9>+F(*e)7H&1d{q4pK1lqL;-t0It8U(ETq!@OM8SD;XpeByZ{t zTH5OT+^RKmFFs9_aZ9;%a&w_UajhF*h%j%{;MECxBj@1B4ZOn~#_mEIvxS<}#zn@t z2L+x71E1L2Hiq@~S~v@mG&YABu4A?tx2v?5^TTVJABl7{vM`0tdqO1f><~@|Aa&Pg zwD$Rgv*pxTpjYMR&(^XI#Que!O535pc(qSWZ_E8ar)H3Beg$PL$=V2HT}K%u3!CruE`D!i&zlCw$fbZPJh5!kY zT9D(F95x7Z_LR2(yQFq?JnV@Uu4{RpP@GY=P-{!a8Z}aaKY0kHz+(A?4-uycYM0{170=&uGx0JV$_i?kss09Bgfu0N#%GTrgpP8xC( z@M^D0SZ$Cxf7#lWkV2x4kte%TCaKnmNt@qhqi;?;PYx4l;)x(v22ad~Zm(^Be3kYq zMPjyE1V$KUKBqIR(NAMP3crQ8SWEK8j{A)>C-Ag8)qYiZ!-ZISrzjw~8B@(l$Wz2* zMTaQqKPvLiJRWa|rYT6rti>w$WlEnx(wn=oR|}V`??-SU633C$R4`iO-@MZvy}Ua( z295oSm2>B%AEry53RvxYO8)}7q)Me2>B!*rTleIcXk}LKV0@-<7w_5aRj6LG4VeKn zXbo_=p}y4G!Y(_;`SC?6R+;`{@t$RA48W6>3jkY2ONZ!hohu@RR4KQt4Wjv$wki;Ez;+1ZYAM%L zSDxv3&oxwAs!W3eoq}$(pf61+vE%JX^6@GK3IZ`qm`yC)^CiZ9 z!ll?sZ1u^5W@dse0W8T!A>CJ{*ebL!!f=JbrO)xV)3a&xFVj1Jk@QBjQbZD4=Ks3D zi+X69EGfn3vsX&d8F|hOZ%tH`nPuLDpD)3gA#?u&;)GpPF6ANGRE=81GQ}$(?p(Sl zSwXK}CpBuo!X@8sRyqWC87pL~)jSLfn&~Qn-P3{_5 z4t6Iu@~~CRk&otyAue%LEm!X;+GuoE@ApOMKrB7?^l@uw{}ztYLuR`VZ-1VtSWY6f z!G8Z?Ej!O**1{uDvGGc|lI#r-!h!V_H?(?lU#<`wEV7wCb6bHEQ6T7?%uB6gb97)+ zQE%5$juj0A2ec9+=ecGEi}YDLd+CYQvaWTYCbBNZUbbSUkBqhNCR%SDT<{PeFc|Mn zGM#^wzxLHnC2`^c3^Q=4!>%{igX;`3PgsLD;a!H{s-#M3tfBwToOoL%8ipD8{i!Qu1nW!Bkg3RKJqe|G(51?ie+5~e4fCYF^#`qiSx@8xT|&BZ4X&UJ#}dJgyN8p2&qRGkx^YF3$!p6Kg=Sl#%$ zN9QQKBu9c7Mq~y6o>32&XJLgve3Z-W@?c~2B?BxsQ*hnUHexHax}gA>Mjosk&=uP7 zRF-qj3aCGTMd-Vuu0s*JIXvdb>%n%2%H{S^@aMxS1oR3ES*BTedSM5ixrtr96Q@CK z{h%ia3N^UQI7}Ag&}sJN(NO8WU0kq|?a(jvcOVdpJCPG)^Mt^vG^OW0x2g)pAlak=)H-j`{eD|GEUC%0`07t@9WLUO>WH- zOeKm|R3pWZ2s0T!;xio9ICaemFqEq7P1X;FG9AWcn%gW?l{tF)YXn?@dfNKzauV%e zwY;_Sr|st{FMd)f8I+RMID{399y6f@cu# zQP)nA0NK>s7rac)2nU;?dZ<(>x)q=VeI~#;pDPopOmr!{&i*f5Kk-$Q80LkK)h#LZ zJ70_3vN)dGJ~oY|>F;4scG+9z)n(zLhrSIjI6!rbxP7t^SvW_eQ=P8!4Y*ZN1DcY_ z3?QuTQ|xF|oM6|?h%#C3$T9;KPEIoVyVLN$bi=;z-m`MJyItTwG6n+T{+NFYdSA!f zUqhV*qC8`;1>7*UqxEV6M30%gFtH|}uiFxK;oa*CbH%rKT*zaHI;Dat)>xcvg^( ze$pNzPd_LGb6#~_*wD4WnG$T+mp<7vUgtjQodz3Or6*?a@k;d1^ z*dHO3mfSs%RCtHrR`shez0&r9c0ob=?VYOp;M(}7z%%SvYguM5tfF-EH=INH%#PSz z(EU;K96hIRiEX%Y$DDu6?tUe|Vng(^AAmb_J$;n($jZ#X%4EczHQEX!q5$jki_GNd ze&EP0MqMKRS;}o$*tA*Z6+yj8$&IE8q7Ju5q1iCJNNW8Y1Zj1NulC?EtGvLf7mki? zua{B?H0(vx(NAgk^17W z`I%y^qu7%IT7zeJZ70FGh~HRiA1l|fQ`<5dn8vot3DFXN2r_*VZDQimM$B%17I2NN z$jqH1!O&MrO7i?EU%&YEqwrn%^iMEj%P@j>KT=Re--05skB}>#G<>G-@3X5xo@3?> zbRX=`=bt@~iPzB#{zGPgL)sq^6VFs$#Nj_0-GB7294Jxzs3iQkgC5O20d&9?e(kn3 zu9JJBT{y(`jGYH2>*Apy;6&-IMEL1tcdat>=*{#g+qhcwG@awan#1=F?{nAKHl9`@ zsd^qbAXTOU=Q9iuld+zq3FjdP&2dSCI%nHGO2wDp!@g5~OA}g9>%Y|IXTEX#^$%(z zfA!0=kTk#kQcj@w?wLjZ&CSJs)mmcKrr$!*j(<&N6ivUC!VM*DzU{aE-a!{d@qH_X z!wLCFA&^A-9sHoyG|XDY42|#g-NU~sq9=lZ+2CtekUzII^rM^FaK4&%rU%?$Fe%ueBGIa=aYa0-LAzMc+fl z7r09E+<00fMg$T#!6P1lDAoFLeUD%gXpa47d9?hVKb5-a7SFleBXKd9N>9EbeA6RZ z4!>GfH#7%bH?yf1?07YVv_W}Wf^F)zMotSm(hhjl?Tu5;C7Dhk3bLLwqwusqh3WigFkVF|MKRT?C~@>uHBMg}$pP34(! zhQ)_DH;}GDs3w36lG~}LF@V$L_}2OiwEJgzE{|Rw)7jVcZ+kO3KA^NwA%HEM$VUMo zZaP8UTn|O4t@M>|Zaup}(}+nvggq&4D()UH`6>$Ch~ru+n^iC3$`X&^j<}Ik-y%}% z*>_T4esN!bsVDGgpQ!Z|7*w_e8gj()fN2IsfE8LHZW>$+aquU*{5zUIO#`DdwiDkB zEVNG+tRNqFk7mHSM@cw+fQA-PT7ru-f2-0r(lJIsp2~pDrym z{?a{Pz&cGXT9*YhvEMI3q_dykov1B1*w3IZ73%BJ(^G|PAZHq>8vaSprts|CZMgHE zoBtfnEPNx4;)Pbkrosu~DtX^c606MKuujfN6;bRT^%S=-dW)!(H!(<9Ctd29h2qzT zxT0@K(r2VOrVruf*Kp~L$N*?81)_0gh8EUkvyV}2Vuy??TZx)B^EH5d_%?k-pfoqn z-Cw!IGGcyJ7E5JRkSo=t`fDjW+B9j@8geWl`KAsSk_CDIgPK|$ZlDJ?tB%thvif6P|0&Grh#}n-x=7hP2Ugjwu}gtU~J72&cXcz zYLhimU~lt!V_JuYI(r=+rb$BLLsS z(Pks6ktHbXSOVcN6Nt%M(blN!IU3x@vBvD+J$`N(C-5e;?f|%w4%(@kfek8QkZq^T zd`{o8Iltfk{`MDqHHExDJB)uf&`)YeYnVSMb4-)ESY-9ek2iP`BQ9eU8Ou&1t;oVE zI{O$TcVnF#rvI4rE|4Yw^E)y+@0hE@=m10ZYx?SC_G;;!sGkr4114YmbyMD$#247k zdqT`^^CZSfIngTAe7t7*#J}TI!nrxj2c$AvO3({o<>J{DX+c+R3a;2?>$f?7{>)JH zFdk?BF2If%u@XW9S*x?PqHED?q+(#bi|x1LupI(mMeVPd+wEh%A;`vc#c8Nh5z+vOkOQ6BS@BFwDFkeoWH9%=Y*L#qKQrJC`#m-_nmewO!{fQ#o#K+I# z%QxpvYuL)!?PgljaOF~K=jw3&JnUfUR+~S5!KBr=8kn@ZogY(PY517Q~h_7JpuGG$`?LrmWYRozw#$nBeK%<3Dh5tp`0wG9`|fvUA`HI!jU?fu}PODBV^Ex78_dnO6a zEn8rk!%X~^?4Ulh|A(`8in6Rr7I4$HZQHhO8UI zm3DP>xI2BLgE}f+cAZ=+j*WpRrgdzL?9mCH)>(PocH?2JbzF)e+r_n*eRV8JERhG% zwGsTwP2=Tv#67i(Iaz6@RX!?c^7dBhMUIb+&>S4kLwXpCGV&lKxylEv=vC^`M* zDk`4&+5;|>tGT(MxqXLB0yoWj8tP}aJytRm(hmHa2pdMR`Poyh@b*%^iW0;Rup81dM4N7Co(DW=o>^*3&oWyp*?Wx+E>^@Qq@_{ zXkwjBrdkz1R%w`K6TOvCE2*j&y?OuRShs$jYw`E6d8K}%f^@HvbyvT>s`$9DxvYmx zm5u?beFKW$q1sk)CTm&I?1t-OBgQkIFusR%2Sc%uHwCxiM(csgj;k%=hbtca!=%k= zx}9i%)2|+%kJ-(G2XG#6}PD+EiPd!lZqX9IGUpRDZMH@!IFHjau=?4DsPzJ)NXUZopjYEb4`7S z#~?`I2zvQ~Lj`!7J-bZJ?qQ3tvpJjr-UFv|9ql&_N&CheTP0HDBkcn^&+MfnoD_W* zY5BxS@1XSvXm;0xMs~b}RBbrIc!a``^6T+(7ArcoKg==lZ`^;k(jgPR&18UewgaC3 zf>-)~86#;x1Kz(RCdK7=0f|YpTuf6G`r%1d%Y*3J9wI0V0wIn)YTOn0?ru*mSj63; z;hJCtX1IHw-fKi4+E}QIe(UunWDP4dTg#qhiC9(eM9|gkjE$ zoF3rRo(EJy2mz#FZ|2JAV$SGn2Ed!SIvd-&*c!V!I5Rr`?}!M-|66fYH%CC4)x|~A z*x4RXl;iTxTx;^Q!k`e+n8gbfNc11zbKKJr@7q#l9qTBv<>Xc)ILOAtpwv|QU-r_T z?1%z^h-SHQQJJ31?GvA@DS0o`-^_Oe4R(NbLE^FXpw-NIn8|6fs3yd5T+*ae%|*mr z*erY}rZZ!zu)oEG4YT(JyslMU|FWPAmP3X?P_?6Cksp~&x-I40krc5Y6V=bx}(`osII4{3%*}XtS zdh6XQFVC(p3vr!rMJr8P7$}qY%{lgpsvKHlh1b+^KVbP>(uytG=_3^f&RGelc(KhC z90vg}IV}Rh3PENL%rE}bAh}OG=?EAL3cb?$*GgkaS-F{}EdG-#)}R31zhdnEipAh@ z>R{>sD+U8tz5ljt_J5+)|E~}=FHZO`MHUZWh7%3O)zY%T*as3JA;!2Yi!(7_=uEjj zcEmu~RVw~rbVd2-Uwuyb1z^ts!OaoHvis~I3^uln>Q?0?Z)+LPuAfk1gmp_5l?p`5 zn`>WVQlwdL;EocByuImP!6^8}vJ~CtT=tQK&Kt5bSBHMHo8dUpuFIUuK3BuexHw4m zGk*#_*0X6vCC@XBV33KtRmN`VN1>^NOhAI9xG8dk*X?@x7joKPf)G$5I$Q+^fe+w# zivJxI{x?DVM~c%YZ3W~B8&8>`MJBM zxy8sQ?T3l*0O4)|%B-zwT64iZozKnDPyQ2uwqyIiZ$Ds^ZD;oC0Z0+^H2R$zZ@#~vHSF`%A(SElt&|wG6mVEB&Cgx4cGZIC~u8w zvIS^BS_H$uSH^5U%6M*-QK^`bJh}46vlEmG8;elw2$jEYpN3`*s|B)@gHO5_vIbFJ zeQnyS61kE$$MUkwpg(InG{b7xyW!bQB2FJXV)n-;-xN&Q_QMjw0%PcNx{T!(FI-&b zpZ_wCGWL%O(r{qp zc1c0IOJo)!93S0ccqp_9#>r{@eLdQ^{z69^@rytce#a|*j01wx=RH)PcQ7IPJ1kWk z+E;W;$>C!34i$ygzky`u z_WO#9VYjhyaH4j+&onZ|?Fw#5aeSiT_NML970sq4pNBM71^ zKLJS@-12MDgrXfe>6-@~R7ef7VQ+^;htfJxMr<(F0i}c@=+$IJKjwHiQ8TJEPd)ky z5lShiW({+O*axg!<%Wg)_7vqp-}=-!(1M5}C?|>i#>jB-ly!)3P@axM`rjQfikJSw zdl0{<^V;kdH^FGEt&(C}hm%5RV(xsod$Ucu@j^z6K0~9FWME{aNoMv1jd0G8@2}5PRC5 z^Ih^!xEZhNcXoO~Ge>cTa;rM3?{a5I1Q$Z;P@+AD|EYb=F^akPHUfYP#EA;J7BdQe&-jN%e-yUS(l-SUI=i~;E1*( z*iNoYt_bMQaFTO#ke1{bcXaI5n04xLvg=AfiuzoQC)y(1{&-T5z!VKMfNJoB$?T}q z!jvw31>c5QQcIB{1B4k1omE}3U>JmqRFTDup%{ARQe!#8dD1UJAH=SvLIdPt>%@CF zqA^`1yi3211H}h7vZs)u5>93i%w&Wa2ZK+_gNflH3W-MN&R*2@wv_ID6-TLtEZ=<{ zMZ1ZId6~kU!sD%X@akjcC4d;w<&0GR?3gQwNxRvj4SUimh2cRjmIl;|ykg=2y;qd; zW}@SHKv(~K#_DwW0t5;$1%N<7a;diH79=k4Yl2$p1-k+}_^fzuI;`>l$c@1!Z8+lG zt+?MV&jEWqTq_g;XN)rKce=TzgUD=cwEohHtCP}-eD+Gs0KR0&@w4E4j@}%8UM_37 zRmbKs{o()lr;=c*GM26LVH`-5j;70m@ZR6sewcZlO;K{@%GJoc}{G zYctKE3_^Q6Zgc&@Vi-{EJsM900bOEVc`3}Fe0y-G->4D@P8X1)&Ztq0SbP#9BL2TA z!@rMFLlYw1Aw-G(v^`E>#_W%o2*J5aluW5XiKu*jj#R5m5T?+XKwXT`&{6%Sm|})p zqD4}V{#$n6UtKLf5lo|*LS|0kPi#fjlUG@!2J}eIrCHngJnRN2&7Nqd^fFAl%<~}1 z3*;+Sj0%6F;gFO*ykEEEQmR{ZhR*jLva3OoA0e#sD*CQD9x0-U$sgazj?1LBDV4-9 zGXzb=sEpi@n+{VR8+52K=N!R&$@zs%lIEcAN|GwS6HltTW_u<5re%U0_>V&V(9}H_ zAb`Co11g93{=U5#s=5Md@c!u*rv7DcSm8HKZSG|-aK6CEJ2du%aK6H>k@0qe&9R~J zNu!9RKS9`aEjr^v|A@Zh@}RKc#O=tvE03P!(znYCVqG@6YrbthU!QPOe%#$JY67uR zG5zdlEvUI6tFWdt)PB=wH0kJ?*w44nWo(1n`F%wX9c%nr z(8ArOOfH{Dykf>WEsGT#wn;J6?cYd84dLZiq9nz5#tmU5Z8*g@Yj(D3&SUr!GaXw2 z{r-E$?AIFKkDXkW}qtKly*!$ItD#|{-2yYM|vksErV z7w%k5M+{OFg~b}N(iVIO{%vL3KlumO56oO9EiSD!|}u);f0T1JcaS?X?u zG_hZO2xR6erR(a|4OJEE4Ea3mzGv=6U$hT2Ab$8nm|HQzHgA?T~cSo zy$mY6mZ>-9#oa_%4mqYU%2z}t!?Tff3u%Nhs6&!iAK|b!ky!bQ+$8z>6>z5QYjuW2 zo4}p%oK6$(@oVO{uppA{?xF2ok+La-%#ZNE*T{hi7V4g{2Nd@6EsN~^nm?|1Vu<{J ztemYcLCtrb$H_O#9oqCp@i*Mz6sIjjoaIK?p*@O2Ozt!RcT;@sJZS z8pxo>Va6vw(jiHfajwsUOMB(}b^Rr2gS%ZR4 zoz$CA>}#hO|2@pkj&w+^0$3C%!1qx6|6y6`_NK;e7M8B!o~CAwu2v5AQpWb*Y|Whi zVQgXl6P2QcUc?m)M2ku_%sn+xkfFc|ZcMNe0G#=<$6edMocY0;&^R46nzZ_4Z$1YP zAkZafR8oVy*2yT36201P=Yz!%K(#>)TTY(NW!^1?L3Zf<);3~&6rP{;bmp`~ zOpGW}(aWC2g&YcDv6$u8##0P-QQ8+ssDZ`n8}Y0CW!S1t@pbfE=Ef#Di%g3eH1H&q zn3)K=agvgcPvGRgkR|>)-yJ7rI{N_~SeXrLk-%PRZ!TR2M?^G4S6Wewq%3~HDd>R*nT zr^R|;(VxSiZGN8{?vriarau3GFX&zFd=^_;;{#hXT;sUb@b7ec8aZo+laoIpckZ6~ z6xw;B-U?KH)L+?2@JR zcPVVu8pNhOvtitR&UKV)+fcAGUxl}aWwUloBXOj*#<@1yg45ay^Bc3$aa!<8`9az! z_^raT8;T=8i=-;$kKvueiTlv7hHq^L>|o}ZGaY(KNcK2iO(-|%`&~MSAbPRvN_6_} zfQOgmtCcmRcsIMJ%v z;u~_#$zP`lW3BO+aT2r+7#hW7^cVXfOp?3{Oze4BlO>tsDOEETipftaf^RqJR%tM} z-fVXX2@-rt%OPNh6|qg0iNl+cJj?ZpIt%mpA353)*lZ$ZK%iFy`!|c{4gart{vSS| z`i>^5B-$qg$b4Ejp;aJ9(V8_eGyp8w3`5c`0$nbK8=_Nt)~N7}-PWk-?5;K-qWj?o zqhBE-{X_24sm)hq{&tskvb+}CnZV`G%?_6vkDKSbtbostdk3HbVa#?D8D4ejaylzr zvyFwHGSW>`8k5!8tv>*_pe=+gYSOF)WiV4+T?@X|c4^;`M2rf5q-}XKxba5XH+pZH zuZb3V3^2j_C>QePuU(2V2E%}Gks>v;#YOk)9e){RVn$A6sMN2s*lE~KFPXKDvwpAM zkobibIm}v%bb`7A4aZr-y}|O+g7f=GadR*fbZ8!bNp7boE{C109c3hN(A?dq-&Dgd zuhX?(WF?)o+GEPwH>Fi^-Y~*&s`Zly3PD9FYv9H91Lv(vhLt)a_SGJP^#*-RJ=rPh zM)N13V}t5PhX(2@4j-h;8)-9j-AhLdpwRoI`^|nbIow=~4cFpFTXwLzi$Mazw^6|f zPQts+yor^mBB+lAFq_VIY~T0wjdZ%PCrX2%hr!L)#hq(fO8Z+NBC}iK-s?y!dP|L9 z7VS8K(DiR+c$O_in$~x~i$`*jeCy^$?!)@aJRxNcLNsTL!J1rSPSf~<<`)%U>D&s> zUDq{Nv*O9u@J>Ua>VH5{-&$MfR7*Z8FS==qr=Af;Xyd>7J zOteXzRU}_-cnWk*vIWr3iF$O3V-`uF9?jUXpACIKmo;Ro>rIPuKzlG1HCiu#e|#w4 z*(={cZ+9#{t9Ed3+1&7nlcVoZQFPd&XuB2YGx29{9231p>#+#VcPd(NsZKAD@#miG z)L37l3n@tRc}G2+#VX&dytb8|YN2|B&B-?+*R0d&)MJ-Pc3l^rWew;-de>R}g059z zbDv*Jc?Y!!D3Qj5dAK2E#V*>#ixX@g3nZIa*!H>J%k|+(@(ua)i(O=DPf*4ge8Vaw zZbS?VPtt^f@E0z8TTKUpj@=I_2U|?t6&2e86YPLC=N_QVmF|`J0=B4{hV&w+n;zmz zSUOGueT~CwCd+vw%PC~Dg*J(I?-Rk&wDKT0(CQbbL+Rm+tTg)_Z5&(7lv!YPS$^jZ zFGm=X#WO69iBu11mFFmY$0K)vjfquH+T42?n8P!uhlzs}k;miEh2-@_K7c~dKnv!M z4yr}!SL&3{N0CIFhC#B?7xeK%0F1r=5mL% z!|6l}?Vi-WM!^8LzYp%DOu`^X(170K%bn!&`7gY_zfLQQ$K!wsz-jdgxI6f7 zIY|F={bncvn6qnUZ2!NzP@3|rA`YN~i~yEyt|buTU0J6^UbV3N`(xx;5e0?3lvVNG z?g*Ug9Ql+2EAOAahvR8k#-7T%UBX?$H$3;76|^6aHQ0~l{l_I7l!FEGhH6cE2+AZl8uM(6&$AJy49cwA=`J=+QkM)7fweymE%A;f zsl6@%l}L#|$v9l)T^1otsz6&O(~$f)l?w?w_*SjeY&rk26S!8lc$06Rfq4Rw zJnR$NaW>1IeUXq=d*nN(1(&#Vh9h@by#MaMrC^XUqyX058?g5OZR_Aa*51q2>>mrS z)TMw6AjBQ44z6R>Lqp_ZQWs-M{w|J0NF9`tlG31xqzglve>@Jxr0-gI#i5p`@eedC zESfG6k^uuWupTl7HqpXPU90>&$Op7j9B*%bbO1NRs|(XEjpE~V{@`%>W`d3YVphBs z7g2Pl*z8lIkcL}%JN~ioY2FNutTwu9aHHijDxzUj0bg56G43;YVH0%U!D_E?o)bKn zPWXD}HxGFoxf*nsbMq`$0iSXKDl#PAX1gV`zgC7$pcaVRA} zUNW+W5Z+Yr=1)>&fgFpcf+2}qqEq}Gcx@s{ zJ-62AyQL>7Iq0RK<2k~0U*8+^h*3#&7<4#BhM<>TKtDe8x+B2?ms?ORl?t?antT-;pTOnIdbhO6W+xybCL zITqHpHIj0dY2>}7w??BSa>|7^b3nuPiWaF^nLy!~n1(=q-U7je z1x2Xb=eexVYP+k!BeuqW-WS~Xez|=uM-=q13X4shjm2t=us0F^S~apPPhx^+&yTG# zAGBmraZ(kmVc)DJP{%c~?(W+Yx(KwcL{J|+*oN9E$L3+5@z~7 z?l;%%Jsmz5LHg7Byx2cDAd^g!lW2=2AlM|9d#TR&WtQRvxYflNOz>{xcdD=5D;sgPfo{)^T48h1w6me5 z^kiNB{lSwMPkw#$H1wQnEGJkaT5k!&DdW_@K?|b4o|KA_V2K+#zue@|X~oSq6z9;2 z_v^eYt+_f>W6t_=xY@Iho2VF)C(f02M=K^K1p}xAx6T8A*M=+>9)rRM!Ro_%ljkV<{G;=> zX4Caz0)xFuvUEOj0bzY2tA({Xn>=O9H6k)vD(7nHtO(&1ge)9qImqBweU`2(D0*nB zl4+-x-hS&indO}d=i@D_&mP+8b`nnwws)yyTv-ht@TI`|th%=_0?pPK7}fc zEq{mj#o~d^k}Raxx@#iM&$U7Ldlj+CVyd5psGlF{niVuIL-mv!#W?3ximS1$pPqwC zh$De@Q>-4WzeP&Em#`yCB9C^XrQk+jPtT|D?#4gdDTqzWLRT?SHB`{LW{C_X;#5|V zeCshEj53gs-cwelS6MUGg1}4hxz&rJLY=l$Pa*Q^OBDpl@gIYK1BJUkozUm09^c)@ zN`^s<3DFO+7CX@JIV(*?Bo!xCghv={9wMs38M~5kQ5rccB{Ib{tEk4+0KUeI-0H+$ zBuiUFxnq`K_jXp)JE_XK${H)1LET@$=1F(SPnI#n#Jt4D%WZtLq7Hzl)m9|oeXx{J z6^eaAI4w^v`TFjP%jUxdFLTe{+m=g9&(uK`0s z<;KaAWE)8kZZfv}hjRAly*5*(iTT>DQ%dpk+) z;#5SdaPm7>auo@&jq))zoj}+;PcclTKp5y*-E5?t=v#c>2KzubM6vfib3fYt3R>T^ z$!)Z1!Qp^jc;YlwaDjl(J`rMV5G1fso=qq_hDQir^^!w(1EPux6^!tV<3I_DQ5d5? zRqKOmk>~qh(StIcCb{-<1@-C9NScwuG*oahq_xOW>=+9da~^vxO(=L}3%lAh2;r17 zsuNvo9y{vU9`rRe_Aqga#jI=&nap)+pvonSH+U5}Gl`VLn0vBCY$412Hi3xeR#lGY z<~dX5F|dYP!Ro+=vXd&4dglzO&0?Wr0$%`nc0EvxLeVz@=G-BoLZX&&4aBp zHQn+yx0Nt3#j;%Uw;Rpz^Hf_#S5Bn;ZCqIUt|3;P#zJ)ED#EJ+1CB2c!X9bjZBRbB z--3uHSVK?UrP@sU;4M6i0w_UTA;;~SMVkj;l6Y&lMysfKMeH|dud$KW=>yA2T(O1t zMCfI1yYY)$u#s`hQ&^-L92hh^nQOR8G-7uV6Lzq($t7raPs}u8b!<84-D7oj-3UrL zn0^S*O7L@aVZuEddkE^S!8Y?EcXT0@g#>@7#S#p0`-_GYT17}J`6YqmR^bym(j$Od zM9umRTV$aZK=2B{V=SY@7@7MPCt5qY5zaiBa^MOLZh@NQ*tPkC`PKcZ0z>4Wwy2VW zj@x^+nz*rarHNzcqh*tEGw!ol8_|GGUlvgVp0_rZA$AYXyBs{Mf1hEyr`Tl#syA;q z1ioy}+k`%mq4XdDOmd3bu!7Y<;BqCm8=0i8>446KPH?1zS3$=gcp+nx(@G8gR6Z<{ z?mBI6u+1_1rC5`E9i%Qm&J|vow47+Aoicb2delvF=@Hxo70kpyH0(mu`fX5%64$-I zzrc)q-uK-B!`4ehPP`nlyVQ?=uo?u0n7b9`Z9)2hh>iz1CcNQ|iOvs9-4#Xsfr+9) z(sAp`dAicdVYB;x#3Hp!|5y|>I@K$J2-U>R; zhl&^Kfg{erBlnP9Pz_=V4Wut2JqS#sl$lwAYv_Sx&cRzbf@_FC?sSxEet=h?4R0>N z{F#DlVEq`g>E9^DlKE2ulKp^6i*lO@CJI&*f!$ds*D~%Q-;j(F){U?^G@x<&oc(Z{ zk^~?Ys9&qYnzypePQb*T8CAuGW=E5^+~Pf9Qnc>&!r#q1%0 zz|Oc`I8%+a`Vy~yi&faq z&cF(weMvPiW!ST@u`~@^$@PU{U{E*zX@m8~$(=2N_4BqdY|9i!3Et-3}Ne=1K- z!IsdlkbR(h4mJz5eXbq(zHKMJkDjqn+UXQ?@`0H#vTf9SFNHwIzP5jv;E%#D2l$H6 zu|uj}6mE%{%*o7%>Z}ZqnpBJimh~ALOUjikTZAhMfA7TQIi!^Y7I1+V40DLA@e8SU zl~}kss?Pdk3dP;~wK*wwn2bf)#V)QK$jpqhT<}Hvo+$M~g3)c47Rd8Ek*D+R*D38S zyXv}4uIWWl_cj)L8eK8_R;+M3&QnT|0^$o+L*`{kGd#MA4NYVrp7TZ zXu{rV%dit*!=1VD{MW*JqrwGduR#xx9TtQ46In7Je|-n1-S350D$LwXJPpvQ+`2OU z?y#GkvB9?7VZUT_rZj@~rqyIsQ<{ddb6@h%^G#vC@P4b~=W=r^KDryaJ6PBRc~PI_ zzVdj>?z)_)wL%Ly9D;eX3Kp6J=}$mE^t=bQf}Fl#*^wzVr8%(&!N9?jYg+O({02#| z8SCv=_kMQ9(1Y*ENb|Bg+!Ius-JY-TzkYd-pK&Lix!LIB#20~f?pc??@h;%mE_NCV z2O5`;Re?XD`V$vuw8~WE{l)h|S%q?_*c4|-zYT9=?9RX4mtGvSOlp`ed;{t<`S>4+ zEwUlH*8>MNq6VJ&#%fh=Z$9+Xw#Yya9qa>jrtKE463-y&FE%YHBf(gb^l%c!Ij zqD}mB*f!|JtAJN+>bje*I&RH-6RKFD@Mrw)Y7L`brQ436`3DFIVr*OIEOff;#X9*I)C@WwJZw_@ zir=^nKDxlH-xFy(tlhhehwaq8g@kf6Ld)|YtZ_Q&NzEXS@_E2R1^7^0Mr!A4DytH1 zO_7i(1kq>K{96_KD;8!DvyJV9ZJ?$tQP-T|3RSaf3Xv3y?drNZwo-nIuV8|s!op`EkwZbN7T)H_8rj1h!qA-A&_JVGBR)iP>aLB>Qv0 zlr>kn02Lmi*N&nX;c$P#G&$M^V;07vWKvigD?eI#;O*Am>I_m3^B7#K(9Ao!6jiR1 zc7%6F)0bz+p+8RLcf=OGxI%Bdd9^Vswc_tBQ$O?46)T6#8C(2e$s>ukXbwlnNQl^d zQ{v6g9PZeKK)39oEbrziqauWAW$nrqW5GQ1&FGD91Xmu|anj|CX;V9H^4f0VT+FV{M+a>118w~Lb zrM4u0rN2p4no95=3zfVR?|7AUeri)+Y;8Szngg?dP!Kd6HSTzalI6JHipnV(<&jtA zD5?*?ZD$=AW;3k-JJ=QL0rU$?tvEQlT2c+Qz3}st0;acq_lyX>+4pfCKn3B;_AQty zes{aAxL+lo<>TA#7}8BkU+tt_1oH^8y>U)i%Uoxs`wDsiu>93qQQT=QFun3qhOEbw z;lF=U!Q_uJe$)6+5!&m|a$BN4ut}A+@9;N)^AFjXEbB8}w_x0|w8nr`-g$rG2V`z% zbEf~4_(;ghhvkdPw#cGb$9lcw@)ht$3Z|6mHtwRQl4#8|ztg74+Ht^qQltn5_VGe+ zm6Sj4X;YU&eVHV>+VpU2)@S9%!fc&ynXZXu*Rn2+$uALy{4s=LoXk>{a5J5OE8I2v zg>3LG+><@I!EHv}*`zJFSgMfuauL^8YJqe%N=OPV2Boc;)5d+!HC_NvgM49tW(F5* zoehr%M44649$7UjF3!U^u(wpBF$qO(6078u{wpZ{ParFWY(^Q2NlbTxnd?RPN=hQb zJyp>|s&qF|hKuO2>W4Y!eCv7oj2m}Evyua!u|!LYx7?5j1PRcbwi!z_QZdeN!yZxU zlQ+5Emb==>=j3wG%JvLI@#1jJux}_{^<;x|0vSB1P}tv@hD@)8nZE)%rBqQ`O2DuM zL%BCzSZ;s}?xk>QXONX6P%9yFE5PGLP&f~LZH{{4)?n{+5Pg~=_&J@i(B+fJ6iEEP zvAlO!y?1b7@8P|xRy|q`JBX!31W=rz^mU&RVIY4l-SM^mX4B)=Rz2^u*HTzVp?fUE z@DZR(QIgKh7k1v#Iwmo@t0xnjjUe~}Rz!~r@9{^YykBub%G*jJg^Ffg!XNCsf^_6a zyR19gBaebVsH>cQh{8H~y+7PXBAg){3SROykxGa4-1{BFH`DA4OXUi2d;q_;M^)wp zQD2(Dpn%JlK@&2jqXDj2Zw^s2z~bt>tbC(v3q(3R6DLj3E9$v`=(n>NE&KX2@qPpJY zdns{Wwf2c5{lQ3()xg$f&Xnyj@$Boqnj*FfI!XJJV1cU3%b--x+{9 zzKx4>+lAl*b|A(WxEp$8Q$|7Md$mzf z3)O?~*x`h`5zX$QFAt>eYfd-*vo@4JpaS+i>4RnOR2QPxLe$=4n@x23X6~%|?{-u= z6z24OO!uR}P^S|C1@Mm{}>`DjR zaKv@J%Z}5((2{-q1ee->_Bat%Lle@IjI_9ofaWL@Gy^K%POYQ7`qj));k6!Wo$s9U zb^kIM3X|HA1Qj4nswbpQHb|n){k#`;C8^X@`-gZlbyzS{d*fyd*2AdP^peKvk}5ce z87%t#h>j+)DZ%+OD}C|$#ZSRo@%#Q_-?KarX9du;`QQg7eA~~E@2UK+w_rqR;6!iG zzjvTbwE26qwuLhcKvKSw4X1!no%p4kS|uOd-!3GZXcM%Mzd2!C6uaJG54;+oFfz}~ zChUs|z|Q+BrN$TM+m)4*Q%{oDZerKUT!irZ$ZCrvw0`^T%007CKY+5z1NqDT`r)}SW)|16 zek19$j9UdZ^_}qFlOCI{B`lDr_Tx^xcq!EaH^s^k>T4B~Vt7I$dnzlbytB9UrNw~dO!SA?^a z40UFl)0DavqFPr&oxg9@mq3h(g5!op`^~csdOhrHWq?^Q9LPP6hMLpbO43f%lWLvd z+1@L-V-`U1{aGWPizNNFM}bc*LMju%axGgz-o|$*bW567*=5V4WIo~fY-JvPt}zBP zMs>&kLL2n^9xF!=dWL*vc?RTKm-vQtCCeOzfPKK+Fi?fUHmQWGX zvbzr6@kdOLAgE4kMA-L#9j*LVo-qbUvXK}d@@2sD_ktA(TL)v;e@H#yF9IG~*zDB~ z*W&q-&R05&$i*NP13Kqm4Mdj`OdVNmRe33EqWP;{Ck+*Vqnqk!QG?dSn&>j&p>QoP z(6=oBlxtEzgmN_ON><~{;if^MN~&)iHjPq2DHD4n2Sb`dd54sx#)Bwk$zbKcq#;^v zCh|e)l$;Z~UZ&98MUu+9s#SvFj$+Fc?8XZ z#2yg&r(Ca0;k!f4hA)a90Kq-x@~1wmXK3B%Clc_vo`=^ej5An4&*R9EODgPnA8EH> zZpmZgLjM@XdH{~A)^oJl(b+Ajc?;LZ#x>MUm>X98yxq$ogpNAQ;QTa*I`Xy4kT^LQtK%;GSSc^YE|?F)~E2 zK;2Ld!rUC;mGrn6E;By`Pu}nG-`-{!C4uaBVfM`FMvV}#?7?R4OOcM>pLZNDt#6{J(k?baUlcs<2oYD6!}z06^nyK(*GJ(% z9W4~tbVX5Jz*M?BWBF7bm+BySyj!~VA>YUg zOTBfS-q9$aapw4q>co1(<9Wwu#>22z^Z=D_XXq{_4V24p-uIBuTef!!A>16#-o)V||MZTMOywBPt`syWp~jb;J-NOnMy5Rw_q@d%IzB8Nv|hzrMMz z{Hfm++#LbUhr^3Bcqxf>Sh<5NBUt;kljA2SaMRti11R4l%UB*7)f}=2L!v^$ zC5?QulxL}f<+oU<)$! z%&DF=Ja8-f>jy;B23R9lOg%Ze{XXc!#qWfNJCH%suxR112Ygx6bGrbd`07+0PHd`M9ZR#TLkTN7bLpiJZ)RYS-5`{*T;ux2cSW=?=NZgh& z_KLOoJ>7n2m$7*rAbCM*T^g+VXPeUVXx6lb8=er`{AD`B_roT}^`6@v4B38_i z0|Mp~m|dB{{PrxEtwEw6;hJYx7V`2FWJYV3`PNG3Yd53nAS#^=IkR47Tn*$N@nj^&$@YBeIMH?@m-yPl&gOce6}06fxu-FT2w} z-^`D59JcEPcV>a;N)#-?Sz3L3+{q58Vo8x7e32uP@X3WQ-OBuk5W=ov3QYx_1`A7q zppLoQe+eYo*AOetL4wz^Nh;~@UCWAit#UIe+iF|($UWbX;|$mR3@fTPdfM&sQ9w5AWR zw{ZWh+esy3QyXIovwwnH^OQI2Q32rA8M~CL^yZ=?1zjQ`D3ly$WJGZ(B_T1GG8HAm zq=RAz94zk2xs| z6pQv&W{)W7X(?Xz)IDIrd!}O^n4KHvyCBKN-m@TPI(bqDA4nB0M6d9cpEhM!*hle$ z`X!?@=}DJ@s0!rkq5yU|<6;jR054yld#hxw6~UVrdB_M&0vYxuF70Av2-i+Yz<>(H&AH^J- zBaO+x_1enV)sjt9xnI7Le@jWi0QM$%$B}Wj`Z^EK@hf_D_%qMQlMqMfFDz&+33xH5^XjGc=SKT0XjN=;^& zrEwNH4~x18Cn{V!ndOwzyCr(XV)zzj_}bMIrM4H7JR)w0STe{BUy5kp~@$S*`2MWn_ignRPm4qV_$S5!y)A~8z6 z#j&zRH+BSMg%a{uRj#Ju8?ObV8RY)-s?vNSA#r(0NrT9fI}xl}%M!s7>V&t30T>(C z4P|DYOt1JOyH!U6WCZxx)>c`fn8aS(WB>X82W!K~AWr7VnjxX=MKQ!iI+O5GElXP0}HZs|goz)P0mh`L=9}-{0WFRV1woj8c;C_>wT>V=@OIcc$FrCB2CQ=XDCer{K zt`+uj{3Jm0Q31=C3_RcI$jV@Lr})i z>djh?vV`~>>Tmk`o({Y6Wxp|+B53r@*XQMz;TY_8>vTw?b_Tj=%x`{Rqj*Zv%?@O_ z>kKw6IiQAh+BJ=3)VF3emac_SZNNahJVp&;RFYJ1f--DZ}%7c*iES9rU;D>0d zukD#jd;OF-oe8=rw>x)s4jC0m+zJ(+b|2R;V8}^47&Psz)g4_=^*w>Pw~zTw@Mc9Q#Ut_I>Si>oRY{2Ez)(lHJ^)2w zPl}aWC9Qj@ZlKN*=FFGwVwWs9s@8C7?j3HA3&CINQ*b%%?d^MH)sxq)ft_c#axapo zFYZvTd7jN4=0>{puP>-fNzExvexY0N&E|Ga9yx_C1QeC*aautR>tHczGX`$rL>6xH-(WU*1tEdVi- zWUsL92QWpypbd!9qe7fgzr0b(hnx6<1N~XTj*!-4=Y+VmrdmBF<4USFdf%*S zY~VFvi1SNWx%q;>$X$L8O#l5*jf+vWwd>U`BzH<%Buqv*tSps8r4omJez>&Q+gG}8 z*upuK3@O+ZmaW0E{@@uT`gU^pQLw0?kUK=_l7^#c8%%Jg0*s*pz^moEB=dnas!J(^ zmQ|gN`|j{NrV~h?F5oNHYQg!Z450)1O>fdx^{Sgk)`b`m-;|vJ-Ohc;#|b}}D}h1h z3DFm9u{Dlktv`o-xW|Q&TA;QC29#3%UW5B@hLnG`FKPyV38V->>NTzz2O57Yv^#d8iV~4R*S4Br7jmXS=6a}1p(mSfs!J6%yc>_1}?4lAPitc#&9_^7Ds;aNhHawQo z;&Bc-!peBPdtUJX!(Rk3G{I|KG`dPP$DZ-79=kW&@U_nV(7zEre13sk;9K=B=lTrS zF_=XN3}We1g1Fo7VAjVp0)$=x6QkM0i851rJDsxb$n<=k0E}1Qs<>Yma z)zG7aPP<6V9k;HsivOh0Qk-;DSTWWfnJd~$xp9!rJ>al25QUfOhY*{&(b=u2Z@H;o zupSnE;m^T^w<*ysNVJQKH@b58h=gnCRmc$Sfw}Ic1aF9lMg;YpyKh(-j@uBCx+J?g zmX;!*p~J-z^iHGNj|rI3p)G75D6tzw;>q(`9SgXUOc>BW*3mavpx0GM+r|tD- zM12)X=3>_$Q~BTZ~rk$sP_4ej)$esx`-n8 z0VT8NN?^IU;kLCQ&3%%kkL?FpO(g11-`_M}uBE=UNb}{`hM&rBvF!^^lZNntsLvD> zEz_ym6v?)|5YoRdLJN5fDoub|IQM9%j6N22)?u=e5h?1eHw;r4>{?d@=bTS!&AVb9 z_ar~iuHk-!5{Dy`pF8H@OeGV@2bxm}s}14zZwOV07b3m3>$^%X^A5sPSH6DE z1pt3cOZxTdm~acOVG>ZzdZHd!#bI4xg=%2pYg_3rRoV7rGRtg zazsl-JUfN~u}Wa8{q0}T%NCCu_;mYuBO8#O1Ea~#4n=UD+eVfW#Ezg?eUEHgeo7Bg zz=5C08(f@I$60^=#(S(S8wmleV`^hFtvB6-o}LK!lp=$|b!3xF!}{5{U4pJ?1mc5Y z<*vl%R&f3hl-8=LM%H^Y_ggoPm(gC!R4h7Pa&VW+hhn*~WXJFY}G-{z1QEWP
    dre>zN|rkpFf2F{y(miY{`uwDr&HN}^?dT0pMl7g>O*aaaN(#vQgHkqr9 zkVzTLE@GujzCw#FE(eNS-m%q5o)tlZ$WmJ8pu53hIuAzvHxEh*D>a^6lZoM%hk*6> ztMR;-+Xt=(@Y6v70C-YV2^)SxOAUjOO_7OZPu+L-X$^DfggAxeG_P3~Pst%QLkg21)O@@D+ZVs=QxaKC;oCt zJf~nlU||{Us#FH|jR%f62uYBonh$9Z?fpAi$&449JtxCP=$H$=@dM3CvR?K?l5G~By`o0nkb{7s!JERe*i_YmsdANpf@Ej6WkUUP132tvu` z>|bDe?+1UCe4!Hi5{uY`fPj5el~o#Pu*eYhNZvc3Aq%bavA&=)g-M%ILY@h$InttF za5kJdBvtPa7#q2%+p)bO=Ey>SVqV)-!=&orM3K_qOH(Sah%e4`&vL5GiLa0GQebBj zwIiWIt$B)h`eFO4_~yJ>n~{PgodSw#e!{UEN2_e-2k7arUZielJ#2mshoz7JLvqH3 z$*u5T12~xmmGWZ!DoWnbPkc5@_Vcv4X?{oj@Gzm7sRck5+gR5HC7u3H08_-U;f)yH z1R@OFHkfMmkn&+9A(r^>`b!T%PV2Ihou5Mro?h+HLj*F3+)z*<#erzEh;^G+geNc|O$k zcuQZ+%x;D}3Ov_O@&SHWz~wzI!sfD}Wb3U_)Q)qli#|UR!Q^q|nb$$U%^DCQGV!F<9AEdooGduGC?M9}84*3pnT@ zE=PCMJ*=YSheOj&l;&ry&kYLaiZob%9j;-!(%u|3J5`r&qIg4oHf>PkvdMR!m#REN zgCrYkq?%uhE?D{bL{X&|%_^MzHA9!ZpC8*hm6F$VuQ?<$g@PR&%q(l>S|mn+zsFJn zOBgOcwZ&ow)G)%sNfLX=!sz#@nQc52=d28-r z+wEOjA{>u>m*iy2mL5CW2hBsT@H;un$$C2)la=6gvnnxX!*6UisCH^G8zlOoTJUQb zOw+$P@>w>}P)tWWIp^y`I^;`Aqu~Y?_PNUpY4r@FNy>7c zu|%LvguWMw&BzZI&c3~rnCh|*}boHab$7}f}x3WMa_Jz1HY zKV)10uj!WKrmv+NiaCQnr_qS$iKfyr8C6B&vzWn4QWhi|rEL1fU0T#h^ve%v4dlQ! zSY)cgW*K8oAI}hQYV31HeR^7Aq~C_ddxLMpWZI_4+`(-mVw$DB{xNIWZP1PoYCyWO zaLMayJ1_8)WUB{3+DLReL{aOoZ*>+U2XA%Ot6fGdExcK26a4kpV@(?KM+y8_{F5$` z+u3v8Kr!y%UW{^L+^3Jtv1I9DNDz?8{VI`8NDqz#7qj#4Un_+AWPHVKUe%Dc=#Wg{ z$sPkapW?Vf^PKQHr`F#vO&(+N-(sQO3N&7^6O&iD)f{8X_$GCo0_~(S&x!~Mx-p`* zN%=yMqPEa91Qga<Ua?vyh*0@s@ zat1K(k6LOj)iLj8)%c#SRT+fKB?l;sv%dOx7l}7nF3GsQVUy9Cp!P|oBnPV)R;oU_ zu#1Xhx6Bs37;X2p6{rVG{+K^rEEW%h+8Shq_qWkzlC`|hDLX@fPmu3!&d<=S`+~vn zBN^yloIw|34UiaWnC?)gom*w|n{8X<*Ggpt)R!M6rcAhF$_^;kK3hxT|F{hTeu3tZ zR6{vh{-l{d;o)a(E!#8E&!&h{UX)qOuGVc0AE|)~p{kx=+F@G8gDDC*5A|_iS!c@^ zZP!gSDUva&=o6_nlgP~PyhPM73_v|P^xA!ESsYqR{5TeeoaiSpkJC98?YXqwD8}{_ z<+HVu0$DLv{{m?R(b+Lbk#?;%{h8?Kc_X$sQp)tEctqr1S_lualgeqS4C%UXP6spY z@O14z3dGzLD2O-{?hw&yGwMy!z}CjYk*s;vq-bZEnXAIXtW>3h%Y1NRHbOZ&HM&yi1OC}$Src(TZ8=*fuAEn?> z(%`Aa<*`|`Cx;;HF#>lD`CX0#+_dC~g@@L0Au&&I)=gyuT;jzdR2H-)OD1+QR{dM`VTb@+#hO9;rG$7U^CLsU$bc&)hTY*GrLOir?Yfg@8e`>VA4x- z@2l3Tcq8C)RJ-x}X!l@FWp{K?59y=PG!}kl8~;@>b#zu`BU61MhT|$L#P(xh<{U{` z-j2T7Jlw+@o}=>%llpb3QB_5G@_3{b7eNSPT}!(*9)0WCENUfpikK(5mrB6*=&!t- z163(gx}^d85d=0MjvslPc6yT9Uz5Y=0~JBvZ(>@pu!xg!lVwG;n@PPpbecUhlDkB~ zJ@qWx$$Y=4j2K%+P1AP>4Wq6Px;edo3;9m(sww!BquMjy1ycxsG-H2IjnTWIjOG_+ zrt*=Pox9{)m#vk3BvylnS;{fFY&$>K_mg09kBik=z`}7O$o5w$&QFy9&(l;eARMzP z?hEc;{*J$VHFNmQycI1JPmu}62a$s9JK@X?UalA>Rrw>L2$~SlV|#BC_X2HI;38D& zdyfKUhjR+GIO?2!=YFTHT%$41r1k3PyQ-N%?Z9wbh3vKnaC?zih$dVN&1r9n;&OL6q~NA;H^E_IK~u@)OIVb$ z{V2(Ul_7pINz?=*CEI7mNw(BTGai2EzuiZ-bE=InA+lYcR2n?1@WD?%MZ3TXEyC)X zLhK@>YRw>Wf@qp}coB&q#qMWSZwMW;jmoHoWT$V@RX)lfD&U84Go6FL1rnL~4Ei|K zx|Lwxwa`^mIjSwU5eQ!%wTiKq0A&pd`8CR z*-BoNFxb+YQ?qEzb8_D}sRAwFGbAPglT|D1LucAZI|fbc8(!!XFfOkSIby z6WlSUh>vK_CZDiUd*4{2S;yvO+TAEmv8^HDdFHWFN1M$za-T*u>30muQm)n?<)drp zS)ajTV!#8xocL)EjI(i>HQsE*s_S2`wh519{T914@$E5R@5yYJC^n6*`N_51Mu5M- zQ%Lt2=X_hO4WsXz(?f&5GkDVT*u-X|=iqa>2g`7eA{e%pGkp2fq$cqp?9G9BUD!eY4{;U7zao(i*0SexnEVR6hW!=Dc z@c%t?_l{Ik`vT%3u>f5O|1E+n5H;3cLdK$Q=H~z26{*zJ)56!lctasaA`eWKZGoGf z*Gqy&4VA6cXYczw14A9E`q5^AoCny8z{c&;qxv4v`Hji1gh|@(av<2|_jmns7jxd0 z#ZNUMDcR#o76BVgOcsF7x3}NeV8q+-z0v&=1C^!(j0AezfIUrQBRb9k3H3-=gE zGBu8hoUtUgt@QZ`)k@W^SeOAvQ0d5Uew{cqHSAb>v{}I4JH_FkTcmAzC||^Bau|dq z0=I@la`np<*BtR+mSvDxx2_WMJUrX3rKdE7n)c-M*L^buoF~6dN!Wfa-URP^(Lg0y zo*V}^zcj=NR-*+Q61kxZDL}BV@D>p%dNXVVs5Ub2CfGEB?{T7ZF1$XYo0_LYy; z!AA5;NWc0%_O^L4MS5Izj2);#5jKyYx`%GTSv%(LYcw#Q-?3Vx{q|d_AL3f$%u6y= z%JUy7RQyhEYD0y~ZZwLV+3d)gw>;5*c<+xP0;9&-d$tmb?+Of5xMG6?AFnHRnCGSfHg!8dBe6RGqak+mCDa&c0-t{!$Iw z*wSP;ZaNAJ1J5`*&COiK5kzS1&Bu-gD3Dh*sF9O&n{|}`uDyqU9aWDdA65P9K63TS zLz2i-JgdlNMsmK+)(9@?Geq)WtAUH`ORCOZvuFdH$Xj36Zd6!DXF(@xz55j2e1Pa= zoT=-V6(RAg@K3TQTDM24d|K0D9iN3BTZvc8-{E5ff{Tdr-z5;GnHaZYC{c5S4_S7C zF%Dg+DtnJMSZ*PoZf_lMc>A&@rz(p-B$VtR)7BZahc;=ynmKsw7i?eE8GV|?g z5r_v>A&>TqKw?6z4?=~ZvH0mU;M<7mE}Fz{IIUc&RD)axb0y@{Jc3FL;nsfN)eSx{ zVkaSfkTOg*wau`SXvHj)8?^>`Gu1e0-fr$2?}c4YvskUyc47I&%{qCWyvnT9;0G1Y zX^2YbDZEraO9cfHDY3yc%-zTjR?4KTDcmBIjG-^Jt%hM8`z?@%o?wIzz`_(&6N<`u zyguGFyy?mu<(4}a4SSN3RY|$MU52HCMXA2$_zIN%EKO}N8$U{B;(EqMmRDJ3NmL|5 z+u4ASMbZ-+Ox!<3L4Vm>gZ%(a%x*vvv%gtYd%3up+5Kx|redJ1B z%l`eUPr&={d&n*kOrr z?7+`Ag4qPMj4S3HlSa!!>oaHRhb3##D)zGQ=Nv>ilNL2zJk~R?8_TEkUdX_V6$~Px zS`9fXcX=+|4ubcFR5|J{2rNJT0W=Q}Y5ww~m3>v8lrzT&JCY&A+2Rcmdcc9N-Un0Yz>EA_nZYBFEHEVP=vxQSkhBS5C2a3nS zAn%6$ST*U~250pFxxp#O4gTJg|DOc7|K2o7Q681;1v$d(e9?e)LkBS;He(s0R8$o$ zBL+0^SX4!Sm>qXz+LbgZVybf{1{zwZD-O*;RM__`J9A5~%*07YKzlp*Vi%g2f!yeK zeER|pAcv?_U=47Ka$eJoq7(B&5Ugm^?>nzS>8)y8-Y-Zi@0aQif}3fotAxK3QCIk| zD}{N7*pk@_@5Hl=Os1evB9ZzD3sct2h88rLMyQPzCBPZQy4}_LYUT*qwS(&@%4DIi zNy8~he`&(bTQxf-ep2gueezsxP06)OW&uP-5tJpn3f&HWUq<@bH&tRPc9e-jt5CQn zvuY=kMAB;^Ul!!qp1O5lA{5ueM^+eJCqB)+reDd3Np3GAy4pki5KSzdIJ5^|waJS+Y0ie&jUE{_ys z%zRK)BLBCBoc}VYh^f1gy@{FWKYxn4S=pNYr$SNv*HaE6T-7~(L4&_$sNIR?S=K-S zXX!Gk0@QS0nEBTPdjl9Yz7^QK7ct6AX?fqjbfBX>V4(1>#uqVV zLTwBg`N}dDJ2Z(em0!vx&DspPWyfZ=_@vc~G=n6EZh)(5Hy5+PhCxeakaxX^bk0`5 zp=Afe#Tuk$GN$n&!(jIyzkmb$uC>xA7jCpljbV4_D2E{q@4B~I2o{EUBI#8;!swJC z3UF9wTEI;#bYANxz;br1IV6qJ$AaHA$PTrcg2p~@T>oZ<&6dt_NNS)>4D+!!Y2^L4 z^F9X+u$io&qgRfgA@5U+@v9i9{8z4-ux~OG5^Wmp<<$z* z(PRrXDngUKqCaO3!Q&s+Xsfl3{MkjYTC9rDfPYPm_OVJ;66JLT#SI}@xu?&HFVu=p zLPkI$n`bN-C|(>VO{(Cx^bDYI_!$<|G%Ys0a%$8+$|q3aU%SjYXE%d}p5};KGsMjj z6|L1nx|3Qz^vH8b&q<`gJ12dUh~q}Ti5cms@I>eO{ATBSY%VwQ9NBXKthG^4g*5rW zY?s##^hREw3XhuYhgDy2Gzs!FYi*XfqqIlvj{th!&8jqWsNQO;(b;f)? zv7A;wX?-1jNW(q@9@mwwfGBY3I5b`SCxEm_R9&THPYR%FvMf+-SG=i z<4BvSN$D9|kMR$;lbN*UgOHXD#|2I%_e9`sn|o4VxK9st+J-wo`GS@~$YQ61-K(fE z#nk-M2HgXkkQIXh6_ypPTE%6R#9Io)+asLdHhK+{qd%I5i04ps4uO_Kz~ImOBsKY_ zyj7@MqO$sM!t1 zelaHXk^UUzC5!dCpK-8U@fPojZ$oz!akN*rm$NV>n#CMoI zlM2%@*jvYz3kEpK)+2qy&taU>r0l9hgBMv~1>{j>orKmd;8LVcrJTxIjrrJPU6f>j zjikBcq}^uQbb;%Dj-Z6Bw^34^Uy-B>!z+~4(oJVS2iu$OQSMBx5t>B~(AJW>A+Q3+ zSdoy*O()GYSZY7W#9(7k7`RLnyJl6K{FHbln_wj{;?;is8a0>=H9{p{AWoUFiE|h^DTWOI=LT z6_+z6QUFg>d%iE5n2x2H9$qD_>x$4HAoO~?DcJxTAA6(y-9q=D{`Sv8w^Hk$<6|nj zB=c;}MrG7Ugpw)pP_W1n^@3yw1{!LHegxg(;VG1YB;E{+b~AfhXr_Cfe-)@Qp z_XzCN=5~QYUBSbEOR19QG5K>Vn}n*l>|w5r-}i4-2fJyVoi8w5yzNvq6Ti;1_Z`P( z?C9+DGBaeX+?OMDbY?jR?iN4VsYVsDyRdWeGn*gjvVxH~T8OlJ?1tyoK$d(|7D#Eh zuI!rso!Jp!IM3dYknG)Yvhjh8@M(_Ldl8Iv}MlD>;dLw!k8c0jSvbV11U7Nx7tZZ zzI)2UgaR)z99jVur088c6{oglD12q&Wvps!yE^^oi)CLBd7*>c&!MTrHT?Dm??-?w zXrkXZ5;&>cM$cula92hs53PzhGE)c#mSZr`$H$uz3-&`HY~Iz-_xEwQekoX&(r1MI zw93w4`&khfbUr5AFvuOGach(o1a?1!V~JHB$f23zEf*wd_cM$oe)sxj(mD(Hr7UcZ zbIcfb&?}Ia%tBZM@}4dKyL};3Zg)_Z_*`@t@2W4ZZV8Si1P_Or_(uJ`y%N3^N=8YnLx@23N-8dI&&{ghKP z&a*QZQa;*CNT0pQ>Pbv?%THS6F^`EV)UqFt@3~@49Z}QCBax z3Nr0ZG9u9>=Pd3DqD^A`Dg!-Oqwha;H$S}uGgfA8TE2#jhMY6qs4o4tHKK`gy9&C7r}9iOH^KEz7trw z`nYyYE_dJJ#${=Wgutu7W@j^lO@t;Jz-vQsO9)U`_mNj?YV|B1ImE5_)S|n-`C7pb z$WxNrD-13tmFw2gNz!i`Cfzzt5_GZy#B0&`=WaE@wmdb@OBB^?=YMxk&7O1>v5V^ugt0(AiBlyIbn!XY_z*E z_8rA{?e#*d)7Si-LaM9egT#%5b|rLS^gN%(4Ik7FBzFtc;&H#j2U~YE182MDSO8Eu z8BoluUGsAY+_npxADLSTO#%bx%Zxt~A2!p^rjZ{~C5DTZ=+Dj_Dz?W>G70;IPL}>g2AkNRRS&+V7m~>WFA3&HQd$C5^CN9>Ic-?DhwwHc;h|_cEo(& z8SP;XiN(CJ5W>_ZjcU;}p0bK+Ice#xZAU-JadOum(oIL|OAI2ZU# zz}7{$;ACrwFj&3Sf6ecww3~KW*CgUzh$Ly_B+WJOUFZ|4KpdC^;hw32{$xU8SgEPbtpZg=6o&6n}d}*m3VC~+AYrRZ`gL1yH zP52ZYRCu|8I>Wz3IsdQ1%kck;bN*i$GEo6^$c8icKAXyzyj<7t4Nh0tW;uu+Him^l zAI~s6hM_5=^4vTx!|${I8S9gJE7RWLdecj~q+%tzYgESXqy&#V(<_=;UT{o3pIL_g(t8pIsl1TC$ zc0GPe=ee`gj+H)=Yzv@kI}F^P!CYxGFBV-WU>TcV9yZFn)7mBWn)K#Z5%IJHUNVJw z1-4d&;_}9RIv!DeQiJamrSIfGJwL%BK6W|2h*lFqF$t4FM#49VT#>ngSGr7n@SU#k zz`<+iRGctD(Q=_S_Q&Jg$JG`#G~UG#0T&q*N)^{Cz`PADMbtm{XuggP7{mb>uOw}I zc}}6z-tT^f0y_7bOk!(GM%rh1v3}W~NiZl93Y*8MM2}HQe-h5ZuumLM%E}%x%AD7` zH6v5PRKsY)z;+nu-y872*dURL@^B&=m@k$bbHnba1vaa+Pp)cKEmEL1p~7A_VBdS?M>v1QfK$ubA`4*=`O% zAC3%rA96?~jW*ESGD&gzz*%Cu2lf&e-Goj`j;1-WeSbeDV5szb_j(2YEy4ugLs3C2 z_$;aYy>g2dsd;XIi_L6L{gLS<y{{vk^{ zvlyXIV_GAZ%X)WoXb3H%PNwPJ-Ab0o*IPb^?{dmuR6PB0ooP(3OTQ_OUxA?(86sC| zv8Oe>U*RL64To_O>E}de46npLShR2}rlONU7NrBVa=L$~zyH5lR2`(@pkUs~bKZ*Z%Lne zrT<>f|CNLZohNbmW9?62T^?!E)5io?vDtt@WrFn5b00LZJ;|D#iWzK-p`Tj1Egz8D z-GvV9O@0o>SIzl+lns|1+LQ?)xRxkTj#U<(ZgT@f1YQBiO|3W74JpjiPQbIi^^0jUnMCcC;Od(t8lEQ^2ee&s8f! zH5^BFFKzGfI_0J_?OwW;A9(l?zMUeSi?k>&Q89eE5gJd~8+VW?CrNqzL%M_ctR`(9 z#5#2 z<44A*>44jB*&k8TvQv963qssg*2_tZNNcYVd-{oYJw6&(AwsV)oY01cC03a%B~m7iV?9|D`GOJ4%46tHt_UY) zjEy;Tkmng*5Q9xPjX4$$U07j%YgMOu)j?89T<$+W#>P(bA}yOgj9qZ z)#F;{n zKN;C&r!8o6*M7(7m3cz+rynt`N%sU z4WXUR-Rda`nc_92uI?_LvZ)UE?}rWFU!GvU#!VY7M!(e03zbm#XZBfbOT13W?G&UU z<+C6DZXmlT)k6GvShFvolI?AUD%Ie9`0zsQmMd`eK+X)9d#_ZDgAo`RX4A*f(%Jin z1Uw*n~crM2-icyx&TaT)w3AYHj+>Gzcptm;MTw!!-{AcXC z{jnY;CUbF2ahk}~)- zR{AnKvdg83oK@n0%wi!6M+Gz{!MmQo4T}=3vIFJHNSE{fG}?q2?@KB8-8*R-_!J7ns(?sV1g9V%kRvL!_n71Y$5 zlnRo&cSG~P7tD@G9H3O<*G;q^Kj3H0#mau~7;v*sQheh6gt!}H&n-KmRYr&_5o+67 znGY9%f1iS+6Pn!(h)#@Dg)tljX<^~o4yS9f&vu+cYcJi==zs!GYx}b_}B94sRsls+|C*R~>RzLNOcYT#aebOcy zhj`7Qxph{#`?3fw#CUT(Si&wc0;Ql7&nv=)&dw(p<%<{Ifk}Roc7};beNW2xu_>Zz zdgOyycqqEQSHy!qrE$%XKE^|pnxC9!07j>Rz@DW6-genD)qdybd+aKFRo<5+fq}U_ zL&p;eXMHl*u!*uM?H*d|`q=XQ#~;L{RU}Hp!n&VZt|9XHg_0Pz)SeWJMjw&#;%45l zI3a~z0oi=-5^vBQ`~!sGC(z&?(5qQ!H8jFZ2+UBcX;AD?{PEE2(7tLD+wvlDBRbzS zQcE4Ug!%|q7?7M6+=~H=^=sRxfHPS!c3Ul?e5*FIWmYSoz^LFr&yCjG`X`IuUI0nA z1oKpwR6GMfEM~nUy3i(8Y=~N0Pkia=(c2$+=Mp&$3>*ZV5TLF``@hUPGWI48c8<1Y zu4eyFefehvQVDwdniWRP9!;D5Wo4C#MXju_8njcu!hZ=R8iYVzQ1ZbJBZA6RfoUt= zukjQyC;%Ewfg=79{Dr!286KYfWBaF3AD@$qr51sJ_bZUb{Iew+0UdD7b5j!Z&KcVr zDNq$W6eB4sXV~oUoA2CPAK9Qv{aZ_FptE6_|7KY3)b>%u{wRC)sNoj$9 zk8%?>6xLM?QSbfU@sH^*pGYAo#pdmA<&$ePMR8A%PSVJcZJBYzSlrYb@S_CeZS!?S zq4joS!+^>bNDMv^8KEU=eG&d4I=l%^Mezyge~?3G3GJ{w|W|BS0kM ze;i?tX1PyT+BZEUggITW$_p>4V%Q#^+eMTyG0l_<3{y-pcg52E@rhiMhPOV-DsK~S zLMz$OU{ls5`i#Y$mW!tTkZ|W7`kZ^*<&>||<(E*QszM}|N<_F%O(44*UM;(vuGv(6 zd*TRJty~)(3fu~%d>}JABx5D6?#+b7X+U;FR;jW-Z7v+<%m`$pgnC;1$vdS`foFXF z^`BE^uBA^g*r2Rk335I0|Jv;=&77_NN79}i{fnXrW>cv0%<`xFTngPrS2H#fS)=ll zRq6LnjIz8$HnN$?@WbLyo}VtL+p$=Xq{ASKwbY zttwy3CqZnw?vyFEf0VRV?8Jv$bu-hWFy!c&Y(uHI#^4 z02t1$DM@JsSHC6Ukk`Doz{x>>*VzR29tq8fN=qAwGR-5xf{tXy zHv6II7h5dq^1&h95{*$li;rH52HYeyv@#F)T$7S|b zXs=&o9nfp_L4SiSJJRm4s@O|ouxUhph0`5*oHJWt+>u~`%XieRUgO+F>c!_|Ikn|M z1;Ql#$zmo*jX_Nz9ax>hPNB)tcbn2W=Lr zBC<7<~SG#@BKWK`v&`p#!EfdwK)RQ`>Z}| zy!JqE!Ios7W(JKNvR96DP5BV)isL=;ST0qxi3bSzd4iO~0Ls4wsS-c+)`2L50d@{y zbj=jB03a)d>cQ9dIrYo^q+;-BO4M!~u|Ad&47+RoRHFOrJ?%Gsv3J9KeOYWw`OU^n zd9=ZeI%){7iF$mAE%jDvvea+sl$d>=BD&5;<1vTau9PM9McNsO(8U%_!cTl+JNx}c z3re$}BTn7+8N!&fMo(7t*yhi=YHaY_r!VP&_(||kcuacG2L*_q=QyqD!_OeHksfaz0FcR)uTc{!_9pNFK$Dn$B z4Zpjq9#RM&0OG;O2_^Vqzr{|G*b^8RxPI-vVv;5#BgY}(|6Y#942U1#jv41Ve7%vZpzvq{~Tnki;zs0E8)2SlYh!-kq{3}42#*520#0NGVzAsq%lR4xSHD0)U zG=EwT$Jk+^H1ZE`8eK6-A>oHNnTugC9@&-{l?$3ygu$gQ?fTs7KUn%KPMf&MLD2M< zaO-~yP5+6If5%4RKcETlJ{$G@ZpM45*|{8l=W~1XqOnMEVQf${^^qsN+Kjk4YiLI% zB5_w38akAP5T5jPQuh1kundSiP6#afOPpiXQsj$M>W!8kw*sdr7 z#htozWlRbuhi>#@-MuxzSGXKjOXdtGV~`{zw#Lv_wd)}z(16J86glLw5#eE(yni+D z(acx2xuTC+%_)3ev@8hzXD1LKSvWic89Xh9@o>=^@WCH`2fMJg zlVKX(L|Ckvn{8Vy0F3X_Zs88Hsr7iD1AEQ5!UQtwvtTfeo@Kxv+Cl8gd*l=#D?EU( zO60%9DRm=f3p3aMnBboTeo9YVy5*HZ_*(XECac)fAB+E)9So9P+f!+*NHgSt)%$*5Y6iePkwHoq2{27M@|hA`-B;V(R2}I*ZL)+JuZ0)+{@!QD-rPPxh-i()@}> zEUd@moQfBUFDE=GhM+;r)sb-XiN zajWE5BuxpsANEl13ge+!Zr=cS))|F#ACM&DoMt-Xa2VxC78rSE6iT0@6S=5$ekO#~ z_i_`F8_f{+CGC10E=MX(4!n!l3m*0q{2DFzQQhKY2iTeZuun7kqqJaLW&KOZHy8lm zxwc~ec*;o!^Vz=gQy2IPx9d&cnSD$1*)N426y3$UBb?}(uzRlmJ#jp6T8Zxk*+2vo z34beBSlPR{I{%}iX8H%;ySSOTmA%zp8ROr^P!;)$we78F%^gUus;i5MIi=QShZ7F_ z0q=t{4~J#Gl`(g`74DZIcTEcmcp*eIIFPK>Y#*_i?~h7$8uHKW?GO9o4;>EcP0uF} zX%1kVm(idtl)YgRu9?h5JYbUa;-X`cbvYn0FI=sg3>eou6Txw$Y(3gUmOxJERZ?F^ zJO3<*BjyF+w<44Pc|ta+oHbCzhtu2Btw1NnOz%zwrE@|d=7!Mlopd;UWyP4f!x_68 z_c%r`*hg=iNUUS}6q=fZy1SRZcLb_2OLDqR+lp>H>qp?rE|f2QvhslMSJD@qU1fNX z_Lmj|i|4)eG?_>1doRU5H9P@$d)6DcD0=29H@I!%U~*TS3KfVO|*9nR%jDvfZE`!DW$b!Olb>eFXiO zyndA8x!2a7F+P>Vmn%Xn514y#3)(M4jaACXD_SK6rt0Mw3zCk%oQQ|YV8tivj!CkY zY}A>Os8MIob>XH4(B_X)lXhW@(ylD&Cut6-v3umyCmqCtqHCD3oI?65ZnC#c_*+bx z?=QBnG4jkydj0@S05B8d3>2nGAb0s&k0XD&ilmjT8R$~j-o+d=p#F~@Z;tY)A|wk^ z{pie0PavBi7_6-RXsJn92PV$W$@O&Pq@ za_~<*Z;}CCKlWu|YeF3_i?^C*Ns;cN#F_=O?eW^PiX!ZFMu>0q`v+TJ7+%O(wJJUR zT-l;bZu}xGN=b-E_Z}^IB-3B1F3F*)Xngx>6l5leX**6@^*|4j(_9lU`=u$7ZS8&` zL>Ng^jIFJig^}$) zV)0*t|9|Tq|2rT-q_Uuam*3G~RaN=iy!XZMawMH+#jPqmoJ5~&b>e)pWZhDtX@BQl z>1H?aW*nNu!Zs0<5)7-uwfTD1@ZiA;-&eJI+^Po01i$cTM@lzjz7$o?zl{0AxU>Pjc#(`Sk|h2b|?K8Ja9!GB^ImT%!HiCfpZs?NO8Nsh2g` z(U_U%{8Yx~OeeD6`VlMq%pZnG+CnnLYuK49EIDI&!}WAqcV3X`DvE_5%NVPl`ZEJ-In+k(fzn$r~j+_ z`peVn4i#8?s2w;To`G!`3y^F_+B!?dg1ShRFU7={WRP{DfT&+qPs%KIxxXzSZHDH% zlFcWmiq9$^CKw$zt(lp=dF4D)PC-=+u?ryW007S9;Lj@WoSK5BGs|(by^)JnO)lh{ zn~czL!P|}W2q2v`FNf$GXye)p~d?IpJue;fJAuYH&0qx)3z~(LYKlENr0x$?T z7+ROaFfaEQ4KygJVv~uk4wn(bnQs{o(u1Mll>9`xNPmIhT(Aj#r5FfP z^Mx9Xrc<`i4~5ymt6;MiPP)3n$dkXK;fDm*Gm3t~k=K&Us?7Eur6Iz6Akfa-q z&GyIM(8CBzq>(ucYV98@9Cizjdb!g4kKq2vS7)-T!4Xthw+eh0Ur=<5eqaxZceJ;8l zE>+)v{em>EdN&Kd$#VJ*p(tr)8nHq7+MH>Gx| zLy#D{e|x9%kdm8i5-8#mK@r~;T6F(M#Qz`8-YGusZ`&Sj(%80b+qUgAwrv}Y zZQE{a+jf)2Y@Gkot#_Z_c`wf17y0D5{f@QfT$5t}dBS8H0FHj{nN1RkZ)?hJ2W!Q~XHUAR>r_X!xb)@5vsRN)c~PW7z-_L~lwl zz*Ll-a7tqU&|B}<->pmq=^K;nW!Jk{84bHU`9&eQi+rc(n$Udz~z=Ar-py9r{etwl2<}QqFI6=_MJ-*nps6K z>HPHYWpe;@9)mf#g9*D|;=5kLv%M_C;pXhY2h&PI?TaC$-buJl`QU+89hLJyVs$X< zMFi+6w9G8a#>v+L&Y=NPFUXr@DIQEM`h`ScHqn-@dmvrA#A{S78^^>%YxcEDXE%}@ zU_`Ik4T2sL=Zy1gw-f#6*v-a!a+q^Ncl1K)tFea@?2Umo?d=iHQ1#LC{3oofqkFy* z%^1Mz{6}P$jwYtoCPvQxoGmah{zqTupOHn}A18wl`q`JPieebJhq-Im zy9IrQw2~Bttfz#a{F5BXGf<4>UyW0+Evp^JsOA#5J zEF7#hK)0!iFRji&t7fR`DJI6GRc5eXD&KTBOIwup>#!sdsVfrO_xi3uu!^MmKbN7PeN&;#^@EH8V z6|?eHIWEnWOb37MGJQ7fNtWU;ze$OFG0p&8Q>=_w9&``p=T3Y540@Z4$V<2Lvi-|n zd_r%rIAc8kNbLU>NO2QeKwZ;F(9zMrR<>9Ve7+Dl^X(qnQ?-9#?LWM_cQXu{ef40e zuowCqy}Y13=WGm(sq_|dW6<&Yorct3O-r(GlF%T3tpMIf51z-BAED+#NV6n-{g?5T z-iz+DMgS~O09gK`;OL+C>mRU)m>5|bIR1NZlssK8Hy{85w!1?}(hH)E4}=z*9S?z4 zq()_EP?nXbtn1QFFe13WgyHVbr?Rv;I1dWHOn(0Cp#UV0G7^R7;_PVW{3jQ(HUPW}^o}loqN|Mw{r{(v{1<4H zEzE2UoLwAE{(pvht@QWb9(tTtC}nv?cIqhPPpHBkx-6FosMF#HHa*Jw zSa~#1C1cK)Ri%>=@ePX2l+TP;A-L}YUny~t@|kQ6Rx^qVf54%H7C*39osr(OCd>#= zpvqPeN5@IDTvAd-P-%=7g&^{x7fIGpYlPDfIi5pYjmfi*$M4!7V0r%qX0CFi z+7AG{?Esjy{~MTP4Xpo`l^QDmE}#vd2<~X%30U+3^soOKSvAZ5fg6RV)CQPPVQ_TV zUj&nZI~=qR1tCyL?2wH9+u>^R0l{u*v-)cflB{onz%mrf0o zjuv!HWnTH3&fNsNFz{}^mF*m&KmNMaTlIA z1pi}OUp}?uH(Iw4Cgh{$3@j`+0*1-v;)Rx+gip13=#`hi*k(d&f_=;%r0#d4(U?0V zPJ=wFzJ2@5=!hwp%qf~8k)+3{d^b94#yHcuL4Vn(vyYa)Sp&fR4FLOpw8iw#+x@@L z{>RIbJliGpRS*IE`jdpQ)C>ihUysm2hZ?(*Km#&9jV>hm=V4o2E4h;sm=DXJnrgy% zIf4Rq=KH{<9pCEj?SD$dsMKNlGOFdx~j3J4lAzb$(?7v=HvTSZxCA>frqCX z{$>WZ8UEen?iyG1mus7rhs^K?KT`mH|4}{qpZNW`plSw=f6D{@0bTZN&mZW(uI&=i zm~ZqEe8P&xwALWdh}Of=5V4`tb;w3Sr)nlIAiFa{;N!xO#IYHRq?o@l^B)Ik`uKPQ za||HvF-f^TY?d3#YH}_II4PCNPWn>X_Su~SkBkrUNThEayjJqmd**<7PznV1;d`dh zO`@11Pq%hhqq{+jdc^Nn{w<3x9c+i@BJ33b;$$}Bj zbT@d*No{~5)AXr=xhF55Q?m7rqstG0gV24|{UN+63SYN9vTe6B5?})nrlw8N{TJvo zh?Pp*0nkMQ{{AC+iGPRgACPfB*sbt^fq{Jma}@(?>|8{8-)DI*SWGB*ODGuZ+|L?J zcq4i*nD0!O+*En58f*}G&l>D>&WmiyT0BI0j~fqMbaw?469WSZF7i`CQ;5wDNRJPI zt`dMJ0Y3!!nTkeQ+F^2B)WFEZz*xs1@P+s*cAT-{H_*Rqe}M|RhyMV4&7TIve{~tu z0sE*%29AI8TL0_I@WjA={HI@bJ(-nsI9QPM?_WstSwxeE|EY!3KzGG_{AtWCZ6e2{Y@3~lXtlT!8v)now zMh1okCK|@N7vYRwzED!rXa-BE^SI_s z#aY#lsmuAr%x>|W0Q7sRlJpGEjWA0tH$g}A6>f#mWL909haHo!NNJcU=6&v>DQ{>I#@nEh*P0h&Nk1$px2||wJI2$@ z`UXP_I`XwLs84$z2gMiWAu+NR)PkHm1G9u`rrkUW z4eYK6LFet;Z4@`gqx|@!ueTznu1h}h3I><- z0pHPbjhqfUMt?H7OI=5lAU9>@=3SIj8UJ;IUoUDhLOYy>+5Rbt=(ab%aI@Cm*7!m!8u7ws%r|y-44e~4_ub%X-<>^{S|?UM6+)zq1eyPP`Jo3Dl5N?q_N+8M8# zG$5(PAqbBO1U=apn`|^QhENj3@H9c2z6=5# znY#j6AI}&EA`L9P@-uFm&0X9wQng;;0M2X{fo^j|j#zv`tP z+(lL0Wgj%iYel_sJ9_?Sxw8`-tfL!H_;`i?ug&f6aeF@Ym-XsHfsIs=2XrLCBC*O%GYY}a**Qf8k7zur`yS#l$M zt_!QrGP#+pO)R!GOQo;O=e&Oil{m?FyncT?{I=`)iZMtW>JY^3;6-ceFv5f@&1kLb zAVY0y0xQ0;e*=4zkF0)G2qoBEtt@IF7+pw08#@3(1I z-}M3A{T1rd8UgOi6=PPl&Kmvqm^+yCt-%JPS_OJA2Owb>r=!<$HXu6IeB3K$9IDv# z*K@v7=0+L<*xM|@ds5A7?yeLo`;*Dn!`I`pP`xRa0c^LHGB1P5mvEXHne6uR?clYrHoP6 zIra$$^wR&e;2!=&Et6qEN2gmxbq*axT3OA7j~vf=O~w)|ciOhvQMwy)o3SxvoSZdV znegnykmlnggZ6UlzG*B$CnYny|&u&k3p?nOV2FXjCZ%(Pq`z0M&cqn7iF1LomoHWhrbBpI6pdC%qF; z`uh>R6H@wnUC1sa$R@#AGC_U<^Qb)Bz-gp=;y_=S*<9p%bdYya!P4u~%AHwnk*h{Idv zDbJIdA6I{=aE~8wd5{K! zUjkLEM71yMncZzrQ5nmML#0C^!y^;NfW!u5xR`I|Gany`U*=c3pT6nGE!7+u;lGH# z(09CKrwbS&!Bi<}7?Zu8zh7K!nC1FBo#pQ6f5qsP2S&F(CGQLgruJF6(H(ef2)$~9 zWVd@=Zjj+&z{8BFGN7L~BBYk(XUuiBo^iV)+af{$zA2ayc>&TTDnmD?eBdt80ddV~ zwVvpqP^fj=S*$~j$G}2BHNQ@!k^e^Vkh=;4b*`24QD?*5y{8>ZyL(zbo;DwsaAdrE z-Pw0J<;1XzOd84gb8KG)7Q%`%RW@4EZ)_}DV#c{zM`6M=fb15ZlzV`!xL1buk#$UM zilvM&HU-1AQ1zSEC%#mk-~e87UUtGHkwHKZD+(kFI%8?>u|`M=RG_n`QSKU->6Frx z&A@Q%$;OvL1Ae%&{Z8^(L0sbbNvxX5q?5T>)D9e^lcEV$3+WZ6S{_Cd+iC_BA4}wd z33zhVrn9AUtnCrR) zHA$r%e`#zlDsSi~bello)M(NhijB>%6py^HofJY{V(}^37Xrtmh${|U5}~`j%H>O! zdapE~v*+jkFy@6Z^x+=2Nxg%HPAIkF359f_w%mMXBsZef=qtIK$630@v@O%iMOsx) zcbei3oGBl1TZU*+mL~;;Wo|WOL-SFavqHml_#gjiW+5wimDOqOQ}I?_RRg zd)`uqb>Iu-Dgp&#bMn}N=#k-;TaF?qlv@?ktbj>wWzq^43|uPzv5Fc3V7|7;SfDqj zVyoWPH7Vc~QM2i1!VY4zQst|#3;i;Hd#Lh@eo^OD0ChllfZct%(0oxn7(?c<&sX&_eQw!FKy zesL-2C9cR*v%faMOg0B9$MDO#(ZwFZufg@pxH*pydeb26=8gVjSb8NV>gpkyZw&l! z)Vu(#qo8)6p~w%60ktx-;1xd!h{=;r63X3%x);?7gYW^vS5^0^Y57HRz)4Us0>2d7 zGyEitv7HAbre~cGRI}g;st&DCdRj}AfubUfL;Z9wikVpg#fBW*)(r%bV+UmziBSIS zJIdfrh|&IgK*XAQnvBEu62IXby$7A43)Iahx9Z+B11P7es|WfdTz+}s9jX*9e0vYE z_Vr5ppxJ*v2N(V_%Xkk>)Kl%AbnoinFi*4RI7aCB@DWd@%F8}g#*PIV(o6C z^?t9C&#d7-1jHeufWuW$*xoQ@AC;#SUg7Rx^LmgPCbf-lH>>3Y#iti`q3~s zZC^tS8JZ}Y)qh5%h!=q>DtDDl);xSi*TM7tWu&#j?+XU3@{@$r4dVa^qsCE*Nn59L zctq&w?2(YfEnRCn^`t_?nr+w)m%hq<+V*hO9&j_F;3&39=d1n zrsRk{qNHGeNuUDnr2BQVZ7J=H{awZTJO0VKISj@H2yNk>NXb%Y~D|I zLS45aS9%iS7eA#)R)gfW3Hz4BFN<=Rr6@2#Mp(;iChU=D^rPSpN^+|_`jsf{*qV#9 zrN z5fo3_x0lIrV?NO(ztY?{zNA4YfIEPh6;}OZkTj4j(`=C4^9FGttso}M|MhfeBTX3r zQI7dZIwbEF`FVfx1R7b&7P-G-k*qR2@Fd;7n5&@FBOtlVxFKc511uef=cSih`ErUld+SCBTYCmJI`fw)y+)`bbK?8_G zP9n7`c7FpuG2=ufL- z4J${VLq|2!C`2n{ltg=Z8@5ZKS;cYV$n)9556L{vK{4Jx|560c1A+ zRRc=@e|Mn%?oFyybpK2<@(M#kLu*M@6Xgc_+aRhjLY4T2h%OdIMvMjxvn-hShnTEP z%Ei2)Jbmqc@|Rb`|GPlXI;p@0IOA3rK%ZyRYr35qzvt5%poax^jFIA#@006b&oSF;2yY*d15XNP_cSx@NPNy%)ptyRy2}Mv?`= z@aztWkD3{i^QM!JI`6k|lLjl^6MqAuSh>))bw}aQBO&UhBh1i2@x7#E_v5h0*I13U z*&G^f&uqeM%0=lJvmFMK*us{Pf!SV<&^<9F?(kV)i@a1VTNw|!MYTHHyemIncO!Yx zujnVApsLj{J~1ztV1*?Yw0q~PJSwH0IhM;#%xQ-u3YA`0L(&D?s8SN^X)A!`(Hx&v zmP@QuI(m-+37utrVw6HyOhXM`$`UNwfD}BKZvgcuG0e-{ca$71L?f8uM667lOf<@F zO8`eH478cLx3fSg#x^UmwzggTbaaH(DAQ{C@~*5Kam?Ah?P_1g>nEpk`ZzK@A}rJMlSCV0Exf-`b@fLr3K3?74WRl( z+#Ya2lTReTbeml1sOUt74%+o4aPo3xZofz}m48h$o_}T7&qes|QzMKwBC5j`!XrES z-iAYXB{HfR)A@aRQ=SBl)q6_bl3(>sIgF(U{tTjl973#2`&;a=c9SPIT}RhTm@xO3u;@9MS--|zEo1o_MBO=BQ&iT!~blP&a0i;gxkuCNm=w{5Ac zdM^46=S2w`JBw2&nxrtv=F?%Gy;=1s0t)C{)yvx=PBUQ=wZhj#*K*amn>O2DwyA-) z8VhZaF%Y5(0d;{;Zfb5QIM`3MI9#aK8Hl#67FspOzf#J3qhSv-!IvjkxF;|*>w%of<7ZG=z?Z(E*EKGH(e-Nh{}5utV64sIdL{S*uBct zTecdI-GDViY5on$hseOZB~33SGE!{EI5iM!hNQe0)=h_bzDm?<3~`j#vPc)5nn0}{ z+sh={2daf}7}EesTRy8J8=<_oqp{>>o|P7%nomulhA7k&vnFIOk}!03SS?Y8E~+Cr z?E|DN+{h2)f+O!+&>6NZrG$m1??6Vi14zgPVdcrSChp_GvE}zCpx6XKG((X#iw&ca zf`!^W2fqPhR^x_(6Y1z5*O4GRl&u+NYTDsf%SS3|(ND%>u2mz^xslc2v5|aPDao7% z=xWO(iHLV?4RYcxW2*b#ty*eiF@;R$URB7O86qQnvl2OB>M}bLW$gg`Q4Cx2*xN- zQgjULRy9d6i;3+Wlm#`_ zjWAk|kk*OQyT;@iZ>5_z(6ymyfOdwtk*;+=i(Xa`S-0IQ+Rp5%exnAL;qF6DcPTIl z;P2M&dW5U;N>5h=t~t5t8U6hD0LD3hVE45|5hGA z^yzkV=jA)}On2ZVd}pNcG0i`I{q+yk5>X&kx8LEFnEZUS)Gs#BX>xPjX*ZKQqLwC_ zygfy*yguRTK{e~U0=0ci>r!pBikJpmcQ$`6jB5z#GEkmRiZCe-f$rmYxxS7c>sYsO(@~}hiHza+EY+S4=!Zq zHAT(h4&~|V!TFq9K$}b>Cx8E~>OP9b)hZbo|6Fh-H zs37S-rhpPqITGv?43`!quy>P1Sb+c(pzwl`;9PrG{PuqhjiljxOGWOWkI)+SQsn_(Cym< zgf9P84^#h7|M%~KO17e`^nd_@&&F_x*hN^2uRafjOEK6gV#=o=7b~eOL*&c_|S(ea*-2aVm4_=gJwjKUfN8OVO`yL*mdK*Vm;TEeE8ABcJq6Jb^qQ6#tycAZ5F-khu|n7H9LN@6RtgH=IYTFF$a()z zc&Nyi#0OaP38eJR>e3sp+J4l2!VOfkA=(xV1;DVT)^Pk91O!DD+5KU?LHQ~Z$K8oy6oJ`OFkOU;`Ox@*wxkY*^9axw?ww>rS z<1x)S!};6x zmlS=myCD5fSbU5D!e*1hDJ4f=mmu_Dc)a;b2JB=snC#Yh=sTGAM%k*8DUKjBUpm>D zp?e(Rm0;Un`$X^2u{0JCy8>UbXCXwY&QL=e8$ZeQp^zvwOk*|-*O{pMYtTl`=IK-? zHc>#hF{Yx=<>-x|^!C|2LbXnPAef#kJqpKvt`vRBVEe%m-hB4apA`*3XBLMIsq7HI(ujHGw(Ih$u6s!o1xGLv->1h^Tl&CjEbkSw2RS*d+w9!26)@}}#TM%D{0~yfB++^|!YfRtLZlgeM7tyUoxdl@P zCoeQWQdZ)pZ9FFWX?>A57x*0ae*(78Jcm&W^rcNH5sBO zu|t0?o3C90-v|@NOqTt%%e{a7&{ePEhah}iA*ua291eKP`x5GoHYj{)-fpYTwyP)RuXM$m@bpbVLOcuO0@fV zu9)FhxOjYqdzKc{XRM1&2iFs^bGBz*_GnXW)kcXSQ(8`7-u?~)1yVR5nEIdJ&n|KwTq-Mw2+Y@mP@*il4G5((gX4Sbe+FTB!d)`E&q-6`0W+%(?3B0Wm4Bum z2OsFu+&Xkxx}|E>o!Sj#Mwa#zB_ArX&=QIv=|TqPth7XbLfzVRkMHHCOac#L;*kt; z#98{KZbhHwtvz=K{gPbN9HeGv4b97+FdIOBS{|Q~Wb7TcTzj%n%%TX)89Y#PhoLEL zqyDtV7R$GNuoVIX)v>@`-ua4^&z&_pqRrto#@RXX+~gSBHjUYEJ?jZj@k=p^H`3;q z3+C9fM#QA2+=l;_#$+JnnO+o&TlW*?oSN?3;x$@k}}DD0eRdM2Lxmi zKNSgIQJ+XX^-8iOe@&w(GRacTau3Sp%cLQ>aG?EmUUuNbt|S(%SN?9#aU(;w>_D5j zD!pb;9B;rLZyT7phdUk!^+aV+JBJ?v!^@IBl70>^|GAzjgk$%Ea?2^h|PBtNsTRS$u>nv3{ba^ehRkZT6N7Wvi?g2di9%TFOHpL)>?nnIvGs+stfK4 z7wdC=dbv8&7pp^@{;--mO(^2*W^xId+|A)*w9Ct(*>8mn&_==r;lmEUDWYo*a%?s? z{5CIm$(M^b+jrV5rm6M6_4dSk_Z=n&YNiRjE=S@^O@-eOl!^Wok(fnrA&ffl3jaU* zFX-GMSA3i13~PI2Uw4b@~4qVg2dj zDLC4>dnlXy8Gip4iC(sntULDl>;^R3KhG6#J?o2jkh-geM z1yn(OVv}1JFKGUTm`YtY?~zSAB@1FZX22&Fk_mq^(?!}BKGOgG20`C3)+A@cGM6F# zHHxS4&B(Nt`(o5sAdQ+_+B{aNKhc&e-rKupMOw_{$c0cz*Yo37$RyUlp>8>JGIGmj z{HBUerjMd8`Ajy|1Y=G0>V}_FMtQBCHu5xLS3^4yO)*>IkN_8LSjdY4cz3M|_CpI7 z9u>RTes{G_iR&7V=Qwx76S`rO9->)e)*Y|CcW?5pTcKF)`(U+Q7Rz;7X%Kr~ISZd~yCC1FwIbxjxCih14qV0M-i>UOW8@u_Ge_E)j*Q zh5!ZxLHqDs3VOiC%M-H`9H5lg=v}1EZ&}nyL2}onABT zKevC+^ZWID0yBiLhGK5m9~^D98MVocxj6r@KD8Z-;6~kGjS_nk;GaL>F~r8D{W6E-2pcx=GTdw3WVQa$XbxR6j$ZV&;*6VfgfN3F|U^bEQl%O_^<;InWky1SO4FyRLX{oqHiuL#k5Q3FWsxxn%a<@#lcW-M z^~T$(Ml%g~vn=P3gSO6M27`COY{dX$bAyZZCEI7N(`%4s{`xIyl)em7u+z7N@PZgW zD@lyx%jSwXKUZQr2lfk>9gTQ?=vajr?$Eh7Ju zKT&$b5sD1)Czo>3!DS{3ut)v3CCP1b8ggQc0!CR%2%>ACyYU5MpwX^ZGmYW)-O~$OMZX?Kn;y~LY=aIv>j6?nd2E=v~fr{EGs2SGp6_$>0J-NmMKizm|h?zr9)F%ar*zvg(m zFMGwdD^Eh#?IIHp_7>>-7k}}X_Nq)7Yb3Ya$lZi+%eG?ZSiQtt~&m4_*O^dA-|Al7ZpFbW<2@B`+R0B)xl-(Xs&0bH$p-f2=_$GuS1?ovQ$$<)He1{}xSSH9F&zyD zSE{nPj7_S{+9~-uE~Tl4iie${?d`{4kY>mw@8jNCWPWtALoEe}(FHS@r2|7W(;}mT z&)di9NmGC@ggRmH09XYHRNl4#D@+8IN&gYdv+VFA>;6uOWv*fyg4Ir`^_2IsTf2_e zxC_&ALjRt=OAcgYtK?U5d#1^NLa2x0HLK?#(TiYvs%W*v2%?ex#rzn@bStZMErpZl zVyT$q&8-rMK~pnC zSpoc)BO`c7gKo;m`Tb%Z&*Nc`V=x z#AulLqLH;kl-xF^W-{bP(`FA%G*Hdu(ZyFs>OY$gc7jXKI}?}LnH(90X{EUfHJMWv zIGYe^qkFs&5O0VI!#U!;5}OY6#-Ow?pbB}m4k>%P=(UexFha)37sdY{7fYi-FqT57@Bw=lIkVJx;5qO)IM z1RdlOip5~2s!%qrM=--4I@yK*X;UC()76uA#tw|#PkF1ClS=ELUf%XBx2QjLRmptO z$@5!QOV`vdZgYXicF6gHOdl<`w`c9hcX*VruE|GVm8_@ngQ)}$ZPzJoQDMEU7NbgV zXca#pe=4}10ak~Y^_#p*Qg)tI#}4!yJ0TubIQDmt{~0tY&CVSy1A>!6fKf922L`FH zswDGwb4*s+kOPDyyv?l!BZzTP=(DN{-_T$N5+nMagaB%HM4_Ms^2V+f`D3$Prx&aM zf!-*Rj6dtX^`5R<(8D5Jr@wwFm&&QT{GQR@@%^&e54P8i#AfLi8C@r)oml3YpNm7` zMDT1Yk9c=Zcz3zSryRzFUDiNb$3GMZUpI^H-RDTh{uDbdj;7n)KYr9)5ZHaGK#Ntz zd)S_H6V>yV;fM?9x4RHjx?f-K)V_`?HFKlk$`0pZ`*(wuCe_ENcdL$wOdVwTV z1#!V61a^@0kU|EslF1r%i-ar;Drvow!QUOu`eC8BL?%Km-y!&iZtrDafD%JWEMKO6x7@O(NBu;#{;oT^C(pqbdE?CaT>ionnGC7GvjqVXvzi}P4Ha;oYm#x(B#4u`8b%Z&2_?t?4ZN&B zg_u0~BqWs9IXIWm0tY^$?8;C|%-4rhnZxzaOHk7@U2tivWoRG$RugWN}#<^(26~^WQ;W}dwogGrlO4bQ*{&jWx@@xO3FB>q*MU60_egM1$ zn*n*4?G&&r#*DD~)S7Q&!-}Q7NO{4X;~J2o!g}>0ad{AcHRdlc>HwSB6-66)A8S|D zouEV9zpWBP%UWc>T7LPGdQt9JHdwI%M?&b%cWjl$Ve}3%|0y zL{gPwXc_vr{B)S{KzIs@B^MQUfi+4E=g#-KTtL0Tby+nF(^$2ih`w8yX3aw~tdJ)G z$21e)!-ceCYNsNi>4~#rzPJ4_5?thDHp-*0&T6%!UO%pOsb6cW>2PBHw7ZEqel=G8 zhXEQ1*zDkp`nwRqFRSB>gG{lFqJs39aNmN3V3!()P*qD9+NPQ3;I2`Ig3TYQlzN7) z{%jeT&w3*6E%5Ec#B<7i*!qrKGk?CM4H0`R_>U7t&uBQ zeahPecplc(?lSZW1B{mrFsdAAX~nnw=^sqfI z?hQ%qVG0XJ5L-tgx4c?n7}?v>I`flLV9YGgW347M7th$~mwBGg{w*O2Ls!r~@_I@G z1SRz{nt-Gbmaqn~BOEiG zrJa$`Rnv~H(vy07!D?f5!xFJDR_=mwA5-q<`8)s91p{daUH@^x`Tzs_zqVFw0mfwn zuq`J*p7=K-1N`_$bfl#HH|irfJ7{T21t?%N)LQKVT_pW*Rx+u>Auv3Dtei<_Zd&1% z#wq9J(Vls9E0UW(5^!dzYzct0Bazqa@yEsF*xTE~JGeitHL`1S(?{JIwuP*5%gW?d@$aG7kB$#Yzj73QIvBIzabSC?9|#dmnG2=kCw|L}Nw0Yd1OMD2a)yFCKuoI^ zLbG<6s^H6rC>(Qe7O%2!f7J1(ZGj+#i?RA(J}z-^g}Rj-=Eq5{oCCQh20U1NeFJk! z*E`B+fNH#}0+DqQ92?HCE5Zh`RnbWg`?%D>xA;2Fy&WBm=XDGR2i=prb3;zfi;k5y zZKVTCGHSY%I;pg?n@<-6m!wNXs>FdJX49{QF+|ICIiu_lR-arIK~#OGV#fmar1_V! zKQ|dli7t0*qGUIT59MQj=Uz)Lxs>+!zCynMbuH0>$6N3IbK#SD((yu|AX zLAha=*nC^v+#em(=^C6rB~6hRFN?N6qqg-MSpMmD1THDPURE`=2*Pl=K_|9x$hNj`DwB=ykNQpm#EHbTx6LS2D4&bN8_%V`eA1}#V|_}mjpDf1Z+$wxh4dukWrU3OOpg*9*%-H zHZd8L?y>ND`%8X{R;Wu%B*k|VoPkSCEAvE-S3uRs`&h6ZWJjcBka^S(`AuC-DvVQx&q|XvQMjZ5Z=vx%%hK^nz@ionj`^$g zw7a^6L#$_50c)hNYe3e@Kh#n$Aqx6Xs6TbfdH@>Tm4BGU9As?9=@# z2j|A%3E)A2ZK(^=fu~?U)%PPNMX5kd<#u@lEf;wNEVZQO+Z>{6Y)7M|3N1zNrV2o zH2EV-ZA5Lni6`KxLek?Z&%EVYpdq@97JbS8*2PF<9ny@Z;aE+O>_ zl4hu6rYnh(KAb`*2?f{TVFQ;9i1Ay3(9J|IstNONUJRH9y?Hn9^oSp{2x#IT+IrzV1K~PNYLOc7jGhaCsbT zxq4$KHT*a>*@ECq)5%+dC#N8HA!F5HhXfJVC$_|r%%HuV zNjl_ojTX>AV-d&3Y)zcJG6LL&Y=_*&RP7>CXsHpgjJ0PR&C6`F;s#=$%7d#L*|$hL z>e}|i;*@Bb##0eeMJvpjsMsxoPcI)XEKOY+IBB?VfYWMKNPvvtw%1?P6jBe4E(+Dy zkA6*JytgoxhWjPQ?*KeZ4xy2!t-&}-#mtIyo3{B1oiL^Too3Nx_oHP?dj z29Bx6_$?=K3ycwFml=pBbR?_>*4Zq`ka9|rI=;zVSk;gZ25J)5W_S*t_93|URyr$F ziw3c|)~Aq_e*(FnyS%u$#o}Eo;Fq-SU4s^3%FIEzjyK#-3!)*Ax#)!SIG9q99*o{Z z_Y7Ve9OT%=)UO<2W*}&~{i;LJs$*8M@cIV57kGrs?m?EW7+Qe|z{$wXYt|OOS-pAv zYxl89E)WdLHniD6Z)iQpat2z{qq5m>(ie&^Tm*T-ewqaLa3{&d)}w%0MEv$C5$K>E zXq`hj#0R+s_8rAqdD5RbFc4xo4YNRI(;3xdl1_Q=wv}$l$a>_;*dkJxzaEz|FG`NC zA()<#d>yQ7#${Wm`&e%Ww^N0AWP0SrB+}FKqrQT?yXH>$v@ZjxnNm_qk73-%ra~Pe z@cqs|+HxmuwqYQywDGaF_DJ73YH3<+VY%0K=#!W~68MzaxvRQ=bt_DQvjV&P+!-qU zg#p}?dRTajPCc2aejZm*=y~!m*$+76pZJg^(#LqqYzx;F;t+LLbtww^%m*r4*Why z2Yot9&c^Dq(;fX474GfLFvNU?hEo>R)JCzaeL zMt>&IJ*f|!?J~Aa--KcDL0?IOq4Hv=P&uPzGD|~sM^keT+G8}vNN)HR%`}vkbvkB{ zK!y(15uECaP*!Zy^bowZw;RKScs*t~?`SHIFoCBRqaDXk2d8)GE3}BG zg4zQhIw4!w*a5tw{Q^$+YJe)-Ug6yy@&rb0a~aex%xfQUdy>87*J5lNq8%Y#w+>t{ z59G)zIB{xwukW+Rm4o3AeK?LBJhwfa{dZc^-3@m{?{*cJU4r&xry+Nx$8Dc|KYlMD z`d?r@G6l$0;DZOQFh29f?D^9ZP>bgi`w+zUj6@LYaCF@F8%o=?-fh{D=44`_z7+=j zbyUlrO+B>X?hxm=Sd>GcJNo8qAIt1=Q0%!8ddi5!*Z<7nb5#GVh}J}ZZKCcv5p|7@ zyM@Z(rOf*+MCRxO{Urm7T@=|ZFGcbSaZHwAaHIucbPfSvq$@J>2@QvVeVfJ1JuV?Ln|SlGpumC<86wr!524@pMP2J?IJ7CK;@JZZtVvm zd0yk2jyv)`VLirC zq?{Hs^I%oLSF)^~taChdE&4Xl4~Dy4`6${his+BkuMUlA!6#IAXsv|Zkr6^uN*aq~ zSA=}On&k=Z!%#8xoHOfn(j$3aDc~LXvp@Q~n!jL=9dCi{m?&Uw3(#U>npP)v$_TB? z+^#ea#|70Vg*aY3G^s+Z$Q=w*q2S(F^Rz>@sByUQ^z%heKhp*If|WVYd>OgN`~7!P z|75bzu1H|Tf(Wcw1pdROk+X?AuvGcyPRTzAWd0>io~fYoM=qEzzDgDtlpC`VeU1Y$ zPK$|1kO?EvgX(=GBu|u6tt&^4&&$W<`d?{$n5F{+x(UfQb#73!0LI&s*a%LOEsvW5 zubrUP;cg&aN$oQ71*BIfR|&FFH{tQN<{iQ9JTpM$z5 z{r0E+sab+RrpBmbILhe$JySAc%-75AJBGryVk zLFxWDCHoFB#jeeJW_Xz&(kq_P`*V2bbFwe#5`#VJ+)k6aC-uA9?=kNHwRkSwqX_0r z#w7QvZmmjt!_n)Qe=js9-|0BkfbhaJ`2QRf^M5h)KPuA()eTi#6|4|{ zUPeNq=U~9zRIan`@!c2k&(3f5r%R)lotnyJ2P-~X>PCy@!g8%NYh2Uy@zciEy#A(r z9WGlMFIR695y>*1T6W76o?84*M&@W;mbIP8*_s63=+;qUp}$H z`MX@3#O)e`letjl4IH6+czMg_;=c@Wd8jBqW8pB@T2RT)!zX|9r(>GGD{HkxWc=zT zrbHZMFByP%56ADNOy0RE<$aKVx@WSGMt^91CUYq7jwq5OR4l54Uy5WZp*=kHsq%+> znt`<$3!IxyZ2;cAsGME!bbu=Kl06?7^cVV^D20p^mii=>@$Id|hVtHNW2y%#y|uBI zRy0W_=Pot+&_!1hzKU{WtfHQju?R9{612Av-R zy~73vD4SnYXfPlND=c$201=ZtHd&)j<1Qk=w(CR!+&aRjrWp zU=HFkJJJfN{zR zy2ixALnLW>@7KIGo7JzS=eXY=LDW&5#;Ae|mHex;)E+nQedP^&r{?as&U@n#9@@Ce zzxk+swiP-^UC&i`EMjvgk%9_KcV1RU-5Zb?)0ARY@l_08i=aQqFQtj*cPnxk#D1q* zP_i(RSc2C&1Q$)NNl34KHBud~P)y8*i8^aFM6jwgp~A3@Ln3^OQ4T(P6+^dku9?C4 z>C?K`^DCp1U{+JKOu#cJM6GumO)S#xCvvhy!*N{D3MqF65ht}KrhfE8nT3s4)ZsC) zZAK0?_6zKN&DL~h%(pAE-=%&dJG$rqo91vtb9fX_NWSuKxuLFJ;X4@o`F4}P$SYox zAwqWunAU&eUsOd1;%Y0rFG>;x=YSRu5m|ed6}_$9InxGeGz*I$i;Vam^_FTjlZfWk z2=j7^?dF6Dk2*;FMvKvj#z8JOFg~e@*=!qSzHg?FipQUli%n@om^sQlMIs5{D$S7| z*m}O^(m0SD8dZRgZ7ay|bc~$2C5`BF9Ru;qkJZqwvu$_`jFAsBarNs6%L1H_&$VG9 zB$N#PD)}1{>-hu_N@UJitER{Xv@<0p>wPRzCos@?=|kx3hpxgY^?;Y+m>*cdwbD9B zG|^t1Ll}eH?7R;0!jbWY^T%4wPV=bFLz99Vj*7SZoW;07t?(Dt6`thth81h9`jP8` zEp+Ep6?RDKyh4X+thaJ>yhx<+I$ySjU=>|ug0PC;F#kPjR!f4}5Cez*e|UP?|EuTm zAMfHn=PJr;wm?N2zH}M~AuX7MBrAZzkNW;#%-D#C(E^ko;02-{JD+VbWS2*4^6n`{ z&3dH2@B(Gl&5$h))B_7XdweRj zdtth^UcP=Ibwi`sxLl*gI>zAy`~Yg!gzV5)U)USW%|Z_FU#MX z?M_sF3@~mKo%=3eQ@aMcp1Jrfw9_0}+qFBeQyDzZmE zk7DMX@7poAr&~mCmc(6%*07?c^KY9e<9K3#&7JTR&bgg{J(6%&(|oMUnLUfn*ZN^T z@tWI{d$1r~P4qHejVQFAxTOn`Bbzy|!kxcgx8pD;C2T?g( z$3w6zg)hSRv=}QJ*ELiDyoo7;sVm4~l#vi3jIHhtt@8sw4kl5-i>SI14~lCiG?$#F^)0PthGnnpLsR8NldJ z&4}=LD;Ifhlt;AwsEi+g>hl%|sa0*NXvhS;{5lYQ=+b=wah>K#URpbNQB2sW@a4g! z1=EHxatL*57o@M=gZkNH-(jR%G?Iljvol#|y*5Q3Yc+9#k+NiVWj1~yGRJ5|yGI2y zzFBPc3c`PWOZPc8=8CtzIfPx@_2Vm~D`{HG}o?&vFKSIoGgvvn_I$`Z5I$CrFn7c-2K zymRr^^C9QAd7V}pC5Da6?dld4TeW7&r$##dV}FBsT72Z27+SG2lAP(0#~t~vah>@a zY(oy{F%OXy+h}$YTH6>X&OIlT@P$`AIG876Ke=)%2ClH4#lC|jnUBY7wBZcTw9D90 zRHtD5>@Xk;+*V18XT=@ZJtw9o+<9J74Y?+&@W*Y&?#4+WK`AF)!poXT`FRh>nzIa2 zHM-0C06WY>BHAdV#W{h0vUuhaO5^G8pf4`@CQ=EW_&w*&66bNG4F0(qG9f&5`R8GD zHKT;$cc1Uf;lkF6@~t`VD)VzjqKSsNSSv1#cYou$z>err_yMdsJ_D-`+5a%Cx;R@{ zGl;m@19gN9od3yNDQ0b8=Ja<)MWBAzUp2^*cdMk4jI34znv~uT*%KI_a)};x5)tGC z!R%48OzR>U)4p@-ld0Ni62P%h53mN=2m*Y~N7I|^@VZQOIz;gDaPdUY2c3fE5o;wP z09WP4<)V=(5B_egkGeOn4zbnmhD;`RvMtO!V+qJO7jvc6R{PHQ{@VyZDJOd91TEtJ zF=g7OIi_%2vS5>px3lmjX{UrKWRNf$B*x&h&>Pf~TQ?eX1vMaR0_1FF)$)s3^AW0C zxKvXNIU3&o*UK~vQ12RRLDe<|hkYkCx97+xww&cz!& z396p8+-k@eir~W@B1!Q6esTO=MvoW=W&=|-+&@X23Mt8RbokAfH`aB~Jyg*!w6?6i zUs{)Rs_V1EK}GYJgWe#?9?SbFOZMJ#zrdG!5jH3T79-mC)pbR zA;HCpYFvY;7qO&i(>q0RNZIy7$#}N8NFr%Sn0E$R!YR5k85XWOnWzZt_|fe5tDUCE zv(!@izlAq7JzlDEpwa&jZ2qSc=)a6FYU^SnYhbVUuVOPXQWoL!7o=c4?D5~Q;?>oQ z{m4Q6LbP~-tANOQ%acn7PFP5Lz)TouasH-s$5p{!47X5py&{}|F16^ux*m&bG03w7 z8gjHh47UrVaKVZ!R8!JED{zBUVbd>2c?UVFYp6%WqC&^7ntdD;ksrRQuha+g%G3>#M?;gF-gt~#k{5ne7-6SxS<#;(iG<+cSNvS-qxYbx!>3REv-nx zhXn-#MtEUhTJfK1V*dLP{5cC@pp@Ppe%pW1y%Z=*+o3Wcy|;Tt)l1_2Bd6rfQls)XnwqoWR~!<)lhij__F6@qwP;SrTd^M2Jxg{FJES&iUK zxHpeAOx*QgNzv2op1S-lZz6pj6b~_YsQzv4Yb!vqS4~>KALl*g758h0Mdqrnd<`w+ zIsEAf3d{7JY{dR$-)YfDhGqXsntTE@M5bYpE+OslgLtTx^X5heX?j(Z~wSa?oJdF@jy{9-(hdr49B<$i%+w@*MW_Wu5=Bhlj3P zG@lnw+ZGmD8XsRAM<0J+5OIhI-PG;`ndk?7yzsKL^pO z8p>#DSbUg4A-SJLnZm?on)MMmw?hWWcf*jsvSRn^W6XA=YkGNB7Yzxr*J0N&n6lY< zNF1n?p@o;fj? zUhOBC7I+evkz5jdojbe4&80YzV%-*Fa`V?g#C@nMlFde{O%$-q#v$<2!_p8bkQzm7 zJU@kZcu^eD$W$PZn8~zV8r)qblY98uo&MNa2i2=aCp-(SIP)k1P)s)cVV`;$OFh@) zvw2SyW7$>Qk-M7dYj84?4Bo&aMA#HoU0sJG$#mf84#9vr z`efgZyQikMdN_6jeXok=I?BP0V9GEc4jN&yabU)z8}X%5&%u-g3jg3MF+%Byd$9MY zJ=+qdoMiKqq(yk2PMsk!hB?ow6LFm49Vs`Kd+6GEPYMTobCjQbb@`#+h|KQ4pF>C`qjx zuggdQ8mgn{yX+<=Mip7W%;l#};F1usa^W$%q+pD3hV2Xe!IO}KEL{T!qIcTF?b|%= zQJEiE7BzL|9Y0Th@aTDlKn*EE5aq#3&=p1LE4YAfjWeA0REhq9zDRd*NW-solMWG< z2R==CpuTP8qc&(3@HQQCU_NAdIY)6mPpp*}%U7>PY*p?~V59nqsSf+QD)m}VSb#3> z1IK2i2jHbJ;Zpu;%kbcZ+jhHbG*DE1_3?Je@T-jw-Fnv&FaPeFFLjridr@t~+(z7{ z>UVcPA)_<2);^;Pd_2PKvl8Acay2@Sj214``PqfADX^$KLbDU~%&fjo4WrfAM-uua z5K2Y&JXCy<5M(vTI`f-6@%s%>GUDDi4A3%0BHPAetn^Up-C_j1{$7k;6^j4>I4i86u@2x7Itnq0$!qrY@_g}2sby((^KpXSIa&1@d^f}bp6ebA#m9`U1f)j_d z9u=6=J4=)+!g#3#4m2HMnC_)D))!s_*Gx0r6ElCm>%j0w z{)lFtklTrW+7Vh#nTw^uIu@pDu_Jns-Ph@HOPzJus3d-6wt~r?a8p$c>cHMIckNt| zU!W=(o?-GWyBR3wjBAL!)v%LI>sp3uV)CvuD4xS?MSiCdg6^D~V)mZ85_@JsTQ5LY z@S8AvO(~bN@i^%E_tu2TWg7k;385EY4*g%JQOZEEyMLuonLlLz=}- zyL;=VnU(pwn+n${bY0gb zTsPL?hTPx+k?)ECQaH4Nf%?17)}**yb7S=2Z2tgaL0{Ru_`CDq*ozE4|?`uZo{eK3KUsn=B^HVi3h>(-EFA*fVHNBexZJ4vRg8o7q9 z1e-hkIHNpvDSknatyw!j#9!rf6td(*L(P1qE~iQhZD618Mmaqj+2?0>pG~cblrqW@ zlellxV*ME2j{>Tp-690(<_c2n)xtzyUgGj-L~e@ZW9CXuv9K~U4?hI~&Qmre^;4Fc zBpe%CpT1f43et5>_-MIqWLv`l1Cmv(Cs^+=7d5A$6_`tIsc-N%{H7y|+QLI0pHiNn z|J`#wl2e2?p+0>|$M_#)1%Eu}A6dbInwAsV67pr7sjI6RCMg+kSMYNq^6Ytps1TIb z7v|OwwlZllq@Lxt&;XRSdfC_)mGp^1r7(%d29q;fMQvU0t@4j6U9V?|P2uK7<0O56#4OxN^;Z|?NOUCvzQ_2r@1NTHA4o0=Xuht_PHZ|7K~+a`;! z$+-QWL!{m;Yw5%4U;PVLb8&{R7b?qVA{CT{!?r5SAqy=S+{1W&|wKR zoOTRR*j&gMZU;8c*=ZweWK@|tmqtCS_i25cYi>cDD-*u#@O1nmm~dEKLpUh41ymY8 z7qnd3BK3Gpm?CUjHLhgn`D&didRW*cCy`(y9ByDjLUDgT**4Zn#(~t=EU|YF?D6%f zb==VcnJP+d6!1ChwFOz+nqnJGNnWoHEb?V9JXLskq~W>LmO8k5iMbzI#u~9gnw2bS zt;dS&E>KN|Y!%e^pK4BUb_;hQIM^^X|vf4Q^mD)P;$4i4h4EYmokC3)5{ubnM~R&Q517~De-tmztky?@}oY-PbE>>0LM2SVo9#wAh88vq%2^; zsYFoT&^{889;w<}n6`SI4ax^$blW(u>EFF@J`xQh%{huGJmVX+^J=xey6r+NY|Z@a zDzeFjW)tXhLlwizzhD$I9E>3Mls~8X-T0~3mO76!vVPXo5;QjS*kEhki!tBOx=oav zQs350s!ejjjfxwqZ9`?1cxm*0$wIkY)m9qV2B;Oh-orFLiLZJ`eq)Wv{SGo+w5z61 zL#sN&zC2y67O02mRf3N}09NUf!h~(pc}8qmh>$}+*os(&KixohgFpR<^}Zz^^Q?X) zq>N+~^T4y3WZ13vi6GMRTd1b3+i(HCRD}|aUXcx5gOnCYjwlGM^DmrWBi_%h;L9Hv zH2MN?>o~<`=bv+?!CVp4^SbGk`F=6F4lW622AF~84LOm!a*O1we23^Up?qkozU5@a z4@k0=()WduA46IseC&8i%*G>KB`n#ePPA|<*{5*vEA^4niwB^;Wk8Ul_!Ek4i(l&R z6oVlQ+RerXZeFUCh94xabjWu;{~T_*APE;cCgUT=lKa#%SG^hCjK;_Tk~k!cQsNGF zq!hMIbkWPwfIpk*{vBZ^rMnX=oKtL)M^uZbL%$ktjDU+r#1a{Bkhq7$pD5qb@ok_t zcOXHll4##d;!BTY`A+Hy4VFL1L%A40J%>tet#}X&&7{DM#Ztsr!>JmuMjiYLrkb4_ zl@EI{*ZIICK#z`tivPWK6+K^dI#OYb1(hYiXG>5r?lWkaaV*4o^_3pwwoyk}59xs1>ojzF;hN>_f>EI|W#}qv369IUb$ip+L+@#aX{Ao0? zN9nVGX#nzoaGtw48e$YmT!({2!A_)($U=(vpWkubt_B1PHuD-dzv%WFiE~EZ<68G4 z{`L#~FCWB{r}l16NV>>tpGa*R);P$q(J_jub~Lp_h9s553SUt;{q-HSMCPxkRi$4+ zh746^jAQIb{;v zw^X)1$H1@!F~CA@m8C!jGbo4*-b;d=as&5t--TE46fGATMHo@Sz=G|ly%cw~u0IjzmEPy~dGi=+SWH zB*Hs%6}`h*WDvS^sgL0xx~G`z3XV@c{?q{vcD0@SNRAdbR*fp0ehc6{#0-_Vn>v5= z`2F_AgX0Ew7oKc8P1E&?*l`O9;=BW*2R>}|>4jePrFe_O0l~|A&9Lcs0ktdlJIC<^ z+Uc@ZAX68$nyArFYKCd@gnd5}1Um)>BBm`%?9Qv{m>dt#Qparbx8Rhnm^Z{~C;Vmp zpcleDJl~^d&ed0Hyr65EV}h|W^XVqV;=C@5n>;~#L>2FrU-aEOU5Ne3T=KsoxZfV7 zB))q_nR5;0@(vL{Grjd6xwAEVnQoeSyfPq`#uGy~Xn)XZ{heB^jr0y4t&KT|h9okK zA!$s4_J;fKDbop~PUIhfMN44A?mv}Q{i|X3k6FxLeQF>*GjL_w2`FtWYvBZ>W-&7V zzjUsx{y=KtuWUIQ3uRv=WR(SO7i?*M6QLsqej%nCkm{yPEsS?IuERB@93VUh43O;! z;D>n!Tu)N;&w^b924%Fga6PW`98FIBLDVew3y1K@n^PWhN|_&64RmxLtf~Rwt(p%( zw^@WvW;q3CtlkTItvffi3XdH|xgaNAJj^-9FUJF+jmK6}?a~2EylwTTG)w3@m(l%G zWg^&?$<{3f`&hg9!p6g_!XC+9I%aw_CoWCcoMpdA zf(0K-WcnpH^;V+;u3KcUPFh1suTO|~$-A28$n=;q-9^lMoucR_nbp48h5(xBl5ct& zT_u@-{Qxc~9IWg~_{Ntj!D5HO)knxuI-FT_^}OKz<0tWB;dB_%Rn$x-B-Gm=+&gI{ zekrp~#|WAQ!W4nN-8E(HH{Fsf{gPV8fb*m3Wn$Xs;^7?}B(WvQwBQ-|6pm_12Ly*+ z7`D<`=@R1aF6;TGk&FViXVciZEV@qt1@iF_t^f=|4o1Up#yZjF04HZ)*RX2F zlUL??FhEAG1f~uPD4YYs?YHh@ctvc(w_S-~s)eB-En=GYzj>&1euniQ@!xIWC-~pA z`u^de&VQso|8moRX7`z~{}e&zeyeF{Xs}!;fc>I_wWJxOWSYY~KPv}YDW#cLn2$Yd z?9HGS@Rt((6&yXxrS^VCM&A%Qhu#)p_NPkwetVnzy%E%=*_CAt0~9)K>lWE4Wvdaj zU6o(+R1<;AmBCJixh6RSPRvz6!30M^*xT_dOqv#Fba%K+fnO$rO!LA5VTW#WlB`e! zSj*jcq0=d+&a5{>Z=3y75g_Otj5kAlx(S$~A&zR;2e#Plb+;P$@aOXiBJsJ$x?g*z z;Xk@Y;Dz%D)BBU*Scac1ZP2)F>{XwV7NX}gbea1o_lggf>?vQZQgk2x%jd1c;lF#OpfL@`{aeuT$) z)Wb>2Gex=JZ*wllS+&f~GY^GwCS!^HDaeam>$W0Ll6)?h;u0J~euOKS7FkDY zGzK27fmNJVaNl5hAfO0dVBH|<(^pzs29 z(h`1OkZkg%#-k`lL2@bQTl;aB=fU1;dUnU! zKg+0`(X23Yb6Su?+1Rs1t^ngzF@xPTyEHj7+Ki1`sHYZC*?XCdJv8AK+|zQOGz7CT zv%}l>Niu?95zX^epC)+h^}}U~%myVXzdAm&x49*Jkrr=*J%@3;qA0ypTj5o4R-@SH zi}D%N%dteRDb>oXJY)P)iM@EU-(ASPT8ncvRZ2K5iIO#x-H4>tntxEFF}ro<+ur~~ z1(8s`oWNJ;4`}E=<);1j1J)z^=amPZwH=Tv#{HjgvjSC{KVmAr^pas@Gz=u_$bgEk z!h)b-Hf$h5IN+L+`;4UPG>fjm*l#jml*#J`HcOnfz{b zWB`Zq*zwCvzQ?R1kI9y!_5GPHflbJ1L@N8uB{#5M1mD* zrhn%%`)f8>w`{zDP_pm{%A#yXnrK;yY%5udL#0Nr#ZRSirJkpa<*iJ>B|f_&F>Pr@7tzIS(CjAyW^sTFhxuBw-sY38hG86BXWgu`;wIjU%Q z@I+#Qk(jd6=o~g?ugG4}a`BOabIs{W$&7EsY9z8whX^AF&CoO6`7!bxwJ^yyaAn6E zIK$vY*@(-jm{^IbfidhBNC|?z1%e#fy1ran+lV~{Ep!_=p9$(ABdtdzm6mZPA0(Ed zMNs-FaV2#m%;T~ukl*EzB(IDxaKJwuWK-a%NR&G86&WVRp9N6PH=t1eMX-Sk{*F`V|0HCmo~@`&DgM*jS)I%F?*Mf&T! z>X?#-b&NiB*LJ2E_k+b;&E2JJ;%EV}(aMdKfr&16CpmK}1E&U;?FlBS%~~YCS!<>9 z%z$9PtBvu_32E9C*Rgz99sq7rV1G^2Pla{U3-kWE6P~r=x&eaXs>0h5=4JZ4MXZL9 zu71KvJLc0>6VxMHPZzN^4Z`o7GJbQdSIBwH8HeJqWS~0cmC4(tT7O(BTP2t%>vqo6 zf+#QD9l(&lN-MPio-fSlt-T1)|I&2VF1&She9ecv$osHaRQ-tI;LULk{ob)W>YJP; z`dm3@6bSXm`|vsY&B<};W~F6hb5pS&=?Pa3vf)I(`ezP-tO>YqzpW`n14u<@U3t!& zT8=p7b!kx*YLx@p^3PMVpL|4{KAvv@2)y}2XPgIR&!JX#zAM)*a030u$xz_7R$SOP zO5@W5RnyO?y-Pj|tF8XhsonPN*UQ|M-v0Jpzv>Lqwr2Z~LZd=`yq4<_1-i}ccp#VD zJDd=&f|1&FD)TE*+6a|VH;>ek_dkVP`(wsO??btL`knan7G>pYw(e&?kd4)&C$WdT zc5AnfB@JIo;0OilZJB|S1@EPB`?n{roU7!y61cb&ivC}=rT@R6^v?&cLCwYucL3d2 ztdZ2Kqw!`p?Asnv0CA%+DejM?Sj;f|bZ&H4DU?7|BAqcBEwN4XGL=(SF!MgE+ycQd zEm)geo97y?qHxDkr%?`1IX|>eFEjD7#QKORuD93)chk$;^_O)XH;Rv!!>y0ci~)X7 zyvC`vr75ypg=fo^M(P9YJF9Y|R2sIn12S~Dm{DIxCJvP28|w_4D^Ik;grKYwX*~Kg zWhTZM(y@WO>;5xQ-3RCM?wj;!gWj8D)s0c~+! z(fG#;NIkaxs%}(jXq+jVK?!IBlSons;#dm}nvR-db)bAWnllVYRjb*qnHde7s-vc| zlo2m%=i*(_^v-UvRe{`w%cFV5_!VXpxi7D?BL@=}Ynk=Zivd-hXoyhfFt({wEx|ve zKNZ%X3_!iGl^dWT!mM*`Q_?p}kGOq1-~mi$nUEL_lvkh~DCtPeTQ{G*p*Pm4)_esl zM_bX$sAGHivxAYii)>GaFs75gLji>|N9mRGPkC3#Mx*xl2Hl6i8&%@eH5#}lEwgf% zjWWSntsbG)wam~fCwg4m*lukjI(Q^Csz@?O0xg-rTO$o;oV81nPL%i=?ETawIpj{< zLFOX)Ns*|~0wMW^6{zgf9$?nA-A6}Sw6}}EFJVx-YJFAvXqT3wORqM6L|j%08n2xseGHSE(0^IYUHAd57 zJe@N@*PFETDF+eLF-IJ6_$q7vs)_)pg1M%bnHKJ+DXY$~l}B>LAH*q-7AN5)?Kp8; zqp_;Hf5}n%9LbQHdNdUE6SsOvalc>7-i5aA4uk%5IpktJUA3e`F|*0!H;^Ln{e{CA zjlr@x0Q0vnSaRw%j4pC>9*OCm?2klzjqTLfL3{r46pp2{idf%wKeBlT^eTsn4!Mgy zdyJBLx1evZ8FBe-wm?mN1tQAyi-`RZo7O!B=ODdhTxJ*!!PQXfE z_~5T@--@uoxz%Aay!>mf2*S!UPVvR%3%0C&PYX{Pj~mwb85@h}TRM>h6I>6UN}&5V z2hmIKz2xUq=AHcHD4W+Xgj@tbI5P+#VYt_zE9NPRTs;M3hnGvImV zi2wE>^(#r9wqpPjh(CTYdp-+wq@0dJYO+_u_E|bu?3z|9qO1SL*PQO#mE)JT&MovS z55>3&giDTy4uwnu5#@0j9V+IMxJu;H<)S9EUfetiHq;mt9 z_gJtq75(pE3sPM^;mnuPWL;vc9`LI;4^xRu_MqYY)9`RAR1Z>z{MkR{pT0X#=Z9tv;+++72r9$(I7nV;iZI204=)Di3&gC2&l!6(HWovW7A!O|?ZmJ5|kX&9pU>Y+8Yst*5?0J?%gC{v;oq{bj>!o+^ma z$~Zl5>>xvgHwS61zb}jrZ7{WkZQKzcpXg8-X?7at<-Je9`~Ao=Hk*9>i0mfV)B>wb z2Zy)4niVS{#6w^qiy($7+QSk)BglQ>C6^h_(XUwyn*q}yo8j_y;7z+9*U`X`l8-%b zoay}Lr9|PaJ~Ft!i}6mrd`aF3tWL&C2MiD4hdN<*efg+J7_&$Z>J*OwA zT%5hOrq+X9*mu?`jTNPUHg3@jy z@>_wY${I+w*8X_gU5C`Pu8Uj={Zi^Sh$O;BKduVY6_oQc`HEzSuGR&a-lmdxci`J6 zzeF#rS2pm@oM<(~A}jbzCur{GD>(SAemhW;eRSVn+k^YEqj_bezr4t@)qZcxmcZL+Y@Bl;@@GKuw62lv)oaLC#V>dddZZ&x904Ph z?PC1*dZgJSqcDLlcz!U~#kpLpkAQ%#F+0f05qt1N;h=Jot-tXkBGiA4{?mv^0?wx8 z|C_p3(%Ra@%)t5|xqz^pv5A76g{|}7i@}PxzxL@vJ|t)H@Zx8u^J5)Dgb-Asn(2hX zgo8wjV`1W&g|ys^Fu2alJHGe;=mi5X{QE(FDTLLa0xaockvQsDJ|?|c>R#T4lI=d( z8pLl~S#%ihV_V2tM@>tTSzGh6ET~2mJc_lWZ_bwv-{wh#kem*g(w+yp>+ye2Y>Ytw z;i{ottdb(??eOb+lN>>1e_ynsIY6TBsiFaS3fjdlNbHaX)W1!}#@e}s(2v^Vp((g1 zij)N4$vFi0RG{?6_xNe~rHeyB*#cth>Y&}}LkEhOB}D+xWfzk~ePTkPo0V)*q1x-b zB^%k%VzUX;&eb8*#7ka^gIu~wG89TzsO)RsGeqy;>MjiNkCbP@dq*9jt195;=#!yT za0QYe>!^hSv+d)qc3~>HnLxX<0?Esxddi3QuF=kcF$@n>EluU|e>&hy(R2#4A@ zxdxhKKrq_{LkH2nupNG@gTYgoHfo4waVku90ZnQpRP=hpJ*pkw#Y+~7NUa@kMUV2h z?t2ofs8aXx2&%hZB&ILSnQETgB)07o_+m|mWLI}#q9HBtH^!nT==XM6VDGg8SoJFW zKRDCBy08C-Hz`^DrO7fk3pu8mQ*f^sya;J4ZSrM6T!EDRM{#0`e%kL5I1}|HYq#_j zjop}=Knf)k$-BI8fl+re3nV~X|L=qG4W6Scuc?ivr?WGTPq58Hzt%BF5t^*265tZ{ zeUBZ`CA7pk9ou?+rPFqoY|KTblUkEvibO}nuOKGHW0 z63P0`OC}B*kOF78nvL{jL-3O2=FvMXJ$d1$f%^i$vl;bn--NTS98D8uQ)hF`^%;Yd$2r333V zKkVlA{awsuZlt2|9m3EM<-JmJ&PQid(8^b##~8zYD+Lj|f%VNJj{;ZjuaJtIc^}DE zS5cS)Bm7Hs71AC(d$)`MS`!ArJ`c6wG|i>3l`~4z3!#a$l`O2~JJEiL#TG!c%5NqH zY*sAhebXqn;Bb#|tme<@#AN|K$f)1BH3npHa)5-cJKi+M_Ei%FV;sEKnxIro+Ir=p z8}P)C*hYL|#^U9zSvfag9WY1~cOTKD&uh-n-%_wh+hz4Gzo}JT?aJ&y4n8nmn_|Xq zogLt#okroK2@DNL2ceU(p_6BT?;hhx)^TzpzWumV&=!iQmaBET+r$C<=z-l&Ku&_R zvEfE_E&|W~6%hH_~>)Mx7r|K$ndM#=`$<&-dTr;NKm#K#oru zj0wqS`EY8c-Iy zo5P7cpFe!Q%R}nh{YtSDnRjUIu(~UQ#oO(7GY~rQ-U{+kgE>*{j3Lw}rjtw583M_7 zSoL)rR6*UUlq{pF0=3F|18L_~jH2@Tdx-HJ54!s9`4tF5ARQx~LNfC9~rj zO?H6}202u}L>yoepp-jKrJAB(t70tyHAEUGhEO-7xDU4fCU@{1888+GJlGdtY>@sR z$A$kt2*F>27>=!tdTeri#GBvrpc7?}4DN$wT7)bY{t@;fss0C?~- z;CEhxTN63mS8u4!46ny^mZNd}hsXOznolpw#7KN4?fEVaHVk^|a^Ct0|Fe6?L9+V9iuD33$(L1z&BAmuBY3IEu=!xc*6 zJ41qB&htBpmVnorU9sPeBm~b$hE)JOFUV}=h;2~OI>&4fy%8eY-Au1jR=v7Y{7%t{ zVCN(H{S?g@%$&@oCWTmVg5>_%8G-M}Z(5auzsqu6?%KVj01f^JHS#~tDij=nVhDex zaDTs66+gD5fY|lHuK0fAIvv!HrbWwpAqkS^T^rG$*=|ExaA{kU$T=5dX5jE`HuN+& zIHCa4=M$k6Z=0=E31)!1)8RPB?b{?*pZ3=4GrT@*SkaSIeWd) z-n>GH*{*hwQIRv21)WiDTR1+<sNGTfw&Ba2DzahFvs4uiv z^0x@h4A}#qsf8p-K`p9n$wm!~4(`Y0%uMM;R}I6Q*wR{kAU#ea8|b~fi1*Xj+vpfR z?fq6+r#_Co=%$_{g2$cJQg~KRT(CjFosTC6Uf!feh1Wh~Ysf#?5gY;O;196t(W-up zR3}82Xgl{MlaBtftrnqajaHF8o+~N!!)AN80E)tIyy>PO2En%wPT$z;c*a-tT_Ebf zS;osgqh=DCd%t{#RX45aHi@;Yw06ws^ETL|AJ;W~4=?!s@wy4>cj%tJmDUXY?*j&G z+LW?Hpc7pDKizsY3uEX1bNm`NWedbl40erdP1MRtSiq9o5I2!Y=*-ig3kktTBsfCD zi0>C(4h~&{(bA+b-mo>tEcRQ zG2fLylIx?Dy^-(*z@U^W2r6Wvhkc-nDwX-gO$OlFy7!5|n~DF1W6JSN%b@5P;5C^)L>Gx#PH?i_C<)n5s6i5_LPHN z6KI3X(3TUpUtsC{1bbBSx9t3f2xWclBzNlSP=0;gr<-&4+hf*Yc&FiQAe zti1(LB+a%iiaUe*0E4@`ySq!{-nhFC?(Xh3xWnK!xWnM?ZiB<)-+P~P?*8Mx7kA%y z71320)sqPf-Eln--ckOW+y4*&v6d>K+HX=aYp=`j1s|2HxC-wy)+l7ZbJQI2aGwkF?idvqOCpCTZQ5e17nl$ob zd@@3y@;h;(A|d>nQn8!H%&auk&RD101((z0+Su#k(>|WR+z;3@Y)2*T2wJX8P8zw2 zVi{`_mQN8VP`FVQPgmhyQ3F=Uu1TF~w)?p3#kfs|d@eaM;#dC$(fk28>0CsY@gceI zh@hB$O`Q_2CSv5E?sPrWv<^F6|1FcMOnxk4Lc5>v{ok#x#5y)68mb=Yk8lhb2x>9 z1?UwKc^+RcW=&?gw%Q<-n29}$uB^4Kc=6aYPTep0X1>lZ1r(0Qed={*PO zS1JheoEVzeQz}^}@7_|-2foRvewz7D*?x;y4x|~^4Lz5k&0=8=*#CN%HO!p@D%SMN z5{yP?2|m={ILxDQrbk8`cf9R749?Af`DahxApXPh3H5tDoSOo*9@xaNW@Ig0Ca`E`9cIRtVLMAY zNmFk~X8Ouk#g?l+RW^Ymp}^+m=GK@CC!~a&oJh5RZOuRHrY*xw^oXH4qP1>)F-xl} zcWl1Um4qp5FHgL5$u`$tu`ewQ*N5sH7>Bl)f){I*Qk4k>370f!02mQy*?fK|o`W0x zRlO-oIE^rY`W1s#M$!ZzV@A7Xj2 zzNWJu&n17sc$U)$STS%C+1>4vs6{vZz5@r@q;Fe*tWHJA-iT6aGe2YPaJRwkaKxsG zH)Q#PL{7x3slOI~LDCYgS$X5yuNEjuE6eU+dE~_QsZFdX5q-0w84=uAA%3129tU8TjU%NSt};A-X|Bzx~dM{~Kriz+M;zoY~S1M3~k@)c={dVM9B*6 zNsPuUhnT_VG+N+!6+>on_Oh0s5RloFT>oNLZ^VLm6D(x81~ORnm5S1Fyba{Xh=2;f z%s|k%D+|f^>w*bKQ8Y}Avn%>|D(p{k3!S3;`EA3ABaP|1{pC(cB$UtUgTf0BT4K0= zeD~Xz2HQD^vC+7=V>mqGh!zM|#`=}`6e>&3e*Sc^TgZ+^U>3k1Sv=$EoSxf2&ETP` zQ9Vy9H<0PyCC|UhziN)!A*=6Vv8>tFHO$S0)LosEqqDVRckjJrWl8kH$nF>q00p2W zPt2alMr5N7^Oi-Ab5*wIH{_xD2J1)8KO%CJuo_R}L~Mx^iMhU~4A-;xxMJqjV)@1L z7~M z_i@nQ`W*r0T;EN;2YOwk=qv#s%%PS$nHgL`AA1HFXSw#h0lGPbbjE5wA84$>?G+vdLac5PGO9( znKN)L`g&V{gq+?RPLNS`xQ*b==kRf0;fz~aa9?=szZ4xKKM-i^N8B}#xyFf$z(^{FR zj9<$4KC#At{JrkQ{iYBS^RVa;0NN}%`PJ~nv3H_Lzq>7xu3>uhXS6wTCW){UE3+$^ zw(Gk*fw&3E5WICXt$1vdqe1pJWE&hB-xofJH@7{DDNPJnrZ4Tg>&6;4+e`aB9r73Z z52S?;Vx#&aIk%L_@NAXGh!WFP!e&_)jvX~I@NT0j^RaS!nT9SgF}0#fQth$zGiOZN zyedgvk4-bt#u}plGpyx8Z(_>cLLCPd}uwK#SWZ@}idFp`91N zmCYG9Sc2g%V5h_)OB{fx8U?2m4r-HPQ^7YSH$%J%?+Ggw1KDWm4k$Rs)$u4AAsW?I^<+j+i z1E)e;STDY?oz78bfWel$>mC1hew1Zy%YduHRG)Q;Tqna zLo&vl+z{vo;TXAkyr?D#oaVSd^r@P=-A{U4oHkw*G?bp}mtD11A{w=v6*j$m%uaOQ z?Q)licg%$=jO}t95)2_TIfqI=KprV-v&D?X4{pVW*%Zg|oNnG3PpZ7NoHva( zZ-ils@^9yFGT)(Z&^MCcd^CdrKLfqFD11W;tr}lDewJ1%`DUv=Zrzq;#ii-s>0y4w z@v$_*Z9%FruYI@G`XGI0^b>tptn4M+Pp0xDR4$AyL|rpQ`E$58KgH!1$k%1dM^~j+ zqH&|$j`avq%+k84!o(F^9(s#aiC3Q-seDH+a+HFQ4(x+zUC+XDjxZ)RptuJ5LZF+I z_P1LXfGU9M(pWozeV`(JY}|F7xt_h?m-@txwM>E=hP0|x z2D9tpCmIv^P;{@X2u$TGjx_ZxoeDFD{Qd$(p6=Psb-&eoq5s|E4I;C;H~oCAegA3RF+utBsoGzI=i(WihH)PAaUye6!CY{O#Xd$UXJwPfsHTV%w2ReZ zUrEJE?}LOZ-@J;OSZn}@RIDqq@i&lUlyjaJ%C58B z{l44!eGCSUQ-$00*3>K0n8cymg_o2_;@zD0^YcdM;hNjU zLzdUY&CTmWEFy{$tPf4u!0sL3rCHNQzI*EQfs5D2Hgxl};Tepe+bVRfechp}ANQ(b zZLu0Rcgn#qHy|iaO8Lyyy;*z7)z0nDBVrQuuQIl}TJ^Z<{qX}cA+3r2=+#&LRP$5j zBVN!Jp6ppjQ}!QPOI`VuB~49cfq6-ja>q%qDies!f2vm&Gulf+T!jkgF?zDU54Egl zRK-wgwn|O6Hix*dRk5900StSxa^*{5r7Imhblxq6%Ebop#YaoB5N2mo@6I+4PS8{r zvwrO6O&+;$yRm0s*|!?zx0W?{m|&+2qF~seo7mrvEJ0vk4mO89#KfD;{y>n zRGkJo$Tn0U^cwwGi0QI%+0ZM^%W^jubPe*XoD*21<@q92w=Q{G9``~A)--p%wte@g zfZs2<$sIbyfrZpE7Z@rCO+`;{a5UE<)*f$vuIIA1{NZkYtxRfO^n<7FBqpW zOv3Tz3b{_hM&88G6pGGFx5W5RzO+;$CM$1Wj0wMNXeV0ZwpJ@mXK1-0DaApuVk=Ex zXC$eB^S5|K3C4H}>h|fE*0oOg+&o}-J5~|H$=WYt5_ZQMyQJ^hRAr_@Rp|3|--;XL z)lb?`*+5S_18iI71g*ZEC-1x3HDKwszW!3yRq}Btj9;8>N3hIi*$Ut(K#P8?F(131 zt&gTt_}XmkEb$cVue$KUD+JUCa=M8c*xayHb!@_X-v9M8<@m` zQj?_2FeO^5+AO88+A5SOyB6)BLL`STC)6h9Qis^6iF>T$=yc>}-@zGDu;S6SE-!TO zdmt<^N{Qk5QS3{$%+BJ_-~?TLtmPgU`wa>3TMW-wQ2~FzKIaYPn1I<>M-eCh4BTN) z35wnrTp%85=P|E*1GT6THs>CSxXVd!U#nzX+iZ2P#257Jg-71jF4jAdztCY<4Guv?5UdRzm2ASS#?R=LLM#SsqUgMV#+Xwyj3M{WX|erQ?x=)p4%F zJz0F)b_bx>9Vp&(I5wi^8!47)yJJnIKb&pQIXRq_qSqZOK6KaB#L-(dN$Zn{!9u1f zZN9{+wN9f` z{_|yQBbk|p+&`&vsvfE62TB`*sh{a`sPbaSkEHrotv|4-t_>u)hDx_7H;6oUkK8q- zQ&`M$7ETgC_TZ67?h6Ma*2)M> z2&-2CF;nB=ptGr*pcnl1fuR3U3MF0xRL(Qdsy?!(%jRYe1+$aVI-Xg+>M#;~hC zSqcvn@Xp{_Gh`b-P$Ey41a*dLXDRGQ7bVZdj0;vqNld?5AU3uXdq7C};wDX`(#tt1 z3h$r~AqRP;CafRukP6ZqHOlsTqP7=$*1M;~G#Z|uR17ahNvy$$TRu`r8?|76^xFc2 zL=cJosSEK?QOZf9UIXcjW2-*m1RR7LnP-2|q9;#~Te_9Q+Vr@P#VC!5Mg6_obn8fa zDw6Vw$vU2P)JA0Z4EjKs(9o|afy^i+2U77{5+-c~?a#Ky$}BKv3C^|%$GB^NJS}*y(>#6n z%&LS&hw&o#VNq@(;T2YDpbFURm$fAkC(JV&|99HoXGuj9xIh@Xq3fbZ8E&MaVwt-+ zMj>q)M1(BkUre&2n=VfaxDPx^YnAbKPH}cN^D)W<%=4n=(nz# z__Klalt^YHBdd^I6VsdqHF%3&(?bEgj?xT^5^|rVEJ{5`jBqZ?uT193RNk_Fsb1o` zRJf6)ozSnfh&a)owdD(7U3!t89WYUZn#ztChLeUG&+pljN`4`{@R@!zWB}o_ z_+Vn~Ft|iLa?2kyMRnJkZ#Tns(T${iq8N$ujGHYzg$9n5oo1kFEy0QFF2SMxuzG9N z2c1Z+b;G#RFw*T1SGL1<5~jsf5w?yb4YHaKvL}-aJ9X#=%~-E>Bf0A^yd{s@$-1K#kaqCicCfZ~2wWt^~Q3 zTAM#H@)A-6g5_nv3zntTPtb@1wF%nr1th%6w_4d8# z!5RYZV&pRL0^9Ne{fX4`lHZBc^8o$`;(rN!MFi`ul+Xk35DS{pSLC0G3W5ak$mmZP z^asX25QHCY>zhAeN)HwVtPZzi>Hvt0p>hvCtbZ&hC&ZRSz7ImrFz73%e=NAWB$$2% zsr|^eH&!T3xJ0lEX^>ZR|6HgmmT7+YEi@2**w3A>JeYnCX)T%F7eKk&%a27p0_&IA_xTgw7!C`2LnTctT*2aCI6gz<^Z{seEP%YExsC*h4BqcB2w6 z(_%a(2|CGrH`+ncp%Sp3aI{(W22KBlb$Id7TXl&NLP$wiGl5BEf>N$Zzh_*Z_ z-i|Av#wlKk%ZN9dp1ff5iBqEd?LE)OicnnviG2A5B5}nd>`$FZH}!HXjp#$eo%krAn( z_F)tZL&(bQr#$4q9-bZA#9bqq8u> zQgF^#DSwI6<1pYBf+C~FKeLoywA88-mzlu4MOLVV6nU_pn}_ph<_EOImSi^Eo5Eia z7QFKPI9|FvOpqTd;uYhsZz`kS-s-B@$2dhQ^NguO{c?Y*ol^G>sy2n9(HHR1kmB@% zQ1Sk&9~m!#ofXcnXOfB>2@zPNQ7>)&`gbC=DdWPR&?5$I*ZOx9wJDO~Am}p^It?vC z<$GRRY4=Bdd`7CkyQgxBOAPE_|5tRHBI&0&Rk+C&_0Iz}JGNLgGjE_*d=~Gd&a?8Q z6M+Na%R}&Q7g;g1>^m~wYhIG6@OEnU6Z7ITO0O#ll?>O-NC zajgtvu}@;STqF<>w*O=v^^^AB!Nv4n;Yad|9l9F&XZQh6w;I4to2;F)W4sF1|MHfg zo>$vUtY}%hczkBlaeg7o!!sr#I4V+09VTw9xQm164_p z*vztOVlIE^b#U8xnA2hY@%r#W7;Zt=IsD7H)vn}4Hufdw)GH-XUc2iwU2o_bjmq|m zb}22(E=7Ww0zBc!m9kM3_5NJZ{$1vIXW-f&nesHHwoy$IQE?|X@~oilOeKfL{QkT) zRor}3YGc(MB+}Wa#X&gdja~~Tf&TNTDL{6k9T&UZC0cxH-CNKpqc(Q*K7+M{2v%VR zEp>{0h&ykJr11zmHrti^&>qzik5vh+UypodX9^$dnWt||XLScETN~bp>;MW;otS-$m<9Ub+y7RpEvc+|lNMALzKF(GRFym1<0e-;wX ze2HtRuBank%$6Dv@J^|i5G{V*;bttT`d7BJuac;;uT-2;m(aSjrO>q(5^S4}sY{ zmF+Ze-%(t2c3&+@m+S;=vNF+LC=6>Fg{)#Bmijzln%+=-@8@sZRh+5av~nn2wP+7r z(R!vO2kC~awRxuG=aMj!lhv~JslBqy zYinBK5g;VSHihu(0t#9;cI(D~ANhq?>lE-c=3re!QS@@la*K&TIcU_OJ9tXxiB$SF zZ(@nza*<()^<5Z)Pzj=?VpUb!F;qHY_*RomRW6oyz!I!71k+Nz!AuQy(T3XUHJ$om zN7;n~Ni`W z+Q?f{T*k1!NUmwEovwB{!kx#_wa-#3ZXx2w!fvqEdBB3+z)Rd5SY`5EP&4j9JB{q-5!)ru9;BTg1YquLRp}T%DF9gA zt+1~g{CPkwAlv~U?x9eZ2;ls%_8dKYAeRZlTK)=0u8TCaM5|mvQ&Fd8>{v>FoGZ;1 z1uV??{y0~pj}C-LWl@(Sk<$s0zm&>;!8BurNhC@uGML3RadaQuYwMF0H`wVN2$cf# zjCklhYzH&?aDrcH-EDvEkpS-*W_uLHz7q470PRAsHwS5z2~-FH)dzp%?lA^&gZB4g z{S61+1$rgtZwI=D2NGjtuaAB80^$d96$` zls*D@4v0JI79j`$B8dLt7L8$#0BBUpk%oT_lw5+9O5$GhGR4U3PpKO`S>IvOCvb9O zA#yvp^fk)yJ%+Sb#6-WVJKd*^tiR)1U@kB*r9U%#g`Zew-v4M^mIc~cnVQG~ot*!h z*G)zDAGl`lWSdkqX*!ti5z57czajTzh`NwvE!A0jueKt!no022CNr{uh418qtSC|Z zkKnILLp)Z&U}WU1={&1#hgn{i%gg%ReyITpby0B9C)$;QKwix~v6I+B`Dx_=8DfjZ?RuFJx{tI8lGGkbLqK{124OSH~ z#PFJUkglj)GP}}$tUb=_BZ6@pv(tEp$*^iK+Xgrh5G@qa$XO7ZZ9wA#L8iKj1W%OB z6!oXNm$8<tc`i<{g! z$~d7Hw!_mTjdD@?5OHgZ+!kjgDR8XSh`Uv!y`2cXzrwAKMvw%6sBd%qzzw{>@R;l9 z3MTIVW~e{#ldd4eQE_Pen{=5X7Bk8(ES_~YT?*sZ4w8t-iv02TIVL-Cn+pR_l7k~q z5wn-TdBkcl!3aF1?AK8brL9mNU)tC8xNg<}!!YtKK-B?#EDyyW*ZBzWcTv(~Ih>&Q z0>FLLskkads+IDMJIP)04xGxK4%|HGIhQe+kGR&Y^077S!Dpx|%k^A;bWHUO3oDyK z1N|$tdt1BhHJQKye`koumeAlCe*dLbc!mhmP^m|EMFY4D>jjIWO6i8gg1;`dA~!@{ ze0-T^`sge@c%h6VDPMtpNl_Qt$J>ASK~1YjI>rN6Nr8chBd=hTn{JX$u0^CkKrRU% zi#p64q%XthhY|31^6u7zS?H}#;Em$v3Uu!OOBwyA15uT%tMXY!X80o%M5fOYSo|AH zKSDhdi}Y@=0v(7!SyH07ic4pCO3u~OXNKj*VR0I~0^bdu+mp#%$iaCMmC8MLIUDI4 zu=ug8n~+31(UXMZs*rQ|^fBr5?&0e6F{A$hf*pv?X)GgfNq3-o+!1q$+iZ^0wR^DM zexAveuFtd>?Y+)X^;%T`tQobOx${O8Huxr~71EiM%TV(Rt`JrnFe-;iSBH`-5aODIBT`^lJ`8jPW1F7FGO~RN!&wdIR zWue=yvSj{psY>9?9rr!t?QGsi)_}50T`)1_hg2rna;e>>5u0hCLou!%`Vk=EU2IM* z^Gk_wBlnkGNw`pZ)x2RXog`il+t8}jg>*uNbIn&!=1>!lHBke1+)R*NW8(;^ur8s2;SsXO>V zWwH*~NM0x7haigo)9B2sUp}v^v4T-<%RnyPv~4Azc2 zaqvhehsCULw;=0iL2oQSa=}QQKsDvgYz8< z9I-nI8JtFR@wcTdD{koUpVYW~ycK z)viS9GEv@vfm_CZ1i6}Wk!0$gbH^A(@0$1iN2Cl3u}1$^CFg;D!>ise@57D0-QcQ% zW&GRa)V1D$pB*xn(Dvtfat_Svt3uk~MNR(7 zLbe%llgKI2p`A@MngO*kLDB4III(9qd3>epdExrMq8%*rCd#=Spkzir|vzTm zg#NJ<<8X`+i~QDdL+oo(BW%O4aGNpnw5oUWeXm>91xbwK3pTRmFbd9t(n47sk=gV^6~S5~5}~{TduI&Rh`uXL;C!kwF9|}&+z{u%ZLH;Hc%gUD3*0e zJr{FNT}TuPFC|N?zyUZ)v}X!Npl2eT=uW_Kd|SbHJaxHXN_t^keW^=%vA9UC+Qzk& zoZ%>Dqh44qQCi#onVj4bzg?6sq zv3213Rt@}}8DfsZmTC7Zm`INJsWMM%H|K_QX}yQ#slwDrM=VGW`3VO!@e;l&@=m6d zPxwXgmi%|IH_`@K*6Q`5!E-LIwco(G5pCCU*b1dsTJmzuwi}@Oui!{ zQ>K^(3Qg0`W4xbF)COz<8Gu(&Z!aF4>E6o8&2 z2m(WD6M|i45e|1$jiU_iUU&#S(F|T#&*~+NN5t%e8E^O>Qua?UEni66yrYC6&JUdO zLw*X&&`6wUNyKAN-(VZN3yVdRmNC%WyFn{`B=uAlz2gLwDu7N=UUdrfsDX8pUf~8D z%7bodYy}JToI-4TyCNS%i!F!g4Exx_bs+n0(vw2A zB)BD}W6hl{!TVbbei|}E>_UX-NV~M_&pcB|+Yh-}{b}|$>Fi0`^U@toQRKx13sMn;}_E|aZ`^oTYpJO#)o>gb+b0wCG z-)m%!0F1N;@)>rOk_V;dF1eA5YNlBmV7w`Fzf(cgH(paXZC31yxo{OarECw6kkwLW zO2cr+M_IXX!<-ZF2+J7{F_B*b5U(NcU$#~l=8-1t4_^?y&lz4V1N2Ez{1QHTIy1NY z;st2G@@71`>wGi23bKSm*)K((2rm=VFSU(&ME&=yOsHQDb>Zg-dGP7|Yy2mk)&IA6 zs9HFh8k+niG5>PAl;u>=gphqi_)~(^Bw@-FQ47ip)i4F>;35hHm5d;&3>sS%Wte~M zn6XbzR=k4y`D5|9-&-da?DrCG#nzuK7oiqtI3A^+`>tQ!XTHAQ-eUP{jWhA0=q&eE z)3qgZCB(q+N<7V`D1YrQ1Sps0j8f19y4uLJnT+~60oghb#S8ZefxU1WO)1YG> zh?rAD181BI+l3I(Id20MDfT|&AD_D_A(0vpU5aAMZ%r~(xqj|!VcSrxWYms^E@$%fBQ6b`S&0Inb4d=e_ z%nCD=_x=SzS{jh5Me004pF%R_%>HKuiLUwZZYDP)LQ1(0pY@sj@?;TD46;c3PH6p* zhOREtQqY#;pwoAM=rq#Y9TSkkMC(Gp_lvtC^qQHa=rUogQyzKWd>O)Om3dRdPmcrw ztjY5CSHzA$Fy^46NT{Tv`Q)s73=%>{gTXGtPh)b5T>6on%EQcnHFW?4_fJo^Fz-}rR@5ZB#N$;`L=y=M4U0Y9iW(y@ zBu|Se7Yp#wV*!QyRQA-50AhXmq76UcZZ*!J1+pB{Y!Z_TQ`{m9EN)b|*4cQ*5YoX= z(tO!_my_Q;oCGRv#S)_nlO*eQURg8B{C$l(q`?R|Z%bR_eoz|W2RLfED!!4mEd?jX&&~Y1&~7YoJDnebH5Mt^1bNELI6jn{&%or+!c4^n7Q&xj$|AaNG7k&#q3K zG%-(x(Bue)J$S^Zd^RvIOnnx@WcIHB%QAC|%E4$FnEu_5Lhkx{`mdEgq;V4vo_n*l z-~DEP0VP>jB`f#15atHaEY_g+C!7$ts6Oko^h>2;{|Vbq<1|nWfrXZO)Ex_NmUF6C{aZJ(>2Q?5v2! zm1kld6kb3TF((J`!j0n{iFC*4WtpWtQ~0qW#EJMyY15lyPoT#(EAxB(G%-LH;hx;d z3ix7L8iEqi*x{!EURbdb36Bs}k4O8yf$T_Ml?AA8RR|zuj-)P&Y%NM-P(ivn0Ruz@ zC>(+11n6Km1QV%|^YEr7YBKLFptmy*BdYvVSwK@jQyn^JCX_%m@BLFSIg>AO&U~1P zAAD~!251VZdR3{ghtEQ#Qp+%ODPGCX?O|Jl=sid?c$A!PE=6ky zP^ysm^YCk6DI`@Bj?k+I3xa>onW5sZy4^j`IA=J3b08JprhH!)hkMdLMv!pHyN16r z_oDO`osyqNY*3=0%%Byrm6%6t6*1=V0p1nmc`Cgr|9u&~&PLzp^r!MLeEJ_k|A`Vg znwp!sGsyi#SgLI5j~a`OF*$ibVeK#{R-2scTNG@n#S$z;LgBhWZl5lK^P zRvePaq3_`KltIQ~-y!uL=Wbuj_G&I;6+lus$$#)x9_L2YN-NfNxv2+YhwF7j9qV5jDZZ|+?p+wYoi!l#^l}0F~hGkI|JkUGv z9=~N`s1>;Rc58nm#3}s%G50qfD?I%Cz`xJ|Ha>>|G)fS{~TzF|0i+@u2+sI z){Lb5-l%E<`h*NWP~=;bFANqDpSD$xU|M&UasFewW{dDDB+@gm7rwCNo$|BxBU_3x z)c|?+GT+OEQ%*YY`5*O}hM1<}SlSe6cq%4>ZD0W`G^TQz&6YeRjDOnNOMRwQC9qAU zlO6-wpLEckFQ{ucO;MnXj~vlVCuqxQ0A4z!mT^StnRtmPA&VaUtOLX%j4bulc^KO; z!WPCb;kt!=wTiDusb5711-9Br+c|qbHB({U$S~LuI9;HTvK^Du)EBZT$r@i@VQ6- z3)Kv8))tfQyf+qI2u6uQVN+`5*1&_%I~x}oVB=f^&HGs7``GmvlBfW&u*wPb-0QY-!E|c?sD@D68vHBo_oj$ z)9(E7QQf0XB@#Toql!e`Yjy~S4Vcl>?f_MD=!>+MYtvAylh%CcVQk6qb_YGP;Z^@Hyp zVy};s9^B>AJKn<*fG_yJJFD(4RAWV-ag6(?g7E$4L2{Gf-ikmHgrVA5V@Kkk3h*O|S^& z3dc0zEsXg-HE?0v8tG%(754GxPNhnQXF9fjf$wfQ&5p~{-A@6PEHwufNpEFPFgrGpOV_^Dch?9e!ly-X4W_8Uw$ zg3Bx+Z^qOrXKd7C3@1(>z z@AofvDC9^Vz46BHR=>7v)MIv-Z_*0n!Mh@X+8~iNM6su$MM`=?gbzT3IWr{zsWCS8 zwt?JfwGDw@ud}=!!0!O;Zz$Y-G08BFuDuaH*G@)!YmrO@-3DdYv6I-q{$~P}r^a|0 zJPFE0=DM6##jydeotp!+K>XKhbhDYTl$?BTzkyM6qx46ni?8*0gEyxT(>6AN!NV}} z9458dF#H1&Nia|t-d~lk!cf%2Gkzav6yXsXWLk}*nnqfcDMc_{Qtt}vx3WTtAvosd zU()W{G8x5miFqd5W58Sc#f!<2@ENhDF3H@{Hy%X z|Bd=98ajWH{o4LZ{grJL<`mI=FZ7PsL;HJ?581CF&-C)P@OH2X8Pn!z3(|YzXya`= z@W_e>FBZ?bA9cG=QWGq8kghZyW#*ka@|7fvtXG^ob8gp4r`kI8yL?^|3?SJ;*fQa( zHWzg0btGCt)>{y^TQg3V`*?R&@~>B>c@4D(j;;g#+>{eRxY|>z$r)_En+~f!QWNoQI#2H}iB0R9CD@PP}4pyfJVOisTo3{bB$UdHE z-W#)@Oxy4)p;Je{;uD322=oFeJqbnfjWUoYga#o3==Nw(D$_MAc|1F%rjzJf%`)(! zS4rqhs=G8io;v`BN%lq#usPTVIJ5$B84OSyv+k>!kze~jWz=|GTM(Kj@>)0o?J z)dzZ%ENs*FuW79cI%$gQA3549&z3hoZ8gU5I&uLyT?`_!galt`a;3GdS`DT}EpE2t_9$*af;sVXSb z$x4Zc$*YLbJG(nKsr1^eiX(SI{}MoOi~wDfQ$dGZnTybof>+dWbpwh?Wax-RM(6|< zSwCLBgfv=_aowpB{+O8@&wSX3qKrnG5_$B@I5Kt;$rbQUH`5P4B_1*z4T0s$6oEtnw zX~S%Cwu>w%eWLA4HsRJ6pZ9pEA>H(AX>iG0`IE zlampoeEwLwl&MUkH7k@KXG;KT@3d9U^`&fc@vk3aS@PFw&xR0BEfpRphPYVlinTrB zNiO#+>t0<17U6p@m^C>_klyW_9@^G@uwd+4V8>wt-&yfkhIa1;%^Sot4Akl?ce zkZiXSPf~YrhsEHZ*VVP^JMBRWvLCYLbb)oPvdgSkmJ|&D z#vauKw|aY%7UHSyxr&EiR@o1{e43EaWX*j?9H{biW@eWk$8^$$-zX1Ymz7H*z@Nl~ zV;Mss$^=2Hll{~vMKYM{(C}bh9|mHIq4 z$%-daT`S!n1dTUKXbXEbOe0zC4F5%!6DX_3T^xx=>xJZ&r=Q1_X|p&;i!BaxGSGB2 z+7K3gsT$yE)}>v^La`1Gb}R3oACT2Nu1-=W;%Hm>MVy?q5Y?cezAB1bZJKNOHTxaey_J&cIuw|2?^5jDaoLx?^4`c941-N6$x!8JgRwCp1Ux$ zf0^dAJe|y)9QM4*FBJI!c=);_(87@vGADDVp9}Te+FhuCgoM<+bq!rEOcOuNySTm) z?;^3)_zUZZ>EHof_i|^D?V*JO#$xHwH_X?Kz>6`~>GGG`e5exy)aIGDM&Jq2K(oTp zGLi!N&LjRLxZuk4W8h{iD_TWiVPa$zA=J_|RY;_rJ$B9sC=ztqE)(y|1KoEePqt=QxcUW-eLi?}At*+X&=5yC_u;7z(u;_23 zUFIC`--;mbUCR;D9c?*;W%@j-#w3zQqRapgWX1cQl?z5dpw>b9e28fLc5|)v1T|o1 zCy=r1wWkJ7xZrofYyILZHZ@!M0=I@gco$}{+AOL2-0aU$)jCNSWYwe;$0lV=V6$v1 zU9B&Dk)u3K`5c*VMEYp*dJO*IDCU|?jO+JBVL-Ba+jL{~T{|nn& zt`z@hUxHQy?}w088n^CoOIlWO$HyRQP{tAt$hSKLVKQ)RSgu_M<*Ixsh_r+Ida#txOsCUi6c- z5SSbf>#5m0fddgk6m|Q9Iil0J8=j`AdQm-j5I>|dfM=RPF)Nxqb&wKUJlS)s_H2MN zIEY;)+)K72tx=2a6OMGL?3EpsQ#-3iRV+;J*c2y5&85veDURd85hI5qucUGsEw~v` z9J>qFaO~dHH^Ql^?1Z{pXmnDjkQJlGc;aHCXjb9;WXY=+{8`Rn0#pLeh|b^c`R_@AHq z_a2`F;s4tH>Vf&0lKQKMli9y@`hQwG6Zocz?T=qT7Fh(@LD|bDi%^OzqC)plN=sW> zL@-{G+cuCUX_7(<4>1q_fKU`c77H#&kUz4ER^TD6}zH`o;IWu$S%nYfh_{Yd^v-1BSf9c7axUSxn?+9JjPE^qYFm?B< zT&g`$@GP4HuM|<$m9|J2RpwOnGR?Vmi-r<+s+TyPpU8(Su`^Xia(A4H+};w+wvdH( zr3#H@EY!kVvqKgeK@~e!OR>DwYIE@}+-s+Sa9j()Y<0RE-g~n&5PHKmu;|;Xnq1z> zXA9(Ju8@S@l$NGzAvlCAi(m|0Jl(bj8H-0($q8BOE>x{sAo-p}FXYcubfnTANSA70 zEmg(5dr@^=si9P34)1Vks`KxRr8{!XAvN(hRp$YioU-VblB`Z;X*8AOy#G+;woBn2MUn=sl#|&t~8jQOq`c5iBX^4EMv*_L!<| z#v9Azb#C$FagTUVBPY{gMx;z0b8P3noI2=0MRhnXTx8(aqC{_u?184k%cZH10GjNPh+m!`S3T4LXSaLBq>n*c-(c{G6AA2 zywf?v#M>2h)a`KbttH(#?kZAh0zHH1Xej0{3{CDuq#}hzsTEdw(&G~`S33kjXdxm- zuoFVsQ;&NK4TD?a7HK>qM+ejF=Z=Q(d_q% z><7@Yqfs=ipRHD=qGQd1#S~IMmmR0pPJ(-Qwt-YXM{VqgQ2KeL@0=}R5a2kzf$@>( z$1{nE5YJmp79|r}RQsh5?3ik7gBPN;-?Wga^aPiXEAJy}r@FGfhL0#i7wakZFZ_Dk zWmB1o9>$LoEb?U!ORilK0sk-`_b^smt9jh#r!$qEB)D>HrjY%2{rKB$y1`xl2OOG_ zH(LWEr1=agN*IuaK|VH3YN1z)G%!Nh&&1`HDo(WSDvSuU{VXbBLL}Rbco4&X^^4R| zf6ui$akD&LtBjnH$3!#L>PGx8)eOoj1K(kF{Ph9D%4Gnf)+ z`&m{-H18795pM~|Bc5ZEntFk)evII z7m*%8(NFzW33`&*Vlg|_;HjnSH-*7cm%@+GqPM`&&w=NDrEazD%~_*=f&;GsgQp$a?)I!0zcK^u85U`? zSp?o1_&@S8hFi@~T?D)<;3UIa{9qZ_Q9nGMcjl;(Po8b^Cm~;feGM0}`1QEQb=FT# z!>Zbvt;XIweoC*_=vtQ{HOZk7KOXnCuDaRs3g$lTUAhH6rD{E?g8Ou5Ma2sRSOa_A zSxkW)9vcos-J|7w`RJ5Spx|jxaFi$^em(AyeOSpj+%BXEc1(E?NKn&i{PJn*&H>m2 zT78}Z=JsU;4!2qTk_J2OunKxmtIM_LSG7Egx;%iojH2pN*6+U5CE4gwZ-Unj^}hZp z+&5p>_b9tq5s$m)!23}Pd6T=EyrlkDkb46HUbJ<$AIwa}euG1OjQadyQgtb&g7@tfb znEq3)(%*fvPqwMmsmhs!e$jz0G=iT@U&OVBDFo>FOMA9?0yZECfB2F&R} z%)P0VW=6;}ziwtaAB$Ov1CiTks#(n=E6bE8{xPM~y`LdvRjd%`sQ1I;H4(9m>AmPy z9}Z|~{<@_2*-4t17Fv}ht5${P(2_!RjT zYTBZq`%QQhvXr5>Su$s6z>uI+NcVBo>6n!VV;j>-8r_JW#m0%rwYv&KhKC+Jv+R`| z$TA(6kZB(rLO?#H zacolW%|Bj3cfElb2kqGNmsOrBFX;s9*rYNr1xQNI2ll?p#vH~^E+qFh$(Miqmu1hq z1?$@vWPN8n?B$2BzQipn>n=j!c^H{!>pT2D8=%5bH)V_XX}{e(7?@OG$jw&b$K&3; zni1pODp0qAs3nI^{THNvV@g4j#;nyzQkY1jyes5Ag0`=Mwx>z!H|QiOOdpVey80W) zbU8?-4!BQ(r9b&LS}JHyVbajNUawB)VQ+)sC1{z3mgpq)mACBXxlh$ihs*2KQ94G< z-J*{q&v~@*`&ZFbxRz)sdMq07IU8qqzQvN9??Uhl>w1A#*k`*jv#{(nXl)6+4;|L; z`vn^(1)eTf@JHxEJJ?|d7Pov2pk+ZDZ|%NjgQfcN8`BY>QP@)|EnGc16N(!T!=twj z9{7%pL1YjgTa<5{v`Njzrup4xf6*u4*W=#sJv$>{*7B6t-KR!GLXv@yq#s2Yg>?^0 z_aTy$H;+8z_^sppj{#suAEoW=$}x6G2JbNQ<1C@Z*3oHaw?hcB3XP+L>2QLLlPT~M z5=5dlm*BLqVfY>V={+*{s=$$g&rc&y4|cCXi7S z^2lkuNFuo+u+>oh;z`)zt3k_(#lPwV$}97qeQ!tpAEX+E4oq80*#$(<%R?y%Vfhs!KDrOTJ!{(EfeN;J?xeCghG;<_qE z%(jiP*qj2fMgQxJQb_HRDc{LMj{MFHiM8ZAb3#DM27a3z4uyS&#-SHt-~Pc2F_67k z?;JVQCUC2~3HQDRD!jT>Y5YwMC{b(jhBl@33tUq`PQj|_migx`c1XF_vT2YG~qm)@e2;tcWcK3ieklSTx zzq7YCJHfZN5lWKVXXjn%3=R(tElFZMc1|e5XEWbSI{~_Iw zQg8@FWBZ+*2VDRM<|N_#)<6R%TCn5Qd1N@4WV{>UY;D}L;U+L@qV4IaR*!}nI57w` z801#RgfZiZZ>LT``ByMMp&8+bhN?`0yk_jxnU5i}A|i~Tor;#W#HjXtBWcTDYo?VU z-x*8mJl>Yfe!4+hbYx*{I}L;cYYsLRT%_sCuSer8in_Zt_>U^Wcd=U)=fK^fyEcM2mNU%WEVdk_tH-Hfi62CBHZ4ewuz5~)Ul8{R)pf$ z$T&Pz+1| z8a4*)Rt8@<7$ot7B=DXZDCC|;hv0N(@(wF@m7NMcq+ZMQwbuhdl6dLKOPyXCXe`~~ z>6Er-usq`i!650?K;zzeQ7V1l(7_4cjsWr$bV;wShhtsB++vh;iiY3){H}s#F#MVb z?9dwwcOrDcY^fJVS4)6o`7f6X968V-QT&7VnME}mt3V>PS;Swxcbj=fK6 zCylfk`TXo0S4@FXu#@1de;Y-?H0}HLZ`%cMcZf>hJxXqP<&Va>hIa>kx zd7a|6ooG|Mm#Fbw2n#B zgdyiXk;?*xo_%&h zl$5>MMNCYAV8ppQ8%dCpPt7B~yIr#Ny<3PAe2AP^+QYQ4=%C7Lu*HRyvop~?H2|V5 zA;+NwBF>5ADPfbYuRI6^-T;a2H%;=jP||X6^R+yp$exur3PKEnml;BJ&4H6NAzZKp zY^WQRx1dSmOu6_&k9Z8ZcDC~?1|eQ0UoW@#c7I%N+e5smFURV9217#G2yEp7O0EezjWPN}ONx%=8X zSetS0L2qD>z_Vn2rQPY&9K>a{>SQ{MPX{x$ewBgmDH zhNKgd2NY{(7?h^2^6);dRC&jQwmgpt&

    q%QV0%+|CdTy} zMQ?!K4NW?lvZOh0SC&q;4wB4H+*@GGQJYHly0mfeci=yPy3p&r#qUU!z#XIg9n z?Qaa!bV%#o2l|MqkQh6fHfxH_Vm1~k=sWx3C;h@8DOq&WlD1o4Nv;Ah;>a&yIK#l* zgtS8_-L8UdGfx>Sc#w47ku8X~a97+XBZJS`yrc8>05=2z(u(c2NdvCJWiS4Ozbv!W zOw_9&=8WaVjW0nwvPh-9bjIdNaAVB~&<2tk72q+h#E5dr|e zU(Pv=2Hyt-(Ce}0pK2hB*8=%HW_jwog35QTjO)D#)JKA-{0<#dXtHiJsy zyR?B7?9@-KkYK66U3cD@@F%#-!A--j`0=_AqOJK7_DaK_M+r#KLY#$Dnd`}^Y-YdNDyD40hYYms29Oz z0ZWfrn~-D6+`U92Cz6U;Mhe7H9a7&f0I>*PdcAq^bDcy5QuQGPv;GAN8Ix(*cI?$b z%B+wVqd?rhea#~eVsIqSSJE!y=odPOh9O2H_GZlRmC57AU)%p9ggUL1zb+pR_yt>qkAP;DmE|Zp6c5PEEzEHL8I$jsE*% zdbqyCTzS@-4pB9xqi3LCNk80(eK5^E-$1&)JgMfU_SS`vsy=dD=*^P3XV^&I3-An) z=4^~8{<5q4tH9QiXT4qHKC znn11$R9vHP_`KP63`5*c&>kImu7SwCCXyjcxq)tsziuT*kx2Fiy#dtvnpTW_)1;P` z{erw+ZUrdeqNl(wQgQ!aCm2Si4wEmxxOV1CHBhz#63~h|{3m1ixVF%nT^A~XS!Gn@ zRU(D~DEgR7_$_vfc#okMhifV1MT+Tou~vP!x{HmaQzO$IHdclE2UCSyo6A3lBv>cf zkT0aVvAQ^H=FTDrTOY#GyW(e{Y8K=3-ce}q_gUXuOevze|L-3Cj$$+^#u;+jxqnkj zH%wl!8xtPLZHG=p7E^Q>y4pipP(Fd=8H+!N+<=%i_X5H_w2LTcpoK9!KX;tq2t{f! zduPggv=X^|mOfuQx)B@6dpBcrz8#SbZ1MY8u@*ktsWxTJGz{vx7M+;PpXpAQ*+c`H zBz-0EcE$XtMXl;odjPtOLVMAnv(ZiUUSIFW-I+=Z>i};dJ|9$f9?}b~o3- zl!pkHi(8RZJ$dGY*5BK$HA2!5vr+0=_ZBaS`neV^_Gv1W<%hO9F!HjT?=`lFLD zk?1H%oyRmlDp()pgSa`>2{*+WNlx@Evyey)PAYJNVUyy=<6ej45Eh5!?Fzm+c+>a1 z-9TZkU-Mw*oi~9vjW3_tM^(l<^AZj16JQ!53f11iL_Jn?W>C`Z?6x1l>REQlSSxz zbVzaFQyMV-P@Ye;C>)aZ-ixHB+rJ+CdwUW(%R1JpZ2GbNXXPjS7Xk3xXV{0x8XLVP6S*0c--$q>18sFQI}8I?k)kC43Bg>&x_Fu zMvj;f_w(AUYErl8zGTfpz%K@W=8b4v<&b+OMD8)GoxdIvEqI(O$N@}bxn(L$cwO&BD8RO@onrbD4S zazcfklRGV15V$aEf?y)2>Xl|(Tjn3Ec>?B7!hm!jqM1z}Nq!JZ?bo>ZMo2_1^rMxQ z?9{>;kuNAI%`qm%OmcR11$mOxi5d__o7I@_a9|Vlao@%4~bNuQGppjyq;j-noytSFV-1Azfl$t%@DJr`K9Ai0Oo0tGe0 c(=C!`(NYqt!vi1%7XN%|=D4@#p|^7X0~@d&D*ylh literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/backport/retrotranslator-transformer-1.2.2.jar b/STRUTS_2_0_X/backport/retrotranslator-transformer-1.2.2.jar new file mode 100644 index 0000000000000000000000000000000000000000..c89e7ed7f993ba1094c5a94b644c4114630645b4 GIT binary patch literal 116677 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 literal 0 HcmV?d00001 diff --git a/STRUTS_2_0_X/backport/translate.bat b/STRUTS_2_0_X/backport/translate.bat new file mode 100644 index 000000000..542b37926 --- /dev/null +++ b/STRUTS_2_0_X/backport/translate.bat @@ -0,0 +1,2 @@ +java -jar retrotranslator-transformer-1.2.2.jar -advanced -srcjar ../lib/struts2-core-2.0.14.jar -destjar struts2-core-j4-2.0.14.jar +java -jar retrotranslator-transformer-1.2.2.jar -advanced -srcjar ../lib/xwork-2.0.7.jar -destjar xwork-j4-2.0.7.jar diff --git a/STRUTS_2_0_X/backport/translate.sh b/STRUTS_2_0_X/backport/translate.sh new file mode 100755 index 000000000..28ff70e28 --- /dev/null +++ b/STRUTS_2_0_X/backport/translate.sh @@ -0,0 +1,3 @@ +#!/bin/sh +java -jar retrotranslator-transformer-1.2.2.jar -advanced -srcjar ../lib/struts2-core-2.0.14.jar -destjar struts2-core-j4-2.0.14.jar +java -jar retrotranslator-transformer-1.2.2.jar -advanced -srcjar ../lib/xwork-2.0.7.jar -destjar xwork-j4-2.0.7.jar diff --git a/STRUTS_2_0_X/core/pom.xml b/STRUTS_2_0_X/core/pom.xml new file mode 100644 index 000000000..b3183803c --- /dev/null +++ b/STRUTS_2_0_X/core/pom.xml @@ -0,0 +1,449 @@ + + + + 4.0.0 + + org.apache.struts + struts2-parent + 2.0.14 + + org.apache.struts + struts2-core + jar + Struts 2 Core + + + scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/core + scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_0_14/core + http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_0_14/core + + + + + + maven-dependency-plugin + 2.0-alpha-4 + + + unpack-xwork + generate-sources + + unpack + + + + + com.opensymphony + xwork + 2.0.7 + sources + + + ${project.build.directory}/xwork-sources + + + + + + org.apache.myfaces.tobago + maven-apt-plugin + + uri=/struts-tags,tlibVersion=2.2.3,jspVersion=1.2,shortName=s,displayName="Struts Tags", + outFile=${basedir}/target/classes/META-INF/struts-tags.tld, + description="To make it easier to access dynamic data; + the Apache Struts framework includes a library of custom tags. + The tags interact with the framework's validation and internationalization features; + to ensure that input is correct and output is localized. + The Struts Tags can be used with JSP FreeMarker or Velocity.", + outTemplatesDir=${basedir}/src/site/resources/tags + + target + false + true + true + true + org.apache.struts.annotations.taglib.apt.TLDAnnotationProcessorFactory + 1.5 + + **/*.java + + + + + compile + + execute + + + + + + + + + + + maven-javadoc-plugin + 2.2 + + ${basedir}/src/main/java;${basedir}/target/xwork-sources + UTF-8 + + + Struts Packages + org.apache.struts2* + + + XWork Packages + com.opensymphony.xwork2* + + + private + + http://java.sun.com/j2se/1.5.0/docs/api + http://java.sun.com/javaee/5/docs/api/ + http://jakarta.apache.org/commons/logging/apidocs/ + http://logging.apache.org/log4j/docs/api/ + + + + + org.codehaus.mojo + rat-maven-plugin + 1.0-alpha-2 + + + pom.xml + src/** + + + src/test/resources/org/apache/struts2/views/jsp/ui/* + src/main/etc/** + src/main/resources/org/apache/struts2/static/dojo/src/** + src/main/resources/org/apache/struts2/static/dojo/* + src/main/resources/org/apache/struts2/static/niftycorners/** + src/test/resources/org/apache/struts2/interceptor/validation/* + src/site/resources/tags/** + + + + + + + + + alljars + + + + maven-javadoc-plugin + 2.2 + + + attach-source + + jar + + + + + ${basedir}/src/main/java;${basedir}/target/xwork-sources + UTF-8 + + + Struts Packages + org.apache.struts2* + + + XWork Packages + com.opensymphony.xwork2* + + + private + + http://java.sun.com/j2se/1.5.0/docs/api + http://java.sun.com/javaee/5/docs/api/ + http://jakarta.apache.org/commons/logging/apidocs/ + http://logging.apache.org/log4j/docs/api/ + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-source + + jar + + + + + + + + + default-tools.jar + + + java.vendor + Sun Microsystems Inc. + + + + + com.sun + tools + 1.5.0 + system + ${java.home}/../lib/tools.jar + + + + + + + + + + com.opensymphony + xwork + 2.0.7 + + + + freemarker + freemarker + 2.3.8 + + + + javax.servlet + servlet-api + 2.4 + provided + + + + javax.servlet + jsp-api + 2.0 + provided + + + + opensymphony + ognl + 2.6.11 + + + + commons-logging + commons-logging + 1.0.4 + + + + + uk.ltd.getahead + dwr + 1.1-beta-3 + true + + + + + velocity + velocity + 1.4 + true + + + + velocity-tools + velocity-tools + 1.1 + true + + + + + commons-fileupload + commons-fileupload + 1.1.1 + true + + + commons-io + commons-io + 1.0 + true + + + + commons-lang + commons-lang + 2.1 + true + + + + + portlet-api + portlet-api + 1.0 + true + + + + org.apache.pluto + pluto + 1.0.1-rc4 + true + + + + + org.springframework + spring-mock + 1.2.8 + true + + + + org.springframework + spring-core + 1.2.8 + test + + + + + + + junit + junit + compile + 3.8.1 + + true + + + + org.testng + testng + 5.1 + true + jdk15 + + + + jmock + jmock + 1.0.1 + test + + + org.easymock + easymock + 2.0 + test + + + + + jmock + jmock-cglib + 1.0.1 + test + + + + mockobjects + mockobjects-core + 0.09 + test + + + + mockobjects + mockobjects-jdk1.3 + 0.09 + test + + + + mockobjects + mockobjects-alt-jdk1.3 + 0.09 + test + + + + mockobjects + mockobjects-alt-jdk1.3-j2ee1.3 + 0.09 + test + + + + mockobjects + mockobjects-jdk1.3-j2ee1.3 + 0.09 + test + + + + log4j + log4j + 1.2.9 + test + + + + + org.apache.struts + struts-annotations + compile + 1.0.2 + true + + + + + diff --git a/STRUTS_2_0_X/core/src/main/etc/taglib-settings.xml b/STRUTS_2_0_X/core/src/main/etc/taglib-settings.xml new file mode 100644 index 000000000..cd2bd2e95 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/etc/taglib-settings.xml @@ -0,0 +1,5 @@ + 1.1 + 1.2 + struts-tags + /tags + A tag library for processing Model-2 command results diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/RequestUtils.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/RequestUtils.java new file mode 100644 index 000000000..9c0574444 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/RequestUtils.java @@ -0,0 +1,56 @@ +/* + * $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; + +import javax.servlet.http.HttpServletRequest; + + +/** + * Request handling utility class. + */ +public class RequestUtils { + + /** + * Retrieves the current request servlet path. + * Deals with differences between servlet specs (2.2 vs 2.3+) + * + * @param request the request + * @return the servlet path + */ + public static String getServletPath(HttpServletRequest request) { + String servletPath = request.getServletPath(); + + if (null != servletPath && !"".equals(servletPath)) { + return servletPath; + } + + String requestUri = request.getRequestURI(); + int startIndex = request.getContextPath().equals("") ? 0 : request.getContextPath().length(); + int endIndex = request.getPathInfo() == null ? requestUri.length() : requestUri.lastIndexOf(request.getPathInfo()); + + if (startIndex > endIndex) { // this should not happen + endIndex = startIndex; + } + + return requestUri.substring(startIndex, endIndex); + } + +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/ServletActionContext.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/ServletActionContext.java new file mode 100644 index 000000000..c6d83b7ca --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/ServletActionContext.java @@ -0,0 +1,149 @@ +/* + * $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; + +import java.util.Map; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.jsp.PageContext; + +import org.apache.struts2.dispatcher.mapper.ActionMapping; + +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.util.ValueStack; + + +/** + * Web-specific context information for actions. This class subclasses ActionContext which + * provides access to things like the action name, value stack, etc. This class adds access to + * web objects like servlet parameters, request attributes and things like the HTTP session. + */ +public class ServletActionContext extends ActionContext implements StrutsStatics { + + private static final long serialVersionUID = -666854718275106687L; + + public static final String STRUTS_VALUESTACK_KEY = "struts.valueStack"; + public static final String ACTION_MAPPING = "struts.actionMapping"; + + @SuppressWarnings("unused") + private ServletActionContext(Map context) { + super(context); + } + + /** + * Gets the current action context + * + * @param req The request + * @return The current action context + */ + public static ActionContext getActionContext(HttpServletRequest req) { + ValueStack vs = getValueStack(req); + if (vs != null) { + return new ActionContext(vs.getContext()); + } else { + return null; + } + } + + /** + * Gets the current value stack for this request + * + * @param req The request + * @return The value stack + */ + public static ValueStack getValueStack(HttpServletRequest req) { + return (ValueStack) req.getAttribute(STRUTS_VALUESTACK_KEY); + } + + /** + * Gets the action mapping for this context + * + * @return The action mapping + */ + public static ActionMapping getActionMapping() { + return (ActionMapping) ActionContext.getContext().get(ACTION_MAPPING); + } + + /** + * Returns the HTTP page context. + * + * @return the HTTP page context. + */ + public static PageContext getPageContext() { + return (PageContext) ActionContext.getContext().get(PAGE_CONTEXT); + } + + /** + * Sets the HTTP servlet request object. + * + * @param request the HTTP servlet request object. + */ + public static void setRequest(HttpServletRequest request) { + ActionContext.getContext().put(HTTP_REQUEST, request); + } + + /** + * Gets the HTTP servlet request object. + * + * @return the HTTP servlet request object. + */ + public static HttpServletRequest getRequest() { + return (HttpServletRequest) ActionContext.getContext().get(HTTP_REQUEST); + } + + /** + * Sets the HTTP servlet response object. + * + * @param response the HTTP servlet response object. + */ + public static void setResponse(HttpServletResponse response) { + ActionContext.getContext().put(HTTP_RESPONSE, response); + } + + /** + * Gets the HTTP servlet response object. + * + * @return the HTTP servlet response object. + */ + public static HttpServletResponse getResponse() { + return (HttpServletResponse) ActionContext.getContext().get(HTTP_RESPONSE); + } + + /** + * Gets the servlet context. + * + * @return the servlet context. + */ + public static ServletContext getServletContext() { + return (ServletContext) ActionContext.getContext().get(SERVLET_CONTEXT); + } + + /** + * Sets the current servlet context object + * + * @param servletContext The servlet context to use + */ + public static void setServletContext(ServletContext servletContext) { + ActionContext.getContext().put(SERVLET_CONTEXT, servletContext); + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsConstants.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsConstants.java new file mode 100644 index 000000000..41c766528 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsConstants.java @@ -0,0 +1,160 @@ +/* + * $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; + +import org.apache.struts2.dispatcher.mapper.CompositeActionMapper; + +/** + * This class provides a central location for framework configuration keys + * used to retrieve and store Struts configuration settings. + */ +public final class StrutsConstants { + + /** Whether Struts is in development mode or not */ + public static final String STRUTS_DEVMODE = "struts.devMode"; + + /** Whether the localization messages should automatically be reloaded */ + public static final String STRUTS_I18N_RELOAD = "struts.i18n.reload"; + + /** The encoding to use for localization messages */ + public static final String STRUTS_I18N_ENCODING = "struts.i18n.encoding"; + + /** Whether to reload the XML configuration or not */ + public static final String STRUTS_CONFIGURATION_XML_RELOAD = "struts.configuration.xml.reload"; + + /** The URL extension to use to determine if the request is meant for a Struts action */ + public static final String STRUTS_ACTION_EXTENSION = "struts.action.extension"; + + /** Whether to use the alterative syntax for the tags or not */ + public static final String STRUTS_TAG_ALTSYNTAX = "struts.tag.altSyntax"; + + /** The HTTP port used by Struts URLs */ + public static final String STRUTS_URL_HTTP_PORT = "struts.url.http.port"; + + /** The HTTPS port used by Struts URLs */ + public static final String STRUTS_URL_HTTPS_PORT = "struts.url.https.port"; + + /** The default includeParams method to generate Struts URLs */ + public static final String STRUTS_URL_INCLUDEPARAMS = "struts.url.includeParams"; + + /** The com.opensymphony.xwork2.ObjectFactory implementation class */ + public static final String STRUTS_OBJECTFACTORY = "struts.objectFactory"; + + /** The com.opensymphony.xwork2.util.ObjectTypeDeterminer implementation class */ + public static final String STRUTS_OBJECTTYPEDETERMINER = "struts.objectTypeDeterminer"; + + /** The package containing actions that use Rife continuations */ + public static final String STRUTS_CONTINUATIONS_PACKAGE = "struts.continuations.package"; + + /** The org.apache.struts2.config.Configuration implementation class */ + public static final String STRUTS_CONFIGURATION = "struts.configuration"; + + /** The default locale for the Struts application */ + public static final String STRUTS_LOCALE = "struts.locale"; + + /** Whether to use a Servlet request parameter workaround necessary for some versions of WebLogic */ + public static final String STRUTS_DISPATCHER_PARAMETERSWORKAROUND = "struts.dispatcher.parametersWorkaround"; + + /** The org.apache.struts2.views.freemarker.FreemarkerManager implementation class */ + public static final String STRUTS_FREEMARKER_MANAGER_CLASSNAME = "struts.freemarker.manager.classname"; + + /** Cache Freemarker templates */ + public static final String STRUTS_FREEMARKER_TEMPLATES_CACHE = "struts.freemarker.templatesCache"; + + /** org.apache.struts2.views.velocity.VelocityManager implementation class */ + public static final String STRUTS_VELOCITY_MANAGER_CLASSNAME = "struts.velocity.manager.classname"; + + /** The Velocity configuration file path */ + public static final String STRUTS_VELOCITY_CONFIGFILE = "struts.velocity.configfile"; + + /** The location of the Velocity toolbox */ + public static final String STRUTS_VELOCITY_TOOLBOXLOCATION = "struts.velocity.toolboxlocation"; + + /** List of Velocity context names */ + public static final String STRUTS_VELOCITY_CONTEXTS = "struts.velocity.contexts"; + + /** The directory containing UI templates */ + public static final String STRUTS_UI_TEMPLATEDIR = "struts.ui.templateDir"; + + /** The default UI template theme */ + public static final String STRUTS_UI_THEME = "struts.ui.theme"; + + /** The maximize size of a multipart request (file upload) */ + public static final String STRUTS_MULTIPART_MAXSIZE = "struts.multipart.maxSize"; + + /** The directory to use for storing uploaded files */ + public static final String STRUTS_MULTIPART_SAVEDIR = "struts.multipart.saveDir"; + + /** + * The org.apache.struts2.dispatcher.multipart.MultiPartRequest parser implementation + * for a multipart request (file upload) + */ + public static final String STRUTS_MULTIPART_PARSER = "struts.multipart.parser"; + + /** Whether Spring should autoWire or not */ + public static final String STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE = "struts.objectFactory.spring.autoWire"; + + /** Whether Spring should use its class cache or not */ + public static final String STRUTS_OBJECTFACTORY_SPRING_USE_CLASS_CACHE = "struts.objectFactory.spring.useClassCache"; + + /** Whether or not XSLT templates should not be cached */ + public static final String STRUTS_XSLT_NOCACHE = "struts.xslt.nocache"; + + /** Location of additional configuration properties files to load */ + public static final String STRUTS_CUSTOM_PROPERTIES = "struts.custom.properties"; + + /** Location of additional localization properties files to load */ + public static final String STRUTS_CUSTOM_I18N_RESOURCES = "struts.custom.i18n.resources"; + + /** The org.apache.struts2.dispatcher.mapper.ActionMapper implementation class */ + public static final String STRUTS_MAPPER_CLASS = "struts.mapper.class"; + + /** Whether the Struts filter should serve static content or not */ + public static final String STRUTS_SERVE_STATIC_CONTENT = "struts.serve.static"; + + /** If static content served by the Struts filter should set browser caching header properties or not */ + public static final String STRUTS_SERVE_STATIC_BROWSER_CACHE = "struts.serve.static.browserCache"; + + /** Allows one to disable dynamic method invocation from the URL */ + public static final String STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION = "struts.enable.DynamicMethodInvocation"; + + /** Whether slashes in action names are allowed or not */ + public static final String STRUTS_ENABLE_SLASHES_IN_ACTION_NAMES = "struts.enable.SlashesInActionNames"; + + /** Prefix used by {@link CompositeActionMapper} to identify its containing {@link org.apache.struts2.dispatcher.mapper.ActionMapper} class. */ + public static final String STRUTS_MAPPER_COMPOSITE = "struts.mapper.composite"; + + public static final String STRUTS_ACTIONPROXYFACTORY = "struts.actionProxyFactory"; + + public static final String STRUTS_FREEMARKER_WRAPPER_ALT_MAP = "struts.freemarker.wrapper.altMap"; + + /** The name of the xwork converter implementation */ + public static final String STRUTS_XWORKCONVERTER = "struts.xworkConverter"; + + public static final String STRUTS_ALWAYS_SELECT_FULL_NAMESPACE = "struts.mapper.alwaysSelectFullNamespace"; + + /** XWork default text provider */ + public static final String STRUTS_XWORKTEXTPROVIDER = "struts.xworkTextProvider"; + + /** The name of the parameter to create when mapping an id (used by some action mappers) */ + public static final String STRUTS_ID_PARAMETER_NAME = "struts.mapper.idParameterName"; + +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsException.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsException.java new file mode 100644 index 000000000..0c57029e6 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsException.java @@ -0,0 +1,104 @@ +/* + * $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; + +import com.opensymphony.xwork2.XWorkException; +import com.opensymphony.xwork2.util.location.Locatable; + + +/** + * A generic runtime exception that optionally contains Location information + */ +public class StrutsException extends XWorkException implements Locatable { + + private static final long serialVersionUID = 888724366243600135L; + + + /** + * Constructs a StrutsException with no detail message. + */ + public StrutsException() { + } + + /** + * Constructs a StrutsException with the specified + * detail message. + * + * @param s the detail message. + */ + public StrutsException(String s) { + this(s, null, null); + } + + /** + * Constructs a StrutsException with the specified + * detail message and target. + * + * @param s the detail message. + * @param target the target of the exception. + */ + public StrutsException(String s, Object target) { + this(s, (Throwable) null, target); + } + + /** + * Constructs a StrutsException with the root cause + * + * @param cause The wrapped exception + */ + public StrutsException(Throwable cause) { + this(null, cause, null); + } + + /** + * Constructs a StrutsException with the root cause and target + * + * @param cause The wrapped exception + * @param target The target of the exception + */ + public StrutsException(Throwable cause, Object target) { + this(null, cause, target); + } + + /** + * Constructs a StrutsException with the specified + * detail message and exception cause. + * + * @param s the detail message. + * @param cause the wrapped exception + */ + public StrutsException(String s, Throwable cause) { + this(s, cause, null); + } + + + /** + * Constructs a StrutsException with the specified + * detail message, cause, and target + * + * @param s the detail message. + * @param cause The wrapped exception + * @param target The target of the exception + */ + public StrutsException(String s, Throwable cause, Object target) { + super(s, cause, target); + } +} \ No newline at end of file diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsStatics.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsStatics.java new file mode 100644 index 000000000..2d6171791 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsStatics.java @@ -0,0 +1,68 @@ +/* + * $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; + + +/** + * Constants used by Struts. The constants can be used to get or set objects + * out of the action context or other collections. + * + *

    + * + * Example: + *

      ActionContext.getContext().put(HTTP_REQUEST, request);
    + *

    + * or + *

    + *

      + * ActionContext context = ActionContext.getContext();
      + * HttpServletRequest request = (HttpServletRequest)context.get(HTTP_REQUEST);
    + */ +public interface StrutsStatics { + + /** + * Constant for the HTTP request object. + */ + public static final String HTTP_REQUEST = "com.opensymphony.xwork2.dispatcher.HttpServletRequest"; + + /** + * Constant for the HTTP response object. + */ + public static final String HTTP_RESPONSE = "com.opensymphony.xwork2.dispatcher.HttpServletResponse"; + + /** + * Constant for an HTTP {@link javax.servlet.RequestDispatcher request dispatcher}. + */ + public static final String SERVLET_DISPATCHER = "com.opensymphony.xwork2.dispatcher.ServletDispatcher"; + + /** + * Constant for the {@link javax.servlet.ServletContext servlet context} object. + */ + public static final String SERVLET_CONTEXT = "com.opensymphony.xwork2.dispatcher.ServletContext"; + + /** + * Constant for the JSP {@link javax.servlet.jsp.PageContext page context}. + */ + public static final String PAGE_CONTEXT = "com.opensymphony.xwork2.dispatcher.PageContext"; + + /** Constant for the PortletContext object */ + public static final String STRUTS_PORTLET_CONTEXT = "struts.portlet.context"; +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsTestCase.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsTestCase.java new file mode 100644 index 000000000..b6671751d --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/StrutsTestCase.java @@ -0,0 +1,57 @@ +/* + * $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; + +import java.util.Map; + +import org.apache.struts2.dispatcher.Dispatcher; +import org.apache.struts2.util.StrutsTestCaseHelper; + +import com.opensymphony.xwork2.XWorkTestCase; + +/** + * Base test case for JUnit testing Struts. + */ +public abstract class StrutsTestCase extends XWorkTestCase { + + /** + * Sets up the configuration settings, XWork configuration, and + * message resources + */ + protected void setUp() throws Exception { + super.setUp(); + initDispatcher(null); + } + + protected Dispatcher initDispatcher(Map params) { + Dispatcher du = StrutsTestCaseHelper.initDispatcher(params); + configurationManager = du.getConfigurationManager(); + configuration = configurationManager.getConfiguration(); + container = configuration.getContainer(); + return du; + } + + protected void tearDown() throws Exception { + super.tearDown(); + StrutsTestCaseHelper.tearDown(); + } + +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/TestNGStrutsTestCase.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/TestNGStrutsTestCase.java new file mode 100644 index 000000000..10681068c --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/TestNGStrutsTestCase.java @@ -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; + +import java.util.Map; + +import org.apache.struts2.dispatcher.Dispatcher; +import org.apache.struts2.util.StrutsTestCaseHelper; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; + +import com.opensymphony.xwork2.TestNGXWorkTestCase; + +/** + * Base test class for TestNG unit tests. Provides common Struts variables + * and performs Struts setup and teardown processes + */ +public class TestNGStrutsTestCase extends TestNGXWorkTestCase { + + @BeforeTest + protected void setUp() throws Exception { + super.setUp(); + initDispatcher(null); + } + + protected Dispatcher initDispatcher(Map params) { + Dispatcher du = StrutsTestCaseHelper.initDispatcher(params); + configurationManager = du.getConfigurationManager(); + configuration = configurationManager.getConfiguration(); + container = configuration.getContainer(); + return du; + } + + @AfterTest + protected void tearDown() throws Exception { + super.tearDown(); + StrutsTestCaseHelper.tearDown(); + } +} + diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/AbstractRemoteCallUIBean.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/AbstractRemoteCallUIBean.java new file mode 100644 index 000000000..ad037697e --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/AbstractRemoteCallUIBean.java @@ -0,0 +1,175 @@ +/* + * $Id$ + * + * Copyright 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. + */ +package org.apache.struts2.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * AbstractRemoteCallUIBean is superclass for all components dealing with remote + * calls. + */ +/** + * TODO: Document AbstractRemoteCallUIBean. + * + * @author $Author$ + * @version $Revision$ $Date$ + */ +public abstract class AbstractRemoteCallUIBean extends ClosingUIBean implements RemoteUICallBean { + + protected String href; + protected String errorText; + protected String afterLoading; + protected String beforeLoading; + protected String executeScripts; + protected String loadingText; + protected String listenTopics; + protected String handler; + protected String formId; + protected String formFilter; + protected String notifyTopics; + protected String showErrorTransportText; + protected String indicator; + protected String showLoadingText; + + public AbstractRemoteCallUIBean(ValueStack stack, HttpServletRequest request, + HttpServletResponse response) { + super(stack, request, response); + } + + public void evaluateExtraParams() { + super.evaluateExtraParams(); + + if (href != null) + addParameter("href", ensureAttributeSafelyNotEscaped(findString(href))); + if (errorText != null) + addParameter("errorText", findString(errorText)); + if (loadingText != null) + addParameter("loadingText", findString(loadingText)); + if (afterLoading != null) + addParameter("afterLoading", findString(afterLoading)); + if (beforeLoading != null) + addParameter("beforeLoading", findString(beforeLoading)); + if (executeScripts != null) + addParameter("executeScripts", findValue(executeScripts, Boolean.class)); + if (listenTopics != null) + addParameter("listenTopics", findValue(listenTopics, String.class)); + if (notifyTopics != null) + addParameter("notifyTopics", findValue(notifyTopics, String.class)); + if (handler != null) + addParameter("handler", findString(handler)); + if (formId != null) + addParameter("formId", findString(formId)); + if (formFilter != null) + addParameter("formFilter", findString(formFilter)); + if (indicator != null) + addParameter("indicator", findString(indicator)); + if (showErrorTransportText != null) + addParameter("showErrorTransportText", findValue(showErrorTransportText, Boolean.class)); + else + addParameter("showErrorTransportText", true); + if (showLoadingText != null) + addParameter("showLoadingText", findString(showLoadingText)); + } + + + @StrutsTagAttribute(description="Topic that will trigger the remote call") + public void setListenTopics(String listenTopics) { + this.listenTopics = listenTopics; + } + + @StrutsTagAttribute(description="The URL to call to obtain the content. Note: If used with ajax context, the value must be set as an url tag value.") + public void setHref(String href) { + this.href = href; + } + + + @StrutsTagAttribute(description="The text to display to the user if the is an error fetching the content") + public void setErrorText(String errorText) { + this.errorText = errorText; + } + + + /* (non-Javadoc) + * @see org.apache.struts2.components.RemoteUICallBean#setAfterLoading(java.lang.String) + */ + public void setAfterLoading(String afterLoading) { + this.afterLoading = afterLoading; + } + + + /* (non-Javadoc) + * @see org.apache.struts2.components.RemoteUICallBean#setBeforeLoading(java.lang.String) + */ + public void setBeforeLoading(String beforeLoading) { + this.beforeLoading = beforeLoading; + } + + + @StrutsTagAttribute(description="Javascript code in the fetched content will be executed", type="Boolean", defaultValue="false") + public void setExecuteScripts(String executeScripts) { + this.executeScripts = executeScripts; + } + + @StrutsTagAttribute(description="Text to be shown while content is being fetched", defaultValue="Loading...") + public void setLoadingText(String loadingText) { + this.loadingText = loadingText; + } + + + @StrutsTagAttribute(description="Javascript function name that will make the request") + public void setHandler(String handler) { + this.handler = handler; + } + + + @StrutsTagAttribute(description="Function name used to filter the fields of the form.") + public void setFormFilter(String formFilter) { + this.formFilter = formFilter; + } + + @StrutsTagAttribute(description="Form id whose fields will be serialized and passed as parameters") + public void setFormId(String formId) { + this.formId = formId; + } + + @StrutsTagAttribute(description="Topics that will published when the remote call completes") + public void setNotifyTopics(String notifyTopics) { + this.notifyTopics = notifyTopics; + } + + + @StrutsTagAttribute(description="Set whether errors will be shown or not", type="Boolean", defaultValue="true") + public void setShowErrorTransportText(String showError) { + this.showErrorTransportText = showError; + } + + @StrutsTagAttribute(description="Id of element that will be shown while making request") + public void setIndicator(String indicator) { + this.indicator = indicator; + } + + @StrutsTagAttribute(description="Show loading text on targets", type="Boolean", defaultValue="true") + public void setShowLoadingText(String showLoadingText) { + this.showLoadingText = showLoadingText; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ActionComponent.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ActionComponent.java new file mode 100644 index 000000000..710beeee2 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ActionComponent.java @@ -0,0 +1,295 @@ +/* + * $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.components; + +import java.io.IOException; +import java.io.Writer; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.jsp.PageContext; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.ServletActionContext; +import org.apache.struts2.StrutsException; +import org.apache.struts2.dispatcher.Dispatcher; +import org.apache.struts2.dispatcher.RequestMap; +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.inject.Inject; +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.util.ValueStackFactory; + +/** + * + *

    This tag enables developers to call actions directly from a JSP page by specifying the action name and an optional + * namespace. The body content of the tag is used to render the results from the Action. Any result processor defined + * for this action in struts.xml will be ignored, unless the executeResult parameter is specified.

    + * + * + * + *
      + *
    • id (String) - the id (if specified) to put the action under stack's context. + *
    • name* (String) - name of the action to be executed (without the extension suffix eg. .action)
    • + *
    • namespace (String) - default to the namespace where this action tag is invoked
    • + *
    • executeResult (Boolean) - default is false. Decides wheather the result of this action is to be executed or not
    • + *
    • ignoreContextParams (Boolean) - default to false. Decides wheather the request parameters are to be included when the action is invoked
    • + *
    + * + * + *
    + * 
    + * public class ActionTagAction extends ActionSupport {
    + *
    + *  public String execute() throws Exception {
    + *      return "done";
    + *  }
    + *
    + *  public String doDefault() throws Exception {
    + *      ServletActionContext.getRequest().setAttribute("stringByAction", "This is a String put in by the action's doDefault()");
    + *      return "done";
    + *  }
    + * }
    + * 
    + * 
    + * + *
    + * 
    + *   
    + *      ....
    + *     
    + *         success.jsp
    + *     
    + *      
    + *         success.jsp
    + *     
    + *      ....
    + *   
    + * 
    + * 
    + * + *
    + * 
    + *  
    The following action tag will execute result and include it in this page
    + *
    + * + *
    + *
    The following action tag will do the same as above, but invokes method specialMethod in action
    + *
    + * + *
    + *
    The following action tag will not execute result, but put a String in request scope + * under an id "stringByAction" which will be retrieved using property tag
    + * + * + * + *
    + * + */ +@StrutsTag(name="action", tldTagClass="org.apache.struts2.views.jsp.ActionTag", description="Execute an action from within a view") +public class ActionComponent extends Component { + private static final Log LOG = LogFactory.getLog(ActionComponent.class); + + protected HttpServletResponse res; + protected HttpServletRequest req; + + protected ActionProxyFactory actionProxyFactory; + protected ActionProxy proxy; + protected String name; + protected String namespace; + protected boolean executeResult; + protected boolean ignoreContextParams; + protected boolean flush = true; + + public ActionComponent(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { + super(stack); + this.req = req; + this.res = res; + } + + /** + * @param actionProxyFactory the actionProxyFactory to set + */ + @Inject + public void setActionProxyFactory(ActionProxyFactory actionProxyFactory) { + this.actionProxyFactory = actionProxyFactory; + } + + public boolean end(Writer writer, String body) { + boolean end = super.end(writer, "", false); + try { + if (flush) { + try { + writer.flush(); + } catch (IOException e) { + LOG.warn("error while trying to flush writer ", e); + } + } + executeAction(); + + if ((getId() != null) && (proxy != null)) { + getStack().setValue("#attr['" + getId() + "']", + proxy.getAction()); + } + } finally { + popComponentStack(); + } + return end; + } + + private Map createExtraContext() { + Map parentParams = null; + + if (!ignoreContextParams) { + parentParams = new ActionContext(getStack().getContext()).getParameters(); + } + + Map newParams = (parentParams != null) ? new HashMap(parentParams) : new HashMap(); + + if (parameters != null) { + newParams.putAll(parameters); + } + + ActionContext ctx = new ActionContext(stack.getContext()); + ServletContext servletContext = (ServletContext) ctx.get(ServletActionContext.SERVLET_CONTEXT); + PageContext pageContext = (PageContext) ctx.get(ServletActionContext.PAGE_CONTEXT); + Map session = ctx.getSession(); + Map application = ctx.getApplication(); + + Dispatcher du = Dispatcher.getInstance(); + Map extraContext = du.createContextMap(new RequestMap(req), + newParams, + session, + application, + req, + res, + servletContext); + + ValueStack newStack = ValueStackFactory.getFactory().createValueStack(stack); + extraContext.put(ActionContext.VALUE_STACK, newStack); + + // add page context, such that ServletDispatcherResult will do an include + extraContext.put(ServletActionContext.PAGE_CONTEXT, pageContext); + + return extraContext; + } + + public ActionProxy getProxy() { + return proxy; + } + + /** + * Execute the requested action. If no namespace is provided, we'll + * attempt to derive a namespace using buildNamespace(). The ActionProxy + * and the namespace will be saved into the instance variables proxy and + * namespace respectively. + * + * @see org.apache.struts2.views.jsp.TagUtils#buildNamespace + */ + private void executeAction() { + String actualName = findString(name, "name", "Action name is required. Example: updatePerson"); + + if (actualName == null) { + throw new StrutsException("Unable to find value for name " + name); + } + + // handle "name!method" convention. + final String actionName; + final String methodName; + + int exclamation = actualName.lastIndexOf("!"); + if (exclamation != -1) { + actionName = actualName.substring(0, exclamation); + methodName = actualName.substring(exclamation + 1); + } else { + actionName = actualName; + methodName = null; + } + + String namespace; + + if (this.namespace == null) { + namespace = TagUtils.buildNamespace(actionMapper, getStack(), req); + } else { + namespace = findString(this.namespace); + } + + // get the old value stack from the request + ValueStack stack = getStack(); + // execute at this point, after params have been set + try { + + proxy = actionProxyFactory.createActionProxy(namespace, actionName, createExtraContext(), executeResult, true); + if (null != methodName) { + proxy.setMethod(methodName); + } + // set the new stack into the request for the taglib to use + req.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack()); + proxy.execute(); + + } catch (Exception e) { + String message = "Could not execute action: " + namespace + "/" + actualName; + LOG.error(message, e); + } finally { + // set the old stack back on the request + req.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack); + } + + if ((getId() != null) && (proxy != null)) { + final Map context = stack.getContext(); + context.put(getId(), proxy.getAction()); + } + } + + @StrutsTagAttribute(required=true,description="Name of the action to be executed (without the extension suffix eg. .action)") + public void setName(String name) { + this.name = name; + } + + @StrutsTagAttribute(description="Namespace for action to call", defaultValue="namespace from where tag is used") + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + @StrutsTagAttribute(description="Whether the result of this action (probably a view) should be executed/rendered", type="Boolean", defaultValue="false") + public void setExecuteResult(boolean executeResult) { + this.executeResult = executeResult; + } + + @StrutsTagAttribute(description="Whether the request parameters are to be included when the action is invoked", type="Boolean", defaultValue="false") + public void setIgnoreContextParams(boolean ignoreContextParams) { + this.ignoreContextParams = ignoreContextParams; + } + + @StrutsTagAttribute(description="Whether the writer should be flush upon end of action component tag, default to true", type="Boolean", defaultValue="true") + public void setFlush(boolean flush) { + this.flush = flush; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ActionError.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ActionError.java new file mode 100644 index 000000000..e76106ab4 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ActionError.java @@ -0,0 +1,66 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + * Render action errors if they exists the specific layout of the rendering depends on + * the theme itself. + * + * + * + *

    Examples + * + *

    + * 
    + *
    + *    <s:actionerror />
    + *    <s:form .... >
    + *       ....
    + *    </s:form>
    + *
    + * 
    + * 
    + * + */ +@StrutsTag(name="actionerror", tldBodyContent="empty", tldTagClass="org.apache.struts2.views.jsp.ui.ActionErrorTag", description="Render action errors if they exists") +public class ActionError extends UIBean { + + public static final String TEMPLATE = "actionerror"; + + + public ActionError(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ActionMessage.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ActionMessage.java new file mode 100644 index 000000000..26978b521 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ActionMessage.java @@ -0,0 +1,62 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + * Render action messages if they exists, specific rendering layout depends on the + * theme itself. + * + * + * + *

    Examples + * + *

    + * 
    + *    <s:actionmessage />
    + *    <s:form .... >
    + *       ....
    + *    </s:form>
    + * 
    + * 
    + * + */ +@StrutsTag(name="actionmessage", tldBodyContent="empty", tldTagClass="org.apache.struts2.views.jsp.ui.ActionMessageTag", description="Render action messages if they exists") +public class ActionMessage extends UIBean { + + private static final String TEMPLATE = "actionmessage"; + + public ActionMessage(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Anchor.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Anchor.java new file mode 100644 index 000000000..e0bc6b46a --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Anchor.java @@ -0,0 +1,171 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + * A tag that creates a HTML <a href='' /> that when clicked calls a URL remote XMLHttpRequest call via the dojo + * framework.

    + * + * + * THE FOLLOWING IS ONLY VALID WHEN AJAX IS CONFIGURED + *

      + *
    • href
    • + *
    • errorText
    • + *
    • listenTopics
    • + *
    • notifyTopics
    • + *
    • executeScripts
    • + *
    • loadingText
    • + *
    • listenTopics
    • + *
    • handler
    • + *
    • formId
    • + *
    • formFilter
    • + *
    • targets
    • + *
    • showErrorTransportText
    • + *
    • targets
    • + *
    • indicator
    • + *
    + * 'resultDivId' Deprecated. Use targets.

    + * 'targets' is a list of element ids whose content will be updated with the + * text returned from request.

    + * 'errorText' is the text that will be displayed when there is an error making the request.

    + * 'onLoadJS' Deprecated. Use 'notifyTopics'.

    + * 'preInvokeJS' Deprecated. Use 'notifyTopics'.

    + * 'executeScripts' if set to true will execute javascript sections in the returned text.

    + * 'loadingText' is the text that will be displayed on the 'targets' elements while making the + * request.

    + * 'handler' is the name of the function that will take care of making the AJAX request. Dojo's widget + * and dom node are passed as parameters).

    + * 'formId' is the id of the html form whose fields will be seralized and passed as parameters + * in the request.

    + * 'formFilter' is the name of a function which will be used to filter the fields that will be + * seralized. This function takes as a parameter the element and returns true if the element + * should be included.

    + * 'listenTopics' comma separated list of topics names, that will trigger a request + * 'indicator' element to be shown while the request executing + * 'showErrorTransportText': whether errors should be displayed (on 'targets')

    + * 'showLoadingText' show loading text on targets

    + * 'notifyTopics' comma separated list of topics names, that will be published. Three parameters are passed:

    + *

      + *
    • data: html or json object when type='load' or type='error'
    • + *
    • type: 'before' before the request is made, 'load' when the request succeeds, or 'error' when it fails
    • + *
    • request: request javascript object, when type='load' or type='error'
    • + *
    + * + * + *

    Examples + * + *

    + * 
    + * <s:a id="link1" theme="ajax" href="/DoIt.action" errorText="An error ocurred" loadingText="Loading...">
    + *     <img border="none" src="<%=request.getContextPath()%>/images/delete.gif"/>
    + *     <s:param name="id" value="1"/>
    + * </s:a>
    + * 
    + * 
    + * + *

    + * + * + * + * Results in + * + * + * + *

    + * + *
    + * 
    + * <a dojoType="BindAnchor" executeScripts="true" id="link1" href="/DoIt.action?id=1" errorText="An error ocurred"></a>
    + * 
    + * 
    + * + *

    + * + * + * + * Here is an example that uses the beforeLoading. This example is in altSyntax=true: + * + * + * + *

    + * + *
    + * 
    + * <s:a id="test" theme="ajax" href="/simpeResult.action" beforeLoading="confirm('Are you sure?')">
    + *  A
    + * </s:a>
    + * 
    + * 
    + * + */ +@StrutsTag(name="a", tldTagClass="org.apache.struts2.views.jsp.ui.AnchorTag", description="Render a HTML href element that when clicked can optionally call a URL via remote XMLHttpRequest and updates its targets") +public class Anchor extends AbstractRemoteCallUIBean { + public static final String OPEN_TEMPLATE = "a"; + public static final String TEMPLATE = "a-close"; + public static final String COMPONENT_NAME = Anchor.class.getName(); + + protected String targets; + + public Anchor(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + public String getDefaultOpenTemplate() { + return OPEN_TEMPLATE; + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + public void evaluateExtraParams() { + super.evaluateExtraParams(); + + if(targets != null) + addParameter("targets", findString(targets)); + } + + @StrutsTagAttribute(description="Comma delimited list of ids of the elements whose content will be updated") + public void setTargets(String targets) { + this.targets = targets; + } + + @StrutsTagAttribute(name="onLoadJS", description="Deprecated. Use 'notifyTopics'. Javascript code execute after reload") + public void setAfterLoading(String afterLoading) { + this.afterLoading = afterLoading; + } + + + @StrutsTagAttribute(name="preInvokeJS", description="Deprecated. Use 'notifyTopics'. Javascript code execute before reload") + public void setBeforeLoading(String beforeLoading) { + this.beforeLoading = beforeLoading; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/AppendIterator.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/AppendIterator.java new file mode 100644 index 000000000..15815e51d --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/AppendIterator.java @@ -0,0 +1,171 @@ +/* + * $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.components; + +import java.io.Writer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.components.Param.UnnamedParametric; +import org.apache.struts2.util.AppendIteratorFilter; +import org.apache.struts2.util.MakeIterator; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + *

    Component for AppendIteratorTag, which jobs is to append iterators to form an + * appended iterator whereby entries goes from one iterator to another after each + * respective iterator is exhausted of entries.

    + * + *

    For example, if there are 3 iterator appended (each iterator has 3 entries), + * the following will be how the appended iterator entries will be arranged:

    + * + *
      + *
    1. First Entry of the First Iterator
    2. + *
    3. Second Entry of the First Iterator
    4. + *
    5. Third Entry of the First Iterator
    6. + *
    7. First Entry of the Second Iterator
    8. + *
    9. Second Entry of the Second Iterator
    10. + *
    11. Third Entry of the Second Iterator
    12. + *
    13. First Entry of the Third Iterator
    14. + *
    15. Second Entry of the Third Iterator
    16. + *
    17. Third Entry of the Third ITerator
    18. + *
    + * + * + * + *
      + *
    • id (String) - the id of which if supplied will have the resultant + * appended iterator stored under in the stack's context
    • + *
    + * + * + * + * + * public class AppendIteratorTagAction extends ActionSupport { + * + * private List myList1; + * private List myList2; + * private List myList3; + * + * + * public String execute() throws Exception { + * + * myList1 = new ArrayList(); + * myList1.add("1"); + * myList1.add("2"); + * myList1.add("3"); + * + * myList2 = new ArrayList(); + * myList2.add("a"); + * myList2.add("b"); + * myList2.add("c"); + * + * myList3 = new ArrayList(); + * myList3.add("A"); + * myList3.add("B"); + * myList3.add("C"); + * + * return "done"; + * } + * + * public List getMyList1() { return myList1; } + * public List getMyList2() { return myList2; } + * public List getMyList3() { return myList3; } + *} + * + * + * + * <s:append id="myAppendIterator"> + * <s:param value="%{myList1}" /> + * <s:param value="%{myList2}" /> + * <s:param value="%{myList3}" /> + * </s:append> + * <s:iterator value="%{#myAppendIterator}"> + * <s:property /> + * </s:iterator> + * + * + * + * @see org.apache.struts2.util.AppendIteratorFilter + * @see org.apache.struts2.views.jsp.iterator.AppendIteratorTag + * + */ +@StrutsTag(name="append", tldTagClass="org.apache.struts2.views.jsp.iterator.AppendIteratorTag", description="Append the values of a list of iterators to one iterator") +public class AppendIterator extends Component implements UnnamedParametric { + + private static final Log _log = LogFactory.getLog(AppendIterator.class); + + private AppendIteratorFilter appendIteratorFilter= null; + private List _parameters; + + public AppendIterator(ValueStack stack) { + super(stack); + } + + public boolean start(Writer writer) { + _parameters = new ArrayList(); + appendIteratorFilter = new AppendIteratorFilter(); + + return super.start(writer); + } + + public boolean end(Writer writer, String body) { + + for (Iterator paramEntries = _parameters.iterator(); paramEntries.hasNext(); ) { + + Object iteratorEntryObj = paramEntries.next(); + if (! MakeIterator.isIterable(iteratorEntryObj)) { + _log.warn("param with value resolved as "+iteratorEntryObj+" cannot be make as iterator, it will be ignored and hence will not appear in the merged iterator"); + continue; + } + appendIteratorFilter.setSource(MakeIterator.convert(iteratorEntryObj)); + } + + appendIteratorFilter.execute(); + + if (getId() != null && getId().length() > 0) { + getStack().getContext().put(getId(), appendIteratorFilter); + } + + appendIteratorFilter = null; + + return super.end(writer, body); + } + + // UnnamedParametric implementation -------------------------------------- + public void addParameter(Object value) { + _parameters.add(value); + } + + @StrutsTagAttribute(description="The id of which if supplied will have the resultant appended iterator stored under in the stack's context") + public void setId(String id) { + super.setId(id); + } +} + + diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Autocompleter.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Autocompleter.java new file mode 100644 index 000000000..71ef014fd --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Autocompleter.java @@ -0,0 +1,305 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + *

    The autocomplete tag is a combobox that can autocomplete text entered on the input box. + * When used on the "simple" theme, the autocompleter can be used like the ComboBox. + * When used on the "ajax" theme, the list can be retieved from an action.

    + * THE FOLLOWING IS ONLY VALID WHEN AJAX IS CONFIGURED + *
      + *
    • href
    • + *
    • errorText
    • + *
    • listenTopics
    • + *
    • notifyTopics
    • + *
    • listenTopics
    • + *
    • formId
    • + *
    • formFilter
    • + *
    • indicator
    • + *
    • loadOnTextChange
    • + *
    • loadMinimumCount
    • + *
    • showDownArrow
    • + *
    • searchType
    • + *
    + * 'dropdownWidth' width in pixels of the drodpdown, same as autocompleter's width by default

    + * 'dropdownHeight' height in pixels of the drodown, 120 px by default

    + * 'forceValidOption' if invalid option is selected, clear autocompleter's text when focus is lost

    + * 'autoComplete', if true, make suggestions on the textbox

    + * 'formId' is the id of the html form whose fields will be seralized and passed as parameters + * in the request.

    + * 'formFilter' is the name of a function which will be used to filter the fields that will be + * seralized. This function takes as a parameter the element and returns true if the element + * should be included.

    + * 'listenTopics' comma separated list of topics names, that will trigger a request + * 'indicator' element to be shown while the request executing + * 'showErrorTransportText': whether errors should be displayed (on 'targets')

    + * 'loadOnTextChange' options will be reloaded everytime a character is typed on the textbox

    + * 'loadMinimumCount' minimum number of characters that will force the content to be loaded

    + * 'showDownError' show or hide the down arrow button

    + * 'searchType' how the search must be performed, options are: "startstring", "startword" and "substring"

    + * 'keyName' name of the field to which the selected key will be assigned

    + * 'iconPath' path of icon used for the dropdown

    + * 'templateCssPath' path to css file used to customize Dojo's widget

    + * 'dataFieldName' name of the field to be used as the list in the returned JSON string

    + * 'notifyTopics' comma separated list of topics names, that will be published. Three parameters are passed:

    + *

      + *
    • data: selected value when type='valuechanged'
    • + *
    • type: 'before' before the request is made, 'valuechanged' when selection changes, 'load' when the request succeeds, or 'error' when it fails
    • + *
    • request: request javascript object, when type='load' or type='error'
    • + *
        + * + * + *

        Autocompleter that gets its list from an action:

        + *<s:autocompleter name="test" href="%{jsonList}" autoComplete="false"/> + *
        + **

        Autocompleter that uses a list:

        + *<s:autocompleter name="test" list="{'apple','banana','grape','pear'}" autoComplete="false"/> + *
        + * + */ +@StrutsTag(name="autocompleter", tldTagClass="org.apache.struts2.views.jsp.ui.AutocompleterTag", description="Renders a combobox with autocomplete and AJAX capabilities") +public class Autocompleter extends ComboBox { + public static final String TEMPLATE = "autocompleter"; + final private static String COMPONENT_NAME = Autocompleter.class.getName(); + + protected String forceValidOption; + protected String searchType; + protected String autoComplete; + protected String delay; + protected String disabled; + protected String href; + protected String dropdownWidth; + protected String dropdownHeight; + protected String formId; + protected String formFilter; + protected String listenTopics; + protected String notifyTopics; + protected String indicator; + protected String loadOnTextChange; + protected String loadMinimumCount; + protected String showDownArrow; + protected String templateCssPath; + protected String iconPath; + protected String keyName; + protected String dataFieldName; + protected String resultsLimit; + + public Autocompleter(ValueStack stack, HttpServletRequest request, + HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + public String getComponentName() { + return COMPONENT_NAME; + } + + + public void evaluateExtraParams() { + super.evaluateExtraParams(); + + if (forceValidOption != null) + addParameter("forceValidOption", findValue(forceValidOption, + Boolean.class)); + if (searchType != null) { + String type = findString(searchType); + if(type != null) + addParameter("searchType", type.toUpperCase()); + } + if (autoComplete != null) + addParameter("autoComplete", findValue(autoComplete, Boolean.class)); + if (delay != null) + addParameter("delay", findValue(delay, Integer.class)); + if (disabled != null) + addParameter("disabled", findValue(disabled, Boolean.class)); + if (href != null) { + addParameter("href", findString(href)); + addParameter("mode", "remote"); + } + if (dropdownHeight != null) + addParameter("dropdownHeight", findValue(dropdownHeight, Integer.class)); + if (dropdownWidth != null) + addParameter("dropdownWidth", findValue(dropdownWidth, Integer.class)); + if (formFilter != null) + addParameter("formFilter", findString(formFilter)); + if (formId != null) + addParameter("formId", findString(formId)); + if (listenTopics != null) + addParameter("listenTopics", findString(listenTopics)); + if (notifyTopics != null) + addParameter("notifyTopics", findString(notifyTopics)); + if (indicator != null) + addParameter("indicator", findString(indicator)); + if (loadOnTextChange != null) + addParameter("loadOnTextChange", findValue(loadOnTextChange, Boolean.class)); + if (loadMinimumCount != null) + addParameter("loadMinimumCount", findValue(loadMinimumCount, Integer.class)); + if (showDownArrow != null) + addParameter("showDownArrow", findValue(showDownArrow, Boolean.class)); + else + addParameter("showDownArrow", Boolean.TRUE); + if(templateCssPath != null) + addParameter("templateCssPath", findString(templateCssPath)); + if(iconPath != null) + addParameter("iconPath", findString(iconPath)); + if(dataFieldName != null) + addParameter("dataFieldName", findString(dataFieldName)); + if(keyName != null) + addParameter("keyName", findString(keyName)); + else { + keyName = name + "Key"; + addParameter("keyName", findString(keyName)); + } + + String keyNameExpr = "%{" + keyName + "}"; + addParameter("key", findString(keyNameExpr)); + if(resultsLimit != null) + addParameter("searchLimit", findString(resultsLimit)); + } + + protected Object findListValue() { + return (list != null) ? findValue(list, Object.class) : null; + } + + @StrutsTagAttribute(description="Whether autocompleter should make suggestion on the textbox", type="Boolean", defaultValue="false") + public void setAutoComplete(String autoComplete) { + this.autoComplete = autoComplete; + } + + @StrutsTagAttribute(description="Enable or disable autocompleter", type="Boolean", defaultValue="false") + public void setDisabled(String disabled) { + this.disabled = disabled; + } + + @StrutsTagAttribute(description="Force selection to be one of the options", type="Boolean", defaultValue="false") + public void setForceValidOption(String forceValidOption) { + this.forceValidOption = forceValidOption; + } + + @StrutsTagAttribute(description="The URL used to load the options") + public void setHref(String href) { + this.href = href; + } + + @StrutsTagAttribute(description="Delay before making the search", type="Integer", defaultValue="100") + public void setDelay(String searchDelay) { + this.delay = searchDelay; + } + + @StrutsTagAttribute(description="how the search must be performed, options are: 'startstring', 'startword' " + + "and 'substring'", defaultValue="stringstart") + public void setSearchType(String searchType) { + this.searchType = searchType; + } + + @StrutsTagAttribute(description="Dropdown's height in pixels", type="Integer", defaultValue="120") + public void setDropdownHeight(String height) { + this.dropdownHeight = height; + } + + @StrutsTagAttribute(description="Dropdown's width", type="Integer", defaultValue="same as textbox") + public void setDropdownWidth(String width) { + this.dropdownWidth = width; + } + + @StrutsTagAttribute(description="Function name used to filter the fields of the form") + public void setFormFilter(String formFilter) { + this.formFilter = formFilter; + } + + @StrutsTagAttribute(description="Form id whose fields will be serialized and passed as parameters") + public void setFormId(String formId) { + this.formId = formId; + } + + @StrutsTagAttribute(description="Topic that will trigger a reload") + public void setListenTopics(String listenTopics) { + this.listenTopics = listenTopics; + } + + @StrutsTagAttribute(description="Topics that will be published when content is reloaded") + public void setNotifyTopics(String onValueChangedPublishTopic) { + this.notifyTopics = onValueChangedPublishTopic; + } + + @StrutsTagAttribute(description="Id of element that will be shown while request is made") + public void setIndicator(String indicator) { + this.indicator = indicator; + } + + @StrutsTagAttribute(description="Minimum number of characters that will force the content to be loaded", type="Integer", defaultValue="3") + public void setLoadMinimumCount(String loadMinimumCount) { + this.loadMinimumCount = loadMinimumCount; + } + + @StrutsTagAttribute(description="Options will be reloaded everytime a character is typed on the textbox", type="Boolean", defaultValue="true") + public void setLoadOnTextChange(String loadOnType) { + this.loadOnTextChange = loadOnType; + } + + @StrutsTagAttribute(description="Show or hide the down arrow button", type="Boolean", defaultValue="true") + public void setShowDownArrow(String showDownArrow) { + this.showDownArrow = showDownArrow; + } + + // Override as not required + @StrutsTagAttribute(description="Iteratable source to populate from.") + public void setList(String list) { + super.setList(list); + } + + @StrutsTagAttribute(description="Template css path") + public void setTemplateCssPath(String templateCssPath) { + this.templateCssPath = templateCssPath; + } + + @StrutsTagAttribute(description="Path to icon used for the dropdown") + public void setIconPath(String iconPath) { + this.iconPath = iconPath; + } + + @StrutsTagAttribute(description="Name of the field to which the selected key will be assigned") + public void setKeyName(String keyName) { + this.keyName = keyName; + } + + @StrutsTagAttribute(description="Name of the field in the returned JSON object that contains the data array", defaultValue="Value specified in 'name'") + public void setDataFieldName(String dataFieldName) { + this.dataFieldName = dataFieldName; + } + + @StrutsTagAttribute(description="Limit how many results are shown as autocompletion options", defaultValue="30") + public void setResultsLimit(String resultsLimit) { + this.resultsLimit = resultsLimit; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Bean.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Bean.java new file mode 100644 index 000000000..1a35c396f --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Bean.java @@ -0,0 +1,155 @@ +/* + * $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.components; + +import java.io.Writer; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.inject.Inject; +import com.opensymphony.xwork2.util.ClassLoaderUtil; +import com.opensymphony.xwork2.ObjectFactory; +import com.opensymphony.xwork2.util.OgnlUtil; +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + *

        Instantiates a class that conforms to the JavaBeans specification. This tag has a body which can contain + * a number of {@link Param} elements to set any mutator methods on that class.

        + *

        + *

        If the id attribute is set on the BeanTag, it will place the instantiated bean into the + * stack's Context.

        + *

        + * + * + * + * + *

          + *
        • id - the stack's context id (if supplied) that the created bean will be store under
        • + *
        • name* - the class name of the bean to be instantiated (must respect JavaBean specification)
        • + *
        + * + * + * + *

        Examples:

        + *

        + *

        + * 
        + * <-- in freemarker form -->
        + * [@s.bean name="org.apache.struts2.example.counter.SimpleCounter" id="counter"]
        + *   [s:param name="foo" value="BAR"/]
        + *   The value of foo is : [s:property value="foo"/], when inside the bean tag.
        + * [/s:bean] + * + * <-- in jsp form --> + * <s:bean name="org.apache.struts2.example.counter.SimpleCounter" id="counter"> + * <s:param name="foo" value="BAR" /> + * The value of foot is : <s:property value="foo"/>, when inside the bean tag <br /> + * </s:bean> + * + *
        + *

        + * + * + *

        This example instantiates a bean called SimpleCounter and sets the foo property (setFoo('BAR')). The + * SimpleCounter object is then pushed onto the Valuestack, which means that we can call its accessor methods (getFoo()) + * with the Property tag and get their values.

        + *

        + *

        In the above example, the id has been set to a value of counter. This means that the SimpleCounter class + * will be placed into the stack's context. You can access the SimpleCounter class using a Struts tag:

        + *

        + *

        + * <-- jsp form -->
        + * <s:property value="#counter" />
        + *
        + * <-- freemarker form -->
        + * [s:property value="#counter.foo"/]
        + * 
        + *

        + *

        In the property tag example, the # tells Ognl to search the context for the SimpleCounter class which has + * an id(key) of counter

        + * + * + * @see Param + */ +@StrutsTag(name="bean", tldTagClass="org.apache.struts2.views.jsp.BeanTag", + description="Instantiate a JavaBean and place it in the context") +public class Bean extends Component { + protected static Log log = LogFactory.getLog(Bean.class); + + protected Object bean; + protected String name; + protected ObjectFactory objectFactory; + + public Bean(ValueStack stack) { + super(stack); + } + + @Inject + public void setObjectFactory(ObjectFactory objectFactory) { + this.objectFactory = objectFactory; + } + + public boolean start(Writer writer) { + boolean result = super.start(writer); + + ValueStack stack = getStack(); + + try { + String beanName = findString(name, "name", "Bean name is required. Example: com.acme.FooBean"); + bean = objectFactory.buildBean(ClassLoaderUtil.loadClass(beanName, getClass()), stack.getContext()); + } catch (Exception e) { + log.error("Could not instantiate bean", e); + + return false; + } + + // push bean on stack + stack.push(bean); + + // store for reference later + if (getId() != null) { + getStack().getContext().put(getId(), bean); + } + + return result; + } + + public boolean end(Writer writer, String body) { + ValueStack stack = getStack(); + stack.pop(); + + return super.end(writer, body); + } + + public void addParameter(String key, Object value) { + OgnlUtil.setProperty(key, value, bean, getStack().getContext()); + } + + @StrutsTagAttribute(description="The class name of the bean to be instantiated (must respect JavaBean specification)", + required=true) + public void setName(String name) { + this.name = name; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Checkbox.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Checkbox.java new file mode 100644 index 000000000..269d4471d --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Checkbox.java @@ -0,0 +1,84 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * Renders an HTML input element of type checkbox, populated by the specified property from the ValueStack. + * + * + *

        Examples + * + *

        + * 
        + * JSP:
        + * <s:checkbox label="checkbox test" name="checkboxField1" value="aBoolean" fieldValue="true"/>
        + *
        + * Velocity:
        + * #tag( Checkbox "label=checkbox test" "name=checkboxField1" "value=aBoolean" )
        + *
        + * Resulting HTML (simple template, aBoolean == true):
        + * <input type="checkbox" name="checkboxField1" value="true" checked="checked" />
        + *
        + * 
        + * 
        + * + */ +@StrutsTag(name="checkbox", tldTagClass="org.apache.struts2.views.jsp.ui.CheckboxTag", description="Render a checkbox input field") +public class Checkbox extends UIBean { + final public static String TEMPLATE = "checkbox"; + + protected String fieldValue; + + public Checkbox(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + protected void evaluateExtraParams() { + if (fieldValue != null) { + addParameter("fieldValue", findString(fieldValue)); + } else { + addParameter("fieldValue", "true"); + } + } + + protected Class getValueClassType() { + return Boolean.class; // for checkboxes, everything needs to end up as a Boolean + } + + @StrutsTagAttribute(description="The actual HTML value attribute of the checkbox.", defaultValue="true") + public void setFieldValue(String fieldValue) { + this.fieldValue = fieldValue; + } + +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/CheckboxList.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/CheckboxList.java new file mode 100644 index 000000000..3638f9cef --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/CheckboxList.java @@ -0,0 +1,57 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + * Creates a series of checkboxes from a list. Setup is like <s:select /> or <s:radio />, but creates checkbox tags. + * + * + * + *

        Examples + * + *

        + * 
        + * <s:checkboxlist name="foo" list="bar"/>
        + * 
        + * 
        + * + */ +@StrutsTag(name="checkboxlist", tldTagClass="org.apache.struts2.views.jsp.ui.CheckboxListTag", description="Render a list of checkboxes") +public class CheckboxList extends ListUIBean { + final public static String TEMPLATE = "checkboxlist"; + + public CheckboxList(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ClosingUIBean.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ClosingUIBean.java new file mode 100644 index 000000000..86a92abf4 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ClosingUIBean.java @@ -0,0 +1,66 @@ +/* + * $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.components; + +import java.io.Writer; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * ClosingUIBean is the standard superclass for UI components such as div etc. + */ +public abstract class ClosingUIBean extends UIBean { + private static final Log LOG = LogFactory.getLog(ClosingUIBean.class); + + protected ClosingUIBean(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + String openTemplate; + + public abstract String getDefaultOpenTemplate(); + + @StrutsTagAttribute(description="Set template to use for opening the rendered html.") + public void setOpenTemplate(String openTemplate) { + this.openTemplate = openTemplate; + } + + public boolean start(Writer writer) { + boolean result = super.start(writer); + try { + evaluateParams(); + + mergeTemplate(writer, buildTemplateName(openTemplate, getDefaultOpenTemplate())); + } catch (Exception e) { + LOG.error("Could not open template", e); + e.printStackTrace(); + } + + return result; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ComboBox.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ComboBox.java new file mode 100644 index 000000000..1c05fc68b --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ComboBox.java @@ -0,0 +1,201 @@ +/* + * $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.components; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.util.MakeIterator; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * The combo box is basically an HTML INPUT of type text and HTML SELECT grouped together to give you a combo box + * functionality. You can place text in the INPUT control by using the SELECT control or type it in directly in + * the text field.

        + * + * In this example, the SELECT will be populated from id=year attribute. Counter is itself an Iterator. It will + * span from first to last. The population is done via javascript, and requires that this tag be surrounded by a + * <form>.

        + * + * Note that unlike the <s:select/> tag, there is no ability to define the individual <option> tags' id attribute + * or content separately. Each of these is simply populated from the toString() method of the list item. Presumably + * this is because the select box isn't intended to actually submit useful data, but to assist the user in filling + * out the text field.

        + * + * + *

        Examples + * + *

        + * 
        + * JSP:
        + * <-- Example One -->
        + * <s:bean name="struts.util.Counter" id="year">
        + *   <s:param name="first" value="text('firstBirthYear')"/>
        + *   <s:param name="last" value="2000"/>
        + *
        + *   <s:combobox label="Birth year" size="6" maxlength="4" name="birthYear" list="#year"/>
        + * </s:bean>
        + *
        + * <-- Example Two -->
        + * 
        + *
        + * <-- Example Two -->
        + * 
        + *
        + * Velocity:
        + * #tag( ComboBox "label=Birth year" "size=6" "maxlength=4" "name=birthYear" "list=#year" )
        + * 
        + * 
        + * + */ +@StrutsTag(name="combobox", tldTagClass="org.apache.struts2.views.jsp.ui.ComboBoxTag", description="Widget that fills a text box from a select") +public class ComboBox extends TextField { + final public static String TEMPLATE = "combobox"; + + protected String list; + protected String listKey; + protected String listValue; + protected String headerKey; + protected String headerValue; + protected String emptyOption; + + + public ComboBox(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + public void evaluateExtraParams() { + super.evaluateExtraParams(); + + Object value = findListValue(); + + if (headerKey != null) { + addParameter("headerKey", findString(headerKey)); + } + if (headerValue != null) { + addParameter("headerValue", findString(headerValue)); + } + if (emptyOption != null) { + addParameter("emptyOption", findValue(emptyOption, Boolean.class)); + } + + if (value != null) { + if (value instanceof Collection) { + Collection tmp = (Collection) value; + addParameter("list", tmp); + if (listKey != null) { + addParameter("listKey", listKey); + } + if (listValue != null) { + addParameter("listValue", listValue); + } + } else if (value instanceof Map) { + Map tmp = (Map) value; + addParameter("list", MakeIterator.convert(tmp)); + addParameter("listKey", "key"); + addParameter("listValue", "value"); + } else if (value.getClass().isArray()) { + Iterator i = MakeIterator.convert(value); + addParameter("list", i); + if (listKey != null) { + addParameter("listKey", listKey); + } + if (listValue != null) { + addParameter("listValue", listValue); + } + } else { + Iterator i = MakeIterator.convert(value); + addParameter("list", i); + if (listKey != null) { + addParameter("listKey", listKey); + } + if (listValue != null) { + addParameter("listValue", listValue); + } + } + } + } + + protected Object findListValue() { + return findValue(list, "list", + "You must specify a collection/array/map/enumeration/iterator. " + + "Example: people or people.{name}"); + } + + @StrutsTagAttribute(description="Iteratable source to populate from. " + + "If this is missing, the select widget is simply not displayed.", required=true) + public void setList(String list) { + this.list = list; + } + + @StrutsTagAttribute(description="Decide if an empty option is to be inserted. Default false.") + public void setEmptyOption(String emptyOption) { + this.emptyOption = emptyOption; + } + + @StrutsTagAttribute(description="Set the header key for the header option.") + public void setHeaderKey(String headerKey) { + this.headerKey = headerKey; + } + + @StrutsTagAttribute(description="Set the header value for the header option.") + public void setHeaderValue(String headerValue) { + this.headerValue = headerValue; + } + + @StrutsTagAttribute(description="Set the key used to retrive the option key.") + public void setListKey(String listKey) { + this.listKey = listKey; + } + + @StrutsTagAttribute(description="Set the value used to retrive the option value.") + public void setListValue(String listValue) { + this.listValue = listValue; + } + + +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Component.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Component.java new file mode 100644 index 000000000..b00103abd --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Component.java @@ -0,0 +1,492 @@ +/* + * $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.components; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Stack; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.StrutsException; +import org.apache.struts2.dispatcher.mapper.ActionMapper; +import org.apache.struts2.dispatcher.mapper.ActionMapping; +import org.apache.struts2.util.FastByteArrayOutputStream; +import org.apache.struts2.views.jsp.TagUtils; +import org.apache.struts2.views.util.ContextUtil; +import org.apache.struts2.views.util.UrlHelper; + +import com.opensymphony.xwork2.inject.Inject; +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.util.TextParseUtil; + +/** + * Base class to extend for UI components. + *

        + * This class is a good extension point when building reuseable UI components. + * + */ +public class Component { + public static final String COMPONENT_STACK = "__component_stack"; + + protected ValueStack stack; + protected Map parameters; + protected String id; + protected ActionMapper actionMapper; + + /** + * Constructor. + * + * @param stack OGNL value stack. + */ + public Component(ValueStack stack) { + this.stack = stack; + this.parameters = new LinkedHashMap(); + getComponentStack().push(this); + } + + /** + * Gets the name of this component. + * @return the name of this component. + */ + private String getComponentName() { + Class c = getClass(); + String name = c.getName(); + int dot = name.lastIndexOf('.'); + + return name.substring(dot + 1).toLowerCase(); + } + + @Inject + public void setActionMapper(ActionMapper mapper) { + this.actionMapper = mapper; + } + + /** + * Gets the OGNL value stack assoicated with this component. + * @return the OGNL value stack assoicated with this component. + */ + public ValueStack getStack() { + return stack; + } + + /** + * Gets the component stack of this component. + * @return the component stack of this component, never null. + */ + public Stack getComponentStack() { + Stack componentStack = (Stack) stack.getContext().get(COMPONENT_STACK); + if (componentStack == null) { + componentStack = new Stack(); + stack.getContext().put(COMPONENT_STACK, componentStack); + } + return componentStack; + } + + /** + * Callback for the start tag of this component. + * Should the body be evaluated? + * + * @param writer the output writer. + * @return true if the body should be evaluated + */ + public boolean start(Writer writer) { + return true; + } + + /** + * Callback for the end tag of this component. + * Should the body be evaluated again? + *

        + * NOTE: will pop component stack. + * @param writer the output writer. + * @param body the rendered body. + * @return true if the body should be evaluated again + */ + public boolean end(Writer writer, String body) { + return end(writer, body, true); + } + + /** + * Callback for the start tag of this component. + * Should the body be evaluated again? + *

        + * NOTE: has a parameter to determine to pop the component stack. + * @param writer the output writer. + * @param body the rendered body. + * @param popComponentStack should the component stack be popped? + * @return true if the body should be evaluated again + */ + protected boolean end(Writer writer, String body, boolean popComponentStack) { + assert(body != null); + + try { + writer.write(body); + } catch (IOException e) { + throw new StrutsException("IOError while writing the body: " + e.getMessage(), e); + } + if (popComponentStack) { + popComponentStack(); + } + return false; + } + + /** + * Pops the component stack. + */ + protected void popComponentStack() { + getComponentStack().pop(); + } + + /** + * Finds the nearest ancestor of this component stack. + * @param clazz the class to look for, or if assignable from. + * @return the component if found, null if not. + */ + protected Component findAncestor(Class clazz) { + Stack componentStack = getComponentStack(); + int currPosition = componentStack.search(this); + if (currPosition >= 0) { + int start = componentStack.size() - currPosition - 1; + + //for (int i = componentStack.size() - 2; i >= 0; i--) { + for (int i = start; i >=0; i--) { + Component component = (Component) componentStack.get(i); + if (clazz.isAssignableFrom(component.getClass()) && component != this) { + return component; + } + } + } + + return null; + } + + /** + * Evaluates the OGNL stack to find a String value. + * @param expr OGNL expression. + * @return the String value found. + */ + protected String findString(String expr) { + return (String) findValue(expr, String.class); + } + + /** + * Evaluates the OGNL stack to find a String value. + *

        + * If the given expression is null a error is logged and a RuntimeException is thrown + * constructed with a messaged based on the given field and errorMsg paramter. + * + * @param expr OGNL expression. + * @param field field name used when throwing RuntimeException. + * @param errorMsg error message used when throwing RuntimeException. + * @return the String value found. + * @throws StrutsException is thrown in case of expression is null. + */ + protected String findString(String expr, String field, String errorMsg) { + if (expr == null) { + throw fieldError(field, errorMsg, null); + } else { + return findString(expr); + } + } + + /** + * Constructs a RuntimeException based on the given information. + *

        + * A message is constructed and logged at ERROR level before being returned + * as a RuntimeException. + * @param field field name used when throwing RuntimeException. + * @param errorMsg error message used when throwing RuntimeException. + * @param e the caused exception, can be null. + * @return the constructed StrutsException. + */ + protected StrutsException fieldError(String field, String errorMsg, Exception e) { + String msg = "tag '" + getComponentName() + "', field '" + field + ( id != null ?"', id '" + id:"") + + ( parameters != null && parameters.containsKey("name")?"', name '" + parameters.get("name"):"") + + "': " + errorMsg; + throw new StrutsException(msg, e); + } + + /** + * Finds a value from the OGNL stack based on the given expression. + * Will always evaluate expr against stack except when expr + * is null. If altsyntax (%{...}) is applied, simply strip it off. + * + * @param expr the expression. Returns null if expr is null. + * @return the value, null if not found. + */ + protected Object findValue(String expr) { + if (expr == null) { + 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); + } + } + + return getStack().findValue(expr); + } + + /** + * Is the altSyntax enabled? [TRUE] + *

        + * See struts.properties where the altSyntax flag is defined. + */ + public boolean altSyntax() { + return ContextUtil.isUseAltSyntax(stack.getContext()); + } + + /** + * Evaluates the OGNL stack to find an Object value. + *

        + * Function just like findValue(String) except that if the + * given expression is null a error is logged and + * a RuntimeException is thrown constructed with a + * messaged based on the given field and errorMsg paramter. + * + * @param expr OGNL expression. + * @param field field name used when throwing RuntimeException. + * @param errorMsg error message used when throwing RuntimeException. + * @return the Object found, is never null. + * @throws StrutsException is thrown in case of not found in the OGNL stack, or expression is null. + */ + protected Object findValue(String expr, String field, String errorMsg) { + if (expr == null) { + throw fieldError(field, errorMsg, null); + } else { + Object value = null; + Exception problem = null; + try { + value = findValue(expr); + } catch (Exception e) { + problem = e; + } + + if (value == null) { + throw fieldError(field, errorMsg, problem); + } + + return value; + } + } + + /** + * Evaluates the OGNL stack to find an Object of the given type. Will evaluate + * expr the portion wrapped with altSyntax (%{...}) + * against stack when altSyntax is on, else the whole expr + * is evaluated against the stack. + *

        + * This method only supports the altSyntax. So this should be set to true. + * @param expr OGNL expression. + * @param toType the type expected to find. + * @return the Object found, or null if not found. + */ + protected Object findValue(String expr, Class toType) { + if (altSyntax() && toType == String.class) { + 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); + } + } + + return getStack().findValue(expr, toType); + } + } + + /** + * Renders an action URL by consulting the {@link org.apache.struts2.dispatcher.mapper.ActionMapper}. + * @param action the action + * @param namespace the namespace + * @param method the method + * @param req HTTP request + * @param res HTTP response + * @param parameters parameters + * @param scheme http or https + * @param includeContext should the context path be included or not + * @param encodeResult should the url be encoded + * @return the action url. + */ + @Deprecated + protected String determineActionURL(String action, String namespace, String method, + HttpServletRequest req, HttpServletResponse res, Map parameters, String scheme, + boolean includeContext, boolean encodeResult) { + return determineActionURL(action, namespace, method, req, res, parameters, scheme, includeContext, encodeResult, false, true); + } + + /** + * Renders an action URL by consulting the {@link org.apache.struts2.dispatcher.mapper.ActionMapper}. + * @param action the action + * @param namespace the namespace + * @param method the method + * @param req HTTP request + * @param res HTTP response + * @param parameters parameters + * @param scheme http or https + * @param includeContext should the context path be included or not + * @param encodeResult should the url be encoded + * @param forceAddSchemeHostAndPort should the scheme host and port be added to the url no matter what + * @param escapeAmp should the ampersands used separate parameters be escaped or not + * @return the action url. + */ + protected String determineActionURL(String action, String namespace, String method, + HttpServletRequest req, HttpServletResponse res, Map parameters, String scheme, + boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort, + boolean escapeAmp) { + String finalAction = findString(action); + String finalMethod = method != null ? findString(method) : method; + String finalNamespace = determineNamespace(namespace, getStack(), req); + ActionMapping mapping = new ActionMapping(finalAction, finalNamespace, finalMethod, parameters); + String uri = actionMapper.getUriFromActionMapping(mapping); + return UrlHelper.buildUrl(uri, req, res, parameters, scheme, includeContext, encodeResult, forceAddSchemeHostAndPort, escapeAmp); + } + + /** + * Determines the namespace of the current page being renderdd. Useful for Form, URL, and href generations. + * @param namespace the namespace + * @param stack OGNL value stack + * @param req HTTP request + * @return the namepsace of the current page being rendered, is never null. + */ + protected String determineNamespace(String namespace, ValueStack stack, HttpServletRequest req) { + String result; + + if (namespace == null) { + result = TagUtils.buildNamespace(actionMapper, stack, req); + } else { + result = findString(namespace); + } + + if (result == null) { + result = ""; + } + + return result; + } + + /** + * Pushes this component's parameter Map as well as the component itself on to the stack + * and then copies the supplied parameters over. Because the component's parameter Map is + * pushed before the component itself, any key-value pair that can't be assigned to componet + * will be set in the parameters Map. + * + * @param params the parameters to copy. + */ + public void copyParams(Map params) { + stack.push(parameters); + stack.push(this); + try { + for (Iterator iterator = params.entrySet().iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + String key = (String) entry.getKey(); + stack.setValue(key, entry.getValue()); + } + } finally { + stack.pop(); + stack.pop(); + } + } + + /** + * Constructs a string representation of the given exception. + * @param t the exception + * @return the exception as a string. + */ + protected String toString(Throwable t) { + FastByteArrayOutputStream bout = new FastByteArrayOutputStream(); + PrintWriter wrt = new PrintWriter(bout); + t.printStackTrace(wrt); + wrt.close(); + + return bout.toString(); + } + + /** + * Gets the parameters. + * @return the parameters. Is never null. + */ + public Map getParameters() { + return parameters; + } + + /** + * Adds all the given parameters to this component's own parameters. + * @param params the parameters to add. + */ + public void addAllParameters(Map params) { + parameters.putAll(params); + } + + /** + * Adds the given key and value to this component's own parameter. + *

        + * If the provided key is null nothing happens. + * If the provided value is null any existing parameter with + * the given key name is removed. + * @param key the key of the new parameter to add. + * @param value the value assoicated with the key. + */ + public void addParameter(String key, Object value) { + if (key != null) { + Map params = getParameters(); + + if (value == null) { + params.remove(key); + } else { + params.put(key, value); + } + } + } + + /** + * Gets the id for referencing element. + * @return the id for referencing element. + */ + public String getId() { + return id; + } + + @StrutsTagAttribute(description="id for referencing element. For UI and form tags it will be used as HTML id attribute") + public void setId(String id) { + if (id != null) { + this.id = findString(id); + } + } + + /** + * Overwrite to set if body shold be used. + * @return always false for this component. + */ + public boolean usesBody() { + return false; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Date.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Date.java new file mode 100644 index 000000000..f6dba3c63 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Date.java @@ -0,0 +1,374 @@ +/* + * $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.components; + +import java.io.IOException; +import java.io.Writer; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.TextProvider; +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + * Format Date object in different ways. + *

        + * The date tag will allow you to format a Date in a quick and easy way. + * You can specify a custom format (eg. "dd/MM/yyyy hh:mm"), you can generate + * easy readable notations (like "in 2 hours, 14 minutes"), or you can just fall back + * on a predefined format with key 'struts.date.format' in your properties file. + * + * If that key is not defined, it will finally fall back to the default DateFormat.MEDIUM + * formatting. + * + * Note: If the requested Date object isn't found on the stack, a blank will be returned. + *

        + * + * Configurable attributes are :- + *
          + *
        • name
        • + *
        • nice
        • + *
        • format
        • + *
        + * + *

        + * + * Following how the date component will work, depending on the value of nice attribute + * (which by default is false) and the format attribute. + * + *

        + * + * Condition 1: With nice attribute as true + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
        i18n keydefault
        struts.date.format.past{0} ago
        struts.date.format.futurein {0}
        struts.date.format.secondsan instant
        struts.date.format.minutes{0,choice,1#one minute|1<{0} minutes}
        struts.date.format.hours{0,choice,1#one hour|1<{0} hours}{1,choice,0#|1#, one minute|1<, {1} minutes}
        struts.date.format.days{0,choice,1#one day|1<{0} days}{1,choice,0#|1#, one hour|1<, {1} hours}
        struts.date.format.years{0,choice,1#one year|1<{0} years}{1,choice,0#|1#, one day|1<, {1} days}
        + * + *

        + * + * Condition 2: With nice attribute as false and format attribute is specified eg. dd/MM/yyyyy + *

        In this case the format attribute will be used.

        + * + *

        + * + * Condition 3: With nice attribute as false and no format attribute is specified + * + * + * + * + * + * + * + * + * + *
        i18n keydefault
        struts.date.formatif one is not found DateFormat.MEDIUM format will be used
        + * + * + * + * + *

        Examples + *

        + *  
        + *  <s:date name="person.birthday" format="dd/MM/yyyy" />
        + *  <s:date name="person.birthday" format="%{getText('some.i18n.key')}" />
        + *  <s:date name="person.birthday" nice="true" />
        + *  <s:date name="person.birthday" />
        + *  
        + * 
        + * + * Date + * + */ +@StrutsTag(name="date", tldBodyContent="empty", tldTagClass="org.apache.struts2.views.jsp.DateTag", description="Render a formatted date.") +public class Date extends Component { + + private static final Log LOG = LogFactory.getLog(Date.class); + /** + * Property name to fall back when no format is specified + */ + public static final String DATETAG_PROPERTY = "struts.date.format"; + /** + * Property name that defines the past notation (default: {0} ago) + */ + public static final String DATETAG_PROPERTY_PAST = "struts.date.format.past"; + private static final String DATETAG_DEFAULT_PAST = "{0} ago"; + /** + * Property name that defines the future notation (default: in {0}) + */ + public static final String DATETAG_PROPERTY_FUTURE = "struts.date.format.future"; + private static final String DATETAG_DEFAULT_FUTURE = "in {0}"; + /** + * Property name that defines the seconds notation (default: in instant) + */ + public static final String DATETAG_PROPERTY_SECONDS = "struts.date.format.seconds"; + private static final String DATETAG_DEFAULT_SECONDS = "an instant"; + /** + * Property name that defines the minutes notation (default: {0,choice,1#one minute|1<{0} minutes}) + */ + public static final String DATETAG_PROPERTY_MINUTES = "struts.date.format.minutes"; + private static final String DATETAG_DEFAULT_MINUTES = "{0,choice,1#one minute|1<{0} minutes}"; + /** + * Property name that defines the hours notation (default: {0,choice,1#one hour|1<{0} hours}{1,choice,0#|1#, one + * minute|1<, {1} minutes}) + */ + public static final String DATETAG_PROPERTY_HOURS = "struts.date.format.hours"; + private static final String DATETAG_DEFAULT_HOURS = "{0,choice,1#one hour|1<{0} hours}{1,choice,0#|1#, one minute|1<, {1} minutes}"; + /** + * Property name that defines the days notation (default: {0,choice,1#one day|1<{0} days}{1,choice,0#|1#, one hour|1<, + * {1} hours}) + */ + public static final String DATETAG_PROPERTY_DAYS = "struts.date.format.days"; + private static final String DATETAG_DEFAULT_DAYS = "{0,choice,1#one day|1<{0} days}{1,choice,0#|1#, one hour|1<, {1} hours}"; + /** + * Property name that defines the years notation (default: {0,choice,1#one year|1<{0} years}{1,choice,0#|1#, one + * day|1<, {1} days}) + */ + public static final String DATETAG_PROPERTY_YEARS = "struts.date.format.years"; + private static final String DATETAG_DEFAULT_YEARS = "{0,choice,1#one year|1<{0} years}{1,choice,0#|1#, one day|1<, {1} days}"; + + private String name; + + private String format; + + private boolean nice; + + public Date(ValueStack stack) { + super(stack); + } + + private TextProvider findProviderInStack() { + for (Iterator iterator = getStack().getRoot().iterator(); iterator + .hasNext();) { + Object o = iterator.next(); + + if (o instanceof TextProvider) { + return (TextProvider) o; + } + } + return null; + } + + /** + * Calculates the difference in time from now to the given date, and outputs it nicely.

        An example:
        Now = + * 2006/03/12 13:38:00, date = 2006/03/12 15:50:00 will output "in 1 hour, 12 minutes". + * + * @param tp text provider + * @param date the date + * @return the date nicely + */ + public String formatTime(TextProvider tp, java.util.Date date) { + java.util.Date now = new java.util.Date(); + StringBuffer sb = new StringBuffer(); + List args = new ArrayList(); + long secs = Math.abs((now.getTime() - date.getTime()) / 1000); + long mins = secs / 60; + long sec = secs % 60; + int min = (int) mins % 60; + long hours = mins / 60; + int hour = (int) hours % 24; + int days = (int) hours / 24; + int day = days % 365; + int years = days / 365; + + if (years > 0) { + args.add(new Long(years)); + args.add(new Long(day)); + args.add(sb); + args.add(null); + sb.append(tp.getText(DATETAG_PROPERTY_YEARS, DATETAG_DEFAULT_YEARS, args)); + } else if (day > 0) { + args.add(new Long(day)); + args.add(new Long(hour)); + args.add(sb); + args.add(null); + sb.append(tp.getText(DATETAG_PROPERTY_DAYS, DATETAG_DEFAULT_DAYS, args)); + } else if (hour > 0) { + args.add(new Long(hour)); + args.add(new Long(min)); + args.add(sb); + args.add(null); + sb.append(tp.getText(DATETAG_PROPERTY_HOURS, DATETAG_DEFAULT_HOURS, args)); + } else if (min > 0) { + args.add(new Long(min)); + args.add(new Long(sec)); + args.add(sb); + args.add(null); + sb.append(tp.getText(DATETAG_PROPERTY_MINUTES, DATETAG_DEFAULT_MINUTES, args)); + } else { + args.add(new Long(sec)); + args.add(sb); + args.add(null); + sb.append(tp.getText(DATETAG_PROPERTY_SECONDS, DATETAG_DEFAULT_SECONDS, args)); + } + + args.clear(); + args.add(sb.toString()); + if (date.before(now)) { + // looks like this date is passed + return tp.getText(DATETAG_PROPERTY_PAST, DATETAG_DEFAULT_PAST, args); + } else { + return tp.getText(DATETAG_PROPERTY_FUTURE, DATETAG_DEFAULT_FUTURE, args); + } + } + + public boolean end(Writer writer, String body) { + String msg = null; + ValueStack stack = getStack(); + java.util.Date date = null; + // find the name on the valueStack, and cast it to a date + try { + date = (java.util.Date) findValue(name); + } catch (Exception e) { + LOG.error("Could not convert object with key '" + name + + "' to a java.util.Date instance"); + // bad date, return a blank instead ? + msg = ""; + } + + //try to find the format on the stack + if (format != null) { + format = findString(format); + } + if (date != null) { + TextProvider tp = findProviderInStack(); + if (tp != null) { + if (nice) { + msg = formatTime(tp, date); + } else { + if (format == null) { + String globalFormat = null; + + // if the format is not specified, fall back using the + // defined property DATETAG_PROPERTY + globalFormat = tp.getText(DATETAG_PROPERTY); + + // if tp.getText can not find the property then the + // returned string is the same as input = + // DATETAG_PROPERTY + if (globalFormat != null + && !DATETAG_PROPERTY.equals(globalFormat)) { + msg = new SimpleDateFormat(globalFormat, + ActionContext.getContext().getLocale()) + .format(date); + } else { + msg = DateFormat.getDateTimeInstance( + DateFormat.MEDIUM, DateFormat.MEDIUM, + ActionContext.getContext().getLocale()) + .format(date); + } + } else { + msg = new SimpleDateFormat(format, ActionContext + .getContext().getLocale()).format(date); + } + } + if (msg != null) { + try { + if (getId() == null) { + writer.write(msg); + } else { + stack.getContext().put(getId(), msg); + } + } catch (IOException e) { + LOG.error("Could not write out Date tag", e); + } + } + } + } + return super.end(writer, ""); + } + + @StrutsTagAttribute(description="Date or DateTime format pattern", rtexprvalue=false) + public void setFormat(String format) { + this.format = format; + } + + @StrutsTagAttribute(description="Whether to print out the date nicely", type="Boolean", defaultValue="false") + public void setNice(boolean nice) { + this.nice = nice; + } + + /** + * @return Returns the name. + */ + public String getName() { + return name; + } + + @StrutsTagAttribute(description="The date value to format", required=true) + public void setName(String name) { + this.name = name; + } + + /** + * @return Returns the format. + */ + public String getFormat() { + return format; + } + + /** + * @return Returns the nice. + */ + public boolean isNice() { + return nice; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/DateTimePicker.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/DateTimePicker.java new file mode 100644 index 000000000..6e0af6c43 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/DateTimePicker.java @@ -0,0 +1,328 @@ +/* + * $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.components; + +import java.text.ParseException; +import java.text.MessageFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + *

        + * Renders a date/time picker in a dropdown container. + *

        + *

        + * A stand-alone DateTimePicker widget that makes it easy to select a date/time, or increment by week, month, + * and/or year. + *

        + * + *

        + * It is possible to customize the user-visible formatting with either the + * 'formatLength' (long, short, medium or full) or 'displayFormat' attributes. By defaulty current + * locale will be used.

        + *

        + * + * Syntax supported by 'displayFormat' is (http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns):- + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
        FormatDescription
        dDay of the month
        DDay of year
        MMonth - Use one or two for the numerical month, three for the abbreviation, or four for the full name, or 5 for the narrow name.
        hHour [1-12].
        HHour [0-23].
        mMinute. Use one or two for zero padding.
        sSecond. Use one or two for zero padding.
        + * + *

        + * The value sent to the server is + * typically a locale-independent value in a hidden field as defined by the name + * attribute. RFC3339 representation is the format used. + *

        + * + *

        + * + * + * + * Examples + * + *

        + * 
        + *
        + * Example 1:
        + *     <s:datetimepicker name="order.date" label="Order Date" />
        + * Example 2:
        + *     <s:datetimepicker name="delivery.date" label="Delivery Date" format="yyyy-MM-dd"  />
        + *
        + * 
        + * 
        + *

        + * + * + * + * The css could be changed by using the following :- + * + * + * + *

        + * 
        + *
        + * <s:datetimepicker name="birthday" label="Birthday" templateCss="...." />
        + *
        + * 
        + * 
        + * + */ +@StrutsTag(name="datetimepicker", tldTagClass="org.apache.struts2.views.jsp.ui.DateTimePickerTag", description="Render datetimepicker") +public class DateTimePicker extends UIBean { + + final public static String TEMPLATE = "datetimepicker"; +// Backported changes from s2 trunk (r657936) +// final private static SimpleDateFormat RFC3339_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + final private static String RFC3339_FORMAT = "yyyy-MM-dd'T'HH:mm:ss"; + final private static String RFC3339_PATTERN = "{0,date," + RFC3339_FORMAT + "}"; + final protected static Log LOG = LogFactory.getLog(DateTimePicker.class); + + protected String iconPath; + protected String formatLength; + protected String displayFormat; + protected String toggleType; + protected String toggleDuration; + protected String type; + + protected String displayWeeks; + protected String adjustWeeks; + protected String startDate; + protected String endDate; + protected String weekStartsOn; + protected String staticDisplay; + protected String dayWidth; + protected String language; + protected String templateCssPath; + + public DateTimePicker(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + public void evaluateParams() { + super.evaluateParams(); + + if(displayWeeks != null) + addParameter("displayWeeks", findString(displayWeeks)); + if(adjustWeeks != null) + addParameter("adjustWeeks", findValue(adjustWeeks, Boolean.class)); + if(startDate != null) + addParameter("startDate", findString(startDate)); + if(endDate != null) + addParameter("endDate", findString(endDate)); + if(weekStartsOn != null) + addParameter("weekStartsOn", findString(weekStartsOn)); + if(staticDisplay != null) + addParameter("staticDisplay", findValue(staticDisplay, Boolean.class)); + if(dayWidth != null) + addParameter("dayWidth", findValue(dayWidth, Integer.class)); + if(language != null) + addParameter("language", findString(language)); + if(value != null) + addParameter("value", findString(value)); + if(iconPath != null) + addParameter("iconPath", findString(iconPath)); + if(formatLength != null) + addParameter("formatLength", findString(formatLength)); + if(displayFormat != null) + addParameter("displayFormat", findString(displayFormat)); + if(toggleType != null) + addParameter("toggleType", findString(toggleType)); + if(toggleDuration != null) + addParameter("toggleDuration", findValue(toggleDuration, + Integer.class)); + if(type != null) + addParameter("type", findString(type)); + else + addParameter("type", "date"); + if(templateCssPath != null) + addParameter("templateCssPath", findString(templateCssPath)); + + // format the value to RFC 3399 + if(parameters.containsKey("value")) { + parameters.put("nameValue", format(parameters.get("value"))); + } else { + if(name != null) { + String expr = name; + if(altSyntax()) { + expr = "%{" + expr + "}"; + } + addParameter("nameValue", format(findValue(expr))); + } + } + } + + @StrutsTagAttribute(description="If true, weekly size of calendar changes to acomodate the month if false," + + " 42 day format is used", type="Boolean", defaultValue="false") + public void setAdjustWeeks(String adjustWeeks) { + this.adjustWeeks = adjustWeeks; + } + + @StrutsTagAttribute(description="How to render the names of the days in the header(narrow, abbr or wide)", defaultValue="narrow") + public void setDayWidth(String dayWidth) { + this.dayWidth = dayWidth; + } + + @StrutsTagAttribute(description="Total weeks to display", type="Integer", defaultValue="6") + public void setDisplayWeeks(String displayWeeks) { + this.displayWeeks = displayWeeks; + } + + @StrutsTagAttribute(description="Last available date in the calendar set", type="Date", defaultValue="2941-10-12") + public void setEndDate(String endDate) { + this.endDate = endDate; + } + + @StrutsTagAttribute(description="First available date in the calendar set", type="Date", defaultValue="1492-10-12") + public void setStartDate(String startDate) { + this.startDate = startDate; + } + + @StrutsTagAttribute(description="Disable all incremental controls, must pick a date in the current display", type="Boolean", defaultValue="false") + public void setStaticDisplay(String staticDisplay) { + this.staticDisplay = staticDisplay; + } + + @StrutsTagAttribute(description="Adjusts the first day of the week 0==Sunday..6==Saturday", type="Integer", defaultValue="0") + public void setWeekStartsOn(String weekStartsOn) { + this.weekStartsOn = weekStartsOn; + } + + @StrutsTagAttribute(description="Language to display this widget in", defaultValue="brower's specified preferred language") + public void setLanguage(String language) { + this.language = language; + } + + @StrutsTagAttribute(description="A pattern used for the visual display of the formatted date, e.g. dd/MM/yyyy") + public void setDisplayFormat(String displayFormat) { + this.displayFormat = displayFormat; + } + + @StrutsTagAttribute(description="Type of formatting used for visual display. Possible values are " + + "long, short, medium or full", defaultValue="short") + public void setFormatLength(String formatLength) { + this.formatLength = formatLength; + } + + @StrutsTagAttribute(description="Path to icon used for the dropdown") + public void setIconPath(String iconPath) { + this.iconPath = iconPath; + } + + @StrutsTagAttribute(description="Duration of toggle in milliseconds", type="Integer", defaultValue="100") + public void setToggleDuration(String toggleDuration) { + this.toggleDuration = toggleDuration; + } + + @StrutsTagAttribute(description="Defines the type of the picker on the dropdown. Possible values are 'date'" + + " for a DateTimePicker, and 'time' for a timePicker", defaultValue="date") + public void setType(String type) { + this.type = type; + } + + @StrutsTagAttribute(description="oggle type of the dropdown. Possible values are plain,wipe,explode,fade", defaultValue="plain") + public void setToggleType(String toggleType) { + this.toggleType = toggleType; + } + + @StrutsTagAttribute(description="Template css path") + public void setTemplateCssPath(String templateCssPath) { + this.templateCssPath = templateCssPath; + } + + private String format(Object obj) { + if(obj == null) + return null; + + if(obj instanceof Date) { + return MessageFormat.format(RFC3339_PATTERN, (Date) obj); + } else if(obj instanceof Calendar) { + return MessageFormat.format(RFC3339_PATTERN, ((Calendar) obj).getTime()); + } else { + // try to parse a date + String dateStr = obj.toString(); + if(dateStr.equalsIgnoreCase("today")) + return MessageFormat.format(RFC3339_PATTERN, new Date()); + + try { + Date date = null; + if(this.displayFormat != null) { + SimpleDateFormat format = new SimpleDateFormat( + (String) getParameters().get("displayFormat")); + date = format.parse(dateStr); + return MessageFormat.format(RFC3339_PATTERN, date); + } else { + // last resource to assume already in correct/default format + return dateStr; + } + } catch (ParseException e) { + LOG.error("Could not parse date", e); + return dateStr; + } + } + } + +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Debug.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Debug.java new file mode 100644 index 000000000..99492df39 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Debug.java @@ -0,0 +1,96 @@ +/* + * $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.components; + +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.util.OgnlUtil; + +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletRequest; +import java.io.Writer; +import java.util.Iterator; +import java.util.Map; +import java.util.ArrayList; +import java.util.List; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.StrutsException; + +@StrutsTag(name="debug", tldTagClass="org.apache.struts2.views.jsp.ui.DebugTag", + description="Prints debugging information") +public class Debug extends UIBean { + public static final String TEMPLATE = "debug"; + + public Debug(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + public boolean start(Writer writer) { + boolean result = super.start(writer); + + ValueStack stack = getStack(); + Iterator iter = stack.getRoot().iterator(); + List stackValues = new ArrayList(stack.getRoot().size()); + while (iter.hasNext()) { + Object o = iter.next(); + Map values; + try { + values = OgnlUtil.getBeanMap(o); + } catch (Exception e) { + throw new StrutsException("Caught an exception while getting the property values of " + o, e); + } + stackValues.add(new DebugMapEntry(o.getClass().getName(), values)); + } + + addParameter("stackValues", stackValues); + + return result; + } + + private class DebugMapEntry implements Map.Entry { + private Object key; + private Object value; + + DebugMapEntry(Object key, Object value) { + this.key = key; + this.value = value; + } + + public Object getKey() { + return key; + } + + public Object getValue() { + return value; + } + + public Object setValue(Object newVal) { + Object oldVal = value; + value = newVal; + return oldVal; + } + } + +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Div.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Div.java new file mode 100644 index 000000000..189e4b47d --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Div.java @@ -0,0 +1,193 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * The div tag when used on the ajax theme, provides a remote call + * from the current page to update a section of content without having to refresh the entire page. + *

        + * It creates a HTML <DIV /> that obtains it's content via a remote XMLHttpRequest call via + * the dojo framework. + *

        + *
        + * + * THE FOLLOWING IS ONLY VALID WHEN AJAX IS CONFIGURED + *
          + *
        • href
        • + *
        • errorText
        • + *
        • afterLoading
        • + *
        • executeScripts
        • + *
        • loadingText
        • + *
        • listenTopics
        • + *
        • handler
        • + *
        • formId
        • + *
        • formFilter
        • + *
        • targets
        • + *
        • notifyTopics
        • + *
        • showErrorTransportText
        • + *
        • indicator
        • + *
        + * 'targets' is a list of element ids whose content will be updated with the + * text returned from request.

        + * 'href' needs to be set as an url tag reference value.

        + * 'errorText' is the text that will be displayed when there is an error making the request.

        + * 'afterLoading' Deprecated. Use 'notifyTopics'.

        + * 'executeScripts' if set to true will execute javascript sections in the returned text.

        + * 'loadingText' is the text that will be displayed on the 'targets' elements while making the + * request.

        + * 'handler' is the name of the function that will take care of making the AJAX request. Dojo's widget + * and dom node are passed as parameters).

        + * 'formId' is the id of the html form whose fields will be seralized and passed as parameters + * in the request.

        + * 'formFilter' is the name of a function which will be used to filter the fields that will be + * seralized. This function takes as a parameter the element and returns true if the element + * should be included.

        + * 'updateFreq' sets(in milliseconds) the update interval.

        + * 'autoStart' if set to true(true by default) starts the timer automatically

        + * 'startTimerListenTopics' is a comma-separated list of topics used to start the timer

        + * 'stopTimerListenTopics' is a comma-separated list of topics used to stop the timer

        + * 'listenTopics' comma separated list of topics names, that will trigger a request

        + * 'indicator' element to be shown while the request executing

        + * 'showErrorTransportText': whether errors should be displayed (on 'targets')

        + * 'showLoadingText' show loading text on targets

        + * 'separateScript' Run scripts in a separate scope, unique for each Div

        + * 'notifyTopics' comma separated list of topics names, that will be published. Three parameters are passed:

        + *

          + *
        • data: html or json object when type='load' or type='error'
        • + *
        • type: 'before' before the request is made, 'load' when the request succeeds, or 'error' when it fails
        • + *
        • request: request javascript object, when type='load' or type='error'
        • + *
        + * + *

        Examples + * + *

        + *       
        + * <s:url id="url" action="AjaxTest" />
        + * <s:div
        + *    id="once"
        + *    theme="ajax"
        + *    href="%{url}"
        + *    loadingText="Loading..."
        + *    listenTopics="/refresh"
        + *    updateFreq="3000"
        + *    autoStart="true"
        + *    formId="form"
        + *></s:div>
        + *       
        + * 
        + *

        + * + */ +@StrutsTag(name="div", tldTagClass="org.apache.struts2.views.jsp.ui.DivTag", description="Render HTML div providing content from remote call via AJAX") +public class Div extends AbstractRemoteCallUIBean { + + public static final String TEMPLATE = "div"; + public static final String TEMPLATE_CLOSE = "div-close"; + public static final String COMPONENT_NAME = Div.class.getName(); + + protected String updateFreq; + protected String autoStart; + protected String delay; + protected String startTimerListenTopics; + protected String stopTimerListenTopics; + protected String refreshOnShow; + protected String separateScripts; + + public Div(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + public String getDefaultOpenTemplate() { + return TEMPLATE; + } + + protected String getDefaultTemplate() { + return TEMPLATE_CLOSE; + } + + public void evaluateExtraParams() { + super.evaluateExtraParams(); + + if (updateFreq != null) + addParameter("updateFreq", findValue(updateFreq, Integer.class)); + if (autoStart != null) + addParameter("autoStart", findValue(autoStart, Boolean.class)); + if (refreshOnShow != null) + addParameter("refreshOnShow", findValue(refreshOnShow, Boolean.class)); + if (delay != null) + addParameter("delay", findValue(delay, Integer.class)); + if (startTimerListenTopics != null) + addParameter("startTimerListenTopics", findString(startTimerListenTopics)); + if (stopTimerListenTopics != null) + addParameter("stopTimerListenTopics", findString(stopTimerListenTopics)); + if (separateScripts != null) + addParameter("separateScripts", findValue(separateScripts, Boolean.class)); + } + + @StrutsTagAttribute(description="Start timer automatically", type="Boolean", defaultValue="true") + public void setAutoStart(String autoStart) { + this.autoStart = autoStart; + } + + @StrutsTagAttribute(description="How long to wait before fetching the content (in milliseconds)", type="Integer") + public void setDelay(String delay) { + this.delay = delay; + } + + @StrutsTagAttribute(description="How often to reload the content (in milliseconds)", type="Integer") + public void setUpdateFreq(String updateInterval) { + this.updateFreq = updateInterval; + } + + @StrutsTagAttribute(description="Topics that will start the timer (for autoupdate)") + public void setStartTimerListenTopics(String startTimerListenTopic) { + this.startTimerListenTopics = startTimerListenTopic; + } + + @StrutsTagAttribute(description="Topics that will stop the timer (for autoupdate)") + public void setStopTimerListenTopics(String stopTimerListenTopic) { + this.stopTimerListenTopics = stopTimerListenTopic; + } + + @StrutsTagAttribute(description="Content will be loaded when div becomes visible, used only inside tabbedPanel", type="Boolean", defaultValue="false") + public void setRefreshOnShow(String refreshOnShow) { + this.refreshOnShow = refreshOnShow; + } + + @StrutsTagAttribute(description="Deprecated. Use 'notifyTopics'. Javascript code execute after reload") + public void setAfterLoading(String afterLoading) { + this.afterLoading = afterLoading; + } + + @StrutsTagAttribute(description="Run scripts in a separate scope, unique for each Div", defaultValue="true") + public void setSeparateScripts(String separateScripts) { + this.separateScripts = separateScripts; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/DoubleListUIBean.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/DoubleListUIBean.java new file mode 100644 index 000000000..ec5385ea0 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/DoubleListUIBean.java @@ -0,0 +1,568 @@ +/* + * $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.components; + +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * DoubleListUIBean is the standard superclass of all Struts double list handling components. + * + *

        + * + * + * + * Note that the doublelistkey and doublelistvalue attribute will default to "key" and "value" + * respectively only when the doublelist attribute is evaluated to a Map or its decendant. + * Other thing else, will result in doublelistkey and doublelistvalue to be null and not used. + * + * + * + */ +public abstract class DoubleListUIBean extends ListUIBean { + + protected String emptyOption; + protected String headerKey; + protected String headerValue; + protected String multiple; + protected String size; + + protected String doubleList; + protected String doubleListKey; + protected String doubleListValue; + protected String doubleName; + protected String doubleValue; + protected String formName; + + protected String doubleId; + protected String doubleDisabled; + protected String doubleMultiple; + protected String doubleSize; + protected String doubleHeaderKey; + protected String doubleHeaderValue; + protected String doubleEmptyOption; + + protected String doubleCssClass; + protected String doubleCssStyle; + + protected String doubleOnclick; + protected String doubleOndblclick; + protected String doubleOnmousedown; + protected String doubleOnmouseup; + protected String doubleOnmouseover; + protected String doubleOnmousemove; + protected String doubleOnmouseout; + protected String doubleOnfocus; + protected String doubleOnblur; + protected String doubleOnkeypress; + protected String doubleOnkeydown; + protected String doubleOnkeyup; + protected String doubleOnselect; + protected String doubleOnchange; + + protected String doubleAccesskey; + + + public DoubleListUIBean(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + public void evaluateExtraParams() { + super.evaluateExtraParams(); + + //Object doubleName = null; + + if (emptyOption != null) { + addParameter("emptyOption", findValue(emptyOption, Boolean.class)); + } + + if (multiple != null) { + addParameter("multiple", findValue(multiple, Boolean.class)); + } + + if (size != null) { + addParameter("size", findString(size)); + } + + if ((headerKey != null) && (headerValue != null)) { + addParameter("headerKey", findString(headerKey)); + addParameter("headerValue", findString(headerValue)); + } + + + if (doubleMultiple != null) { + addParameter("doubleMultiple", findValue(doubleMultiple, Boolean.class)); + } + + if (doubleSize != null) { + addParameter("doubleSize", findString(doubleSize)); + } + + if (doubleDisabled != null) { + addParameter("doubleDisabled", findValue(doubleDisabled, Boolean.class)); + } + + if (doubleName != null) { + addParameter("doubleName", findString(this.doubleName)); + } + + if (doubleList != null) { + addParameter("doubleList", doubleList); + } + + Object tmpDoubleList = findValue(doubleList); + if (doubleListKey != null) { + addParameter("doubleListKey", doubleListKey); + }else if (tmpDoubleList instanceof Map) { + addParameter("doubleListKey", "key"); + } + + 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); + } + } + + addParameter("doubleListValue", doubleListValue); + }else if (tmpDoubleList instanceof Map) { + addParameter("doubleListValue", "value"); + } + + + if (formName != null) { + addParameter("formName", findString(formName)); + } else { + // ok, let's look it up + Component form = findAncestor(Form.class); + if (form != null) { + addParameter("formName", form.getParameters().get("name")); + } + } + + Class valueClazz = getValueClassType(); + + if (valueClazz != null) { + if (doubleValue != null) { + addParameter("doubleNameValue", findValue(doubleValue, valueClazz)); + } else if (doubleName != null) { + addParameter("doubleNameValue", findValue(doubleName.toString(), valueClazz)); + } + } else { + if (doubleValue != null) { + addParameter("doubleNameValue", findValue(doubleValue)); + } else if (doubleName != null) { + addParameter("doubleNameValue", findValue(doubleName.toString())); + } + } + + 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); + } + } else if (form != null) { + addParameter("doubleId", form.getParameters().get("id") + "_" +escape(this.doubleName)); + } else { + addParameter("doubleId", escape(doubleName !=null ? findString(doubleName) : null)); + } + + if (doubleOnclick != null) { + addParameter("doubleOnclick", findString(doubleOnclick)); + } + + if (doubleOndblclick != null) { + addParameter("doubleOndblclick", findString(doubleOndblclick)); + } + + if (doubleOnmousedown != null) { + addParameter("doubleOnmousedown", findString(doubleOnmousedown)); + } + + if (doubleOnmouseup != null) { + addParameter("doubleOnmouseup", findString(doubleOnmouseup)); + } + + if (doubleOnmouseover != null) { + addParameter("doubleOnmouseover", findString(doubleOnmouseover)); + } + + if (doubleOnmousemove != null) { + addParameter("doubleOnmousemove", findString(doubleOnmousemove)); + } + + if (doubleOnmouseout != null) { + addParameter("doubleOnmouseout", findString(doubleOnmouseout)); + } + + if (doubleOnfocus != null) { + addParameter("doubleOnfocus", findString(doubleOnfocus)); + } + + if (doubleOnblur != null) { + addParameter("doubleOnblur", findString(doubleOnblur)); + } + + if (doubleOnkeypress != null) { + addParameter("doubleOnkeypress", findString(doubleOnkeypress)); + } + + if (doubleOnkeydown != null) { + addParameter("doubleOnkeydown", findString(doubleOnkeydown)); + } + + if (doubleOnselect != null) { + addParameter("doubleOnselect", findString(doubleOnselect)); + } + + if (doubleOnchange != null) { + addParameter("doubleOnchange", findString(doubleOnchange)); + } + + if (doubleCssClass != null) { + addParameter("doubleCss", findString(doubleCssClass)); + } + + if (doubleCssStyle != null) { + addParameter("doubleStyle", findString(doubleCssStyle)); + } + + if (doubleHeaderKey != null && doubleHeaderValue != null) { + addParameter("doubleHeaderKey", findString(doubleHeaderKey)); + addParameter("doubleHeaderValue", findString(doubleHeaderValue)); + } + + if (doubleEmptyOption != null) { + addParameter("doubleEmptyOption", findValue(doubleEmptyOption, Boolean.class)); + } + + if (doubleAccesskey != null) { + addParameter("doubleAccesskey", findString(doubleAccesskey)); + } + } + + @StrutsTagAttribute(description="The second iterable source to populate from.", required=true) + public void setDoubleList(String doubleList) { + this.doubleList = doubleList; + } + + @StrutsTagAttribute(description="The key expression to use for second list") + public void setDoubleListKey(String doubleListKey) { + this.doubleListKey = doubleListKey; + } + + @StrutsTagAttribute(description="The value expression to use for second list") + public void setDoubleListValue(String doubleListValue) { + this.doubleListValue = doubleListValue; + } + + @StrutsTagAttribute(description="The name for complete component", required=true) + public void setDoubleName(String doubleName) { + this.doubleName = doubleName; + } + + @StrutsTagAttribute(description="The value expression for complete component") + public void setDoubleValue(String doubleValue) { + this.doubleValue = doubleValue; + } + + @StrutsTagAttribute(description="The form name this component resides in and populates to") + public void setFormName(String formName) { + this.formName = formName; + } + + public String getFormName() { + return formName; + } + + @StrutsTagAttribute(description="The css class for the second list") + public void setDoubleCssClass(String doubleCssClass) { + this.doubleCssClass = doubleCssClass; + } + + public String getDoubleCssClass() { + return doubleCssClass; + } + + @StrutsTagAttribute(description="The css style for the second list") + public void setDoubleCssStyle(String doubleCssStyle) { + this.doubleCssStyle = doubleCssStyle; + } + + public String getDoubleCssStyle() { + return doubleCssStyle; + } + + @StrutsTagAttribute(description="The header key for the second list") + public void setDoubleHeaderKey(String doubleHeaderKey) { + this.doubleHeaderKey = doubleHeaderKey; + } + + public String getDoubleHeaderKey() { + return doubleHeaderKey; + } + + @StrutsTagAttribute(description="The header value for the second list") + public void setDoubleHeaderValue(String doubleHeaderValue) { + this.doubleHeaderValue = doubleHeaderValue; + } + + public String getDoubleHeaderValue() { + return doubleHeaderValue; + } + + @StrutsTagAttribute(description="Decides if the second list will add an empty option") + public void setDoubleEmptyOption(String doubleEmptyOption) { + this.doubleEmptyOption = doubleEmptyOption; + } + + public String getDoubleEmptyOption() { + return this.doubleEmptyOption; + } + + + public String getDoubleDisabled() { + return doubleDisabled; + } + + @StrutsTagAttribute(description="Decides if a disable attribute should be added to the second list") + public void setDoubleDisabled(String doubleDisabled) { + this.doubleDisabled = doubleDisabled; + } + + public String getDoubleId() { + return doubleId; + } + + @StrutsTagAttribute(description="The id of the second list") + public void setDoubleId(String doubleId) { + this.doubleId = doubleId; + } + + public String getDoubleMultiple() { + return doubleMultiple; + } + + @StrutsTagAttribute(description=" Decides if multiple attribute should be set on the second list") + public void setDoubleMultiple(String doubleMultiple) { + this.doubleMultiple = doubleMultiple; + } + + public String getDoubleOnblur() { + return doubleOnblur; + } + + @StrutsTagAttribute(description="Set the onblur attribute of the second list") + public void setDoubleOnblur(String doubleOnblur) { + this.doubleOnblur = doubleOnblur; + } + + public String getDoubleOnchange() { + return doubleOnchange; + } + + @StrutsTagAttribute(description="Set the onchange attribute of the second list") + public void setDoubleOnchange(String doubleOnchange) { + this.doubleOnchange = doubleOnchange; + } + + public String getDoubleOnclick() { + return doubleOnclick; + } + + @StrutsTagAttribute(description="Set the onclick attribute of the second list") + public void setDoubleOnclick(String doubleOnclick) { + this.doubleOnclick = doubleOnclick; + } + + public String getDoubleOndblclick() { + return doubleOndblclick; + } + + @StrutsTagAttribute(description="Set the ondbclick attribute of the second list") + public void setDoubleOndblclick(String doubleOndblclick) { + this.doubleOndblclick = doubleOndblclick; + } + + public String getDoubleOnfocus() { + return doubleOnfocus; + } + + @StrutsTagAttribute(description="Set the onfocus attribute of the second list") + public void setDoubleOnfocus(String doubleOnfocus) { + this.doubleOnfocus = doubleOnfocus; + } + + public String getDoubleOnkeydown() { + return doubleOnkeydown; + } + + @StrutsTagAttribute(description="Set the onkeydown attribute of the second list") + public void setDoubleOnkeydown(String doubleOnkeydown) { + this.doubleOnkeydown = doubleOnkeydown; + } + + public String getDoubleOnkeypress() { + return doubleOnkeypress; + } + + @StrutsTagAttribute(description="Set the onkeypress attribute of the second list") + public void setDoubleOnkeypress(String doubleOnkeypress) { + this.doubleOnkeypress = doubleOnkeypress; + } + + public String getDoubleOnkeyup() { + return doubleOnkeyup; + } + + @StrutsTagAttribute(description="Set the onkeyup attribute of the second list") + public void setDoubleOnkeyup(String doubleOnkeyup) { + this.doubleOnkeyup = doubleOnkeyup; + } + + public String getDoubleOnmousedown() { + return doubleOnmousedown; + } + + @StrutsTagAttribute(description="Set the onmousedown attribute of the second list") + public void setDoubleOnmousedown(String doubleOnmousedown) { + this.doubleOnmousedown = doubleOnmousedown; + } + + public String getDoubleOnmousemove() { + return doubleOnmousemove; + } + + @StrutsTagAttribute(description="Set the onmousemove attribute of the second list") + public void setDoubleOnmousemove(String doubleOnmousemove) { + this.doubleOnmousemove = doubleOnmousemove; + } + + public String getDoubleOnmouseout() { + return doubleOnmouseout; + } + + @StrutsTagAttribute(description="Set the onmouseout attribute of the second list") + public void setDoubleOnmouseout(String doubleOnmouseout) { + this.doubleOnmouseout = doubleOnmouseout; + } + + public String getDoubleOnmouseover() { + return doubleOnmouseover; + } + + @StrutsTagAttribute(description="Set the onmouseover attribute of the second list") + public void setDoubleOnmouseover(String doubleOnmouseover) { + this.doubleOnmouseover = doubleOnmouseover; + } + + public String getDoubleOnmouseup() { + return doubleOnmouseup; + } + + @StrutsTagAttribute(description="Set the onmouseup attribute of the second list") + public void setDoubleOnmouseup(String doubleOnmouseup) { + this.doubleOnmouseup = doubleOnmouseup; + } + + public String getDoubleOnselect() { + return doubleOnselect; + } + + @StrutsTagAttribute(description="Set the onselect attribute of the second list") + public void setDoubleOnselect(String doubleOnselect) { + this.doubleOnselect = doubleOnselect; + } + + public String getDoubleSize() { + return doubleSize; + } + + @StrutsTagAttribute(description="Set the size attribute of the second list") + public void setDoubleSize(String doubleSize) { + this.doubleSize = doubleSize; + } + + public String getDoubleList() { + return doubleList; + } + + public String getDoubleListKey() { + return doubleListKey; + } + + public String getDoubleListValue() { + return doubleListValue; + } + + public String getDoubleName() { + return doubleName; + } + + public String getDoubleValue() { + return doubleValue; + } + + @StrutsTagAttribute(description="Decides of an empty option is to be inserted in the second list", type="Boolean", defaultValue="false") + public void setEmptyOption(String emptyOption) { + this.emptyOption = emptyOption; + } + + @StrutsTagAttribute(description="Set the header key of the second list. Must not be empty! " + + "'-1' and '' is correct, '' is bad.") + public void setHeaderKey(String headerKey) { + this.headerKey = headerKey; + } + + @StrutsTagAttribute(description=" Set the header value of the second list") + public void setHeaderValue(String headerValue) { + this.headerValue = headerValue; + } + + @StrutsTagAttribute(description="Creates a multiple select. " + + "The tag will pre-select multiple values if the values are passed as an Array " + + "(of appropriate types) via the value attribute.") + public void setMultiple(String multiple) { + // TODO: Passing a Collection may work too? + this.multiple = multiple; + } + + @StrutsTagAttribute(description="Size of the element box (# of elements to show)", type="Integer") + public void setSize(String size) { + this.size = size; + } + + @StrutsTagAttribute(description="Set the html accesskey attribute.") + public void setDoubleAccesskey(String doubleAccesskey) { + this.doubleAccesskey = doubleAccesskey; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/DoubleSelect.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/DoubleSelect.java new file mode 100644 index 000000000..5d586cce5 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/DoubleSelect.java @@ -0,0 +1,65 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * Renders two HTML select elements with second one changing displayed values depending on selected entry of first one. + * + * + *

        Examples + * + *

        + * 
        + * <s:doubleselect label="doubleselect test1" name="menu" list="{'fruit','other'}" doubleName="dishes" doubleList="top == 'fruit' ? {'apple', 'orange'} : {'monkey', 'chicken'}" />
        + * <s:doubleselect label="doubleselect test2" name="menu" list="#{'fruit':'Nice Fruits', 'other':'Other Dishes'}" doubleName="dishes" doubleList="top == 'fruit' ? {'apple', 'orange'} : {'monkey', 'chicken'}" />
        + * 
        + * 
        + * + */ +@StrutsTag(name="doubleselect", tldTagClass="org.apache.struts2.views.jsp.ui.DoubleSelectTag", description="Renders two HTML select elements with second one changing displayed values depending on " + + "selected entry of first one.") +public class DoubleSelect extends DoubleListUIBean { + final public static String TEMPLATE = "doubleselect"; + + + public DoubleSelect(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + public void evaluateExtraParams() { + super.evaluateExtraParams(); + + // force the onchange parameter + addParameter("onchange", getParameters().get("id") + "Redirect(this.options.selectedIndex)"); + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Else.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Else.java new file mode 100644 index 000000000..6824a3f4d --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Else.java @@ -0,0 +1,74 @@ +/* + * $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.components; + +import java.io.Writer; +import java.util.Map; + +import org.apache.struts2.views.annotations.StrutsTag; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + *

        Perform basic condition flow. 'If' tag could be used by itself or with 'Else If' Tag and/or single/multiple 'Else' + * Tag.

        + * + * + * + * + * + * no params + * + * + * + * + *
        + * 
        + *  <s:if test="%{false}">
        + *      <div>Will Not Be Executed</div>
        + *  </s:if>
        + *  <s:elseif test="%{true}">
        + *      <div>Will Be Executed</div>
        + *  </s:elseif>
        + *  <s:else>
        + *      <div>Will Not Be Executed</div>
        + *  </s:else>
        + * 
        + * 
        + * + */ +@StrutsTag(name="else", tldTagClass="org.apache.struts2.views.jsp.ElseTag", description="Else tag") +public class Else extends Component { + public Else(ValueStack stack) { + super(stack); + } + + public boolean start(Writer writer) { + Map context = stack.getContext(); + Boolean ifResult = (Boolean) context.get(If.ANSWER); + + context.remove(If.ANSWER); + + return !((ifResult == null) || (ifResult.booleanValue())); + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ElseIf.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ElseIf.java new file mode 100644 index 000000000..2c9995ef4 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ElseIf.java @@ -0,0 +1,107 @@ +/* + * $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.components; + +import java.io.Writer; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + *

        Perform basic condition flow. 'If' tag could be used by itself or with 'Else If' Tag and/or single/multiple 'Else' + * Tag.

        + * + * + * + * + * + * + *
          + * + *
        • test* (Boolean) - Logic to determined if body of tag is to be displayed
        • + * + *
        + * + * + * + * + *
        + * 
        + *  <s:if test="%{false}">
        + *      <div>Will Not Be Executed</div>
        + *  </s:if>
        + *  <s:elseif test="%{true}">
        + *      <div>Will Be Executed</div>
        + *  </s:elseif>
        + *  <s:else>
        + *      <div>Will Not Be Executed</div>
        + *  </s:else>
        + * 
        + * 
        + * + */ +@StrutsTag(name="elseif", tldTagClass="org.apache.struts2.views.jsp.ElseIfTag", description="Elseif tag") +public class ElseIf extends Component { + public ElseIf(ValueStack stack) { + super(stack); + } + + protected Boolean answer; + protected String test; + + public boolean start(Writer writer) { + Boolean ifResult = (Boolean) stack.getContext().get(If.ANSWER); + + if ((ifResult == null) || (ifResult.booleanValue())) { + return false; + } + + //make the comparision + answer = (Boolean) findValue(test, Boolean.class); + + if (answer == null) { + answer = Boolean.FALSE; + } + if (answer.booleanValue()) { + stack.getContext().put(If.ANSWER, answer); + } + return answer != null && answer.booleanValue(); + } + + public boolean end(Writer writer, String body) { + if (answer == null) { + answer = Boolean.FALSE; + } + if (answer.booleanValue()) { + stack.getContext().put(If.ANSWER, answer); + } + return super.end(writer, ""); + } + + @StrutsTagAttribute(description="Expression to determine if body of tag is to be displayed", type="Boolean", required=true) + public void setTest(String test) { + this.test = test; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/FieldError.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/FieldError.java new file mode 100644 index 000000000..55bb4b4d3 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/FieldError.java @@ -0,0 +1,111 @@ +/* + * $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.components; + +import java.util.ArrayList; +import java.util.List; + +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; + +/** + * + * + * Render field errors if they exists. Specific layout depends on the particular theme. + * + * + * + *

        Examples + * + *

        + * 
        + *
        + *    <!-- example 1 -->
        + *    <s:fielderror />
        + *
        + *    <!-- example 2 -->
        + *    <s:fielderror>
        + *         <s:param>field1</s:param>
        + *         <s:param>field2</s:param>
        + *    </s:fielderror>
        + *    <s:form .... >
        + *       ....
        + *    </s:form>
        + *
        + *    OR
        + *
        + *    <s:fielderror>
        + *          <s:param value="%{'field1'}" />
        + *          <s:param value="%{'field2'}" />
        + *    </s:fielderror>
        + *    <s:form .... >
        + *       ....
        + *    </s:form>
        + *
        + * 
        + * 
        + * + * + *

        Description

        + * + * + *

        + * 
        + *
        + * Example 1: display all field errors

        + * Example 2: display field errors only for 'field1' and 'field2'

        + * + * + *

        + * + */ +@StrutsTag(name="fielderror", tldTagClass="org.apache.struts2.views.jsp.ui.FieldErrorTag", description="Render field error (all " + + "or partial depending on param tag nested)if they exists") +public class FieldError extends UIBean implements UnnamedParametric { + + private List errorFieldNames = new ArrayList(); + + public FieldError(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + private static final String TEMPLATE = "fielderror"; + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + public void addParameter(Object value) { + if (value != null) { + errorFieldNames.add(value.toString()); + } + } + + public List getFieldErrorFieldNames() { + return errorFieldNames; + } +} + diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/File.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/File.java new file mode 100644 index 000000000..0b020cf52 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/File.java @@ -0,0 +1,101 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * Renders an HTML file input element. + * + * + *

        Examples + * + *

        + * 
        + * <s:file name="anUploadFile" accept="text/*" />
        + * <s:file name="anohterUploadFIle" accept="text/html,text/plain" />
        + * 
        + * 
        + * + */ +@StrutsTag(name="file", tldTagClass="org.apache.struts2.views.jsp.ui.FileTag", description="Render a file input field") +public class File extends UIBean { + private final static Log log = LogFactory.getLog(File.class); + + final public static String TEMPLATE = "file"; + + protected String accept; + protected String size; + + public File(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + public void evaluateParams() { + super.evaluateParams(); + + Form form = (Form) findAncestor(Form.class); + if (form != null) { + String encType = (String) form.getParameters().get("enctype"); + if (!"multipart/form-data".equals(encType)) { + // uh oh, this isn't good! Let's warn the developer + log.warn("Struts has detected a file upload UI tag (s:file) being used without a form set to enctype 'multipart/form-data'. This is probably an error!"); + } + + String method = (String) form.getParameters().get("method"); + if (!"post".equalsIgnoreCase(method)) { + // uh oh, this isn't good! Let's warn the developer + log.warn("Struts has detected a file upload UI tag (s:file) being used without a form set to method 'POST'. This is probably an error!"); + } + } + + if (accept != null) { + addParameter("accept", findString(accept)); + } + + if (size != null) { + addParameter("size", findString(size)); + } + } + + @StrutsTagAttribute(description="HTML accept attribute to indicate accepted file mimetypes") + public void setAccept(String accept) { + this.accept = accept; + } + + @StrutsTagAttribute(description="HTML size attribute", required=false, type="Integer") + public void setSize(String size) { + this.size = size; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Form.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Form.java new file mode 100644 index 000000000..df24c7e30 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Form.java @@ -0,0 +1,494 @@ +/* + * $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.components; + +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ActionInvocation; +import com.opensymphony.xwork2.ObjectFactory; +import com.opensymphony.xwork2.config.Configuration; +import com.opensymphony.xwork2.config.RuntimeConfiguration; +import com.opensymphony.xwork2.config.entities.ActionConfig; +import com.opensymphony.xwork2.config.entities.InterceptorMapping; +import com.opensymphony.xwork2.inject.Inject; +import com.opensymphony.xwork2.interceptor.MethodFilterInterceptorUtil; +import com.opensymphony.xwork2.util.TextUtils; +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.validator.ActionValidatorManagerFactory; +import com.opensymphony.xwork2.validator.FieldValidator; +import com.opensymphony.xwork2.validator.ValidationInterceptor; +import com.opensymphony.xwork2.validator.Validator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.StrutsConstants; +import org.apache.struts2.dispatcher.Dispatcher; +import org.apache.struts2.dispatcher.mapper.ActionMapping; +import org.apache.struts2.portlet.context.PortletActionContext; +import org.apache.struts2.portlet.util.PortletUrlHelper; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.views.util.UrlHelper; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +/** + * + *

        + * Renders HTML an input form.

        + *

        + * The remote form allows the form to be submitted without the page being refreshed. The results from the form + * can be inserted into any HTML element on the page.

        + *

        + * NOTE:

        + * The order / logic in determining the posting url of the generated HTML form is as follows:- + *

          + *
        1. + * If the action attribute is not specified, then the current request will be used to + * determine the posting url + *
        2. + *
        3. + * If the action is given, Struts will try to obtain an ActionConfig. This will be + * successfull if the action attribute is a valid action alias defined struts.xml. + *
        4. + *
        5. + * If the action is given and is not an action alias defined in struts.xml, Struts + * will used the action attribute as if it is the posting url, separting the namespace + * from it and using UrlHelper to generate the final url. + *
        6. + *
        + *

        + * + *

        + *

        Examples + *

        + *

        + * 
        + * 

        + * <s:form ... /> + *

        + * + *

        + * + */ +@StrutsTag(name="form", tldTagClass="org.apache.struts2.views.jsp.ui.FormTag", description="Renders an input form") +public class Form extends ClosingUIBean { + /** + * Provide a logging instance. + */ + private static final Log LOG = LogFactory.getLog(Form.class); + + public static final String OPEN_TEMPLATE = "form"; + public static final String TEMPLATE = "form-close"; + + private int sequence = 0; + + protected String onsubmit; + protected String action; + protected String target; + protected String enctype; + protected String method; + protected String namespace; + protected String validate; + protected String portletMode; + protected String windowState; + protected String acceptcharset; + + protected boolean enableDynamicMethodInvocation = true; + protected Configuration configuration; + protected ObjectFactory objectFactory; + + public Form(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected boolean evaluateNameValue() { + return false; + } + + public String getDefaultOpenTemplate() { + return OPEN_TEMPLATE; + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + @Inject(StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION) + public void setEnableDynamicMethodInvocation(String enable) { + enableDynamicMethodInvocation = "true".equals(enable); + } + + @Inject + public void setConfiguration(Configuration configuration) { + this.configuration = configuration; + } + + @Inject + public void setObjectFactory(ObjectFactory objectFactory) { + this.objectFactory = objectFactory; + } + + + /* + * Revised for Portlet actionURL as form action, and add wwAction as hidden + * field. Refer to template.simple/form.vm + */ + protected void evaluateExtraParams() { + super.evaluateExtraParams(); + + //boolean isAjax = "ajax".equalsIgnoreCase(this.theme); + + if (validate != null) { + addParameter("validate", findValue(validate, Boolean.class)); + } + + // calculate the action and namespace + /*String action = null; + if (this.action != null) { + // if it isn't specified, we'll make somethig up + action = findString(this.action); + } + + if (Dispatcher.getInstance().isPortletSupportActive() && PortletActionContext.isPortletRequest()) { + evaluateExtraParamsPortletRequest(namespace, action); + } else { + String namespace = determineNamespace(this.namespace, getStack(), + request); + evaluateExtraParamsServletRequest(action, namespace, isAjax); + }*/ + + if (onsubmit != null) { + addParameter("onsubmit", findString(onsubmit)); + } + + if (target != null) { + addParameter("target", findString(target)); + } + + if (enctype != null) { + addParameter("enctype", findString(enctype)); + } + + if (method != null) { + addParameter("method", findString(method)); + } + + if (acceptcharset != null) { + addParameter("acceptcharset", findString(acceptcharset)); + } + + // keep a collection of the tag names for anything special the templates might want to do (such as pure client + // side validation) + if (!parameters.containsKey("tagNames")) { + // we have this if check so we don't do this twice (on open and close of the template) + addParameter("tagNames", new ArrayList()); + } + } + + /** + * The Form component determines its HTML element id as follows:- + *
          + *
        1. if an 'id' attribute is specified.
        2. + *
        3. if an 'action' attribute is specified, it will be used as the id.
        4. + *
        + */ + protected void populateComponentHtmlId(Form form) { + boolean isAjax = "ajax".equalsIgnoreCase(this.theme); + + String action = null; + if (this.action != null) { + // if it isn't specified, we'll make somethig up + action = findString(this.action); + } + + if (id != null) { + addParameter("id", escape(id)); + } + + // if no id given, it will be tried to generate it from the action attribute in the + // corresponding evaluateExtraParams method + if (Dispatcher.getInstance().isPortletSupportActive() && PortletActionContext.isPortletRequest()) { + evaluateExtraParamsPortletRequest(namespace, action); + } else { + String namespace = determineNamespace(this.namespace, getStack(), + request); + evaluateExtraParamsServletRequest(action, namespace, isAjax); + } + } + + /** + * @param isAjax + * @param namespace + * @param action + */ + private void evaluateExtraParamsServletRequest(String action, String namespace, boolean isAjax) { + if (action == null) { + // no action supplied? ok, then default to the current request (action or general URL) + ActionInvocation ai = (ActionInvocation) getStack().getContext().get(ActionContext.ACTION_INVOCATION); + if (ai != null) { + action = ai.getProxy().getActionName(); + namespace = ai.getProxy().getNamespace(); + } else { + // hmm, ok, we need to just assume the current URL cut down + String uri = request.getRequestURI(); + action = uri.substring(uri.lastIndexOf('/')); + } + } + + String actionMethod = ""; + // FIXME: our implementation is flawed - the only concept of ! should be in DefaultActionMapper + // handle "name!method" convention. + if (enableDynamicMethodInvocation) { + if (action.indexOf("!") != -1) { + int endIdx = action.lastIndexOf("!"); + actionMethod = action.substring(endIdx + 1, action.length()); + action = action.substring(0, endIdx); + } + } + + final ActionConfig actionConfig = configuration.getRuntimeConfiguration().getActionConfig(namespace, action); + String actionName = action; + if (actionConfig != null) { + + ActionMapping mapping = new ActionMapping(action, namespace, actionMethod, parameters); + String result = UrlHelper.buildUrl(actionMapper.getUriFromActionMapping(mapping), request, response, null); + addParameter("action", result); + + // let's try to get the actual action class and name + // this can be used for getting the list of validators + addParameter("actionName", actionName); + try { + Class clazz = objectFactory.getClassInstance(actionConfig.getClassName()); + addParameter("actionClass", clazz); + } catch (ClassNotFoundException e) { + // this is OK, we'll just move on + } + + addParameter("namespace", namespace); + + // if the name isn't specified, use the action name + if (name == null) { + addParameter("name", action); + } + + // if the id isn't specified, use the action name + if (id == null && action!=null) { + addParameter("id", escape(action)); + } + } else if (action != 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. + + // 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."); + } + + String result = UrlHelper.buildUrl(action, request, response, null); + addParameter("action", result); + + // namespace: cut out anything between the start and the last / + int slash = result.lastIndexOf('/'); + if (slash != -1) { + addParameter("namespace", result.substring(0, slash)); + } else { + addParameter("namespace", ""); + } + + // name/id: cut out anything between / and . should be the id and name + if (id == null) { + slash = result.lastIndexOf('/'); + int dot = result.indexOf('.', slash); + if (dot != -1) { + id = result.substring(slash + 1, dot); + } else { + id = result.substring(slash + 1); + } + addParameter("id", escape(id)); + } + } + + // WW-1284 + // evaluate if client-side js is to be enabled. (if validation interceptor + // does allow validation eg. method is not filtered out) + evaluateClientSideJsEnablement(actionName, namespace, actionMethod); + } + + private void evaluateClientSideJsEnablement(String actionName, String namespace, String actionMethod) { + + // Only evaluate if Client-Side js is to be enable when validate=true + Boolean validate = (Boolean) getParameters().get("validate"); + if (validate != null && validate) { + + addParameter("performValidation", Boolean.FALSE); + + RuntimeConfiguration runtimeConfiguration = configuration.getRuntimeConfiguration(); + ActionConfig actionConfig = runtimeConfiguration.getActionConfig(namespace, actionName); + + if (actionConfig != null) { + List interceptors = actionConfig.getInterceptors(); + for (InterceptorMapping interceptorMapping : interceptors) { + if (ValidationInterceptor.class.isInstance(interceptorMapping.getInterceptor())) { + ValidationInterceptor validationInterceptor = (ValidationInterceptor) interceptorMapping.getInterceptor(); + + Set excludeMethods = validationInterceptor.getExcludeMethodsSet(); + Set includeMethods = validationInterceptor.getIncludeMethodsSet(); + + if (MethodFilterInterceptorUtil.applyMethod(excludeMethods, includeMethods, actionMethod)) { + addParameter("performValidation", Boolean.TRUE); + } + return; + } + } + } + } + } + + /** + * Constructs the action url adapted to a portal environment. + * + * @param action The action to create the URL for. + */ + private void evaluateExtraParamsPortletRequest(String namespace, String action) { + + String type = "action"; + if (TextUtils.stringSet(method)) { + if ("GET".equalsIgnoreCase(method.trim())) { + type = "render"; + } + } + if (action != null) { + String result = PortletUrlHelper.buildUrl(action, namespace, null, + getParameters(), type, portletMode, windowState); + addParameter("action", result); + + // namespace: cut out anything between the start and the last / + int slash = result.lastIndexOf('/'); + if (slash != -1) { + addParameter("namespace", result.substring(0, slash)); + } else { + addParameter("namespace", ""); + } + + // name/id: cut out anything between / and . should be the id and + // name + if (id == null) { + slash = action.lastIndexOf('/'); + int dot = action.indexOf('.', slash); + if (dot != -1) { + id = action.substring(slash + 1, dot); + } else { + id = action.substring(slash + 1); + } + addParameter("id", escape(id)); + } + } + + } + + public List getValidators(String name) { + Class actionClass = (Class) getParameters().get("actionClass"); + if (actionClass == null) { + return Collections.EMPTY_LIST; + } + + List all = ActionValidatorManagerFactory.getInstance().getValidators(actionClass, (String) getParameters().get("actionName")); + List validators = new ArrayList(); + for (Validator validator : all) { + if (validator instanceof FieldValidator) { + FieldValidator fieldValidator = (FieldValidator) validator; + if (fieldValidator.getFieldName().equals(name)) { + validators.add(fieldValidator); + } + } + } + + return validators; + } + + /** + * Get a incrementing sequence unique to this Form component. + * It is used by Form component's child that might need a + * sequence to make them unique. + * + * @return int + */ + protected int getSequence() { + return sequence++; + } + + @StrutsTagAttribute(description="HTML onsubmit attribute") + public void setOnsubmit(String onsubmit) { + this.onsubmit = onsubmit; + } + + @StrutsTagAttribute(description="Set action name to submit to, without .action suffix", defaultValue="current action") + public void setAction(String action) { + this.action = action; + } + + @StrutsTagAttribute(description="HTML form target attribute") + public void setTarget(String target) { + this.target = target; + } + + @StrutsTagAttribute(description="HTML form enctype attribute") + public void setEnctype(String enctype) { + this.enctype = enctype; + } + + @StrutsTagAttribute(description="HTML form method attribute") + public void setMethod(String method) { + this.method = method; + } + + @StrutsTagAttribute(description="Namespace for action to submit to", defaultValue="current namespace") + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + @StrutsTagAttribute(description="Whether client side/remote validation should be performed. Only" + + " useful with theme xhtml/ajax", type="Boolean", defaultValue="false") + public void setValidate(String validate) { + this.validate = validate; + } + + @StrutsTagAttribute(description="The portlet mode to display after the form submit") + public void setPortletMode(String portletMode) { + this.portletMode = portletMode; + } + + @StrutsTagAttribute(description="The window state to display after the form submit") + public void setWindowState(String windowState) { + this.windowState = windowState; + } + + @StrutsTagAttribute(description="The accepted charsets for this form. The values may be comma or blank delimited.") + public void setAcceptcharset(String acceptcharset) { + this.acceptcharset = acceptcharset; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/FormButton.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/FormButton.java new file mode 100644 index 000000000..865ec230a --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/FormButton.java @@ -0,0 +1,164 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * FormButton. + */ +public abstract class FormButton extends UIBean { + + static final String BUTTONTYPE_INPUT = "input"; + static final String BUTTONTYPE_BUTTON = "button"; + static final String BUTTONTYPE_IMAGE = "image"; + + protected String action; + protected String method; + protected String align; + protected String type; + + public FormButton(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + //public void evaluateParams() { + public void evaluateExtraParams() { + super.evaluateExtraParams(); + if (align == null) { + align = "right"; + } + + String submitType = BUTTONTYPE_INPUT; + if (type != null && (BUTTONTYPE_BUTTON.equalsIgnoreCase(type) || (supportsImageType() && BUTTONTYPE_IMAGE.equalsIgnoreCase(type)))) + { + submitType = type; + } + + //super.evaluateParams(); + + addParameter("type", submitType); + + if (!BUTTONTYPE_INPUT.equals(submitType) && (label == null)) { + addParameter("label", getParameters().get("nameValue")); + } + + if (action != null || method != null) { + String name; + + if (action != null) { + name = "action:" + findString(action); + + if (method != null) { + name += "!" + findString(method); + } + } else { + name = "method:" + findString(method); + } + + addParameter("name", name); + } + + addParameter("align", findString(align)); + + } + + /** + * Override UIBean's implementation, such that component Html id is determined + * in the following order :- + *
          + *
        1. This component id attribute
        2. + *
        3. [containing_form_id]_[this_component_name]
        4. + *
        5. [containing_form_id]_[this_component_action]_[this_component_method]
        6. + *
        7. [containing_form_id]_[this_component_method]
        8. + *
        9. [this_component_name]
        10. + *
        11. [this_component_action]_[this_component_method]
        12. + *
        13. [this_component_method]
        14. + *
        15. [an increasing sequential number unique to the form starting with 0]
        16. + *
        + */ + protected void populateComponentHtmlId(Form form) { + 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; + } + } + else { + if (form != null && form.getParameters().get("id") != null) { + _tmp_id = _tmp_id + form.getParameters().get("id").toString() + "_"; + } + if (name != null) { + _tmp_id = _tmp_id + escape(name); + } else if (action != null || method != null){ + if (action != null) { + _tmp_id = _tmp_id + escape(action); + } + if (method != null) { + _tmp_id = _tmp_id + "_" + escape(method); + } + } else { + // if form is null, this component is used, without a form, i guess + // there's not much we could do then. + if (form != null) { + _tmp_id = _tmp_id + form.getSequence(); + } + } + } + addParameter("id", _tmp_id); + } + + /** + * Indicate whether the concrete button supports the type "image". + * + * @return true if type image is supported. + */ + protected abstract boolean supportsImageType(); + + @StrutsTagAttribute(description="Set action attribute.") + public void setAction(String action) { + this.action = action; + } + + @StrutsTagAttribute(description="Set method attribute.") + public void setMethod(String method) { + this.method = method; + } + + @StrutsTagAttribute(description="HTML align attribute.") + public void setAlign(String align) { + this.align = align; + } + + @StrutsTagAttribute(description="The type of submit to use. Valid values are input, " + + "button and image.", defaultValue="input") + public void setType(String type) { + this.type = type; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/GenericUIBean.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/GenericUIBean.java new file mode 100644 index 000000000..a1d631fb9 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/GenericUIBean.java @@ -0,0 +1,128 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.util.ContainUtil; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + * Renders an custom UI widget using the specified templates. Additional objects can be passed in to the template + * using the param tags.

        + * + * Freemarker:

        + * Objects provided can be retrieve from within the template via $parameters._paramname_.

        + * + * Jsp:

        + * Objects provided can be retrieve from within the template via <s:property value="%{parameters._paramname_}" />

        + * + * + * In the bottom JSP and Velocity samples, two parameters are being passed in to the component. From within the + * component, they can be accessed as:-

        + * + * Freemarker:

        + * $parameters.get('key1') and $parameters.get('key2') or $parameters.key1 and $parameters.key2

        + * + * Jsp:

        + * <s:property value="%{parameters.key1}" /> and <s:property value="%{'parameters.key2'}" /> or + * <s:property value="%{parameters.get('key1')}" /> and <s:property value="%{parameters.get('key2')}" />

        + * + * Currently, your custom UI components can be written in Velocity, JSP, or Freemarker, and the correct rendering + * engine will be found based on file extension.

        + * + * Remember: the value params will always be resolved against the ValueStack so if you mean to pass a + * string literal to your component, make sure to wrap it in quotes i.e. value="'value1'" otherwise, the the value + * stack will search for an Object on the stack with a method of getValue1(). (now that i've written this, i'm not + * entirely sure this is the case. i should verify this manana)

        + * + * + * + *

        Examples + * + *

        + * 
        + * JSP
        + *     <s:component template="/my/custom/component.vm"/>
        + *
        + *       or
        + *
        + *     <s:component template="/my/custom/component.vm">
        + *       <s:param name="key1" value="value1"/>
        + *       <s:param name="key2" value="value2"/>
        + *     </s:component>
        + *
        + * Velocity
        + *     #s-component( "template=/my/custom/component.vm" )
        + *
        + *       or
        + *
        + *     #s-component( "template=/my/custom/component.vm" )
        + *       #s-param( "name=key1" "value=value1" )
        + *       #s-param( "name=key2" "value=value2" )
        + *     #end
        + *
        + * Freemarker
        + *    <@s..component template="/my/custom/component.ftl" />
        + *
        + *      or
        + *
        + *    <@s..component template="/my/custom/component.ftl">
        + *       <@s..param name="key1" value="%{'value1'}" />
        + *       <@s..param name="key2" value="%{'value2'}" />
        + *    </@s..component>
        + *
        + * 
        + * 
        + * + *

        + * + * NOTE: + * + * + * If Jsp is used as the template, the jsp template itself must lie within the + * webapp itself and not the classpath. Unlike Freemarker or Velocity, JSP template + * could not be picked up from the classpath. + * + * + * + */ +@StrutsTag(name="component", tldTagClass="org.apache.struts2.views.jsp.ui.ComponentTag", description="Render a custom ui widget") +public class GenericUIBean extends UIBean { + private final static String TEMPLATE = "empty"; + + public GenericUIBean(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + public boolean contains(Object obj1, Object obj2) { + return ContainUtil.contains(obj1, obj2); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Head.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Head.java new file mode 100644 index 000000000..830481c6f --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Head.java @@ -0,0 +1,140 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.StrutsConstants; + +import com.opensymphony.xwork2.inject.Inject; +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + * Renders parts of the HEAD section for an HTML file. This is useful as some themes require certain CSS and JavaScript + * includes.

        + * + * If, for example, your page has ajax components integrated, without having the default theme set to ajax, you might + * want to use the head tag with theme="ajax" so that the typical ajax header setup will be included in the + * page.

        + * + * The tag also includes the option to set a custom datepicker theme if needed. See calendarcss parameter for + * description for details.

        + * + * If you use the ajax theme you can turn a debug flag on by setting the debug parameter to true. + * + * + * + *

        Examples + * + *

        + * 
        + * <head>
        + *   <title>My page</title>
        + *   <s:head/>
        + * </head>
        + * 
        + * 
        + * + *
        + * 
        + * <head>
        + *   <title>My page</title>
        + *   <s:head theme="ajax" calendarcss="calendar-green"/>
        + * </head>
        + * 
        + * 
        + * + *
        + * 
        + * <head>
        + *   <title>My page</title>
        + *   <s:head theme="ajax" debug="true"/>
        + * </head>
        + * 
        + * 
        + * + */ +@StrutsTag(name="head", tldBodyContent="empty", tldTagClass="org.apache.struts2.views.jsp.ui.HeadTag", + description="Render a chunk of HEAD for your HTML file") +public class Head extends UIBean { + public static final String TEMPLATE = "head"; + + private String calendarcss = "calendar-blue.css"; + private boolean debug; + private String encoding; + + public Head(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + @Inject(StrutsConstants.STRUTS_I18N_ENCODING) + public void setEncoding(String encoding) { + this.encoding = encoding; + } + + public void evaluateParams() { + super.evaluateParams(); + + if (calendarcss != null) { + String css = findString(calendarcss); + if (css != null && css.trim().length() > 0) { + if (css.lastIndexOf(".css") < 0) { + addParameter("calendarcss", css + ".css"); + } else { + addParameter("calendarcss", css); + } + } + } + + addParameter("encoding", encoding); + addParameter("debug", Boolean.valueOf(debug).toString()); + } + + public String getCalendarcss() { + return calendarcss; + } + + @StrutsTagAttribute(description="The jscalendar css theme to use", defaultValue="calendar-blue.css") + public void setCalendarcss(String calendarcss) { + //TODO remove this one + this.calendarcss = calendarcss; + } + + public boolean isDebug() { + return debug; + } + + @StrutsTagAttribute(description="Set to true to enable debugging mode for AJAX themes") + public void setDebug(boolean debug) { + this.debug = debug; + } + + +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Hidden.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Hidden.java new file mode 100644 index 000000000..092f5e32d --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Hidden.java @@ -0,0 +1,63 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * Renders an HTML input element of type hidden, populated by the specified property from the ValueStack. + * + * + *

        Examples + * + *

        + * 
        + * <-- example one -->
        + * <s:hidden name="foo" />
        + * <-- example two -->
        + * <s:hidden name="foo" value="bar" />
        + *
        + * Example One Resulting HTML (if foo evaluates to bar):
        + * <input type="hidden" name="foo" value="bar" />
        + * Example Two Resulting HTML (if getBar method of the action returns 'bar')
        + * <input type="hidden" name="foo" value="bar" />
        + * 
        + * 
        + * + */ +@StrutsTag(name="hidden", tldTagClass="org.apache.struts2.views.jsp.ui.HiddenTag", description="Render a hidden input field") +public class Hidden extends UIBean { + final public static String TEMPLATE = "hidden"; + + public Hidden(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/I18n.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/I18n.java new file mode 100644 index 000000000..f89995389 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/I18n.java @@ -0,0 +1,134 @@ +/* + * $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.components; + +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.LocaleProvider; +import com.opensymphony.xwork2.TextProviderFactory; +import com.opensymphony.xwork2.util.LocalizedTextUtil; +import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.StrutsException; +import org.apache.struts2.dispatcher.Dispatcher; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import java.io.Writer; +import java.util.Locale; +import java.util.ResourceBundle; + +/** + * + * + * Gets a resource bundle and place it on the value stack. This allows + * the text tag to access messages from any bundle, and not just the bundle + * associated with the current action. + * + * + * + *

        + * + * + * + *

          + *
        • name* - the resource bundle's name (eg foo/bar/customBundle)
        • + *
        + * + * + * + *

        + * + * Example: + * + *

        + * 
        + *
        + * <s:i18n name="myCustomBundle">
        + *    The i18n value for key aaa.bbb.ccc in myCustomBundle is <s:property value="text('aaa.bbb.ccc')" />
        + * </s:i18n>
        + *
        + * 
        + * 
        + * + * + *
        + * 
        + *
        + * <s:i18n name="some.package.bundle" >
        + *      <s:text name="some.key" />
        + * </s:i18n>
        + *
        + * 
        + * 
        + * + */ +@StrutsTag(name="i18n", tldTagClass="org.apache.struts2.views.jsp.I18nTag", description="Get a resource bundle" + + " and place it on the value stack") +public class I18n extends Component { + protected boolean pushed; + protected String name; + + public I18n(ValueStack stack) { + super(stack); + } + + public boolean start(Writer writer) { + boolean result = super.start(writer); + + try { + String name = this.findString(this.name, "name", "Resource bundle name is required. Example: foo or foo_en"); + ResourceBundle bundle = (ResourceBundle) findValue("texts('" + name + "')"); + + if (bundle == null) { + bundle = LocalizedTextUtil.findResourceBundle(name, (Locale) getStack().getContext().get(ActionContext.LOCALE)); + } + + if (bundle != null) { + final Locale locale = (Locale) getStack().getContext().get(ActionContext.LOCALE); + TextProviderFactory tpf = new TextProviderFactory(); + Dispatcher.getInstance().getContainer().inject(tpf); + getStack().push(tpf.createInstance(bundle, new LocaleProvider() { + public Locale getLocale() { + return locale; + } + })); + pushed = true; + } + } catch (Exception e) { + String msg = "Could not find the bundle " + name; + throw new StrutsException(msg, e); + } + + return result; + } + + public boolean end(Writer writer, String body) { + if (pushed) { + getStack().pop(); + } + + return super.end(writer, body); + } + + @StrutsTagAttribute(description="Name of ressource bundle to use (eg foo/bar/customBundle)", required=true, defaultValue="String") + public void setName(String name) { + this.name = name; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/If.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/If.java new file mode 100644 index 000000000..4c3cfc43d --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/If.java @@ -0,0 +1,98 @@ +/* + * $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.components; + +import java.io.Writer; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + *

        Perform basic condition flow. 'If' tag could be used by itself or + * with 'Else If' Tag and/or single/multiple 'Else' Tag.

        + * + * + * + * + * + * + *
          + * + *
        • test* (Boolean) - Logic to determined if body of tag is to be displayed
        • + * + *
        + * + * + * + * + *
        + * 
        + *  <s:if test="%{false}">
        + *      <div>Will Not Be Executed</div>
        + *  </s:if>
        + *  <s:elseif test="%{true}">
        + *      <div>Will Be Executed</div>
        + *  </s:elseif>
        + *  <s:else>
        + *      <div>Will Not Be Executed</div>
        + *  </s:else>
        + * 
        + * 
        + * + * @see Else + * @see ElseIf + * + */ +@StrutsTag(name="if", tldTagClass="org.apache.struts2.views.jsp.IfTag", description="If tag") +public class If extends Component { + public static final String ANSWER = "struts.if.answer"; + + Boolean answer; + String test; + + @StrutsTagAttribute(description="Expression to determine if body of tag is to be displayed", type="Boolean", required=true) + public void setTest(String test) { + this.test = test; + } + + public If(ValueStack stack) { + super(stack); + } + + public boolean start(Writer writer) { + answer = (Boolean) findValue(test, Boolean.class); + + if (answer == null) { + answer = Boolean.FALSE; + } + stack.getContext().put(ANSWER, answer); + return answer.booleanValue(); + } + + public boolean end(Writer writer, String body) { + stack.getContext().put(ANSWER, answer); + return super.end(writer, body); + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Include.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Include.java new file mode 100644 index 000000000..bcb6a2231 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Include.java @@ -0,0 +1,411 @@ +/* + * $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.components; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.Writer; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import java.util.StringTokenizer; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.RequestUtils; +import org.apache.struts2.StrutsConstants; +import org.apache.struts2.util.FastByteArrayOutputStream; + +import com.opensymphony.xwork2.inject.Inject; +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + *

        Include a servlet's output (result of servlet or a JSP page).

        + *

        Note: Any additional params supplied to the included page are not accessible within the rendered page + * through the <s:property...> tag!

        + * + * + * + * + *
          + *
        • value* (String) - jsp page to be included
        • + *
        + * + * + * + *

        Examples + *

        + * 
        + * <-- One: -->
        + * <s:include value="myJsp.jsp" />
        + *
        + * <-- Two: -->
        + * <s:include value="myJsp.jsp">
        + *    <s:param name="param1" value="value2" />
        + *    <s:param name="param2" value="value2" />
        + * </s:include>
        + *
        + * <-- Three: -->
        + * <s:include value="myJsp.jsp">
        + *    <s:param name="param1">value1</s:param>
        + *    <s:param name="param2">value2<s:param>
        + * </s:include>
        + * 
        + *
        + * 
        + * Example one - do an include myJsp.jsp page
        + * Example two - do an include to myJsp.jsp page with parameters param1=value1 and param2=value2
        + * Example three - do an include to myJsp.jsp page with parameters param1=value1 and param2=value2
        + * 
        + * 
        + * + */ +@StrutsTag(name="include", tldTagClass="org.apache.struts2.views.jsp.IncludeTag", description="Include a servlet's output " + + "(result of servlet or a JSP page)") +public class Include extends Component { + + private static final Log _log = LogFactory.getLog(Include.class); + + private static String encoding; + private static boolean encodingDefined = true; + + protected String value; + private HttpServletRequest req; + private HttpServletResponse res; + private static String defaultEncoding; + + public Include(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { + super(stack); + this.req = req; + this.res = res; + } + + @Inject(StrutsConstants.STRUTS_I18N_ENCODING) + public static void setDefaultEncoding(String encoding) { + defaultEncoding = encoding; + } + + 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(); + + // Add URL + urlBuf.append(page); + + // Add request parameters + if (parameters.size() > 0) { + urlBuf.append('?'); + + String concat = ""; + + // Set parameters + Iterator iter = parameters.entrySet().iterator(); + + while (iter.hasNext()) { + Map.Entry entry = (Map.Entry) iter.next(); + Object name = entry.getKey(); + List values = (List) entry.getValue(); + + for (int i = 0; i < values.size(); i++) { + urlBuf.append(concat); + urlBuf.append(name); + urlBuf.append('='); + + try { + urlBuf.append(URLEncoder.encode(values.get(i).toString(), "UTF-8")); + } catch (Exception e) { + _log.warn("unable to url-encode "+values.get(i).toString()+", it will be ignored"); + } + + concat = "&"; + } + } + } + + String result = urlBuf.toString(); + + // Include + try { + include(result, writer, req, res); + } catch (Exception e) { + LogFactory.getLog(getClass()).warn("Exception thrown during include of " + result, e); + } + + return super.end(writer, body); + } + + @StrutsTagAttribute(description="The jsp/servlet output to include", required=true) + public void setValue(String value) { + this.value = value; + } + + public static String getContextRelativePath(ServletRequest request, String relativePath) { + String returnValue; + + if (relativePath.startsWith("/")) { + returnValue = relativePath; + } else if (!(request instanceof HttpServletRequest)) { + returnValue = relativePath; + } else { + HttpServletRequest hrequest = (HttpServletRequest) request; + String uri = (String) request.getAttribute("javax.servlet.include.servlet_path"); + + if (uri == null) { + uri = RequestUtils.getServletPath(hrequest); + } + + returnValue = uri.substring(0, uri.lastIndexOf('/')) + '/' + relativePath; + } + + // .. is illegal in an absolute path according to the Servlet Spec and will cause + // known problems on Orion application servers. + if (returnValue.indexOf("..") != -1) { + Stack stack = new Stack(); + StringTokenizer pathParts = new StringTokenizer(returnValue.replace('\\', '/'), "/"); + + while (pathParts.hasMoreTokens()) { + String part = pathParts.nextToken(); + + if (!part.equals(".")) { + if (part.equals("..")) { + stack.pop(); + } else { + stack.push(part); + } + } + } + + StringBuffer flatPathBuffer = new StringBuffer(); + + for (int i = 0; i < stack.size(); i++) { + flatPathBuffer.append("/").append(stack.elementAt(i)); + } + + returnValue = flatPathBuffer.toString(); + } + + return returnValue; + } + + public void addParameter(String key, Object value) { + // don't use the default implementation of addParameter, + // instead, include tag requires that each parameter be a list of objects, + // just like the HTTP servlet interfaces are (String[]) + if (value != null) { + List currentValues = (List) parameters.get(key); + + if (currentValues == null) { + currentValues = new ArrayList(); + parameters.put(key, currentValues); + } + + currentValues.add(value); + } + } + + public static void include(String aResult, Writer writer, ServletRequest request, HttpServletResponse response) throws ServletException, IOException { + String resourcePath = getContextRelativePath(request, aResult); + RequestDispatcher rd = request.getRequestDispatcher(resourcePath); + + if (rd == null) { + throw new ServletException("Not a valid resource path:" + resourcePath); + } + + PageResponse pageResponse = new PageResponse(response); + + // Include the resource + rd.include((HttpServletRequest) request, pageResponse); + + //write the response back to the JspWriter, using the correct encoding. + String encoding = getEncoding(); + + if (encoding != null) { + //use the encoding specified in the property file + pageResponse.getContent().writeTo(writer, encoding); + } else { + //use the platform specific encoding + pageResponse.getContent().writeTo(writer, null); + } + } + + /** + * Get the encoding specified by the property 'struts.i18n.encoding' in struts.properties, + * or return the default platform encoding if not specified. + *

        + * Note that if the property is not initially defined, this will return the system default, + * even if the property is later defined. This is mainly for performance reasons. Undefined + * properties throw exceptions, which are a costly operation. + *

        + * If the property is initially defined, it is read every time, until is is undefined, and then + * the system default is used. + *

        + * Why not cache it completely? Some applications will wish to be able to dynamically set the + * encoding at runtime. + * + * @return The encoding to be used. + */ + private static String getEncoding() { + if (encodingDefined) { + try { + encoding = defaultEncoding; + } catch (IllegalArgumentException e) { + encoding = System.getProperty("file.encoding"); + encodingDefined = false; + } + } + + return encoding; + } + + + /** + * Implementation of ServletOutputStream that stores all data written + * to it in a temporary buffer accessible from {@link #getBuffer()} . + * + * @author Joe Walnes + * @author Scott Farquhar + */ + static final class PageOutputStream extends ServletOutputStream { + + private FastByteArrayOutputStream buffer; + + + public PageOutputStream() { + buffer = new FastByteArrayOutputStream(); + } + + + /** + * Return all data that has been written to this OutputStream. + */ + public FastByteArrayOutputStream getBuffer() throws IOException { + flush(); + + return buffer; + } + + public void close() throws IOException { + buffer.close(); + } + + public void flush() throws IOException { + buffer.flush(); + } + + public void write(byte[] b, int o, int l) throws IOException { + buffer.write(b, o, l); + } + + public void write(int i) throws IOException { + buffer.write(i); + } + + public void write(byte[] b) throws IOException { + buffer.write(b); + } + } + + + /** + * Simple wrapper to HTTPServletResponse that will allow getWriter() + * and getResponse() to be called as many times as needed without + * causing conflicts. + *

        + * The underlying outputStream is a wrapper around + * {@link PageOutputStream} which will store + * the written content to a buffer. + *

        + * This buffer can later be retrieved by calling {@link #getContent}. + * + * @author Joe Walnes + * @author Scott Farquhar + */ + static final class PageResponse extends HttpServletResponseWrapper { + + protected PrintWriter pagePrintWriter; + protected ServletOutputStream outputStream; + private PageOutputStream pageOutputStream = null; + + + /** + * Create PageResponse wrapped around an existing HttpServletResponse. + */ + public PageResponse(HttpServletResponse response) { + super(response); + } + + + /** + * Return the content buffered inside the {@link PageOutputStream}. + * + * @return + * @throws IOException + */ + public FastByteArrayOutputStream getContent() throws IOException { + //if we are using a writer, we need to flush the + //data to the underlying outputstream. + //most containers do this - but it seems Jetty 4.0.5 doesn't + if (pagePrintWriter != null) { + pagePrintWriter.flush(); + } + + return ((PageOutputStream) getOutputStream()).getBuffer(); + } + + /** + * Return instance of {@link PageOutputStream} + * allowing all data written to stream to be stored in temporary buffer. + */ + public ServletOutputStream getOutputStream() throws IOException { + if (pageOutputStream == null) { + pageOutputStream = new PageOutputStream(); + } + + return pageOutputStream; + } + + /** + * Return PrintWriter wrapper around PageOutputStream. + */ + public PrintWriter getWriter() throws IOException { + if (pagePrintWriter == null) { + pagePrintWriter = new PrintWriter(new OutputStreamWriter(getOutputStream(), getCharacterEncoding())); + } + + return pagePrintWriter; + } + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/InputTransferSelect.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/InputTransferSelect.java new file mode 100644 index 000000000..ccad62b1c --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/InputTransferSelect.java @@ -0,0 +1,339 @@ +/* + * $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.components; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import com.opensymphony.xwork2.util.ValueStack; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Map; +import java.util.LinkedHashMap; + +/** + * + * + * Create a input transfer select component which is basically an text input + * and <select ...> tag with buttons in the middle of them allowing text + * to be added to the transfer select. Will auto-select all its + * elements upon its containing form submision. + * + * + * + *

        + * + * + * + * + * NOTE: The id and doubleId need not be supplied as they will generated provided + * that the inputtransferselect tag is being used in a form tag. The generated id + * and doubleId will be <form_id>_<inputtransferselect_doubleName> and + * <form_id>_<inputtransferselect_doubleName> respectively. + * + * + * + *

        + * + *

        + * 
        + *
        + * <-- minimum configuration -->
        + * <s:inputtransferselect
        + *      label="Favourite Cartoons Characters"
        + *      name="cartoons"
        + *      list="{'Popeye', 'He-Man', 'Spiderman'}"
        + *  />
        + *
        + * 
        + * 
        + * + */ +@StrutsTag(name="inputtransferselect", tldTagClass="org.apache.struts2.views.jsp.ui.InputTransferSelectTag", description="Renders an input form") +public class InputTransferSelect extends ListUIBean { + + private static final Log _log = LogFactory.getLog(InputTransferSelect.class); + + private static final String TEMPLATE = "inputtransferselect"; + + protected String size; + protected String multiple; + + protected String allowRemoveAll; + protected String allowUpDown; + + protected String leftTitle; + protected String rightTitle; + + protected String buttonCssClass; + protected String buttonCssStyle; + + protected String addLabel; + protected String removeLabel; + protected String removeAllLabel; + protected String upLabel; + protected String downLabel; + + protected String headerKey; + protected String headerValue; + + + public InputTransferSelect(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + + public void evaluateExtraParams() { + super.evaluateExtraParams(); + + if (size == null || size.trim().length() <= 0) { + addParameter("size", "5"); + } + + if (multiple == null || multiple.trim().length() <= 0) { + addParameter("multiple", Boolean.TRUE); + } + + // allowUpDown + addParameter("allowUpDown", allowUpDown != null ? findValue(allowUpDown, Boolean.class) : Boolean.TRUE); + + // allowRemoveAll + addParameter("allowRemoveAll", allowRemoveAll != null ? findValue(allowRemoveAll, Boolean.class) : Boolean.TRUE); + + + // leftTitle + if (leftTitle != null) { + addParameter("leftTitle", findValue(leftTitle, String.class)); + } + + // rightTitle + if (rightTitle != null) { + addParameter("rightTitle", findValue(rightTitle, String.class)); + } + + + // buttonCssClass + if (buttonCssClass != null && buttonCssClass.trim().length() > 0) { + addParameter("buttonCssClass", buttonCssClass); + } + + // buttonCssStyle + if (buttonCssStyle != null && buttonCssStyle.trim().length() > 0) { + addParameter("buttonCssStyle", buttonCssStyle); + } + + // addLabel + addParameter("addLabel", addLabel != null ? findValue(addLabel, String.class) : "->" ); + + // removeLabel + addParameter("removeLabel", removeLabel != null ? findValue(removeLabel, String.class) : "<-"); + + // removeAllLabel + addParameter("removeAllLabel", removeAllLabel != null ? findValue(removeAllLabel, String.class) : "<<--"); + + + // upLabel + addParameter("upLabel", upLabel != null ? findValue(upLabel, String.class) : "^"); + + + // leftDownLabel + addParameter("downLabel", downLabel != null ? findValue(downLabel, String.class) : "v"); + + if ((headerKey != null) && (headerValue != null)) { + addParameter("headerKey", findString(headerKey)); + addParameter("headerValue", findString(headerValue)); + } + + + + // inform the form component our select tag infos, so they know how to select + // its elements upon onsubmit + Form formAncestor = (Form) findAncestor(Form.class); + if (formAncestor != null) { + + // inform ancestor form that we are having a customOnsubmit (see form-close.ftl [simple theme]) + enableAncestorFormCustomOnsubmit(); + + + // key -> select tag id, value -> headerKey (if exists) + Map formInputtransferselectIds = (Map) formAncestor.getParameters().get("inputtransferselectIds"); + + // init lists + if (formInputtransferselectIds == null) { + formInputtransferselectIds = new LinkedHashMap(); + } + + // id + String tmpId = (String) getParameters().get("id"); + String tmpHeaderKey = (String) getParameters().get("headerKey"); + if (tmpId != null && (! formInputtransferselectIds.containsKey(tmpId))) { + formInputtransferselectIds.put(tmpId, tmpHeaderKey); + } + + formAncestor.getParameters().put("inputtransferselectIds", formInputtransferselectIds); + + } + else { + _log.warn("form enclosing inputtransferselect "+this+" not found, auto select upon form submit of inputtransferselect will not work"); + } + } + + public String getSize() { + return size; + } + + @StrutsTagAttribute(description="the size of the select box") + public void setSize(String size) { + this.size = size; + } + + public String getMultiple() { + return multiple; + } + + @StrutsTagAttribute(description="Determine whether or not multiple entries are shown") + public void setMultiple(String multiple) { + this.multiple = multiple; + } + + public String getAllowRemoveAll() { + return allowRemoveAll; + } + + @StrutsTagAttribute(description="Determine whether the remove all button will display") + public void setAllowRemoveAll(String allowRemoveAll) { + this.allowRemoveAll = allowRemoveAll; + } + + public String getAllowUpDown() { + return allowUpDown; + } + + @StrutsTagAttribute(description="Determine whether items in the list can be reordered") + public void setAllowUpDown(String allowUpDown) { + this.allowUpDown = allowUpDown; + } + + public String getLeftTitle() { + return leftTitle; + } + + @StrutsTagAttribute(description="the left hand title") + public void setLeftTitle(String leftTitle) { + this.leftTitle = leftTitle; + } + + public String getRightTitle() { + return rightTitle; + } + + @StrutsTagAttribute(description="the right hand title") + public void setRightTitle(String rightTitle) { + this.rightTitle = rightTitle; + } + + public String getButtonCssClass() { + return buttonCssClass; + } + + @StrutsTagAttribute(description="the css class used for rendering buttons") + public void setButtonCssClass(String buttonCssClass) { + this.buttonCssClass = buttonCssClass; + } + + public String getButtonCssStyle() { + return buttonCssStyle; + } + + @StrutsTagAttribute(description="the css style used for rendering buttons") + public void setButtonCssStyle(String buttonCssStyle) { + this.buttonCssStyle = buttonCssStyle; + } + + public String getAddLabel() { + return addLabel; + } + + @StrutsTagAttribute(description="the label used for the add button") + public void setAddLabel(String addLabel) { + this.addLabel = addLabel; + } + + public String getRemoveLabel() { + return removeLabel; + } + + @StrutsTagAttribute(description="the label used for the remove button") + public void setRemoveLabel(String removeLabel) { + this.removeLabel = removeLabel; + } + + public String getRemoveAllLabel() { + return removeAllLabel; + } + + @StrutsTagAttribute(description="the label used for the remove all button") + public void setRemoveAllLabel(String removeAllLabel) { + this.removeAllLabel = removeAllLabel; + } + + public String getUpLabel() { + return upLabel; + } + + @StrutsTagAttribute(description="the label used for the up button") + public void setUpLabel(String upLabel) { + this.upLabel = upLabel; + } + + public String getDownLabel() { + return downLabel; + } + + @StrutsTagAttribute(description="the label used for the down button") + public void setDownLabel(String downLabel) { + this.downLabel = downLabel; + } + + public String getHeaderKey() { + return headerKey; + } + + @StrutsTagAttribute(description="the header key of the select box") + public void setHeaderKey(String headerKey) { + this.headerKey = headerKey; + } + + public String getHeaderValue() { + return headerValue; + } + + @StrutsTagAttribute(description="the header value of the select box") + public void setHeaderValue(String headerValue) { + this.headerValue = headerValue; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/IteratorComponent.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/IteratorComponent.java new file mode 100644 index 000000000..24d1d3eb4 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/IteratorComponent.java @@ -0,0 +1,289 @@ +/* + * $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.components; + +import java.io.Writer; +import java.util.Iterator; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.util.MakeIterator; +import org.apache.struts2.views.jsp.IteratorStatus; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + *

        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.

        + * + * + * + *

          + * + *
        • status (String) - if specified, an instanceof IteratorStatus will be pushed into stack upon each iteration
        • + * + *
        • value (Object) - the source to iterate over, must be iteratable, else an the object itself will be put into a + * newly created List (see MakeIterator#convert(Object)
        • + * + *
        • id (String) - if specified the current iteration object will be place with this id in Struts stack's context + * scope
        • + * + *
        + * + * + * + * + * + *

        The following example retrieves the value of the getDays() method of the current object on the value stack and + * uses it to iterate over. The <s:property/> tag prints out the current value of the iterator.

        + * + * + * + *
        + * 
        + * <s:iterator value="days">
        + *   <p>day is: <s:property/></p>
        + * </s:iterator>
        + * 
        + * 
        + * + * + * + * + *

        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 + * colours:

        + * + * + * + * + *
        + * 
        + *
        + * <s:bean name="org.apache.struts2.example.IteratorExample" id="it">
        + *   <s:param name="day" value="'foo'"/>
        + *   <s:param name="day" value="'bar'"/>
        + * </s:bean>
        + * 

        + * <table border="0" cellspacing="0" cellpadding="1"> + * <tr> + * <th>Days of the week</th> + * </tr> + *

        + * <s:iterator value="#it.days" status="rowstatus"> + * <tr> + * <s:if test="#rowstatus.odd == true"> + * <td style="background: grey"><s:property/></td> + * </s:if> + * <s:else> + * <td><s:property/></td> + * </s:else> + * </tr> + * </s:iterator> + * </table> + * + * + *

        + * + * + * + *

        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:

        + * + * + * + *
        + * 
        + *
        + *  <s:iterator value="groupDao.groups" status="groupStatus">
        + *      <tr class="<s:if test="#groupStatus.odd == true ">odd</s:if><s:else>even</s:else>">
        + *          <td><s:property value="name" /></td>
        + *          <td><s:property value="description" /></td>
        + *          <td>
        + *              <s:iterator value="users" status="userStatus">
        + *                  <s:property value="fullName" /><s:if test="!#userStatus.last">,</s:if>
        + *              </s:iterator>
        + *          </td>
        + *      </tr>
        + *  </s:iterator>
        + *
        + * 
        + * 
        + *

        + * + * + * + *

        The next example iterates over a an action collection and passes every iterator value to another action. The + * trick here lies in the use of the '[0]' operator. It takes the current iterator value and passes it on to the edit + * action. Using the '[0]' operator has the same effect as using >s:property />. (The latter, however, does not + * work from inside the param tag).

        + * + * + * + *
        + * 
        + *
        + *      <s:action name="entries" id="entries"/>
        + *      <s:iterator value="#entries.entries" >
        + *          <s:property value="name" />
        + *          <s:property />
        + *          <s:push value="...">
        + *              <s:action name="edit" id="edit" >
        + *                  <s:param name="entry" value="[0]" />
        + *              </s:action>
        + *          </push>
        + *      </s:iterator>
        + *
        + * 
        + * 
        + * + * + * + *

        To simulate a simple loop with iterator tag, the following could be done. + * It does the loop 5 times. + * + * + * + *
        + * 
        + *
        + * <s:iterator status="stat" value="{1,2,3,4,5}" >
        + *    <!-- grab the index (start with 0 ... ) -->
        + *    <s:property value="#stat.index" />
        + *
        + *    <!-- grab the top of the stack which should be the -->
        + *    <!-- current iteration value (0, 1, ... 5) -->
        + *    <s:property value="top" />
        + * </s:iterator>
        + *
        + * 
        + * 
        + * + */ +@StrutsTag(name="iterator", tldTagClass="org.apache.struts2.views.jsp.IteratorTag", description="Iterate over a iterable value") +public class IteratorComponent extends Component { + protected Iterator iterator; + protected IteratorStatus status; + protected Object oldStatus; + protected IteratorStatus.StatusState statusState; + protected String statusAttr; + protected String value; + + public IteratorComponent(ValueStack stack) { + super(stack); + } + + public boolean start(Writer writer) { + //Create an iterator status if the status attribute was set. + if (statusAttr != null) { + statusState = new IteratorStatus.StatusState(); + status = new IteratorStatus(statusState); + } + + ValueStack stack = getStack(); + + if (value == null) { + value = "top"; + } + iterator = MakeIterator.convert(findValue(value)); + + // get the first + if ((iterator != null) && iterator.hasNext()) { + Object currentValue = iterator.next(); + stack.push(currentValue); + + String id = getId(); + + if ((id != null) && (currentValue != null)) { + //pageContext.setAttribute(id, currentValue); + //pageContext.setAttribute(id, currentValue, PageContext.REQUEST_SCOPE); + stack.getContext().put(id, currentValue); + } + + // Status object + if (statusAttr != null) { + statusState.setLast(!iterator.hasNext()); + oldStatus = stack.getContext().get(statusAttr); + stack.getContext().put(statusAttr, status); + } + + return true; + } else { + super.end(writer, ""); + return false; + } + } + + public boolean end(Writer writer, String body) { + ValueStack stack = getStack(); + if (iterator != null) { + stack.pop(); + } + + if (iterator!=null && iterator.hasNext()) { + Object currentValue = iterator.next(); + stack.push(currentValue); + + String id = getId(); + + if ((id != null) && (currentValue != null)) { + //pageContext.setAttribute(id, currentValue); + //pageContext.setAttribute(id, currentValue, PageContext.REQUEST_SCOPE); + stack.getContext().put(id, currentValue); + } + + // Update status + if (status != null) { + statusState.next(); // Increase counter + statusState.setLast(!iterator.hasNext()); + } + + return true; + } else { + // Reset status object in case someone else uses the same name in another iterator tag instance + if (status != null) { + if (oldStatus == null) { + stack.getContext().put(statusAttr, null); + } else { + stack.getContext().put(statusAttr, oldStatus); + } + } + super.end(writer, ""); + return false; + } + } + + @StrutsTagAttribute(description="If specified, an instanceof IteratorStatus will be pushed into stack upon each iteration", + type="Boolean", defaultValue="false") + public void setStatus(String status) { + this.statusAttr = status; + } + + @StrutsTagAttribute(description="the iteratable source to iterate over, else an the object itself will be put into a newly created List") + public void setValue(String value) { + this.value = value; + } + +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Label.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Label.java new file mode 100644 index 000000000..db8d06340 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Label.java @@ -0,0 +1,95 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * Renders an HTML LABEL that will allow you to output label:name combination that has the same format treatment as + * the rest of your UI controls.

        + * + * + *

        Examples + *

        + * + * In this example, a label is rendered. The label is retrieved from a ResourceBundle via the key attribute + * giving you an output of 'User Name: Ford.Prefect'. Assuming that i18n message userName corresponds + * to 'User Name' and the action's getUserName() method returns 'Ford.Prefect'

        + * + *

        + * 
        + * <s:label key="userName" />
        + * 
        + * 
        + *
        + * 
        + * <s:label name="userName" label="User Name" />
        + * 
        + * 
        + * + */ +@StrutsTag(name="label", tldTagClass="org.apache.struts2.views.jsp.ui.LabelTag", description="Render a label that displays" + + " read-only information") +public class Label extends UIBean { + final public static String TEMPLATE = "label"; + + protected String forAttr; + + public Label(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + protected void evaluateExtraParams() { + super.evaluateExtraParams(); + + if (forAttr != null) { + addParameter("for", findString(forAttr)); + } + + // try value first, then name (this overrides the default behavior in the superclass) + if (value != null) { + addParameter("nameValue", findString(value)); + } else if (name != null) { + String expr = name; + if (altSyntax()) { + expr = "%{" + expr + "}"; + } + + addParameter("nameValue", findString(expr)); + } + } + + @StrutsTagAttribute(description=" HTML for attribute") + public void setFor(String forAttr) { + this.forAttr = forAttr; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ListUIBean.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ListUIBean.java new file mode 100644 index 000000000..d6ce92366 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/ListUIBean.java @@ -0,0 +1,152 @@ +/* + * $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.components; + +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.util.ContainUtil; +import org.apache.struts2.util.MakeIterator; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * DoubleListUIBean is the standard superclass of all Struts list handling components. + * + *

        + * + * + * + * 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. + * + * + * + */ +public abstract class ListUIBean extends UIBean { + protected Object list; + protected String listKey; + protected String listValue; + + // indicate if an exception is to be thrown when value attribute is null + protected boolean throwExceptionOnNullValueAttribute = false; + + protected ListUIBean(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + public void evaluateExtraParams() { + Object value = null; + + if (list == null) { + list = parameters.get("list"); + } + + if (list instanceof String) { + value = findValue((String) list); + } else if (list instanceof Collection) { + value = list; + } else if (MakeIterator.isIterable(list)) { + value = MakeIterator.convert(list); + } + if (value == null) { + if (throwExceptionOnNullValueAttribute) { + // will throw an exception if not found + value = findValue((list == null) ? (String) list : list.toString(), "list", + "The requested list key '" + list + "' could not be resolved as a collection/array/map/enumeration/iterator type. " + + "Example: people or people.{name}"); + } + else { + // ww-1010, allows value with null value to be compatible with ww + // 2.1.7 behaviour + value = findValue((list == null)?(String) list:list.toString()); + } + } + + if (value instanceof Collection) { + addParameter("list", value); + } else { + addParameter("list", MakeIterator.convert(value)); + } + + if (value instanceof Collection) { + addParameter("listSize", new Integer(((Collection) value).size())); + } else if (value instanceof Map) { + addParameter("listSize", new Integer(((Map) value).size())); + } else if (value != null && value.getClass().isArray()) { + addParameter("listSize", new Integer(Array.getLength(value))); + } + + if (listKey != null) { + 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); + } + } + addParameter("listValue", listValue); + } else if (value instanceof Map) { + addParameter("listValue", "value"); + } + } + + public boolean contains(Object obj1, Object obj2) { + return ContainUtil.contains(obj1, obj2); + } + + protected Class getValueClassType() { + return null; // don't convert nameValue to anything, we need the raw value + } + + @StrutsTagAttribute(description="Iterable source to populate from. If the list is a Map (key, value), the Map key will become the option 'value'" + + " parameter and the Map value will become the option body.", required=true) + public void setList(Object list) { + this.list = list; + } + + @StrutsTagAttribute(description=" Property of list objects to get field value from") + public void setListKey(String listKey) { + this.listKey = listKey; + } + + @StrutsTagAttribute(description="Property of list objects to get field content from") + public void setListValue(String listValue) { + this.listValue = listValue; + } + + + public void setThrowExceptionOnNullValueAttribute(boolean throwExceptionOnNullValueAttribute) { + this.throwExceptionOnNullValueAttribute = throwExceptionOnNullValueAttribute; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/MergeIterator.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/MergeIterator.java new file mode 100644 index 000000000..1d8ff3d8b --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/MergeIterator.java @@ -0,0 +1,184 @@ +/* + * $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.components; + +import java.io.Writer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.components.Param.UnnamedParametric; +import org.apache.struts2.util.MakeIterator; +import org.apache.struts2.util.MergeIteratorFilter; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + *

        Component for MergeIteratorTag, which job is to merge iterators and successive + * call to the merged iterator will cause each merge iterator to have a chance to + * expose its element, subsequently next call will allow the next iterator to expose + * its element. Once the last iterator is done exposing its element, the first iterator + * is allowed to do so again (unless it is exhausted of entries).

        + * + *

        Internally the task are delegated to MergeIteratorFilter

        + * + *

        Example if there are 3 lists being merged, each list have 3 entries, the following will + * be the logic.

        + *
          + *
        1. Display first element of the first list
        2. + *
        3. Display first element of the second list
        4. + *
        5. Display first element of the third list
        6. + *
        7. Display second element of the first list
        8. + *
        9. Display second element of the second list
        10. + *
        11. Display second element of the third list
        12. + *
        13. Display third element of the first list
        14. + *
        15. Display thrid element of the second list
        16. + *
        17. Display third element of the thrid list
        18. + *
        + * + * + * + *
          + *
        • id (String) - the id where the resultant merged iterator will be stored in the stack's context
        • + *
        + * + * + * + * + * public class MergeIteratorTagAction extends ActionSupport { + * + * private List myList1; + * private List myList2; + * private List myList3; + * + * public List getMyList1() { + * return myList1; + * } + * + * public List getMyList2() { + * return myList2; + * } + * + * public List getMyList3() { + * return myList3; + * } + * + * + * public String execute() throws Exception { + * + * myList1 = new ArrayList(); + * myList1.add("1"); + * myList1.add("2"); + * myList1.add("3"); + * + * myList2 = new ArrayList(); + * myList2.add("a"); + * myList2.add("b"); + * myList2.add("c"); + * + * myList3 = new ArrayList(); + * myList3.add("A"); + * myList3.add("B"); + * myList3.add("C"); + * + * return "done"; + * } + * } + * + * + * + * <s:merge id="myMergedIterator1"> + * <s:param value="%{myList1}" /> + * <s:param value="%{myList2}" /> + * <s:param value="%{myList3}" /> + * </s:merge> + * <s:iterator value="%{#myMergedIterator1}"> + * <s:property /> + * </s:iterator> + * + * + * + * This wil generate "1aA2bB3cC". + * + * + * @see org.apache.struts2.util.MergeIteratorFilter + * @see org.apache.struts2.views.jsp.iterator.MergeIteratorTag + * + */ +@StrutsTag(name="merge", tldTagClass="org.apache.struts2.views.jsp.iterator.MergeIteratorTag", description="Merge the values " + + "of a list of iterators into one iterator") +public class MergeIterator extends Component implements UnnamedParametric { + + private static final Log _log = LogFactory.getLog(MergeIterator.class); + + private MergeIteratorFilter mergeIteratorFilter = null; + private List _parameters; + + public MergeIterator(ValueStack stack) { + super(stack); + } + + public boolean start(Writer writer) { + + mergeIteratorFilter = new MergeIteratorFilter(); + _parameters = new ArrayList(); + + return super.start(writer); + } + + public boolean end(Writer writer, String body) { + + for (Iterator parametersIterator = _parameters.iterator(); parametersIterator.hasNext(); ) { + Object iteratorEntryObj = parametersIterator.next(); + if (! MakeIterator.isIterable(iteratorEntryObj)) { + _log.warn("param with value resolved as "+iteratorEntryObj+" cannot be make as iterator, it will be ignored and hence will not appear in the merged iterator"); + continue; + } + mergeIteratorFilter.setSource(MakeIterator.convert(iteratorEntryObj)); + } + + mergeIteratorFilter.execute(); + + // if id exists, we put it in the stack's context + if (getId() != null && getId().length() > 0) { + getStack().getContext().put(getId(), mergeIteratorFilter); + } + + mergeIteratorFilter = null; + + return super.end(writer, body); + } + + @StrutsTagAttribute(description="The id where the resultant merged iterator will be stored in the stack's context") + public void setId(String id) { + super.setId(id); + } + + // == UnnamedParametric interface implementation --------------------- + public void addParameter(Object value) { + _parameters.add(value); + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/OptGroup.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/OptGroup.java new file mode 100644 index 000000000..278017765 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/OptGroup.java @@ -0,0 +1,145 @@ +/* + * $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.components; + +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.inject.Container; +import com.opensymphony.xwork2.inject.Inject; +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + * Create a optgroup component which needs to resides within a select tag. + * + * + * + *

        + * + * + * + * This component is to be used within a Select component. + * + * + * + *

        + * + *

        + * 
        + *
        + * <s:select label="My Selection"
        + *            name="mySelection"
        + *            value="%{'POPEYE'}"
        + *            list="%{#{'SUPERMAN':'Superman', 'SPIDERMAN':'spiderman'}}">
        + *    <s:optgroup label="Adult"
        + *                 list="%{#{'SOUTH_PARK':'South Park'}}" />
        + *    <s:optgroup label="Japanese"
        + *                 list="%{#{'POKEMON':'pokemon','DIGIMON':'digimon','SAILORMOON':'Sailormoon'}}" />
        + * </s:select>
        + *
        + * 
        + * 
        + * + */ +@StrutsTag(name="optgroup", tldTagClass="org.apache.struts2.views.jsp.ui.OptGroupTag", description="Renders a Select Tag's OptGroup Tag") +public class OptGroup extends Component { + + public static final String INTERNAL_LIST_UI_BEAN_LIST_PARAMETER_KEY = "optGroupInternalListUiBeanList"; + + private static Log _log = LogFactory.getLog(OptGroup.class); + + protected HttpServletRequest req; + protected HttpServletResponse res; + + protected ListUIBean internalUiBean; + + public OptGroup(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { + super(stack); + this.req = req; + this.res = res; + internalUiBean = new ListUIBean(stack, req, res) { + protected String getDefaultTemplate() { + return "empty"; + } + }; + } + + @Inject + public void setContainer(Container container) { + container.inject(internalUiBean); + } + + public boolean end(Writer writer, String body) { + Select select = (Select) findAncestor(Select.class); + if (select == null) { + _log.error("incorrect use of OptGroup component, this component must be used within a Select component", + new IllegalStateException("incorrect use of OptGroup component, this component must be used within a Select component")); + return false; + } + internalUiBean.start(writer); + internalUiBean.end(writer, body); + + List listUiBeans = (List) select.getParameters().get(INTERNAL_LIST_UI_BEAN_LIST_PARAMETER_KEY); + if (listUiBeans == null) { + listUiBeans = new ArrayList(); + } + listUiBeans.add(internalUiBean); + select.addParameter(INTERNAL_LIST_UI_BEAN_LIST_PARAMETER_KEY, listUiBeans); + + return false; + } + + @StrutsTagAttribute(description="Set the label attribute") + public void setLabel(String label) { + internalUiBean.setLabel(label); + } + + @StrutsTagAttribute(description="Set the disable attribute.") + public void setDisabled(String disabled) { + internalUiBean.setDisabled(disabled); + } + + @StrutsTagAttribute(description="Set the list attribute.") + public void setList(String list) { + internalUiBean.setList(list); + } + + @StrutsTagAttribute(description="Set the listKey attribute.") + public void setListKey(String listKey) { + internalUiBean.setListKey(listKey); + } + + @StrutsTagAttribute(description="Set the listValue attribute.") + public void setListValue(String listValue) { + internalUiBean.setListValue(listValue); + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/OptionTransferSelect.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/OptionTransferSelect.java new file mode 100644 index 000000000..00a3d51a0 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/OptionTransferSelect.java @@ -0,0 +1,577 @@ +/* + * $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.components; + +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + * Create a option transfer select component which is basically two <select ...> + * tag with buttons in the middle of them allowing options in each of the + * <select ...> to be moved between themselves. Will auto-select all its + * elements upon its containing form submision. + * + * + * + *

        + * + * + * + * + * NOTE: The id and doubleId need not be supplied as they will generated provided + * that the optiontransferselect tag is being used in a form tag. The generated id + * and doubleId will be <form_id>_<optiontransferselect_doubleName> and + * <form_id>_<optiontransferselect_doubleName> respectively. + * + * + * + *

        + * + *

        + * 
        + *
        + * <-- minimum configuration -->
        + * <s:optiontransferselect
        + *      label="Favourite Cartoons Characters"
        + *      name="leftSideCartoonCharacters"
        + *      list="{'Popeye', 'He-Man', 'Spiderman'}"
        + *      doubleName="rightSideCartoonCharacters"
        + *      doubleList="{'Superman', 'Mickey Mouse', 'Donald Duck'}"
        + *  />
        + *
        + *  <-- possible configuration -->
        + *  <s:optiontransferselect
        + *      label="Favourite Cartoons Characters"
        + *      name="leftSideCartoonCharacters"
        + *      leftTitle="Left Title"
        + *      rightTitle="Right Title"
        + *      list="{'Popeye', 'He-Man', 'Spiderman'}"
        + *      multiple="true"
        + *      headerKey="headerKey"
        + *      headerValue="--- Please Select ---"
        + *      emptyOption="true"
        + *      doubleList="{'Superman', 'Mickey Mouse', 'Donald Duck'}"
        + *      doubleName="rightSideCartoonCharacters"
        + *      doubleHeaderKey="doubleHeaderKey"
        + *      doubleHeaderValue="--- Please Select ---"
        + *      doubleEmptyOption="true"
        + *      doubleMultiple="true"
        + *  />
        + *
        + * 
        + * 
        + * + */ +@StrutsTag(name="optiontransferselect", tldTagClass="org.apache.struts2.views.jsp.ui.OptionTransferSelectTag", description="Renders an input form") +public class OptionTransferSelect extends DoubleListUIBean { + + private static final Log _log = LogFactory.getLog(OptionTransferSelect.class); + + private static final String TEMPLATE = "optiontransferselect"; + + protected String allowAddToLeft; + protected String allowAddToRight; + protected String allowAddAllToLeft; + protected String allowAddAllToRight; + protected String allowSelectAll; + protected String allowUpDownOnLeft; + protected String allowUpDownOnRight; + + protected String leftTitle; + protected String rightTitle; + + protected String buttonCssClass; + protected String buttonCssStyle; + + protected String addToLeftLabel; + protected String addToRightLabel; + protected String addAllToLeftLabel; + protected String addAllToRightLabel; + protected String selectAllLabel; + protected String leftUpLabel; + protected String leftDownlabel; + protected String rightUpLabel; + protected String rightDownLabel; + + protected String addToLeftOnclick; + protected String addToRightOnclick; + protected String addAllToLeftOnclick; + protected String addAllToRightOnclick; + protected String selectAllOnclick; + protected String upDownOnLeftOnclick; + protected String upDownOnRightOnclick; + + + public OptionTransferSelect(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + + public void evaluateExtraParams() { + super.evaluateExtraParams(); + + Object doubleValue = null; + + // override DoubleListUIBean's + if (doubleList != null) { + doubleValue = findValue(doubleList); + addParameter("doubleList", doubleValue); + } + if (size == null || size.trim().length() <= 0) { + addParameter("size", "15"); + } + if (doubleSize == null || doubleSize.trim().length() <= 0) { + addParameter("doubleSize", "15"); + } + if (multiple == null || multiple.trim().length() <= 0) { + addParameter("multiple", Boolean.TRUE); + } + if (doubleMultiple == null || doubleMultiple.trim().length() <= 0) { + addParameter("doubleMultiple", Boolean.TRUE); + } + + + + + + // buttonCssClass + if (buttonCssClass != null && buttonCssClass.trim().length() > 0) { + addParameter("buttonCssClass", buttonCssClass); + } + + // buttonCssStyle + if (buttonCssStyle != null && buttonCssStyle.trim().length() > 0) { + addParameter("buttonCssStyle", buttonCssStyle); + } + + + + // allowSelectAll + addParameter("allowSelectAll", + allowSelectAll != null ? findValue(allowSelectAll, Boolean.class) : Boolean.TRUE); + + // allowAddToLeft + addParameter("allowAddToLeft", + allowAddToLeft != null ? findValue(allowAddToLeft, Boolean.class) : Boolean.TRUE); + + // allowAddToRight + addParameter("allowAddToRight", + allowAddToRight != null ? findValue(allowAddToRight, Boolean.class) : Boolean.TRUE); + + // allowAddAllToLeft + addParameter("allowAddAllToLeft", + allowAddAllToLeft != null ? findValue(allowAddAllToLeft, Boolean.class) : Boolean.TRUE); + + // allowAddAllToRight + addParameter("allowAddAllToRight", + allowAddAllToRight != null ? findValue(allowAddAllToRight, Boolean.class) : Boolean.TRUE); + + // allowUpDownOnLeft + addParameter("allowUpDownOnLeft", + allowUpDownOnLeft != null ? findValue(allowUpDownOnLeft, Boolean.class) : Boolean.TRUE); + + // allowUpDownOnRight + addParameter("allowUpDownOnRight", + allowUpDownOnRight != null ? findValue(allowUpDownOnRight, Boolean.class) : Boolean.TRUE); + + + // leftTitle + if (leftTitle != null) { + addParameter("leftTitle", findValue(leftTitle, String.class)); + } + + // rightTitle + if (rightTitle != null) { + addParameter("rightTitle", findValue(rightTitle, String.class)); + } + + + // addToLeftLabel + addParameter("addToLeftLabel", + addToLeftLabel != null ? findValue(addToLeftLabel, String.class) : "<-" ); + + // addToRightLabel + addParameter("addToRightLabel", + addToRightLabel != null ? findValue(addToRightLabel, String.class) : "->"); + + // addAllToLeftLabel + addParameter("addAllToLeftLabel", + addAllToLeftLabel != null ? findValue(addAllToLeftLabel, String.class) : "<<--"); + + // addAllToRightLabel + addParameter("addAllToRightLabel", + addAllToRightLabel != null ? findValue(addAllToRightLabel, String.class) : "-->>"); + + // selectAllLabel + addParameter("selectAllLabel", + selectAllLabel != null ? findValue(selectAllLabel, String.class) : "<*>"); + + // leftUpLabel + addParameter("leftUpLabel", + leftUpLabel != null ? findValue(leftUpLabel, String.class) : "^"); + + + // leftDownLabel + addParameter("leftDownLabel", + leftDownlabel != null ? findValue(leftDownlabel, String.class) : "v"); + + + // rightUpLabel + addParameter("rightUpLabel", + rightUpLabel != null ? findValue(rightUpLabel, String.class) : "^"); + + + // rightDownlabel + addParameter("rightDownLabel", + rightDownLabel != null ? findValue(rightDownLabel, String.class) : "v"); + + + // selectAllOnclick + addParameter("selectAllOnclick", + selectAllOnclick != null ? findValue(selectAllOnclick, String.class) : ""); + + // addToLeftOnclick + addParameter("addToLeftOnclick", + addToLeftOnclick != null ? findValue(addToLeftOnclick, String.class) : ""); + + // addToRightOnclick + addParameter("addToRightOnclick", + addToRightOnclick != null ? findValue(addToRightOnclick, String.class) : ""); + + // addAllToLeftOnclick + addParameter("addAllToLeftOnclick", + addAllToLeftOnclick != null ? findValue(addAllToLeftOnclick, String.class) : ""); + + // addAllToRightOnclick + addParameter("addAllToRightOnclick", + addAllToRightOnclick != null ? findValue(addAllToRightOnclick, String.class) : ""); + + // upDownOnLeftOnclick + addParameter("upDownOnLeftOnclick", + upDownOnLeftOnclick != null ? findValue(upDownOnLeftOnclick, String.class) : ""); + + // upDownOnRightOnclick + addParameter("upDownOnRightOnclick", + upDownOnRightOnclick != null ? findValue(upDownOnRightOnclick, String.class) : ""); + + + // inform the form component our select tag infos, so they know how to select + // its elements upon onsubmit + Form formAncestor = (Form) findAncestor(Form.class); + if (formAncestor != null) { + + // inform ancestor form that we are having a customOnsubmit (see form-close.ftl [simple theme]) + enableAncestorFormCustomOnsubmit(); + + + // key -> select tag id, value -> headerKey (if exists) + Map formOptiontransferselectIds = (Map) formAncestor.getParameters().get("optiontransferselectIds"); + Map formOptiontransferselectDoubleIds = (Map) formAncestor.getParameters().get("optiontransferselectDoubleIds"); + + // init lists + if (formOptiontransferselectIds == null) { + formOptiontransferselectIds = new LinkedHashMap(); + } + if (formOptiontransferselectDoubleIds == null) { + formOptiontransferselectDoubleIds = new LinkedHashMap(); + } + + + // id + String tmpId = (String) getParameters().get("id"); + String tmpHeaderKey = (String) getParameters().get("headerKey"); + if (tmpId != null && (! formOptiontransferselectIds.containsKey(tmpId))) { + formOptiontransferselectIds.put(tmpId, tmpHeaderKey); + } + + // doubleId + String tmpDoubleId = (String) getParameters().get("doubleId"); + String tmpDoubleHeaderKey = (String) getParameters().get("doubleHeaderKey"); + if (tmpDoubleId != null && (! formOptiontransferselectDoubleIds.containsKey(tmpDoubleId))) { + formOptiontransferselectDoubleIds.put(tmpDoubleId, tmpDoubleHeaderKey); + } + + formAncestor.getParameters().put("optiontransferselectIds", formOptiontransferselectIds); + formAncestor.getParameters().put("optiontransferselectDoubleIds", formOptiontransferselectDoubleIds); + + } + else { + _log.warn("form enclosing optiontransferselect "+this+" not found, auto select upon form submit of optiontransferselect will not work"); + } + } + + + + public String getAddAllToLeftLabel() { + return addAllToLeftLabel; + } + + @StrutsTagAttribute(description="Set Add To Left button label") + public void setAddAllToLeftLabel(String addAllToLeftLabel) { + this.addAllToLeftLabel = addAllToLeftLabel; + } + + public String getAddAllToRightLabel() { + return addAllToRightLabel; + } + + @StrutsTagAttribute(description="Set Add All To Right button label") + public void setAddAllToRightLabel(String addAllToRightLabel) { + this.addAllToRightLabel = addAllToRightLabel; + } + + public String getAddToLeftLabel() { + return addToLeftLabel; + } + + @StrutsTagAttribute(description="Set Add To Left button label") + public void setAddToLeftLabel(String addToLeftLabel) { + this.addToLeftLabel = addToLeftLabel; + } + + public String getAddToRightLabel() { + return addToRightLabel; + } + + @StrutsTagAttribute(description="Set Add To Right button label") + public void setAddToRightLabel(String addToRightLabel) { + this.addToRightLabel = addToRightLabel; + } + + public String getAllowAddAllToLeft() { + return allowAddAllToLeft; + } + + @StrutsTagAttribute(description="Enable Add All To Left button") + public void setAllowAddAllToLeft(String allowAddAllToLeft) { + this.allowAddAllToLeft = allowAddAllToLeft; + } + + public String getAllowAddAllToRight() { + return allowAddAllToRight; + } + + @StrutsTagAttribute(description="Enable Add All To Right button") + public void setAllowAddAllToRight(String allowAddAllToRight) { + this.allowAddAllToRight = allowAddAllToRight; + } + + public String getAllowAddToLeft() { + return allowAddToLeft; + } + + @StrutsTagAttribute(description="Enable Add To Left button") + public void setAllowAddToLeft(String allowAddToLeft) { + this.allowAddToLeft = allowAddToLeft; + } + + public String getAllowAddToRight() { + return allowAddToRight; + } + + @StrutsTagAttribute(description="Enable Add To Right button") + public void setAllowAddToRight(String allowAddToRight) { + this.allowAddToRight = allowAddToRight; + } + + public String getLeftTitle() { + return leftTitle; + } + + @StrutsTagAttribute(description="Enable up / down on the left side") + public void setAllowUpDownOnLeft(String allowUpDownOnLeft) { + this.allowUpDownOnLeft = allowUpDownOnLeft; + } + + public String getAllowUpDownOnLeft() { + return this.allowUpDownOnLeft; + } + + @StrutsTagAttribute(description="Enable up / down on the right side") + public void setAllowUpDownOnRight(String allowUpDownOnRight) { + this.allowUpDownOnRight = allowUpDownOnRight; + } + + public String getAllowUpDownOnRight() { + return this.allowUpDownOnRight; + } + + @StrutsTagAttribute(description="Set Left title") + public void setLeftTitle(String leftTitle) { + this.leftTitle = leftTitle; + } + + public String getRightTitle() { + return rightTitle; + } + + @StrutsTagAttribute(description="Set Right title") + public void setRightTitle(String rightTitle) { + this.rightTitle = rightTitle; + } + + @StrutsTagAttribute(description="Enable Select All button") + public void setAllowSelectAll(String allowSelectAll) { + this.allowSelectAll = allowSelectAll; + } + + public String getAllowSelectAll() { + return this.allowSelectAll; + } + + @StrutsTagAttribute(description="Set Select All button label") + public void setSelectAllLabel(String selectAllLabel) { + this.selectAllLabel = selectAllLabel; + } + + public String getSelectAllLabel() { + return this.selectAllLabel; + } + + @StrutsTagAttribute(description="Set buttons css class") + public void setButtonCssClass(String buttonCssClass) { + this.buttonCssClass = buttonCssClass; + } + + public String getButtonCssClass() { + return buttonCssClass; + } + + @StrutsTagAttribute(description="Set button css style") + public void setButtonCssStyle(String buttonCssStyle) { + this.buttonCssStyle = buttonCssStyle; + } + + public String getButtonCssStyle() { + return this.buttonCssStyle; + } + + @StrutsTagAttribute(description="Up label for the left side") + public void setLeftUpLabel(String leftUpLabel) { + this.leftUpLabel = leftUpLabel; + } + public String getLeftUpLabel() { + return this.leftUpLabel; + } + + @StrutsTagAttribute(description="Down label for the left side.") + public void setLeftDownLabel(String leftDownLabel) { + this.leftDownlabel = leftDownLabel; + } + public String getLeftDownLabel() { + return this.leftDownlabel; + } + + @StrutsTagAttribute(description="Up label for the right side.") + public void setRightUpLabel(String rightUpLabel) { + this.rightUpLabel = rightUpLabel; + } + public String getRightUpLabel() { + return this.rightUpLabel; + } + + @StrutsTagAttribute(description="Down label for the left side.") + public void setRightDownLabel(String rightDownlabel) { + this.rightDownLabel = rightDownlabel; + } + public String getRightDownLabel() { + return rightDownLabel; + } + + public String getAddAllToLeftOnclick() { + return addAllToLeftOnclick; + } + + @StrutsTagAttribute(description="Javascript to run after Add All To Left button pressed") + public void setAddAllToLeftOnclick(String addAllToLeftOnclick) { + this.addAllToLeftOnclick = addAllToLeftOnclick; + } + + public String getAddAllToRightOnclick() { + return addAllToRightOnclick; + } + + @StrutsTagAttribute(description="Javascript to run after Add All To Right button pressed") + public void setAddAllToRightOnclick(String addAllToRightOnclick) { + this.addAllToRightOnclick = addAllToRightOnclick; + } + + public String getAddToLeftOnclick() { + return addToLeftOnclick; + } + + @StrutsTagAttribute(description="Javascript to run after Add To Left button pressed") + public void setAddToLeftOnclick(String addToLeftOnclick) { + this.addToLeftOnclick = addToLeftOnclick; + } + + public String getAddToRightOnclick() { + return addToRightOnclick; + } + + @StrutsTagAttribute(description="Javascript to run after Add To Right button pressed") + public void setAddToRightOnclick(String addToRightOnclick) { + this.addToRightOnclick = addToRightOnclick; + } + + @StrutsTagAttribute(description="Javascript to run after up / down on the left side buttons pressed") + public void setUpDownOnLeftOnclick(String upDownOnLeftOnclick) { + this.upDownOnLeftOnclick = upDownOnLeftOnclick; + } + + public String getUpDownOnLeftOnclick() { + return this.upDownOnLeftOnclick; + } + + @StrutsTagAttribute(description="Javascript to run after up / down on the right side buttons pressed") + public void setUpDownOnRightOnclick(String upDownOnRightOnclick) { + this.upDownOnRightOnclick = upDownOnRightOnclick; + } + + public String getUpDownOnRightOnclick() { + return this.upDownOnRightOnclick; + } + + @StrutsTagAttribute(description="Javascript to run after Select All button pressed") + public void setSelectAllOnclick(String selectAllOnclick) { + this.selectAllOnclick = selectAllOnclick; + } + + public String getSelectAllOnclick() { + return this.selectAllOnclick; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Param.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Param.java new file mode 100644 index 000000000..2aee7073a --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Param.java @@ -0,0 +1,157 @@ +/* + * $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.components; + +import java.io.Writer; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.StrutsException; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + *

        This tag can be used to parameterize other tags.

        + * The include tag and bean tag are examples of such tags. + *

        + * The parameters can be added with or without a name as key. + * If the tag provides a name attribute the parameters are added using the + * {@link Component#addParameter(String, Object) addParamter} method. + * For unnamed parameters the Tag must implement the {@link UnnamedParametric} interface defined in + * this class (e.g. The TextTag does this). + *

        + * This tag has the following two paramters. + * + *

          + *
        • name (String) - the name of the parameter
        • + *
        • value (Object) - the value of the parameter
        • + *
        + * + *

        + * Note: + * When you declare the param tag, the value can be defined in either a value attribute or + * as text between the start and end tag. Struts behaves a bit different according to these two situations. + * This is best illustrated using an example: + *
        <param name="color">blue</param> <-- (A) --> + *
        <param name="color" value="blue"/> <-- (B) --> + *
        In the first situation (A) the value would be evaluated to the stack as a java.lang.String object. + * And in situation (B) the value would be evaluated to the stack as a java.lang.Object object. + *
        For more information see WW-808. + * + * + *

        Examples + * + *

        + * <ui:component>
        + *  <ui:param name="key"     value="[0]"/>
        + *  <ui:param name="value"   value="[1]"/>
        + *  <ui:param name="context" value="[2]"/>
        + * </ui:component>
        + * 
        + * + *

        + * + * where the key will be the identifier and the value the result of an OGNL expression run against the current + * ValueStack. + * + *

        + * This second example demonstrates how the text tag can use parameters from this param tag. + * + *

        + * <s:text name="cart.total.cost">
        + *     <s:param value="#session.cartTotal"/>
        + * </s:text>
        + * 
        + * + *

        + * + * @see Include + * @see Bean + * @see Text + * + */ +@StrutsTag(name="param", tldTagClass="org.apache.struts2.views.jsp.ParamTag", description="Parametrize other tags") +public class Param extends Component { + protected String name; + protected String value; + + public Param(ValueStack stack) { + super(stack); + } + + public boolean end(Writer writer, String body) { + Component component = findAncestor(Component.class); + if (value != null) { + if (component instanceof UnnamedParametric) { + ((UnnamedParametric) component).addParameter(findValue(value)); + } else { + String name = findString(this.name); + + if (name == null) { + throw new StrutsException("No name found for following expression: " + name); + } + + Object value = findValue(this.value); + component.addParameter(name, value); + } + } else { + if (component instanceof UnnamedParametric) { + ((UnnamedParametric) component).addParameter(body); + } else { + component.addParameter(findString(name), body); + } + } + + return super.end(writer, ""); + } + + public boolean usesBody() { + return true; + } + + @StrutsTagAttribute(description="Name of Parameter to set") + public void setName(String name) { + this.name = name; + } + + @StrutsTagAttribute(description="Value expression for Parameter to set", defaultValue="The value of evaluating provided name against stack") + public void setValue(String value) { + this.value = value; + } + + + /** + * Tags can implement this to support nested param tags without the name attribute. + *

        + * The {@link Text TextTag} uses this approach. For unnamed parameters an example is given in the class + * javadoc for {@link Param ParamTag}. + */ + public interface UnnamedParametric { + + /** + * Adds the given value as a parameter to the outer tag. + * @param value the value + */ + public void addParameter(Object value); + } + +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Password.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Password.java new file mode 100644 index 000000000..81819bf0b --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Password.java @@ -0,0 +1,76 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * Render an HTML input tag of type password.

        + * + * + *

        Examples + *

        + * + * In this example, a password control is displayed. For the label, we are calling ActionSupport's getText() to + * retrieve password label from a resource bundle.

        + * + *

        + * 
        + * <s:password label="%{text('password')}" name="password" size="10" maxlength="15" />
        + * 
        + * 
        + * + */ +@StrutsTag(name="password", tldTagClass="org.apache.struts2.views.jsp.ui.PasswordTag", description="Render an HTML input tag of type password") +public class Password extends TextField { + final public static String TEMPLATE = "password"; + + protected String showPassword; + + public Password(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + public void evaluateExtraParams() { + super.evaluateExtraParams(); + + if (showPassword != null) { + addParameter("showPassword", findValue(showPassword, Boolean.class)); + } + } + + @StrutsTagAttribute(description="Whether to show input", type="Boolean", defaultValue="false") + public void setShowPassword(String showPassword) { + this.showPassword = showPassword; + } + +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Property.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Property.java new file mode 100644 index 000000000..24b479d5d --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Property.java @@ -0,0 +1,158 @@ +/* + * $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.components; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.util.TextUtils; + +/** + * + * + * Used to get the property of a value, which will default to the top of + * the stack if none is specified. + * + * + * + *

        + * + * + * + * + *

          + *
        • default (String) - The default value to be used if value attribute is null
        • + *
        • escape (Boolean) - Escape HTML. Default to true
        • + *
        • value (Object) - value to be displayed
        • + *
        + * + * + * + * + *
        + * 
        + *
        + * 
        + *     
        + *     
        + *
        + *     TextUtils
        + *     
        + * 
        + *
        + * 
        + * 
        + * + *
        + * 
        + *
        + * Example 1 prints the result of myBean's getMyBeanProperty() method.
        + * Example 2 prints the result of myBean's getMyBeanProperty() method and if it is null, print 'a default value' instead.
        + *
        + * 
        + * 
        + * + * + *
        + * 
        + *
        + * <s:property value="getText('some.key')" />
        + *
        + * 
        + * 
        + * + */ +@StrutsTag(name="property", tldBodyContent="empty", tldTagClass="org.apache.struts2.views.jsp.PropertyTag", + description="Print out expression which evaluates against the stack") +public class Property extends Component { + private static final Log LOG = LogFactory.getLog(Property.class); + + public Property(ValueStack stack) { + super(stack); + } + + private String defaultValue; + private String value; + private boolean escape = true; + + @StrutsTagAttribute(description="The default value to be used if value attribute is null") + public void setDefault(String defaultValue) { + this.defaultValue = defaultValue; + } + + @StrutsTagAttribute(description=" Whether to escape HTML", type="Boolean", defaultValue="true") + public void setEscape(boolean escape) { + this.escape = escape; + } + + @StrutsTagAttribute(description="Value to be displayed", type="Object", defaultValue="<top of stack>") + public void setValue(String value) { + this.value = value; + } + + public boolean start(Writer writer) { + boolean result = super.start(writer); + + String actualValue = null; + + 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); + } + } + + // exception: don't call findString(), since we don't want the + // expression parsed in this one case. it really + // doesn't make sense, in fact. + actualValue = (String) getStack().findValue(value, String.class); + + try { + if (actualValue != null) { + writer.write(prepare(actualValue)); + } else if (defaultValue != null) { + writer.write(prepare(defaultValue)); + } + } catch (IOException e) { + LOG.info("Could not print out value '" + value + "'", e); + } + + return result; + } + + private String prepare(String value) { + if (escape) { + return TextUtils.htmlEncode(value); + } else { + return value; + } + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Push.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Push.java new file mode 100644 index 000000000..3429139e8 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Push.java @@ -0,0 +1,150 @@ +/* + * $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.components; + +import java.io.Writer; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + *

        Push value on stack for simplified usage.

        + * + * + * + *
          + *
        • value* (Object) - value to be pushed into the top of the stack
        • + *
        + * + * + * + *

        Examples + *

        + * 
        + * <s:push value="user">
        + *     <s:propery value="firstName" />
        + *     <s:propery value="lastName" />
        + * </s:push>
        + * 
        + * 
        + * + * + * Pushed user into the stack, and hence property tag could access user's properties + * (firstName, lastName etc) since user is not at the top of the stack + * + * + *
        + * 
        + *  <s:push value="myObject">                              ----- (1)
        + *       <s:bean name="jp.SomeBean" id="myBean"/>        ----- (2)
        + *          <s:param name="myParam" value="top"/>        ----- (3)
        + *       </s:bean>
        + *   </s:push>
        + * 
        + * 
        + * + *
        + * 
        + * when in (1), myObject is at the top of the stack
        + * when in (2), jp.SomeBean is in the top of stack, also in stack's context with key myBean
        + * when in (3), top will get the jp.SomeBean instance
        + * 
        + * 
        + * + *
        + * 
        + * <s:push value="myObject">                                       ---(A)
        + *    <s:bean name="jp.SomeBean" id="myBean"/>                   ---(B)
        + *       <s:param name="myParam" value="top.mySomeOtherValue"/>  ---(C)
        + *    </s:bean>
        + * </s:push>
        + * 
        + * 
        + * + *
        + * 
        + * when in (A), myObject is at the top of the stack
        + * when in (B), jp.SomeBean is at the top of the stack, also in context with key myBean
        + * when in (C), top refers to jp.SomeBean instance. so top.mySomeOtherValue would invoke SomeBean's mySomeOtherValue() method
        + * 
        + * 
        + * + *
        + * 
        + * <s:push value="myObject">                                 ---- (i)
        + *    <s:bean name="jp.SomeBean" id="myBean"/>             ---- (ii)
        + *       <s:param name="myParam" value="[1].top"/>         -----(iii)
        + *    </s:bean>
        + * </s:push>
        + * 
        + * 
        + * + *
        + * 
        + * when in (i), myObject is at the top of the stack
        + * when in (ii), jp.SomeBean is at the top of the stack, followed by myObject
        + * when in (iii), [1].top will returned top of the cut of stack starting from myObject, namely myObject itself
        + * 
        + * 
        + * + */ +@StrutsTag(name="push", tldTagClass="org.apache.struts2.views.jsp.PushTag", description="Push value on stack for simplified usage.") +public class Push extends Component { + protected String value; + protected boolean pushed; + + public Push(ValueStack stack) { + super(stack); + } + + public boolean start(Writer writer) { + boolean result = super.start(writer); + + ValueStack stack = getStack(); + + if (stack != null) { + stack.push(findValue(value, "value", "You must specify a value to push on the stack. Example: person")); + pushed = true; + } else { + pushed = false; // need to ensure push is assigned, otherwise we may have a leftover value + } + + return result; + } + + public boolean end(Writer writer, String body) { + ValueStack stack = getStack(); + + if (pushed && (stack != null)) { + stack.pop(); + } + + return super.end(writer, body); + } + + @StrutsTagAttribute(description="Value to push on stack", required=true) + public void setValue(String value) { + this.value = value; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Radio.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Radio.java new file mode 100644 index 000000000..dd825fab1 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Radio.java @@ -0,0 +1,63 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * Render a radio button input field.

        + * + * + *

        Examples + *

        + * + * In this example, a radio control is displayed with a list of genders. The gender list is built from attribute + * id=genders. The framework calls getGenders() which will return a Map. For examples using listKey and listValue attributes, + * see the section select tag. The default selected one will be determined (in this case) by the getMale() method + * in the action class which should retun a value similar to the key of the getGenters() map if that particular + * gender is to be selected.

        + * + *

        + * 
        + * <s:action name="GenderMap" id="genders"/>
        + * <s:radio label="Gender" name="male" list="#genders.genders"/>
        + * 
        + * 
        + * + */ +@StrutsTag(name="radio", tldTagClass="org.apache.struts2.views.jsp.ui.RadioTag", description="Renders a radio button input field") +public class Radio extends ListUIBean { + final public static String TEMPLATE = "radiomap"; + + public Radio(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/RemoteUICallBean.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/RemoteUICallBean.java new file mode 100644 index 000000000..71730954f --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/RemoteUICallBean.java @@ -0,0 +1,54 @@ +/* + * $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.components; + + +public interface RemoteUICallBean { + + void setListenTopics(String topics); + + void setNotifyTopics(String topics); + + void setHref(String href); + + void setErrorText(String errorText); + + void setAfterLoading(String afterLoading); + + void setBeforeLoading(String beforeLoading); + + void setExecuteScripts(String executeScripts); + + void setLoadingText(String loadingText); + + void setHandler(String handler); + + void setFormFilter(String formFilter); + + void setFormId(String formId); + + void setShowErrorTransportText(String showError); + + void setShowLoadingText(String showLoadingText); + + void setIndicator(String indicator); + +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Reset.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Reset.java new file mode 100644 index 000000000..eb970a42b --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Reset.java @@ -0,0 +1,105 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * Render a reset button. The reset tag is used together with the form tag to provide form resetting. + * The reset can have two different types of rendering: + *
          + *
        • input: renders as html <input type="reset"...>
        • + *
        • button: renders as html <button type="reset"...>
        • + *
        + * Please note that the button type has advantages by adding the possibility to seperate the submitted value from the + * text shown on the button face, but has issues with Microsoft Internet Explorer at least up to 6.0 + * + * + *

        Examples + * + *

        + * 
        + * <s:reset value="Reset" />
        + * 
        + * 
        + * + *
        + * 
        + * Render an button reset:
        + * <s:reset type="button" key="reset"/>
        + * 
        + * 
        + * + */ +@StrutsTag(name="reset", tldTagClass="org.apache.struts2.views.jsp.ui.ResetTag", description="Render a reset button") +public class Reset extends FormButton { + final public static String TEMPLATE = "reset"; + + protected String action; + protected String method; + protected String align; + protected String type; + + public Reset(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return Reset.TEMPLATE; + } + + public void evaluateParams() { + + if ((key == null) && (value == null)) { + value = "Reset"; + } + + if (((key != null)) && (value == null)) { + this.value = "%{getText('"+key +"')}"; + } + + super.evaluateParams(); + + } + + /** + * Indicate whether the concrete button supports the type "image". + * + * @return false to indicate type image is supported. + */ + protected boolean supportsImageType() { + return false; + } + + @StrutsTagAttribute(description="Supply a reset button text apart from reset value. Will have no effect for " + + "input type reset, since button text will always be the value parameter.") + public void setLabel(String label) { + super.setLabel(label); + } + +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Select.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Select.java new file mode 100644 index 000000000..55f090e64 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Select.java @@ -0,0 +1,145 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + * Render an HTML input tag of type select. + * + * + * + *

        Examples + *

        + * 
        + *
        + * <s:select label="Pets"
        + *        name="petIds"
        + *        list="petDao.pets"
        + *        listKey="id"
        + *        listValue="name"
        + *        multiple="true"
        + *        size="3"
        + *        required="true"
        + * />
        + *
        + * <s:select label="Months"
        + *        name="months"
        + *        headerKey="-1" headerValue="Select Month"
        + *        list="#{'01':'Jan', '02':'Feb', [...]}"
        + *        value="selectedMonth"
        + *        required="true"
        + * />
        + *
        + * // The month id (01, 02, ...) returned by the getSelectedMonth() call
        + * // against the stack will be auto-selected
        + *
        + * 
        + * 
        + * + *

        + * + * + * + * Note: For any of the tags that use lists (select probably being the most ubiquitous), which uses the OGNL list + * notation (see the "months" example above), it should be noted that the map key created (in the months example, + * the '01', '02', etc.) is typed. '1' is a char, '01' is a String, "1" is a String. This is important since if + * the value returned by your "value" attribute is NOT the same type as the key in the "list" attribute, they + * WILL NOT MATCH, even though their String values may be equivalent. If they don't match, nothing in your list + * will be auto-selected.

        + * + * + * + */ +@StrutsTag(name="select", tldTagClass="org.apache.struts2.views.jsp.ui.SelectTag", description="Render a select element") +public class Select extends ListUIBean { + final public static String TEMPLATE = "select"; + + protected String emptyOption; + protected String headerKey; + protected String headerValue; + protected String multiple; + protected String size; + + public Select(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + public void evaluateExtraParams() { + super.evaluateExtraParams(); + + if (emptyOption != null) { + addParameter("emptyOption", findValue(emptyOption, Boolean.class)); + } + + if (multiple != null) { + addParameter("multiple", findValue(multiple, Boolean.class)); + } + + if (size != null) { + addParameter("size", findString(size)); + } + + if ((headerKey != null) && (headerValue != null)) { + addParameter("headerKey", findString(headerKey)); + addParameter("headerValue", findString(headerValue)); + } + } + + @StrutsTagAttribute(description="Whether or not to add an empty (--) option after the header option", type="Boolean", defaultValue="false") + public void setEmptyOption(String emptyOption) { + this.emptyOption = emptyOption; + } + + @StrutsTagAttribute(description=" Key for first item in list. Must not be empty! '-1' and '' is correct, '' is bad.") + public void setHeaderKey(String headerKey) { + this.headerKey = headerKey; + } + + @StrutsTagAttribute(description="Value expression for first item in list") + public void setHeaderValue(String headerValue) { + this.headerValue = headerValue; + } + + @StrutsTagAttribute(description=" Creates a multiple select. The tag will pre-select multiple values" + + " if the values are passed as an Array (of appropriate types) via the value attribute. Passing " + + "a Collection may work too? Haven't tested this.", type="Boolean", defaultValue="false") + public void setMultiple(String multiple) { + this.multiple = multiple; + } + + @StrutsTagAttribute(description="Size of the element box (# of elements to show)", type="Integer") + public void setSize(String size) { + this.size = size; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Set.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Set.java new file mode 100644 index 000000000..942b8b0af --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Set.java @@ -0,0 +1,148 @@ +/* + * $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.components; + +import java.io.Writer; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + *

        The set tag assigns a value to a variable in a specified scope. It is useful when you wish to assign a variable to a + * complex expression and then simply reference that variable each time rather than the complex expression. This is + * useful in both cases: when the complex expression takes time (performance improvement) or is hard to read (code + * readability improvement).

        + *

        If the tag is used with body content, the evaluation of the value parameter is omitted. Instead, the String to + * which the body eveluates is set as value for the scoped variable.

        + * + * The scopes available are as follows :- + *
          + *
        • application - the value will be set in application scope according to servlet spec. using the name as its key
        • + *
        • session - the value will be set in session scope according to servlet spec. using the name as key
        • + *
        • request - the value will be set in request scope according to servlet spec. using the name as key
        • + *
        • page - the value will be set in request scope according to servlet sepc. using the name as key
        • + *
        • action - the value will be set in the request scope and Struts' action context using the name as key
        • + *
        + * + * NOTE:

        + * If no scope is specified, it will default to action scope. + * + * + * + *

        Parameters + * + * + * + *

          + * + *
        • name* (String): The name of the new variable that is assigned the value of value
        • + * + *
        • value (Object): The value that is assigned to the variable named name
        • + * + *
        • scope (String): The scope in which to assign the variable. Can be application, session, + * request, page, or action. By default it is action.
        • + * + *
        + * + * + * + *

        Examples + * + *

        + * 
        + * <s:set name="personName" value="person.name"/>
        + * Hello, <s:property value="#personName"/>. How are you?
        + * 
        + * 
        + * + */ +@StrutsTag(name="set", tldBodyContent="JSP", tldTagClass="org.apache.struts2.views.jsp.SetTag", description="Assigns a value to a variable in a specified scope") +public class Set extends Component { + protected String name; + protected String scope; + protected String value; + + public Set(ValueStack stack) { + super(stack); + } + + public boolean end(Writer writer, String body) { + ValueStack stack = getStack(); + + Object o; + if (value == null) { + if (body!=null && !body.equals("")) { + o = body; + } else { + o = findValue("top"); + } + } else { + o = findValue(value); + } + + body=""; + + String name; + if (altSyntax()) { + name = findString(this.name, "name", "Name is required"); + } else { + name = this.name; + + if (this.name == null) { + throw fieldError("name", "Name is required", null); + } + } + + if ("application".equalsIgnoreCase(scope)) { + stack.setValue("#application['" + name + "']", o); + } else if ("session".equalsIgnoreCase(scope)) { + stack.setValue("#session['" + name + "']", o); + } else if ("request".equalsIgnoreCase(scope)) { + stack.setValue("#request['" + name + "']", o); + } else if ("page".equalsIgnoreCase(scope)) { + stack.setValue("#attr['" + name + "']", o, false); + } else { + stack.getContext().put(name, o); + stack.setValue("#attr['" + name + "']", o, false); + } + + return super.end(writer, body); + } + + @StrutsTagAttribute(description=" The name of the new variable that is assigned the value of value", required=true) + public void setName(String name) { + this.name = name; + } + + @StrutsTagAttribute(description="The scope in which to assign the variable. Can be application" + + ", session, request, page, or action.", defaultValue="action") + public void setScope(String scope) { + this.scope = scope; + } + + @StrutsTagAttribute(description="The value that is assigned to the variable named name") + public void setValue(String value) { + this.value = value; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Submit.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Submit.java new file mode 100644 index 000000000..afd38fc2c --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Submit.java @@ -0,0 +1,338 @@ +/* + * $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.components; + +import java.io.Writer; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * Render a submit button. The submit tag is used together with the form tag to provide asynchronous form submissions. + * The submit can have three different types of rendering: + *
          + *
        • input: renders as html <input type="submit"...>
        • + *
        • image: renders as html <input type="image"...>
        • + *
        • button: renders as html <button type="submit"...>
        • + *
        + * Please note that the button type has advantages by adding the possibility to seperate the submitted value from the + * text shown on the button face, but has issues with Microsoft Internet Explorer at least up to 6.0 + * + * + *

        Examples + *

        + * 
        + * <s:submit value="%{'Submit the form'}" />
        + * 
        + * 
        + *
        + * 
        + * Render an image submit:
        + * <s:submit type="image" value="%{'Submit the form'}" src="submit.gif"/>
        + * 
        + * 
        + *
        + * 
        + * Render an button submit:
        + * <s:submit type="button" value="%{'Submit the form'}"/>
        + * 
        + * 
        + * + * + * THE FOLLOWING IS ONLY VALID WHEN AJAX IS CONFIGURED + *
          + *
        • href
        • + *
        • errorText
        • + *
        • listenTopics
        • + *
        • notifyTopics
        • + *
        • executeScripts
        • + *
        • loadingText
        • + *
        • listenTopics
        • + *
        • handler
        • + *
        • formId
        • + *
        • formFilter
        • + *
        • targets
        • + *
        • showErrorTransportText
        • + *
        • targets
        • + *
        • indicator
        • + *
        + * 'resultDivId' Deprecated. Use targets.

        + * 'targets' is a list of element ids whose content will be updated with the + * text returned from request.

        + * 'errorText' is the text that will be displayed when there is an error making the request.

        + * 'onLoadJS' Deprecated. Use 'notifyTopics'.

        + * 'preInvokeJS' Deprecated. Use 'notifyTopics'.

        + * 'executeScripts' if set to true will execute javascript sections in the returned text.

        + * 'loadingText' is the text that will be displayed on the 'targets' elements while making the + * request.

        + * 'handler' is the name of the function that will take care of making the AJAX request. Dojo's widget + * and dom node are passed as parameters).

        + * 'formId' is the id of the html form whose fields will be seralized and passed as parameters + * in the request.

        + * 'formFilter' is the name of a function which will be used to filter the fields that will be + * seralized. This function takes as a parameter the element and returns true if the element + * should be included.

        + * 'listenTopics' comma separated list of topics names, that will trigger a request + * 'indicator' element to be shown while the request executing + * 'showErrorTransportText': whether errors should be displayed (on 'targets')

        + * 'showLoadingText' show loading text on targets

        + * 'notifyTopics' comma separated list of topics names, that will be published. Three parameters are passed:

        + *

          + *
        • data: html or json object when type='load' or type='error'
        • + *
        • type: 'before' before the request is made, 'load' when the request succeeds, or 'error' when it fails
        • + *
        • request: request javascript object, when type='load' or type='error'
        • + *
        + * + * + * + * Show the results in another div. If you want your results to be shown in + * a div, use the resultDivId where the id is the id of the div you want them + * shown in. This is an inner HTML approah. Your results get jammed into + * the div for you. Here is a sample of this approach: + * + * + *
        + * 
        + * Remote form replacing another div:
        + * <div id='two' style="border: 1px solid yellow;">Initial content</div>
        + * <s:form
        + *       id='theForm2'
        + *       cssStyle="border: 1px solid green;"
        + *       action='/AjaxRemoteForm.action'
        + *       method='post'
        + *       theme="ajax">
        + *
        + *   <input type='text' name='data' value='Struts User' />
        + *   <s:submit value="GO2" theme="ajax" resultDivId="two" />
        + *
        + * </s:form >
        + * 
        + * 
        + * + */ +@StrutsTag(name="submit", tldTagClass="org.apache.struts2.views.jsp.ui.SubmitTag", description="Render a submit button") +public class Submit extends FormButton implements RemoteUICallBean{ + + private static final Log LOG = LogFactory.getLog(Submit.class); + + final public static String TEMPLATE = "submit"; + + protected String href; + protected String errorText; + protected String executeScripts; + protected String loadingText; + protected String listenTopics; + protected String handler; + protected String formId; + protected String formFilter; + protected String src; + protected String notifyTopics; + protected String showErrorTransportText; + protected String indicator; + protected String showLoadingText; + //these two are called "preInvokeJS" and "onLoadJS" on the tld + //Names changed here to keep some consistency + protected String beforeLoading; + protected String afterLoading; + + //this one is called "resultDivId" on the tld + protected String targets; + + public Submit(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + public void evaluateParams() { + if ((key == null) && (value == null)) { + value = "Submit"; + } + + if (((key != null)) && (value == null)) { + this.value = "%{getText('"+key +"')}"; + } + + super.evaluateParams(); + } + + public void evaluateExtraParams() { + super.evaluateExtraParams(); + + if (href != null) + addParameter("href", findString(href)); + if (errorText != null) + addParameter("errorText", findString(errorText)); + if (loadingText != null) + addParameter("loadingText", findString(loadingText)); + if (afterLoading != null) + addParameter("afterLoading", findString(afterLoading)); + if (beforeLoading != null) + addParameter("beforeLoading", findString(beforeLoading)); + if (executeScripts != null) + addParameter("executeScripts", findValue(executeScripts, Boolean.class)); + if (listenTopics != null) + addParameter("listenTopics", findString(listenTopics)); + if (notifyTopics != null) + addParameter("notifyTopics", findString(notifyTopics)); + if (handler != null) + addParameter("handler", findString(handler)); + if (formId != null) + addParameter("formId", findString(formId)); + if (formFilter != null) + addParameter("formFilter", findString(formFilter)); + if (src != null) + addParameter("src", findString(src)); + if (indicator != null) + addParameter("indicator", findString(indicator)); + if (targets != null) + addParameter("targets", findString(targets)); + if (showLoadingText != null) + addParameter("showLoadingText", findString(showLoadingText)); + } + + /** + * Indicate whether the concrete button supports the type "image". + * + * @return true to indicate type image is supported. + */ + protected boolean supportsImageType() { + return true; + } + + /** + * Overrides to be able to render body in a template rather than always before the template + */ + public boolean end(Writer writer, String body) { + evaluateParams(); + try { + addParameter("body", body); + + mergeTemplate(writer, buildTemplateName(template, getDefaultTemplate())); + } catch (Exception e) { + LOG.error("error when rendering", e); + } + finally { + popComponentStack(); + } + + return false; + } + + @StrutsTagAttribute(description="Topic that will trigger the remote call") + public void setListenTopics(String listenTopics) { + this.listenTopics = listenTopics; + } + + @StrutsTagAttribute(description="The theme to use for the element. This tag will usually use the ajax theme.") + public void setTheme(String theme) { + super.setTheme(theme); + } + + @StrutsTagAttribute(description="The URL to call to obtain the content. Note: If used with ajax context, the value must be set as an url tag value.") + public void setHref(String href) { + this.href = href; + } + + @StrutsTagAttribute(description="The text to display to the user if the is an error fetching the content") + public void setErrorText(String errorText) { + this.errorText = errorText; + } + + @StrutsTagAttribute(name="onLoadJS", description="Deprecated. Use 'notifyTopics'. Javascript code execute after reload") + public void setAfterLoading(String afterLoading) { + this.afterLoading = afterLoading; + } + + + @StrutsTagAttribute(name="preInvokeJS", description="Deprecated. Use 'notifyTopics'. Javascript code execute before reload") + public void setBeforeLoading(String beforeLoading) { + this.beforeLoading = beforeLoading; + } + + @StrutsTagAttribute(description="Javascript code in the fetched content will be executed", type="Boolean", defaultValue="false") + public void setExecuteScripts(String executeScripts) { + this.executeScripts = executeScripts; + } + + @StrutsTagAttribute(description="Text to be shown while content is being fetched", defaultValue="Loading...") + public void setLoadingText(String loadingText) { + this.loadingText = loadingText; + } + + @StrutsTagAttribute(description="Javascript function name that will make the request") + public void setHandler(String handler) { + this.handler = handler; + } + + @StrutsTagAttribute(description="Function name used to filter the fields of the form.") + public void setFormFilter(String formFilter) { + this.formFilter = formFilter; + } + + @StrutsTagAttribute(description="Form id whose fields will be serialized and passed as parameters") + public void setFormId(String formId) { + this.formId = formId; + } + + @StrutsTagAttribute(description="Supply an image src for image type submit button. Will have no effect for types input and button.") + public void setSrc(String src) { + this.src = src; + } + + @StrutsTagAttribute(description="Comma delimited list of ids of the elements whose content will be updated") + public void setTargets(String targets) { + this.targets = targets; + } + + + @StrutsTagAttribute(description="Topics that will published when the remote call completes") + public void setNotifyTopics(String notifyTopics) { + this.notifyTopics = notifyTopics; + } + + + @StrutsTagAttribute(description="Set whether errors will be shown or not", type="Boolean", defaultValue="true") + public void setShowErrorTransportText(String showErrorTransportText) { + this.showErrorTransportText = showErrorTransportText; + } + + + @StrutsTagAttribute(description="Set indicator") + public void setIndicator(String indicator) { + this.indicator = indicator; + } + + @StrutsTagAttribute(description="Show loading text on targets", type="Boolean", defaultValue="true") + public void setShowLoadingText(String showLoadingText) { + this.showLoadingText = showLoadingText; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TabbedPanel.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TabbedPanel.java new file mode 100644 index 000000000..83e5e548f --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TabbedPanel.java @@ -0,0 +1,151 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * The tabbedpanel widget is primarily an AJAX component, where each tab can either be local content or remote + * content (refreshed each time the user selects that tab).

        + * If the useSelectedTabCookie attribute is set to true, the id of the selected tab is saved in a cookie on activation. + * When coming back to this view, the cookie is read and the tab will be activated again, unless an actual value for the + * selectedTab attribute is specified.

        + * If you want to use the cookie feature, please be sure that you provide a unique id for your tabbedpanel component, + * since this will also be the identifying name component of the stored cookie.

        + * + * + *

        Examples + *

        + * + * The following is an example of a tabbedpanel and panel tag utilizing local and remote content.

        + * + *

        + * 
        + * <s:tabbedPanel id="test" >
        + *    <s:div id="one" label="one" theme="ajax" labelposition="top" >
        + *        This is the first pane<br/>
        + *        <s:form>
        + *            <s:textfield name="tt" label="Test Text"/>  <br/>
        + *            <s:textfield name="tt2" label="Test Text2"/>
        + *        </s:form>
        + *    </s:div>
        + *    <s:div id="three" label="remote" theme="ajax" href="/AjaxTest.action" >
        + *        This is the remote tab
        + *    </s:div>
        + * </s:tabbedPanel>
        + * 
        + * 
        + * + */ +@StrutsTag(name="tabbedPanel", tldTagClass="org.apache.struts2.views.jsp.ui.TabbedPanelTag", description="Render a tabbedPanel widget.") +public class TabbedPanel extends ClosingUIBean { + public static final String TEMPLATE = "tabbedpanel"; + public static final String TEMPLATE_CLOSE = "tabbedpanel-close"; + final private static String COMPONENT_NAME = TabbedPanel.class.getName(); + + protected String selectedTab; + protected String closeButton; + protected String doLayout ; + protected String templateCssPath; + protected String useSelectedTabCookie; + + public TabbedPanel(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + + protected void evaluateExtraParams() { + super.evaluateExtraParams(); + + if(selectedTab != null) + addParameter("selectedTab", findString(selectedTab)); + if(closeButton != null) + addParameter("closeButton", findString(closeButton)); + addParameter("doLayout", doLayout != null ? findValue(doLayout, Boolean.class) : Boolean.FALSE); + if(labelPosition != null) { + //dojo has some weird name for label positions + if(labelPosition.equalsIgnoreCase("left")) + labelPosition = "left-h"; + if(labelPosition.equalsIgnoreCase("right")) + labelPosition = "right-h"; + addParameter("labelPosition", null); + addParameter("labelPosition", labelPosition); + } + if(templateCssPath != null) + addParameter("templateCssPath", findString(templateCssPath)); + if(useSelectedTabCookie != null) { + addParameter("useSelectedTabCookie", findString(useSelectedTabCookie)); + } + } + + public String getDefaultOpenTemplate() { + return TEMPLATE; + } + + protected String getDefaultTemplate() { + return TEMPLATE_CLOSE; + } + + public String getComponentName() { + return COMPONENT_NAME; + } + + @StrutsTagAttribute(description="The id to assign to the component.", required=true) + public void setId(String id) { + // This is required to override tld generation attributes to required=true + super.setId(id); + } + + + @StrutsTagAttribute(description=" The id of the tab that will be selected by default") + public void setSelectedTab(String selectedTab) { + this.selectedTab = selectedTab; + } + + @StrutsTagAttribute(description="Where the close button will be placed, possible values are 'tab' and 'pane'") + public void setCloseButton(String closeButton) { + this.closeButton = closeButton; + } + + @StrutsTagAttribute(description="If doLayout is false, the tab container's height equals the height of the currently selected tab", type="Boolean", defaultValue="false") + public void setDoLayout(String doLayout) { + this.doLayout = doLayout; + } + + @StrutsTagAttribute(description="Template css path") + public void setTemplateCssPath(String templateCssPath) { + this.templateCssPath = templateCssPath; + } + + @StrutsTagAttribute(required = false, defaultValue = "false", description = "If set to true, the id of the last selected " + + "tab will be stored in cookie. If the view is rendered, it will be tried to read this cookie and activate " + + "the corresponding tab on success, unless overridden by the selectedTab attribute. The cookie name is \"Struts2TabbedPanel_selectedTab_\"+id.") + public void setUseSelectedTabCookie( String useSelectedTabCookie ) { + this.useSelectedTabCookie = useSelectedTabCookie; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Text.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Text.java new file mode 100644 index 000000000..b78e76e00 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Text.java @@ -0,0 +1,190 @@ +/* + * $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.components; + +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.TextUtils; +import com.opensymphony.xwork2.util.ValueStack; +import com.opensymphony.xwork2.TextProvider; + +/** + * + * Render a I18n text message. + * + *

        + * + * The message must be in a resource bundle + * with the same name as the action that it is associated with. In practice + * this means that you should create a properties file in the same package + * as your Java class with the same name as your class, but with .properties + * extension. + * + *

        + * + * 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. + * + * + * + * + * + * + * + *

          + *
        • name* (String) - the i18n message key
        • + *
        + * + * + * + *

        + * + * Example: + *

        + * 
        + *
        + * Accessing messages from a given bundle (the i18n Shop example bundle in the first example) and using bundle defined through the framework in the second example.

        + * + * + *
        + * + *
        + * 
        + *
        + * <!-- First Example -->
        + * <s:i18n name="struts.action.test.i18n.Shop">
        + *     <s:text name="main.title"/>
        + * </s:i18n>
        + *
        + * <!-- Second Example -->
        + * <s:text name="main.title" />
        + *
        + * <!-- Third Examlpe -->
        + * <s:text name="i18n.label.greetings">
        + *    <s:param >Mr Smith</s:param>
        + * </s:text>
        + *
        + * 
        + * 
        + * + * + *
        + * 
        + *
        + * <-- Fourth Example -->
        + * <s:text name="some.key" />
        + *
        + * <-- Fifth Example -->
        + * <s:text name="some.invalid.key" >
        + *    The Default Message That Will Be Displayed
        + * </s:text>
        + *
        + * 
        + * 
        + * + * @see Param + * + */ +@StrutsTag(name="text", tldTagClass="org.apache.struts2.views.jsp.TextTag", description="Render a I18n text message") +public class Text extends Component implements Param.UnnamedParametric { + private static final Log LOG = LogFactory.getLog(Text.class); + + protected List values = Collections.EMPTY_LIST; + protected String actualName; + protected String name; + + public Text(ValueStack stack) { + super(stack); + } + + @StrutsTagAttribute(description=" Name of resource property to fetch", required=true) + public void setName(String name) { + this.name = name; + } + + + public boolean usesBody() { + // overriding this to true such that EVAL_BODY_BUFFERED is return and + // bodyContent will be valid hence, text between start & end tag will + // be honoured as default message (WW-1268) + return true; + } + + public boolean end(Writer writer, String body) { + actualName = findString(name, "name", "You must specify the i18n key. Example: welcome.header"); + String defaultMessage; + if (TextUtils.stringSet(body)) { + defaultMessage = body; + } else { + defaultMessage = actualName; + } + String msg = null; + ValueStack stack = getStack(); + + for (Iterator iterator = getStack().getRoot().iterator(); + iterator.hasNext();) { + Object o = iterator.next(); + + if (o instanceof TextProvider) { + TextProvider tp = (TextProvider) o; + msg = tp.getText(actualName, defaultMessage, values, stack); + + break; + } + } + + if (msg != null) { + try { + if (getId() == null) { + writer.write(msg); + } else { + stack.getContext().put(getId(), msg); + } + } catch (IOException e) { + LOG.error("Could not write out Text tag", e); + } + } + + return super.end(writer, ""); + } + + public void addParameter(String key, Object value) { + addParameter(value); + } + + public void addParameter(Object value) { + if (values.isEmpty()) { + values = new ArrayList(4); + } + + values.add(value); + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TextArea.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TextArea.java new file mode 100644 index 000000000..55a62347d --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TextArea.java @@ -0,0 +1,103 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * Render HTML textarea tag.

        + * + * + *

        Examples + * + *

        + * 
        + * <s:textarea label="Comments" name="comments" cols="30" rows="8"/>
        + * 
        + * 
        + * + * @see TabbedPanel + * + */ +@StrutsTag(name="textarea", tldTagClass="org.apache.struts2.views.jsp.ui.TextareaTag", description="Render HTML textarea tag.") +public class TextArea extends UIBean { + final public static String TEMPLATE = "textarea"; + + protected String cols; + protected String readonly; + protected String rows; + protected String wrap; + + public TextArea(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + public void evaluateExtraParams() { + super.evaluateExtraParams(); + + if (readonly != null) { + addParameter("readonly", findValue(readonly, Boolean.class)); + } + + if (cols != null) { + addParameter("cols", findString(cols)); + } + + if (rows != null) { + addParameter("rows", findString(rows)); + } + + if (wrap != null) { + addParameter("wrap", findString(wrap)); + } + } + + @StrutsTagAttribute(description="HTML cols attribute", type="Integer") + public void setCols(String cols) { + this.cols = cols; + } + + @StrutsTagAttribute(description="Whether the textarea is readonly", type="Boolean", defaultValue="false") + public void setReadonly(String readonly) { + this.readonly = readonly; + } + + @StrutsTagAttribute(description="HTML rows attribute", type="Integer") + public void setRows(String rows) { + this.rows = rows; + } + + @StrutsTagAttribute(description="HTML wrap attribute") + public void setWrap(String wrap) { + this.wrap = wrap; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TextField.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TextField.java new file mode 100644 index 000000000..cf4d4929f --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TextField.java @@ -0,0 +1,109 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * Render an HTML input field of type text

        + * + * + *

        Examples + *

        + * + * In this example, a text control for the "user" property is rendered. The label is also retrieved from a ResourceBundle via the key attribute. + * + *

        + * 
        + * <s:textfield key="user" />
        + * 
        + * 
        + * + *
        + * 
        + * <s:textfield name="user" label="User Name" />
        + * 
        + * 
        + + */ +@StrutsTag(name="textfield", tldTagClass="org.apache.struts2.views.jsp.ui.TextFieldTag", description="Render an HTML input field of type text") +public class TextField extends UIBean { + /** + * The name of the default template for the TextFieldTag + */ + final public static String TEMPLATE = "text"; + + + protected String maxlength; + protected String readonly; + protected String size; + + public TextField(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + protected void evaluateExtraParams() { + super.evaluateExtraParams(); + + if (size != null) { + addParameter("size", findString(size)); + } + + if (maxlength != null) { + addParameter("maxlength", findString(maxlength)); + } + + if (readonly != null) { + addParameter("readonly", findValue(readonly, Boolean.class)); + } + } + + @StrutsTagAttribute(description="HTML maxlength attribute", type="Integer") + public void setMaxlength(String maxlength) { + this.maxlength = maxlength; + } + + @StrutsTagAttribute(description="Deprecated. Use maxlength instead.", type="Integer") + public void setMaxLength(String maxlength) { + this.maxlength = maxlength; + } + + @StrutsTagAttribute(description="Whether the input is readonly", type="Boolean", defaultValue="false") + public void setReadonly(String readonly) { + this.readonly = readonly; + } + + @StrutsTagAttribute(description="HTML size attribute", type="Integer") + public void setSize(String size) { + this.size = size; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Token.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Token.java new file mode 100644 index 000000000..9fd151b8a --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Token.java @@ -0,0 +1,119 @@ +/* + * $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.components; + +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.util.TokenHelper; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * Stop double-submission of forms.

        + * + * The token tag is used to help with the "double click" submission problem. It is needed if you are using the + * TokenInterceptor or the TokenSessionInterceptor. The s:token tag merely places a hidden element that contains + * the unique token.

        + * + * + *

        Examples + * + *

        + * 
        + * <s:token />
        + * 
        + * 
        + * + * @see org.apache.struts2.interceptor.TokenInterceptor + * @see org.apache.struts2.interceptor.TokenSessionStoreInterceptor + * + */ +@StrutsTag(name="token", tldTagClass="org.apache.struts2.views.jsp.ui.TokenTag", description="Stop double-submission of forms") +public class Token extends UIBean { + + public static final String TEMPLATE = "token"; + + public Token(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + /** + * First looks for the token in the PageContext using the supplied name (or {@link org.apache.struts2.util.TokenHelper#DEFAULT_TOKEN_NAME} + * if no name is provided) so that the same token can be re-used for the scope of a request for the same name. If + * the token is not in the PageContext, a new Token is created and set into the Session and the PageContext with + * the name. + */ + protected void evaluateExtraParams() { + super.evaluateExtraParams(); + + String tokenName; + Map parameters = getParameters(); + + if (parameters.containsKey("name")) { + tokenName = (String) parameters.get("name"); + } else { + if (name == null) { + tokenName = TokenHelper.DEFAULT_TOKEN_NAME; + } else { + tokenName = findString(name); + + if (tokenName == null) { + tokenName = name; + } + } + + addParameter("name", tokenName); + } + + String token = buildToken(tokenName); + addParameter("token", token); + addParameter("tokenNameField", TokenHelper.TOKEN_NAME_FIELD); + } + + /** + * This will be removed in a future version of Struts. + * @deprecated Templates should use $parameters from now on, not $tag. + */ + public String getTokenNameField() { + return TokenHelper.TOKEN_NAME_FIELD; + } + + private String buildToken(String name) { + Map context = stack.getContext(); + Object myToken = context.get(name); + + if (myToken == null) { + myToken = TokenHelper.setToken(name); + context.put(name, myToken); + } + + return myToken.toString(); + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Tree.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Tree.java new file mode 100644 index 000000000..3e60a31e0 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/Tree.java @@ -0,0 +1,433 @@ +/* + * $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.components; + +import java.io.Writer; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + * Renders a tree widget with AJAX support.

        + * + * The id attribute is normally specified, such that it could be looked up using + * javascript if necessary.

        + * + * + * + *

        Examples + * + *

        + * 
        + *
        + * <-- statically -->
        + * <s:tree id="..." label="...">
        + *    <s:treenode id="..." label="..." />
        + *    <s:treenode id="..." label="...">
        + *        <s:treenode id="..." label="..." />
        + *        <s:treenode id="..." label="..." />
        + *    &;lt;/s:treenode>
        + *    <s:treenode id="..." label="..." />
        + * </s:tree>
        + *
        + * <-- dynamically -->
        + * <s:tree
        + *          id="..."
        + *          rootNode="..."
        + *          nodeIdProperty="..."
        + *          nodeTitleProperty="..."
        + *          childCollectionProperty="..." />
        + *
        + * 
        + * 
        + * + */ +@StrutsTag(name="tree", tldTagClass="org.apache.struts2.views.jsp.ui.TreeTag", description="Render a tree widget.") +public class Tree extends ClosingUIBean { + + private static final String TEMPLATE = "tree-close"; + private static final String OPEN_TEMPLATE = "tree"; + + private String toggle = "fade"; + private String treeSelectedTopic; + private String treeExpandedTopic; + private String treeCollapsedTopic; + protected String rootNodeAttr; + protected String childCollectionProperty; + protected String nodeTitleProperty; + protected String nodeIdProperty; + private String showRootGrid; + + private String showGrid; + private String blankIconSrc; + private String gridIconSrcL; + private String gridIconSrcV; + private String gridIconSrcP; + private String gridIconSrcC; + private String gridIconSrcX; + private String gridIconSrcY; + private String expandIconSrcPlus; + private String expandIconSrcMinus; + private String iconWidth; + private String iconHeight; + private String toggleDuration; + private String templateCssPath; + + public Tree(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + public boolean start(Writer writer) { + boolean result = super.start(writer); + + if (this.label == null) { + if ((rootNodeAttr == null) + || (childCollectionProperty == null) + || (nodeTitleProperty == null) + || (nodeIdProperty == null)) { + fieldError("label","The TreeTag requires either a value for 'label' or ALL of 'rootNode', " + + "'childCollectionProperty', 'nodeTitleProperty', and 'nodeIdProperty'", null); + } + } + return result; + } + + protected void evaluateExtraParams() { + super.evaluateExtraParams(); + + if (toggle != null) { + addParameter("toggle", findString(toggle)); + } + + if (treeSelectedTopic != null) { + addParameter("treeSelectedTopic", findString(treeSelectedTopic)); + } + + if (treeExpandedTopic != null) { + addParameter("treeExpandedTopic", findString(treeExpandedTopic)); + } + + if (treeCollapsedTopic != null) { + addParameter("treeCollapsedTopic", findString(treeCollapsedTopic)); + } + + if (rootNodeAttr != null) { + addParameter("rootNode", findValue(rootNodeAttr)); + } + + if (childCollectionProperty != null) { + addParameter("childCollectionProperty", findString(childCollectionProperty)); + } + + if (nodeTitleProperty != null) { + addParameter("nodeTitleProperty", findString(nodeTitleProperty)); + } + + if (nodeIdProperty != null) { + addParameter("nodeIdProperty", findString(nodeIdProperty)); + } + + if (showRootGrid != null) { + addParameter("showRootGrid", findValue(showRootGrid, Boolean.class)); + } + + + if (showGrid != null) { + addParameter("showGrid", findValue(showGrid, Boolean.class)); + } + + if (blankIconSrc != null) { + addParameter("blankIconSrc", findString(blankIconSrc)); + } + + if (gridIconSrcL != null) { + addParameter("gridIconSrcL", findString(gridIconSrcL)); + } + + if (gridIconSrcV != null) { + addParameter("gridIconSrcV", findString(gridIconSrcV)); + } + + if (gridIconSrcP != null) { + addParameter("gridIconSrcP", findString(gridIconSrcP)); + } + + if (gridIconSrcC != null) { + addParameter("gridIconSrcC", findString(gridIconSrcC)); + } + + if (gridIconSrcX != null) { + addParameter("gridIconSrcX", findString(gridIconSrcX)); + } + + if (gridIconSrcY != null) { + addParameter("gridIconSrcY", findString(gridIconSrcY)); + } + + if (expandIconSrcPlus != null) { + addParameter("expandIconSrcPlus", findString(expandIconSrcPlus)); + } + + if (expandIconSrcMinus != null) { + addParameter("expandIconSrcMinus", findString(expandIconSrcMinus)); + } + + if (iconWidth != null) { + addParameter("iconWidth", findValue(iconWidth, Integer.class)); + } + if (iconHeight != null) { + addParameter("iconHeight", findValue(iconHeight, Integer.class)); + } + if (toggleDuration != null) { + addParameter("toggleDuration", findValue(toggleDuration, Integer.class)); + } + if (templateCssPath != null) { + addParameter("templateCssPath", findString(templateCssPath)); + } + } + + public String getDefaultOpenTemplate() { + return OPEN_TEMPLATE; + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + public String getToggle() { + return toggle; + } + + @StrutsTagAttribute(description="The toggle property (either 'explode' or 'fade')", defaultValue="fade") + public void setToggle(String toggle) { + this.toggle = toggle; + } + + public String getTreeSelectedTopic() { + return treeSelectedTopic; + } + + @StrutsTagAttribute(description="The treeSelectedTopic property") + public void setTreeSelectedTopic(String treeSelectedTopic) { + this.treeSelectedTopic = treeSelectedTopic; + } + + public String getTreeExpandedTopic() { + return treeExpandedTopic; + } + + @StrutsTagAttribute(description="The treeExpandedTopic property.") + public void setTreeExpandedTopic(String treeExpandedTopic) { + this.treeExpandedTopic = treeExpandedTopic; + } + + public String getTreeCollapsedTopic() { + return treeCollapsedTopic; + } + + @StrutsTagAttribute(description="The treeCollapsedTopic property.") + public void setTreeCollapsedTopic(String treeCollapsedTopic) { + this.treeCollapsedTopic = treeCollapsedTopic; + } + + public String getRootNode() { + return rootNodeAttr; + } + + @StrutsTagAttribute(description="The rootNode property.") + public void setRootNode(String rootNode) { + this.rootNodeAttr = rootNode; + } + + public String getChildCollectionProperty() { + return childCollectionProperty; + } + + @StrutsTagAttribute(description="The childCollectionProperty property.") + public void setChildCollectionProperty(String childCollectionProperty) { + this.childCollectionProperty = childCollectionProperty; + } + + public String getNodeTitleProperty() { + return nodeTitleProperty; + } + + @StrutsTagAttribute(description="The nodeTitleProperty property.") + public void setNodeTitleProperty(String nodeTitleProperty) { + this.nodeTitleProperty = nodeTitleProperty; + } + + public String getNodeIdProperty() { + return nodeIdProperty; + } + + @StrutsTagAttribute(description="The nodeIdProperty property.") + public void setNodeIdProperty(String nodeIdProperty) { + this.nodeIdProperty = nodeIdProperty; + } + + @StrutsTagAttribute(description="The showRootGrid property (default true).") + public void setShowRootGrid(String showRootGrid) { + this.showRootGrid = showRootGrid; + } + + public String getShowRootGrid() { + return showRootGrid; + } + + public String getBlankIconSrc() { + return blankIconSrc; + } + + @StrutsTagAttribute(description="Blank icon image source.") + public void setBlankIconSrc(String blankIconSrc) { + this.blankIconSrc = blankIconSrc; + } + + public String getExpandIconSrcMinus() { + return expandIconSrcMinus; + } + + @StrutsTagAttribute(description="Expand icon (-) image source.") + public void setExpandIconSrcMinus(String expandIconSrcMinus) { + this.expandIconSrcMinus = expandIconSrcMinus; + } + + public String getExpandIconSrcPlus() { + return expandIconSrcPlus; + } + + @StrutsTagAttribute(description="Expand Icon (+) image source.") + public void setExpandIconSrcPlus(String expandIconSrcPlus) { + this.expandIconSrcPlus = expandIconSrcPlus; + } + + public String getGridIconSrcC() { + return gridIconSrcC; + } + + @StrutsTagAttribute(description="Image source for under child item child icons.") + public void setGridIconSrcC(String gridIconSrcC) { + this.gridIconSrcC = gridIconSrcC; + } + + public String getGridIconSrcL() { + return gridIconSrcL; + } + + + @StrutsTagAttribute(description=" Image source for last child grid.") + public void setGridIconSrcL(String gridIconSrcL) { + this.gridIconSrcL = gridIconSrcL; + } + + public String getGridIconSrcP() { + return gridIconSrcP; + } + + @StrutsTagAttribute(description="Image source for under parent item child icons.") + public void setGridIconSrcP(String gridIconSrcP) { + this.gridIconSrcP = gridIconSrcP; + } + + public String getGridIconSrcV() { + return gridIconSrcV; + } + + @StrutsTagAttribute(description="Image source for vertical line.") + public void setGridIconSrcV(String gridIconSrcV) { + this.gridIconSrcV = gridIconSrcV; + } + + public String getGridIconSrcX() { + return gridIconSrcX; + } + + @StrutsTagAttribute(description="Image source for grid for sole root item.") + public void setGridIconSrcX(String gridIconSrcX) { + this.gridIconSrcX = gridIconSrcX; + } + + public String getGridIconSrcY() { + return gridIconSrcY; + } + + @StrutsTagAttribute(description="Image source for grid for last root item.") + public void setGridIconSrcY(String gridIconSrcY) { + this.gridIconSrcY = gridIconSrcY; + } + + public String getIconHeight() { + return iconHeight; + } + + + @StrutsTagAttribute(description="Icon height", defaultValue="18px") + public void setIconHeight(String iconHeight) { + this.iconHeight = iconHeight; + } + + public String getIconWidth() { + return iconWidth; + } + + @StrutsTagAttribute(description="Icon width", defaultValue="19px") + public void setIconWidth(String iconWidth) { + this.iconWidth = iconWidth; + } + + + + public String getTemplateCssPath() { + return templateCssPath; + } + + @StrutsTagAttribute(description="Template css path", defaultValue="{contextPath}/struts/tree.css.") + public void setTemplateCssPath(String templateCssPath) { + this.templateCssPath = templateCssPath; + } + + public String getToggleDuration() { + return toggleDuration; + } + + @StrutsTagAttribute(description="Toggle duration in milliseconds", defaultValue="150") + public void setToggleDuration(String toggleDuration) { + this.toggleDuration = toggleDuration; + } + + public String getShowGrid() { + return showGrid; + } + + @StrutsTagAttribute(description="Show grid", type="Boolean", defaultValue="true") + public void setShowGrid(String showGrid) { + this.showGrid = showGrid; + } +} + diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TreeNode.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TreeNode.java new file mode 100644 index 000000000..b00da63dd --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/TreeNode.java @@ -0,0 +1,103 @@ +/* + * $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.components; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + * Renders a tree node within a tree widget with AJAX support.

        + * + * Either of the following combinations should be used depending on if the tree + * is to be constrcted dynamically or statically.

        + * + * Dynamically + *

          + *
        • id - id of this tree node
        • + *
        • title - label to be displayed for this tree node
        • + *
        + * + * Statically + *
          + *
        • rootNode - the parent node of which this tree is derived from
        • + *
        • nodeIdProperty - property to obtained this current tree node's id
        • + *
        • nodeTitleProperty - property to obtained this current tree node's title
        • + *
        • childCollectionProperty - property that returnds this current tree node's children
        • + *
        + * + * + * + *

        Examples + * + *

        + * 
        + *
        + * <-- statically -->
        + * <s:tree id="..." label="...">
        + *    <s:treenode id="..." label="..." />
        + *    <s:treenode id="..." label="...">
        + *        <s:treenode id="..." label="..." />
        + *        <s:treenode id="..." label="..." />
        + *    &;lt;/s:treenode>
        + *    <s:treenode id="..." label="..." />
        + * </s:tree>
        + *
        + * <-- dynamically -->
        + * <s:tree
        + *          id="..."
        + *          rootNode="..."
        + *          nodeIdProperty="..."
        + *          nodeTitleProperty="..."
        + *          childCollectionProperty="..." />
        + *
        + * 
        + * 
        + * + */ +@StrutsTag(name="treenode", tldTagClass="org.apache.struts2.views.jsp.ui.TreeNodeTag", description="Render a tree node within a tree widget.") +public class TreeNode extends ClosingUIBean { + private static final String TEMPLATE = "treenode-close"; + private static final String OPEN_TEMPLATE = "treenode"; + + public TreeNode(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + public String getDefaultOpenTemplate() { + return OPEN_TEMPLATE; + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + @StrutsTagAttribute(description="Label expression used for rendering tree node label.", required=true) + public void setLabel(String label) { + super.setLabel(label); + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/UIBean.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/UIBean.java new file mode 100644 index 000000000..3311cee4d --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/UIBean.java @@ -0,0 +1,1063 @@ +/* + * $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.components; + +import java.io.Writer; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.StrutsConstants; +import org.apache.struts2.components.template.Template; +import org.apache.struts2.components.template.TemplateEngine; +import org.apache.struts2.components.template.TemplateEngineManager; +import org.apache.struts2.components.template.TemplateRenderingContext; +import org.apache.struts2.views.util.ContextUtil; + +import com.opensymphony.xwork2.config.ConfigurationException; +import com.opensymphony.xwork2.inject.Inject; +import com.opensymphony.xwork2.util.ValueStack; + +/** + * UIBean is the standard superclass of all Struts UI componentns. + * It defines common Struts and html properties all UI components should present for usage. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
        AttributeThemeData TypesDescription
        templateDirn/aStringdefine the template directory
        themen/aStringdefine the theme name
        templaten/aStringdefine the template name
        + * + * + * + *

        + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
        AttributeThemeData TypesDescription
        cssClasssimpleStringdefine html class attribute
        cssStylesimpleStringdefine html style attribute
        titlesimpleStringdefine html title attribute
        disabledsimpleStringdefine html disabled attribute
        labelxhtmlStringdefine label of form element
        labelPositionxhtmlStringdefine label position of form element (top/left), default to left
        requiredpositionxhtmlStringdefine required label position of form element (left/right), default to right
        namesimpleStringForm Element's field name mapping
        requiredxhtmlBooleanadd * to label (true to add false otherwise)
        tabIndexsimpleStringdefine html tabindex attribute
        valuesimpleObjectdefine value of form element
        + * + * + * + *

        + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
        AttributeThemeData TypesDescription
        onclicksimpleStringhtml javascript onclick attribute
        ondbclicksimpleStringhtml javascript ondbclick attribute
        onmousedownsimpleStringhtml javascript onmousedown attribute
        onmouseupsimpleStringhtml javascript onmouseup attribute
        onmouseoversimpleStringhtml javascript onmouseover attribute
        onmouseoutsimpleStringhtml javascript onmouseout attribute
        onfocussimpleStringhtml javascript onfocus attribute
        onblursimpleStringhtml javascript onblur attribute
        onkeypresssimpleStringhtml javascript onkeypress attribute
        onkeyupsimpleStringhtml javascript onkeyup attribute
        onkeydownsimpleStringhtml javascript onkeydown attribute
        onselectsimpleStringhtml javascript onselect attribute
        onchangesimpleStringhtml javascript onchange attribute
        + * + * + * + *

        + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
        AttributeData TypeDefaultDescription
        tooltipStringnoneSet the tooltip of this particular component
        jsTooltipEnabledStringfalseEnable js tooltip rendering
        tooltipIconString/struts/static/tooltip/tooltip.gifThe url to the tooltip icon
        tooltipDelayString500Tooltip shows up after the specified timeout (miliseconds). A behavior similar to that of OS based tooltips.
        keysimpleStringThe name of the property this input field represents. This will auto populate the name, label, and value
        + * + * + * + * + * + * + * Every Form UI component (in xhtml / css_xhtml or any others that extends of them) could + * have tooltip assigned to a them. The Form component's tooltip related attribute once + * defined will be applicable to all form UI component that is created under it unless + * explicitly overriden by having the Form UI component itself defined that tooltip attribute. + * + *

        + * + * In Example 1, the textfield will inherit the tooltipDelay adn tooltipIcon attribte from + * its containing form. In other words, although it doesn't defined a tooltipAboveMousePointer + * attribute, it will have that attributes inherited from its containing form. + * + *

        + * + * In Example 2, the the textfield will inherite both the tooltipDelay and + * tooltipIcon attribute from its containing form but tooltipDelay + * attribute is overriden at the textfield itself. Hence, the textfield actually will + * have tooltipIcon defined as /myImages/myIcon.gif, inherited from its containing form and + * tooltipDelay defined as 5000, due to overriden at the textfield itself. + * + *

        + * + * Example 3, 4 and 5 shows different way of setting the tooltipConfig attribute.
        + * Example 3:Set tooltip config through body of param tag
        + * Example 4:Set tooltip config through value attribute of param tag
        + * Example 5:Set tooltip config through tooltipConfig attribute of component tag
        + * + * + * + * + *

        + * 
        + *
        + * <!-- Example 1: -->
        + * <s:form
        + *          tooltipConfig="#{'tooltipDelay':'500',
        + *                           'tooltipIcon='/myImages/myIcon.gif'}" .... >
        + *   ....
        + *     <s:textfield label="Customer Name" tooltip="Enter the customer name" .... />
        + *   ....
        + * </s:form>
        + *
        + * <!-- Example 2: -->
        + * <s:form
        + *         tooltipConfig="#{'tooltipDelay':'500',
        + *                          'tooltipIcon':'/myImages/myIcon.gif'}" ... >
        + *   ....
        + *     <s:textfield label="Address"
        + *          tooltip="Enter your address"
        + *          tooltipConfig="#{'tooltipDelay':'5000'}" />
        + *   ....
        + * </s:form>
        + *
        + *
        + * <-- Example 3: -->
        + * <s:textfield
        + *        label="Customer Name"
        + *        tooltip="One of our customer Details'">
        + *        <s:param name="tooltipConfig">
        + *             tooltipDelay = 500 |
        + *             tooltipIcon = /myImages/myIcon.gif
        + *        </s:param>
        + * </s:textfield>
        + *
        + *
        + * <-- Example 4: -->
        + * <s:textfield
        + *          label="Customer Address"
        + *          tooltip="Enter The Customer Address" >
        + *          <s:param
        + *              name="tooltipConfig"
        + *              value="#{'tooltipDelay':'500',
        + *                       'tooltipIcon':'/myImages/myIcon.gif'}" />
        + * </s:textfield>
        + *
        + *
        + * <-- Example 5: -->
        + * <s:textfield
        + *          label="Customer Telephone Number"
        + *          tooltip="Enter customer Telephone Number"
        + *          tooltipConfig="#{'tooltipDelay':'500',
        + *                           'tooltipIcon':'/myImages/myIcon.gif'}" />
        + *
        + * 
        + * 
        + * + */ +public abstract class UIBean extends Component { + private static final Log LOG = LogFactory.getLog(UIBean.class); + + protected HttpServletRequest request; + protected HttpServletResponse response; + + public UIBean(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack); + this.request = request; + this.response = response; + this.templateSuffix = ContextUtil.getTemplateSuffix(stack.getContext()); + } + + // The templateSuffic to use, overrides the default one if not null. + protected String templateSuffix; + + // The template to use, overrides the default one. + protected String template; + + // templateDir and theme attributes + protected String templateDir; + protected String theme; + + // shortcut, sets label, name, and value + protected String key; + + protected String cssClass; + protected String cssStyle; + protected String disabled; + protected String label; + protected String labelPosition; + protected String requiredposition; + protected String name; + protected String required; + protected String tabindex; + protected String value; + protected String title; + + // HTML scripting events attributes + protected String onclick; + protected String ondblclick; + protected String onmousedown; + protected String onmouseup; + protected String onmouseover; + protected String onmousemove; + protected String onmouseout; + protected String onfocus; + protected String onblur; + protected String onkeypress; + protected String onkeydown; + protected String onkeyup; + protected String onselect; + protected String onchange; + + // common html attributes + protected String accesskey; + + // javascript tooltip attribute + protected String tooltip; + protected String tooltipConfig; + + protected String defaultTemplateDir; + protected String defaultUITheme; + protected TemplateEngineManager templateEngineManager; + + @Inject(StrutsConstants.STRUTS_UI_TEMPLATEDIR) + public void setDefaultTemplateDir(String dir) { + this.defaultTemplateDir = dir; + } + + @Inject(StrutsConstants.STRUTS_UI_THEME) + public void setDefaultUITheme(String theme) { + this.defaultUITheme = theme; + } + + @Inject + public void setTemplateEngineManager(TemplateEngineManager mgr) { + this.templateEngineManager = mgr; + } + + public boolean end(Writer writer, String body) { + evaluateParams(); + try { + super.end(writer, body, false); + mergeTemplate(writer, buildTemplateName(template, getDefaultTemplate())); + } catch (Exception e) { + LOG.error("error when rendering", e); + } + finally { + popComponentStack(); + } + + return false; + } + + /** + * A contract that requires each concrete UI Tag to specify which template should be used as a default. For + * example, the CheckboxTab might return "checkbox.vm" while the RadioTag might return "radio.vm". This value + * not begin with a '/' unless you intend to make the path absolute rather than relative to the + * current theme. + * + * @return The name of the template to be used as the default. + */ + protected abstract String getDefaultTemplate(); + + protected Template buildTemplateName(String myTemplate, String myDefaultTemplate) { + String template = myDefaultTemplate; + + if (myTemplate != null) { + template = findString(myTemplate); + } + + String templateDir = getTemplateDir(); + String theme = getTheme(); + + return new Template(templateDir, theme, template); + + } + + protected void mergeTemplate(Writer writer, Template template) throws Exception { + final TemplateEngine engine = templateEngineManager.getTemplateEngine(template, templateSuffix); + if (engine == null) { + throw new ConfigurationException("Unable to find a TemplateEngine for template " + template); + } + + if (LOG.isDebugEnabled()) { + LOG.debug("Rendering template " + template); + } + + final TemplateRenderingContext context = new TemplateRenderingContext(template, writer, getStack(), getParameters(), this); + engine.renderTemplate(context); + } + + public String getTemplateDir() { + String templateDir = null; + + if (this.templateDir != null) { + templateDir = findString(this.templateDir); + } + + // If templateDir is not explicitly given, + // try to find attribute which states the dir set to use + if ((templateDir == null) || (templateDir.equals(""))) { + templateDir = (String) stack.findValue("#attr.templateDir"); + } + + // Default template set + if ((templateDir == null) || (templateDir.equals(""))) { + templateDir = defaultTemplateDir; + } + + // Defaults to 'template' + if ((templateDir == null) || (templateDir.equals(""))) { + templateDir = "template"; + } + + return templateDir; + } + + public String getTheme() { + String theme = null; + + if (this.theme != null) { + theme = findString(this.theme); + } + + if ( theme == null || theme.equals("") ) { + Form form = (Form) findAncestor(Form.class); + if (form != null) { + theme = form.getTheme(); + } + } + + // If theme set is not explicitly given, + // try to find attribute which states the theme set to use + if ((theme == null) || (theme.equals(""))) { + theme = (String) stack.findValue("#attr.theme"); + } + + // Default theme set + if ((theme == null) || (theme.equals(""))) { + theme = defaultUITheme; + } + + return theme; + } + + public void evaluateParams() { + addParameter("templateDir", getTemplateDir()); + addParameter("theme", getTheme()); + + String name = null; + + if (this.key != null) { + + if(this.name == null) { + this.name = key; + } + + if(this.label == null) { + this.label = "%{getText('"+ key +"')}"; + } + + } + + if (this.name != null) { + name = findString(this.name); + addParameter("name", name); + } + + if (label != null) { + addParameter("label", findString(label)); + } + + if (labelPosition != null) { + addParameter("labelposition", findString(labelPosition)); + } + + if (requiredposition != null) { + addParameter("requiredposition", findString(requiredposition)); + } + + if (required != null) { + addParameter("required", findValue(required, Boolean.class)); + } + + if (disabled != null) { + addParameter("disabled", findValue(disabled, Boolean.class)); + } + + if (tabindex != null) { + addParameter("tabindex", findString(tabindex)); + } + + if (onclick != null) { + addParameter("onclick", findString(onclick)); + } + + if (ondblclick != null) { + addParameter("ondblclick", findString(ondblclick)); + } + + if (onmousedown != null) { + addParameter("onmousedown", findString(onmousedown)); + } + + if (onmouseup != null) { + addParameter("onmouseup", findString(onmouseup)); + } + + if (onmouseover != null) { + addParameter("onmouseover", findString(onmouseover)); + } + + if (onmousemove != null) { + addParameter("onmousemove", findString(onmousemove)); + } + + if (onmouseout != null) { + addParameter("onmouseout", findString(onmouseout)); + } + + if (onfocus != null) { + addParameter("onfocus", findString(onfocus)); + } + + if (onblur != null) { + addParameter("onblur", findString(onblur)); + } + + if (onkeypress != null) { + addParameter("onkeypress", findString(onkeypress)); + } + + if (onkeydown != null) { + addParameter("onkeydown", findString(onkeydown)); + } + + if (onkeyup != null) { + addParameter("onkeyup", findString(onkeyup)); + } + + if (onselect != null) { + addParameter("onselect", findString(onselect)); + } + + if (onchange != null) { + addParameter("onchange", findString(onchange)); + } + + if (accesskey != null) { + addParameter("accesskey", findString(accesskey)); + } + + if (cssClass != null) { + addParameter("cssClass", findString(cssClass)); + } + + if (cssStyle != null) { + addParameter("cssStyle", findString(cssStyle)); + } + + if (title != null) { + addParameter("title", findString(title)); + } + + + // see if the value was specified as a parameter already + if (parameters.containsKey("value")) { + parameters.put("nameValue", parameters.get("value")); + } else { + if (evaluateNameValue()) { + final Class valueClazz = getValueClassType(); + + if (valueClazz != null) { + if (value != null) { + addParameter("nameValue", findValue(value, valueClazz)); + } else if (name != null) { + String expr = name; + if (altSyntax()) { + expr = "%{" + expr + "}"; + } + + addParameter("nameValue", findValue(expr, valueClazz)); + } + } else { + if (value != null) { + addParameter("nameValue", findValue(value)); + } else if (name != null) { + addParameter("nameValue", findValue(name)); + } + } + } + } + + final Form form = (Form) findAncestor(Form.class); + + // create HTML id element + populateComponentHtmlId(form); + + if (form != null ) { + addParameter("form", form.getParameters()); + + if ( name != null ) { + // list should have been created by the form component + List tags = (List) form.getParameters().get("tagNames"); + tags.add(name); + } + } + + + + + + // tooltip & tooltipConfig + if (tooltipConfig != null) { + addParameter("tooltipConfig", findValue(tooltipConfig)); + } + if (tooltip != null) { + addParameter("tooltip", findString(tooltip)); + + Map tooltipConfigMap = getTooltipConfig(this); + + if (form != null) { // inform the containing form that we need tooltip javascript included + form.addParameter("hasTooltip", Boolean.TRUE); + + // tooltipConfig defined in component itseilf will take precedence + // over those defined in the containing form + Map overallTooltipConfigMap = getTooltipConfig(form); + overallTooltipConfigMap.putAll(tooltipConfigMap); // override parent form's tooltip config + + for (Iterator i = overallTooltipConfigMap.entrySet().iterator(); i.hasNext(); ) { + Map.Entry entry = (Map.Entry) i.next(); + addParameter((String) entry.getKey(), entry.getValue()); + } + } + else { + LOG.warn("No ancestor Form found, javascript based tooltip will not work, however standard HTML tooltip using alt and title attribute will still work "); + } + } + evaluateExtraParams(); + + } + + 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("[\\.\\[\\]]", "_"); + } else { + return ""; + } + } + + /** + * Ensures an unescaped attribute value cannot be vulnerable to XSS attacks + * + * @param val The value to check + * @return The escaped value + */ + protected String ensureAttributeSafelyNotEscaped(String val) { + if (val != null) { + return val.replaceAll("\"", """); + } else { + return ""; + } + } + + protected void evaluateExtraParams() { + } + + protected boolean evaluateNameValue() { + return true; + } + + protected Class getValueClassType() { + return String.class; + } + + public void addFormParameter(String key, Object value) { + Form form = (Form) findAncestor(Form.class); + if (form != null) { + form.addParameter(key, value); + } + } + + protected void enableAncestorFormCustomOnsubmit() { + Form form = (Form) findAncestor(Form.class); + if (form != null) { + form.addParameter("customOnsubmitEnabled", Boolean.TRUE); + } else { + LOG.warn("Cannot find an Ancestor form, custom onsubmit is NOT enabled"); + } + } + + protected Map getTooltipConfig(UIBean component) { + Object tooltipConfigObj = component.getParameters().get("tooltipConfig"); + Map tooltipConfig = new LinkedHashMap(); + + if (tooltipConfigObj instanceof Map) { + // we get this if its configured using + // 1] UI component's tooltipConfig attribute OR + // 2] param tag value attribute + + tooltipConfig = new LinkedHashMap((Map)tooltipConfigObj); + } else if (tooltipConfigObj instanceof String) { + + // we get this if its configured using + // ... tag's body + String tooltipConfigStr = (String) tooltipConfigObj; + String[] tooltipConfigArray = tooltipConfigStr.split("\\|"); + + for (int a=0; a 1) { + value = configEntry[1].trim(); + tooltipConfig.put(key, value.toString()); + } + else { + LOG.warn("component "+component+" tooltip config param "+key+" has no value defined, skipped"); + } + } + } + return tooltipConfig; + } + + /** + * Create HTML id element for the component and populate this component parmaeter + * map. Additionally, a parameter named escapedId is populated which contains the found id value filtered by + * {@link #escape(String)}, needed eg. for naming Javascript identifiers based on the id value. + * + * The order is as follows :- + *
          + *
        1. This component id attribute
        2. + *
        3. [containing_form_id]_[this_component_name]
        4. + *
        5. [this_component_name]
        6. + *
        + * + * @param form + */ + protected void populateComponentHtmlId(Form form) { + String tryId; + if (id != null) { + // this check is needed for backwards compatibility with 2.1.x + if (altSyntax()) { + tryId = findString(id); + } else { + tryId = id; + } + } else if (form != null) { + tryId = form.getParameters().get("id") + "_" + + escape(name != null ? findString(name) : null); + } else { + tryId = escape(name != null ? findString(name) : null); + } + addParameter("id", tryId); + addParameter("escapedId", escape(tryId)); + } + + @StrutsTagAttribute(description="The template directory.") + public void setTemplateDir(String templateDir) { + this.templateDir = templateDir; + } + + @StrutsTagAttribute(description="The theme (other than default) to use for rendering the element") + public void setTheme(String theme) { + this.theme = theme; + } + + public String getTemplate() { + return template; + } + + @StrutsTagAttribute(description="The template (other than default) to use for rendering the element") + public void setTemplate(String template) { + this.template = template; + } + + @StrutsTagAttribute(description="The css class to use for element") + public void setCssClass(String cssClass) { + this.cssClass = cssClass; + } + + @StrutsTagAttribute(description="The css style definitions for element to use") + public void setCssStyle(String cssStyle) { + this.cssStyle = cssStyle; + } + + @StrutsTagAttribute(description="Set the html title attribute on rendered html element") + public void setTitle(String title) { + this.title = title; + } + + @StrutsTagAttribute(description="Set the html disabled attribute on rendered html element") + public void setDisabled(String disabled) { + this.disabled = disabled; + } + + @StrutsTagAttribute(description="Label expression used for rendering a element specific label") + public void setLabel(String label) { + this.label = label; + } + + @StrutsTagAttribute(description="Define label position of form element (top/left)") + public void setLabelposition(String labelPosition) { + this.labelPosition = labelPosition; + } + + @StrutsTagAttribute(description="Define required position of required form element (left|right)") + public void setRequiredposition(String requiredposition) { + this.requiredposition = requiredposition; + } + + @StrutsTagAttribute(description="The name to set for element") + public void setName(String name) { + this.name = name; + } + + @StrutsTagAttribute(description="If set to true, the rendered element will indicate that input is required", type="Boolean", defaultValue="false") + public void setRequired(String required) { + this.required = required; + } + + @StrutsTagAttribute(description="Set the html tabindex attribute on rendered html element") + public void setTabindex(String tabindex) { + this.tabindex = tabindex; + } + + @StrutsTagAttribute(description="Preset the value of input element.") + public void setValue(String value) { + this.value = value; + } + + @StrutsTagAttribute(description="Set the html onclick attribute on rendered html element") + public void setOnclick(String onclick) { + this.onclick = onclick; + } + + @StrutsTagAttribute(description="Set the html ondblclick attribute on rendered html element") + public void setOndblclick(String ondblclick) { + this.ondblclick = ondblclick; + } + + @StrutsTagAttribute(description="Set the html onmousedown attribute on rendered html element") + public void setOnmousedown(String onmousedown) { + this.onmousedown = onmousedown; + } + + @StrutsTagAttribute(description="Set the html onmouseup attribute on rendered html element") + public void setOnmouseup(String onmouseup) { + this.onmouseup = onmouseup; + } + + @StrutsTagAttribute(description="Set the html onmouseover attribute on rendered html element") + public void setOnmouseover(String onmouseover) { + this.onmouseover = onmouseover; + } + + @StrutsTagAttribute(description="Set the html onmousemove attribute on rendered html element") + public void setOnmousemove(String onmousemove) { + this.onmousemove = onmousemove; + } + + @StrutsTagAttribute(description="Set the html onmouseout attribute on rendered html element") + public void setOnmouseout(String onmouseout) { + this.onmouseout = onmouseout; + } + + @StrutsTagAttribute(description="Set the html onfocus attribute on rendered html element") + public void setOnfocus(String onfocus) { + this.onfocus = onfocus; + } + + @StrutsTagAttribute(description=" Set the html onblur attribute on rendered html element") + public void setOnblur(String onblur) { + this.onblur = onblur; + } + + @StrutsTagAttribute(description="Set the html onkeypress attribute on rendered html element") + public void setOnkeypress(String onkeypress) { + this.onkeypress = onkeypress; + } + + @StrutsTagAttribute(description="Set the html onkeydown attribute on rendered html element") + public void setOnkeydown(String onkeydown) { + this.onkeydown = onkeydown; + } + + @StrutsTagAttribute(description="Set the html onkeyup attribute on rendered html element") + public void setOnkeyup(String onkeyup) { + this.onkeyup = onkeyup; + } + + @StrutsTagAttribute(description="Set the html onselect attribute on rendered html element") + public void setOnselect(String onselect) { + this.onselect = onselect; + } + + @StrutsTagAttribute(description="Set the html onchange attribute on rendered html element") + public void setOnchange(String onchange) { + this.onchange = onchange; + } + + @StrutsTagAttribute(description="Set the html accesskey attribute on rendered html element") + public void setAccesskey(String accesskey) { + this.accesskey = accesskey; + } + + @StrutsTagAttribute(description="Set the tooltip of this particular component") + public void setTooltip(String tooltip) { + this.tooltip = tooltip; + } + + @StrutsTagAttribute(description="Set the tooltip configuration") + public void setTooltipConfig(String tooltipConfig) { + this.tooltipConfig = tooltipConfig; + } + + @StrutsTagAttribute(description="Set the key (name, value, label) for this particular component") + public void setKey(String key) { + this.key = key; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/URL.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/URL.java new file mode 100644 index 000000000..1e503bffa --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/URL.java @@ -0,0 +1,425 @@ +/* + * $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.components; + +import java.io.IOException; +import java.io.Writer; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.StrutsException; +import org.apache.struts2.StrutsConstants; +import org.apache.struts2.dispatcher.Dispatcher; +import org.apache.struts2.portlet.context.PortletActionContext; +import org.apache.struts2.portlet.util.PortletUrlHelper; +import org.apache.struts2.views.util.UrlHelper; + +import com.opensymphony.xwork2.inject.Inject; +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + *

        This tag is used to create a URL.

        + * + *

        You can use the "param" tag inside the body to provide + * additional request parameters.

        + * + * NOTE: + *

        By default request parameters will be separated using escaped ampersands (i.e., &amp;). + * This is necessary for XHTML compliance, however, when using the URL generated by this tag + * with the <s:property> tag, the escapeAmp attribute should be used to disable + * ampersand escaping.

        + * + * NOTE: + *

        When includeParams is 'all' or 'get', the parameter defined in param tag will take + * precedence and will not be overriden if they exists in the parameter submitted. For + * example, in Example 3 below, if there is a id parameter in the url where the page this + * tag is included like http://://editUser.action?id=3333&name=John + * the generated url will be http://:/context>/editUser.action?id=22&name=John + * cause the parameter defined in the param tag will take precedence.

        + * + * + * + * + * + * + *
          + *
        • action (String) - (value or action choose either one, if both exist value takes precedence) action's name (alias)
        • + *
        • value (String) - (value or action choose either one, if both exist value takes precedence) the url itself
        • + *
        • scheme (String) - http scheme (http, https) defaults to the scheme this request is in
        • + *
        • namespace - action's namespace
        • + *
        • method (String) - action's method name, defaults to 'execute'
        • + *
        • encode (Boolean) - url encode the generated url. Defaults to 'true'.
        • + *
        • includeParams (String) - The includeParams attribute may have the value 'none', 'get' or 'all'. Defaults to 'get'. + * none - include no parameters in the URL + * get - include only GET parameters in the URL (default) + * all - include both GET and POST parameters in the URL + *
        • + *
        • includeContext (Boolean) - Specifies whether to include the web app context path. Defaults to 'true'.
        • + *
        • escapeAmp (Boolean) - Specifies whether to escape ampersand (&) to (&amp;) or not. Defaults to 'true'.
        • + *
        • portletMode (String) - The resulting portlet mode.
        • + *
        • windowState (String) - The resulting portlet window state.
        • + *
        • portletUrlType (String) - Specifies if this should be a portlet render or action URL.
        • + *
        • forceAddSchemeHostAndPort (Boolean) - Specifies whether to force the addition of scheme, host and port or not.
        • + *
        + * + * + * + *

        Examples + *

        + * 
        + *
        + * <-- Example 1 -->
        + * <s:url value="editGadget.action">
        + *     <s:param name="id" value="%{selected}" />
        + * </s:url>
        + *
        + * <-- Example 2 -->
        + * <s:url action="editGadget">
        + *     <s:param name="id" value="%{selected}" />
        + * </s:url>
        + *
        + * <-- Example 3-->
        + * <s:url includeParams="get"  >
        + *     <s:param name="id" value="%{'22'}" />
        + * </s:url>
        + *
        + * 
        + * 
        + * + * @see Param + * + */ +@StrutsTag(name="url", tldTagClass="org.apache.struts2.views.jsp.URLTag", description="This tag is used to create a URL") +public class URL extends Component { + private static final Log LOG = LogFactory.getLog(URL.class); + + /** + * The includeParams attribute may have the value 'none', 'get' or 'all'. + * It is used when the url tag is used without a value attribute. + * Its value is looked up on the ValueStack + * If no includeParams is specified then 'get' is used. + * none - include no parameters in the URL + * get - include only GET parameters in the URL (default) + * all - include both GET and POST parameters in the URL + */ + public static final String NONE = "none"; + public static final String GET = "get"; + public static final String ALL = "all"; + + private HttpServletRequest req; + private HttpServletResponse res; + + protected String includeParams; + protected String scheme; + protected String value; + protected String action; + protected String namespace; + protected String method; + protected boolean encode = true; + protected boolean includeContext = true; + protected boolean escapeAmp = true; + protected String portletMode; + protected String windowState; + protected String portletUrlType; + protected String anchor; + protected boolean forceAddSchemeHostAndPort; + protected String urlIncludeParams; + protected ExtraParameterProvider extraParameterProvider; + + public URL(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { + super(stack); + this.req = req; + this.res = res; + } + + @Inject(StrutsConstants.STRUTS_URL_INCLUDEPARAMS) + public void setUrlIncludeParams(String urlIncludeParams) { + this.urlIncludeParams = urlIncludeParams; + } + + @Inject(required=false) + public void setExtraParameterProvider(ExtraParameterProvider provider) { + this.extraParameterProvider = provider; + } + + public boolean start(Writer writer) { + boolean result = super.start(writer); + + if (value != null) { + value = findString(value); + } + + // no explicit url set so attach params from current url, do + // this at start so body params can override any of these they wish. + try { + // ww-1266 + String includeParams = (urlIncludeParams != null ? urlIncludeParams.toLowerCase() : GET); + + if (this.includeParams != null) { + includeParams = findString(this.includeParams); + } + + if (NONE.equalsIgnoreCase(includeParams)) { + mergeRequestParameters(value, parameters, Collections.EMPTY_MAP); + } else if (ALL.equalsIgnoreCase(includeParams)) { + mergeRequestParameters(value, parameters, req.getParameterMap()); + + // for ALL also include GET parameters + includeGetParameters(); + includeExtraParameters(); + } else if (GET.equalsIgnoreCase(includeParams) || (includeParams == null && value == null && action == null)) { + includeGetParameters(); + includeExtraParameters(); + } else if (includeParams != null) { + LOG.warn("Unknown value for includeParams parameter to URL tag: " + includeParams); + } + } catch (Exception e) { + LOG.warn("Unable to put request parameters (" + req.getQueryString() + ") into parameter map.", e); + } + + + return result; + } + + private void includeExtraParameters() { + if (extraParameterProvider != null) { + mergeRequestParameters(value, parameters, extraParameterProvider.getExtraParameters()); + } + } + private void includeGetParameters() { + if(!(Dispatcher.getInstance().isPortletSupportActive() && PortletActionContext.isPortletRequest())) { + String query = extractQueryString(); + mergeRequestParameters(value, parameters, UrlHelper.parseQueryString(query)); + } + } + + private String extractQueryString() { + // Parse the query string to make sure that the parameters come from the query, and not some posted data + String query = req.getQueryString(); + if (query == null) { + query = (String) req.getAttribute("javax.servlet.forward.query_string"); + } + + if (query != null) { + // Remove possible #foobar suffix + int idx = query.lastIndexOf('#'); + + if (idx != -1) { + query = query.substring(0, idx); + } + } + return query; + } + + public boolean end(Writer writer, String body) { + String scheme = req.getScheme(); + + if (this.scheme != null) { + scheme = this.scheme; + } + + String result; + if (value == null && action != null) { + if (Dispatcher.getInstance().isPortletSupportActive() && PortletActionContext.isPortletRequest()) { + result = PortletUrlHelper.buildUrl(action, namespace, method, parameters, portletUrlType, portletMode, windowState); + } + else { + result = determineActionURL(action, namespace, method, req, res, parameters, scheme, includeContext, encode, forceAddSchemeHostAndPort, escapeAmp); + } + } else { + if (Dispatcher.getInstance().isPortletSupportActive() && PortletActionContext.isPortletRequest()) { + result = PortletUrlHelper.buildResourceUrl(value, parameters); + } + else { + String _value = value; + + // We don't include the request parameters cause they would have been + // prioritised before this [in start(Writer) method] + if (_value != null && _value.indexOf("?") > 0) { + _value = _value.substring(0, _value.indexOf("?")); + } + result = UrlHelper.buildUrl(_value, req, res, parameters, scheme, includeContext, encode, forceAddSchemeHostAndPort, escapeAmp); + } + } + if ( anchor != null && anchor.length() > 0 ) { + result += '#' + anchor; + } + + String id = getId(); + + if (id != null) { + getStack().getContext().put(id, result); + + // add to the request and page scopes as well + req.setAttribute(id, result); + } else { + try { + writer.write(result); + } catch (IOException e) { + throw new StrutsException("IOError: " + e.getMessage(), e); + } + } + return super.end(writer, body); + } + + @StrutsTagAttribute(description="The includeParams attribute may have the value 'none', 'get' or 'all'", defaultValue="get") + public void setIncludeParams(String includeParams) { + this.includeParams = includeParams; + } + + @StrutsTagAttribute(description="Set scheme attribute") + public void setScheme(String scheme) { + this.scheme = scheme; + } + + @StrutsTagAttribute(description="The target value to use, if not using action") + public void setValue(String value) { + this.value = value; + } + + @StrutsTagAttribute(description="The action to generate the URL for, if not using value") + public void setAction(String action) { + this.action = action; + } + + @StrutsTagAttribute(description="The namespace to use") + public void setNamespace(String namespace) { + this.namespace = namespace; + } + + @StrutsTagAttribute(description="The method of action to use") + public void setMethod(String method) { + this.method = method; + } + + @StrutsTagAttribute(description="Whether to encode parameters", type="Boolean", defaultValue="true") + public void setEncode(boolean encode) { + this.encode = encode; + } + + @StrutsTagAttribute(description="Whether actual context should be included in URL", type="Boolean", defaultValue="true") + public void setIncludeContext(boolean includeContext) { + this.includeContext = includeContext; + } + + @StrutsTagAttribute(description="The resulting portlet mode") + public void setPortletMode(String portletMode) { + this.portletMode = portletMode; + } + + @StrutsTagAttribute(description="The resulting portlet window state") + public void setWindowState(String windowState) { + this.windowState = windowState; + } + + @StrutsTagAttribute(description="Specifies if this should be a portlet render or action URL. Default is \"render\". To create an action URL, use \"action\".") + public void setPortletUrlType(String portletUrlType) { + this.portletUrlType = portletUrlType; + } + + @StrutsTagAttribute(description="The anchor for this URL") + public void setAnchor(String anchor) { + this.anchor = anchor; + } + + @StrutsTagAttribute(description="Specifies whether to escape ampersand (&) to (&amp;) or not", type="Boolean", defaultValue="true") + public void setEscapeAmp(boolean escapeAmp) { + this.escapeAmp = escapeAmp; + } + + @StrutsTagAttribute(description="Specifies whether to force the addition of scheme, host and port or not", type="Boolean", defaultValue="false") + public void setForceAddSchemeHostAndPort(boolean forceAddSchemeHostAndPort) { + this.forceAddSchemeHostAndPort = forceAddSchemeHostAndPort; + } + + + /** + * Merge request parameters into current parameters. If a parameter is + * already present, than the request parameter in the current request and value atrribute + * will not override its value. + * + * The priority is as follows:- + *
          + *
        • parameter from the current request (least priority)
        • + *
        • parameter form the value attribute (more priority)
        • + *
        • parameter from the param tag (most priority)
        • + *
        + * + * @param value the value attribute (url to be generated by this component) + * @param parameters component parameters + * @param contextParameters request parameters + */ + protected void mergeRequestParameters(String value, Map parameters, Map contextParameters){ + + Map mergedParams = new LinkedHashMap(contextParameters); + + // Merge contextParameters (from current request) with parameters specified in value attribute + // eg. value="someAction.action?id=someId&venue=someVenue" + // where the parameters specified in value attribute takes priority. + + if (value != null && value.trim().length() > 0 && value.indexOf("?") > 0) { + mergedParams = new LinkedHashMap(); + + String queryString = value.substring(value.indexOf("?")+1); + + mergedParams = UrlHelper.parseQueryString(queryString); + for (Iterator iterator = contextParameters.entrySet().iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + Object key = entry.getKey(); + + if (!mergedParams.containsKey(key)) { + mergedParams.put(key, entry.getValue()); + } + } + } + + + // Merge parameters specified in value attribute + // eg. value="someAction.action?id=someId&venue=someVenue" + // with parameters specified though param tag + // eg. + // where parameters specified through param tag takes priority. + + for (Iterator iterator = mergedParams.entrySet().iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + Object key = entry.getKey(); + + if (!parameters.containsKey(key)) { + parameters.put(key, entry.getValue()); + } + } + } + + public static interface ExtraParameterProvider { + public Map getExtraParameters(); + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/UpDownSelect.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/UpDownSelect.java new file mode 100644 index 000000000..fc0e8337f --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/UpDownSelect.java @@ -0,0 +1,225 @@ +/* + * $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.components; + +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import com.opensymphony.xwork2.util.ValueStack; + +/** + * + * + * Create a Select component with buttons to move the elements in the select component + * up and down. When the containing form is submited, its elements will be submitted in + * the order they are arranged (top to bottom). + * + * + * + *

        + * + *

        + * 
        + *
        + * <!-- Example 1: simple example -->
        + * <s:updownselect
        + * list="#{'england':'England', 'america':'America', 'germany':'Germany'}"
        + * name="prioritisedFavouriteCountries"
        + * headerKey="-1"
        + * headerValue="--- Please Order Them Accordingly ---"
        + * emptyOption="true" />
        + *
        + * <!-- Example 2: more complex example -->
        + * <s:updownselect
        + * list="defaultFavouriteCartoonCharacters"
        + * name="prioritisedFavouriteCartoonCharacters"
        + * headerKey="-1"
        + * headerValue="--- Please Order ---"
        + * emptyOption="true"
        + * allowMoveUp="true"
        + * allowMoveDown="true"
        + * allowSelectAll="true"
        + * moveUpLabel="Move Up"
        + * moveDownLabel="Move Down"
        + * selectAllLabel="Select All" />
        + *
        + * 
        + * 
        + * + * @version $Date$ $Id$ + * + * @s.tag name="updownselect" tld-body-content="JSP" tld-tag-class="org.apache.struts2.views.jsp.ui.UpDownSelectTag" + * description="Render a up down select element" + */ +@StrutsTag(name="updownselect", tldTagClass="org.apache.struts2.views.jsp.ui.UpDownSelectTag", + description="Create a Select component with buttons to move the elements in the select component up and down") +public class UpDownSelect extends Select { + + private static final Log _log = LogFactory.getLog(UpDownSelect.class); + + + final public static String TEMPLATE = "updownselect"; + + protected String allowMoveUp; + protected String allowMoveDown; + protected String allowSelectAll; + + protected String moveUpLabel; + protected String moveDownLabel; + protected String selectAllLabel; + + + public String getDefaultTemplate() { + return TEMPLATE; + } + + public UpDownSelect(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + public void evaluateParams() { + super.evaluateParams(); + + + // override Select's default + if (size == null || size.trim().length() <= 0) { + addParameter("size", "5"); + } + if (multiple == null || multiple.trim().length() <= 0) { + addParameter("multiple", Boolean.TRUE); + } + + + + if (allowMoveUp != null) { + addParameter("allowMoveUp", findValue(allowMoveUp, Boolean.class)); + } + if (allowMoveDown != null) { + addParameter("allowMoveDown", findValue(allowMoveDown, Boolean.class)); + } + if (allowSelectAll != null) { + addParameter("allowSelectAll", findValue(allowSelectAll, Boolean.class)); + } + + if (moveUpLabel != null) { + addParameter("moveUpLabel", findString(moveUpLabel)); + } + if (moveDownLabel != null) { + addParameter("moveDownLabel", findString(moveDownLabel)); + } + if (selectAllLabel != null) { + addParameter("selectAllLabel", findString(selectAllLabel)); + } + + + // inform our form ancestor about this UpDownSelect so the form knows how to + // auto select all options upon it submission + Form ancestorForm = (Form) findAncestor(Form.class); + if (ancestorForm != null) { + + // inform form ancestor that we are using a custom onsubmit + enableAncestorFormCustomOnsubmit(); + + Map m = (Map) ancestorForm.getParameters().get("updownselectIds"); + if (m == null) { + // map with key -> id , value -> headerKey + m = new LinkedHashMap(); + } + m.put(getParameters().get("id"), getParameters().get("headerKey")); + ancestorForm.getParameters().put("updownselectIds", m); + } + else { + _log.warn("no ancestor form found for updownselect "+this+", therefore autoselect of all elements upon form submission will not work "); + } + } + + + public String getAllowMoveUp() { + return allowMoveUp; + } + + @StrutsTagAttribute(description="Whether move up button should be displayed", type="Boolean", defaultValue="true") + public void setAllowMoveUp(String allowMoveUp) { + this.allowMoveUp = allowMoveUp; + } + + + + public String getAllowMoveDown() { + return allowMoveDown; + } + + @StrutsTagAttribute(description="Whether move down button should be displayed", type="Boolean", defaultValue="true") + public void setAllowMoveDown(String allowMoveDown) { + this.allowMoveDown = allowMoveDown; + } + + + + public String getAllowSelectAll() { + return allowSelectAll; + } + + @StrutsTagAttribute(description="Whether or not select all button should be displayed", type="Boolean", defaultValue="true") + public void setAllowSelectAll(String allowSelectAll) { + this.allowSelectAll = allowSelectAll; + } + + + public String getMoveUpLabel() { + return moveUpLabel; + } + + @StrutsTagAttribute(description="Text to display on the move up button", defaultValue="^") + public void setMoveUpLabel(String moveUpLabel) { + this.moveUpLabel = moveUpLabel; + } + + + + public String getMoveDownLabel() { + return moveDownLabel; + } + + @StrutsTagAttribute(description="Text to display on the move down button", defaultValue="v") + public void setMoveDownLabel(String moveDownLabel) { + this.moveDownLabel = moveDownLabel; + } + + + + public String getSelectAllLabel() { + return selectAllLabel; + } + + @StrutsTagAttribute(description="Text to display on the select all button", defaultValue="*") + public void setSelectAllLabel(String selectAllLabel) { + this.selectAllLabel = selectAllLabel; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/AbstractFilterModel.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/AbstractFilterModel.java new file mode 100644 index 000000000..f3a39bd81 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/AbstractFilterModel.java @@ -0,0 +1,104 @@ +/* + * $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.components.table; + +import java.util.Vector; + +import javax.swing.table.AbstractTableModel; +import javax.swing.table.DefaultTableModel; +import javax.swing.table.TableModel; + + +/** + */ +abstract public class AbstractFilterModel extends AbstractTableModel { + + protected TableModel model; + + + public AbstractFilterModel(TableModel tm) { + model = tm; + } + + + public boolean isCellEditable(int par1, int par2) { + return model.isCellEditable(par1, par2); + } + + public Class getColumnClass(int par1) { + return model.getColumnClass(par1); + } + + public int getColumnCount() { + return model.getColumnCount(); + } + + public String getColumnName(int par1) { + return model.getColumnName(par1); + } + + public void setModel(TableModel model) { + this.model = model; + this.fireTableDataChanged(); + } + + public TableModel getModel() { + return model; + } + + public int getRowCount() { + return model.getRowCount(); + } + + public void setValueAt(Object par1, int par2, int par3) { + model.setValueAt(par1, par2, par3); + } + + public Object getValueAt(int par1, int par2) { + return model.getValueAt(par1, par2); + } + + public void addRow(Vector data) throws IllegalStateException { + if (model instanceof DefaultTableModel) { + ((DefaultTableModel) model).addRow(data); + } else if (model instanceof AbstractFilterModel) { + ((AbstractFilterModel) model).addRow(data); + } else { + throw (new IllegalStateException("Error attempting to add a row to an underlying model that is not a DefaultTableModel.")); + } + } + + public void removeAllRows() throws ArrayIndexOutOfBoundsException, IllegalStateException { + while (this.getRowCount() > 0) { + this.removeRow(0); + } + } + + public void removeRow(int rowNum) throws ArrayIndexOutOfBoundsException, IllegalStateException { + if (model instanceof DefaultTableModel) { + ((DefaultTableModel) model).removeRow(rowNum); + } else if (model instanceof AbstractFilterModel) { + ((AbstractFilterModel) model).removeRow(rowNum); + } else { + throw (new IllegalStateException("Error attempting to remove a row from an underlying model that is not a DefaultTableModel.")); + } + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/RenderFilterModel.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/RenderFilterModel.java new file mode 100644 index 000000000..9ab1d5e14 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/RenderFilterModel.java @@ -0,0 +1,47 @@ +/* + * $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.components.table; + +import javax.swing.table.TableModel; + + +/** + */ +public class RenderFilterModel extends AbstractFilterModel { + + private static final long serialVersionUID = -2501708467650344057L; + + private boolean rendered; + + + public RenderFilterModel(TableModel tm) { + super(tm); + } + + + public void setRendered(boolean rendered) { + this.rendered = rendered; + } + + public boolean isRendered() { + return rendered; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/SortFilterModel.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/SortFilterModel.java new file mode 100644 index 000000000..402343e81 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/SortFilterModel.java @@ -0,0 +1,199 @@ +/* + * $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.components.table; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collections; + +import javax.swing.JTable; +import javax.swing.event.TableModelEvent; +import javax.swing.event.TableModelListener; +import javax.swing.table.TableModel; + + +/** + */ +public class SortFilterModel extends AbstractFilterModel implements TableModelListener, SortableTableModel { + + private static final long serialVersionUID = 2214225803442793597L; + + private ArrayList rows = new ArrayList(); + + /** + * These are just here to implement the interface + */ + private String _sortDirection = NONE; + private boolean dirty = true; + private int sortColumn = -1; + + + public SortFilterModel(TableModel tm) { + super(tm); + setModel(tm); + } + + + public boolean isCellEditable(int r, int c) { + if ((rows.size() > 0) && (r < rows.size())) { + return model.isCellEditable(((Row) rows.get(r)).index, c); + } + + return false; + } + + public void setModel(TableModel tm) { + super.setModel(tm); + rows.ensureCapacity(model.getRowCount()); + model.addTableModelListener(this); + sortColumn = -1; + dirty = true; + refresh(); + } + + public int getSortedColumnNumber() { + return sortColumn; + } + + public String getSortedDirection(int columnNumber) { + if (getSortedColumnNumber() < 0) { + return NONE; + } + + return _sortDirection; + } + + public void setValueAt(Object aValue, int r, int c) { + if ((rows.size() > 0) && (r < rows.size())) { + model.setValueAt(aValue, ((Row) rows.get(r)).index, c); + } + } + + /* compute the moved row for the three methods that access + model elements + */ + public Object getValueAt(int r, int c) { + if ((rows.size() > 0) && (r < rows.size())) { + return model.getValueAt(((Row) rows.get(r)).index, c); + } + + return null; + } + + public void addMouseListener(final JTable table) { + table.getTableHeader().addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent event) { + // check for double click + if (event.getClickCount() < 2) { + return; + } + + // find column of click and + int tableColumn = table.columnAtPoint(event.getPoint()); + + // translate to table model index and sort + int modelColumn = table.convertColumnIndexToModel(tableColumn); + sort(modelColumn); + } + }); + } + + public void removeRow(int rowNum) throws ArrayIndexOutOfBoundsException, IllegalStateException { + int mappedRow = ((Row) rows.get(rowNum)).index; + super.removeRow(mappedRow); + } + + public void sort(int columnNumber, String direction) { + _sortDirection = ASC; + dirty = true; + sort(columnNumber); + + if (DESC.equals(direction)) { + sort(columnNumber); + _sortDirection = DESC; + } + } + + /** + * Implements the TableModelListener interface to receive + * notifications of * changes to the table model. SortFilterModel needs + * to receive events for adding and removing rows. + */ + public void tableChanged(TableModelEvent e) { + dirty = true; + refresh(); + fireTableChanged(e); + } + + protected void refresh() { + rows.clear(); + + for (int i = 0; i < model.getRowCount(); i++) { + rows.add(new Row(i)); + } + + if (dirty && (sortColumn > -1)) { + sort(sortColumn); + } + } + + protected void sort(int c) { + boolean sorted = (sortColumn == c); + sortColumn = c; + + if (dirty || !sorted) { + Collections.sort(rows); + dirty = false; + } else { + Collections.reverse(rows); + } + + fireTableDataChanged(); + } + + + /* this inner class holds the index of the model row + * Rows are compared by looking at the model row entries + * in the sort column + */ + private class Row implements Comparable { + public int index; + + public Row(int index) { + this.index = index; + } + + public int compareTo(Object other) { + Row otherRow = (Row) other; + Object a = model.getValueAt(index, sortColumn); + Object b = model.getValueAt(otherRow.index, sortColumn); + + boolean areTheyCompareable = (a instanceof Comparable && b instanceof Comparable && (a.getClass() == b.getClass())); + + if (areTheyCompareable) { + return ((Comparable) a).compareTo((Comparable) b); + } else { + return a.toString().compareTo(b.toString()); + } + } + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/SortableTableModel.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/SortableTableModel.java new file mode 100644 index 000000000..e060980db --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/SortableTableModel.java @@ -0,0 +1,40 @@ +/* + * $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.components.table; + +import javax.swing.table.TableModel; + + +/** + */ +public interface SortableTableModel extends TableModel { + + final static public String NONE = "NONE"; + final static public String ASC = "ASC"; + final static public String DESC = "DESC"; + + + public int getSortedColumnNumber(); + + public String getSortedDirection(int columnNumber); + + public void sort(int columnNumber, String direction); +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/WebTable.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/WebTable.java new file mode 100644 index 000000000..88d9fa352 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/WebTable.java @@ -0,0 +1,354 @@ +/* + * $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.components.table; + +import java.io.Writer; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.swing.table.TableModel; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; +import org.apache.struts2.StrutsException; +import org.apache.struts2.components.GenericUIBean; +import org.apache.struts2.components.table.renderer.CellRenderer; + +import com.opensymphony.xwork2.util.ValueStack; + +@StrutsTag(name="table", tldTagClass="org.apache.struts2.views.jsp.ui.table.WebTableTag", description="Instantiate a JavaBean and place it in the context") +public class WebTable extends GenericUIBean { + private static final Log LOG = LogFactory.getLog(WebTable.class); + + final public static String TEMPLATE = "table"; + + protected String sortOrder = SortableTableModel.NONE; + protected String modelName = null; + protected TableModel model = null; + protected WebTableColumn[] columns = null; + protected boolean sortableAttr = false; + protected int sortColumn = -1; + protected int curRow = 0; + + public WebTable(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + protected String getDefaultTemplate() { + return TEMPLATE; + } + + public boolean end(Writer writer, String body) { + if (sortableAttr && model instanceof SortableTableModel) { + LOG.debug("we are looking for " + getSortColumnLinkName()); + + String sortColumn = request.getParameter(getSortColumnLinkName()); + String sortOrder = request.getParameter(getSortOrderLinkName()); + + try { + if ((sortColumn != null) || (sortOrder != null)) { + if (sortColumn != null) { + try { + this.sortColumn = Integer.parseInt(sortColumn); + } catch (Exception ex) { + if (LOG.isDebugEnabled()) { + LOG.debug("coudn't convert column, take default"); + } + } + } + + if (sortOrder != null) { + this.sortOrder = sortOrder; + } + } else { + LOG.debug("no sorting info in the request"); + } + + if (this.sortColumn >= 0) { + LOG.debug("we have the sortColumn " + Integer.toString(this.sortColumn)); + LOG.debug("we have the sortOrder " + this.sortOrder); + + try { + ((SortableTableModel) model).sort(this.sortColumn, this.sortOrder); + } catch (Exception ex) { + if (LOG.isDebugEnabled()) { + LOG.debug("couldn't sort the data"); + } + } + + LOG.debug("we just sorted the data"); + } + } catch (Exception e) { + throw new StrutsException("Error with WebTable: " + toString(e), e); + } + } + + return super.end(writer, body); + } + + public WebTableColumn getColumn(int index) { + try { + return (columns[index]); + } catch (Exception E) { + //blank + } + + return null; + } + + protected void evaluateExtraParams() { + if (modelName != null) { + modelName = findString(modelName); + + Object obj = stack.findValue(this.modelName); + + if (obj instanceof TableModel) { + setModel((TableModel) obj); + } + } + + super.evaluateExtraParams(); + } + + protected int getNumberOfVisibleColumns() { + int count = 0; + + for (int i = 0; i < columns.length; ++i) { + if (!columns[i].isHidden()) { + ++count; + } + } + + return count; + } + + public int getColumnCount() { + return (columns.length); + } + + public void setColumnDisplayName(int column, String displayName) { + columns[column].setDisplayName(displayName); + } + + public void getColumnDisplayName(int column) { + columns[column].getDisplayName(); + } + + public void setColumnHidden(int column, boolean hide) { + columns[column].setHidden(hide); + } + + public boolean isColumnHidden(int column) { + return columns[column].isHidden(); + } + + public void setColumnRenderer(int column, CellRenderer renderer) { + columns[column].setRenderer(renderer); + } + + public CellRenderer getColumnRenderer(int column) { + return columns[column].getRenderer(); + } + + public WebTableColumn[] getColumns() { + return columns; + } + + public String[] getFormattedRow(int row) { + ArrayList data = new ArrayList(getNumberOfVisibleColumns()); + + for (int i = 0; i < getColumnCount(); ++i) { + if (columns[i].isVisible()) { + data.add(columns[i].getRenderer().renderCell(this, model.getValueAt(row, i), row, i)); + } + } + + return (String[]) data.toArray(new String[0]); + } + + public void setModel(TableModel model) { + this.model = model; + columns = new WebTableColumn[this.model.getColumnCount()]; + + for (int i = 0; i < columns.length; ++i) { + columns[i] = new WebTableColumn(this.model.getColumnName(i), i); + } + + if ((sortableAttr) && !(this.model instanceof SortableTableModel)) { + this.model = new SortFilterModel(this.model); + } + } + + public TableModel getModel() { + return (model); + } + + /** + * The name of model to use + * @s.tagattribute required="true" type="String" + */ + public void setModelName(String modelName) { + this.modelName = modelName; + } + + public String getModelName() { + return modelName; + } + + public Object getRawData(int row, int column) { + return model.getValueAt(row, column); + } + + public Iterator getRawDataRowIterator() { + return new WebTableRowIterator(this, WebTableRowIterator.RAW_DATA); + } + + public Object[] getRow(int row) { + ArrayList data = new ArrayList(getNumberOfVisibleColumns()); + + for (int i = 0; i < getColumnCount(); ++i) { + if (columns[i].isVisible()) { + data.add(model.getValueAt(row, i)); + } + } + + return data.toArray(new Object[0]); + } + + public int getRowCount() { + return model.getRowCount(); + } + + public Iterator getRowIterator() { + return new WebTableRowIterator(this); + } + + @StrutsTagAttribute(description="Index of column to sort data by", type="Integer") + public void setSortColumn(int sortColumn) { + this.sortColumn = sortColumn; + } + + public int getSortColumn() { + if (model instanceof SortableTableModel) { + return ((SortableTableModel) model).getSortedColumnNumber(); + } + + return -1; + } + + public String getSortColumnLinkName() { + return "WEBTABLE_" + modelName + "_SORT_COLUMN"; + } + + @StrutsTagAttribute(description="Set sort order. Allowed values are NONE, ASC and DESC", defaultValue="NONE") + public void setSortOrder(String sortOrder) { + if (sortOrder.equals(SortableTableModel.NONE)) { + this.sortOrder = SortableTableModel.NONE; + } else if (sortOrder.equals(SortableTableModel.DESC)) { + this.sortOrder = SortableTableModel.DESC; + } else if (sortOrder.equals(SortableTableModel.ASC)) { + this.sortOrder = SortableTableModel.ASC; + } else { + this.sortOrder = SortableTableModel.NONE; + } + } + + public String getSortOrder() { + if ((model instanceof SortableTableModel) && (getSortColumn() >= 0)) { + return ((SortableTableModel) model).getSortedDirection(getSortColumn()); + } + + return SortableTableModel.NONE; + } + + public String getSortOrderLinkName() { + return "WEBTABLE_" + modelName + "_SORT_ORDER"; + } + + @StrutsTagAttribute(description="Whether the table should be sortable. Requires that model implements " + + "org.apache.struts2.components.table.SortableTableModel if set to true.", type="Boolean", defaultValue="false") + public void setSortable(boolean sortable) { + sortableAttr = sortable; + + if ((sortableAttr) && (model != null) && !(model instanceof SortableTableModel)) { + model = new SortFilterModel(model); + } + } + + public boolean isSortable() { + return sortableAttr; + } + + /** + * inner class to iteratoe over a row of the table. + * It can return formatted data, using the columnRenderer + * for the column or it can return the raw data. + */ + public class WebTableRowIterator implements Iterator { + public static final int FORMATTED_DATA = 0; + public static final int RAW_DATA = 1; + protected WebTable _table; + protected int _curRow = 0; + protected int _mode = 0; + + protected WebTableRowIterator(WebTable table) { + this(table, FORMATTED_DATA); + } + + protected WebTableRowIterator(WebTable table, int mode) { + _table = table; + _mode = mode; + } + + public boolean hasNext() { + if (_table == null) { + return false; + } + + return (_table.getRowCount() > _curRow); + } + + public Object next() throws NoSuchElementException { + if (_table == null) { + throw new NoSuchElementException("WebTable is null"); + } + + if (!hasNext()) { + throw new NoSuchElementException("Beyond end of WebTable"); + } + + if (_mode == RAW_DATA) { + return _table.getRow(_curRow++); + } + + return _table.getFormattedRow(_curRow++); + } + + public void remove() throws UnsupportedOperationException, IllegalStateException { + throw new UnsupportedOperationException("Remove not supported in WebTable"); + } + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/WebTableColumn.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/WebTableColumn.java new file mode 100644 index 000000000..8b46195e5 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/WebTableColumn.java @@ -0,0 +1,84 @@ +/* + * $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.components.table; + +import org.apache.struts2.components.table.renderer.CellRenderer; +import org.apache.struts2.components.table.renderer.DefaultCellRenderer; + + +/** + */ +public class WebTableColumn { + + static final private CellRenderer DEFAULT_RENDERER = new DefaultCellRenderer(); + + + CellRenderer _renderer = null; + String _displayName = null; + String _name = null; + boolean _hidden = false; + int _offset = -1; + + + public WebTableColumn(String name, int offset) { + _name = name; + _offset = offset; + _displayName = name; + _renderer = DEFAULT_RENDERER; + } + + + public void setDisplayName(String displayName) { + _displayName = displayName; + } + + public String getDisplayName() { + return (_displayName); + } + + public void setHidden(boolean hidden) { + _hidden = hidden; + } + + public boolean isHidden() { + return _hidden; + } + + public String getName() { + return (_name); + } + + public int getOffset() { + return (_offset); + } + + public void setRenderer(CellRenderer renderer) { + _renderer = renderer; + } + + public CellRenderer getRenderer() { + return (_renderer); + } + + public boolean isVisible() { + return !isHidden(); + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/AbstractCellRenderer.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/AbstractCellRenderer.java new file mode 100644 index 000000000..a9009f2e9 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/AbstractCellRenderer.java @@ -0,0 +1,74 @@ +/* + * $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.components.table.renderer; + +import org.apache.struts2.components.table.WebTable; + + +/** + * this is the base class that most renderers will be derived from. + * It allows setting the alignment. Subclasses should set there actuall + * content by implementing getCellValue + */ +abstract public class AbstractCellRenderer implements CellRenderer { + + /** + * used for horizontal cell alignmnet + */ + protected String _alignment = null; + + + public void setAlignment(String alignment) { + _alignment = alignment; + } + + public String getAlignment() { + return _alignment; + } + + /** + * implememnts CellRenderer renderCell. It sets the alignment. gets the actual + * data from getCellValue + */ + public String renderCell(WebTable table, Object data, int row, int col) { + if (isAligned()) { + StringBuffer buf = new StringBuffer(256); + buf.append("
        "); + buf.append(getCellValue(table, data, row, col)); + buf.append("
        "); + + return buf.toString(); + } + + return getCellValue(table, data, row, col); + } + + protected boolean isAligned() { + return _alignment != null; + } + + /** + * this is the method that subclasses need to implement to set their value. + * they should not override renderCell unless they want to change the alignmnent + * renderering + */ + abstract protected String getCellValue(WebTable table, Object data, int row, int col); +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/BooleanCellRenderer.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/BooleanCellRenderer.java new file mode 100644 index 000000000..b9a8cadae --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/BooleanCellRenderer.java @@ -0,0 +1,65 @@ +/* + * $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.components.table.renderer; + +import org.apache.struts2.components.table.WebTable; + + +/** + */ +public class BooleanCellRenderer extends AbstractCellRenderer { + + /** + * value used if the boolean object is false + */ + protected String _falseValue = "false"; + + /** + * value used if the boolean object is true + */ + protected String _trueValue = "true"; + + + public BooleanCellRenderer() { + super(); + } + + + public String getCellValue(WebTable table, Object data, int row, int col) { + if (data == null) { + return ""; + } + + if (data instanceof Boolean) { + return ((Boolean) data).booleanValue() ? _trueValue : _falseValue; + } + + return data.toString(); //if here then not a boolean + } + + public void setFalseValue(String falseValue) { + _falseValue = falseValue; + } + + public void setTrueValue(String trueValue) { + _trueValue = trueValue; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/CellRenderer.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/CellRenderer.java new file mode 100644 index 000000000..0364fadbf --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/CellRenderer.java @@ -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 org.apache.struts2.components.table.renderer; + +import org.apache.struts2.components.table.WebTable; + +/** + */ +public interface CellRenderer { + + public String renderCell(WebTable table, Object data, int row, int col); +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/DateCellRenderer.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/DateCellRenderer.java new file mode 100644 index 000000000..e0cca59b0 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/DateCellRenderer.java @@ -0,0 +1,64 @@ +/* + * $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.components.table.renderer; + +import java.text.SimpleDateFormat; + +import org.apache.struts2.components.table.WebTable; + + +/** + */ +public class DateCellRenderer extends AbstractCellRenderer { + + SimpleDateFormat _formater = new SimpleDateFormat(); + + /** + * this is the string that SimpleDateFormat needs to display the date + * + * @see SimpleDateFormat + */ + String _formatString = null; + + + public DateCellRenderer() { + super(); + } + + + public String getCellValue(WebTable table, Object data, int row, int col) { + + if (data == null) { + return ""; + } + + if (data instanceof java.util.Date) { + return _formater.format((java.util.Date) data); + } + + return data.toString(); + } + + public void setFormatString(String format) { + _formatString = format; + _formater.applyPattern(_formatString); + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/DefaultCellRenderer.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/DefaultCellRenderer.java new file mode 100644 index 000000000..5b7b5ace6 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/DefaultCellRenderer.java @@ -0,0 +1,42 @@ +/* + * $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.components.table.renderer; + +import org.apache.struts2.components.table.WebTable; + + +/** + */ +public class DefaultCellRenderer extends AbstractCellRenderer { + + public DefaultCellRenderer() { + super(); + } + + + public String getCellValue(WebTable table, Object data, int row, int col) { + if (data != null) { + return data.toString(); + } + + return "null"; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/FixedTextCellRenderer.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/FixedTextCellRenderer.java new file mode 100644 index 000000000..aa877c2f7 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/FixedTextCellRenderer.java @@ -0,0 +1,49 @@ +/* + * $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.components.table.renderer; + +import org.apache.struts2.components.table.WebTable; + + +/** + * usefull if a column has an embeded ID number needed for a link but you want it to + * say something else. + */ +public class FixedTextCellRenderer extends AbstractCellRenderer { + + /** + * this is the text that will be shown in the column + */ + protected String _text = ""; + + + public String getCellValue(WebTable table, Object data, int row, int col) { + return _text; + } + + public void setText(String text) { + _text = text; + } + + public String getText() { + return _text; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/LinkCellRenderer.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/LinkCellRenderer.java new file mode 100644 index 000000000..ec98a35a5 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/LinkCellRenderer.java @@ -0,0 +1,243 @@ +/* + * $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.components.table.renderer; + +import org.apache.struts2.components.table.WebTable; + + +/** + */ +public class LinkCellRenderer extends AbstractCellRenderer { + + /** + * this is the actual renderer tha will be used to display the text + */ + protected CellRenderer _delegateRenderer = new DefaultCellRenderer(); + + /** + * the CSS class this link belongs to. Optional + */ + protected String _cssClass = null; + + /** + * the id attribute this link belongs to. Optional + */ + protected String _cssId = null; + + /** + * this is the link we are setting (required) + */ + protected String _link = null; + + /** + * the (Java)script/ function to execute when the link is clicked. Optional + */ + protected String _onclick = null; + + /** + * the (Java)script/ function to execute when the link is clicked twice. Optional + */ + protected String _ondblclick = null; + + /** + * the (Java)script/ function to execute when cursor is away from the link. Optional + */ + protected String _onmouseout = null; + + /** + * the (Java)script/ function to execute when cursor is over the link. Optional + */ + protected String _onmouseover = null; + + /** + * if set there will be a parameter attached to link. (optional) + * This should be extended to allow multiple parameters + */ + protected String _param = null; + + /** + * directly set the value for the param. Will overide paramColumn if set. + * optional. Either this or paramColumn must be set if param is used. + * Will be ignored if param not used + */ + protected String _paramValue = null; + + /** + * the target frame to open in. Optional + */ + protected String _target = null; + + /** + * the title attribute this link belongs to. Optional + */ + protected String _title = null; + + /** + * additional parameters after the above parameter is generated. Optional + */ + protected String _trailParams = null; + + /** + * if used the param value will be taken from another column in the table. Useful if each row + * needs a different paramter. The paramter can be taken from a hidden cell. + * if paramValue is also set it will overrid this. (option either this or paramValue must be set + * if param is used. Will be ignored if param not used + */ + protected int _paramColumn = -1; + + + public LinkCellRenderer() { + } + + + /** + * should the link data be encodeed? + */ + public String getCellValue(WebTable table, Object data, int row, int col) { + String value = _delegateRenderer.renderCell(table, data, row, col); + + StringBuffer cell = new StringBuffer(256); + cell.append("").append(value).append(""); + + return cell.toString(); + } + + public void setCssClass(String cssClass) { + _cssClass = cssClass; + } + + public void setCssId(String cssId) { + _cssId = cssId; + } + + public void setLink(String link) { + _link = link; + } + + public void setOnclick(String onclick) { + _onclick = onclick; + } + + public void setOndblclick(String ondblclick) { + _ondblclick = ondblclick; + } + + public void setOnmouseout(String onmouseout) { + _onmouseout = onmouseout; + } + + public void setOnmouseover(String onmouseover) { + _onmouseover = onmouseover; + } + + public void setParam(String param) { + _param = param; + } + + public void setParamColumn(int paramColumn) { + _paramColumn = paramColumn; + } + + public void setParamValue(String paramValue) { + _paramValue = paramValue; + } + + /** + * used to set the renderer to delgate to. + * if the render is an AbstractCellRenderer then it will take the alignment from + * the delegate renderer and set it that way. + */ + public void setRenderer(CellRenderer delegateRenderer) { + _delegateRenderer = delegateRenderer; + + if (_delegateRenderer instanceof AbstractCellRenderer) { + setAlignment(((AbstractCellRenderer) _delegateRenderer).getAlignment()); + } + } + + public void setTarget(String target) { + _target = target; + } + + public void setTitle(String title) { + _title = title; + } + + public void setTrailParams(String trailParams) { + _trailParams = trailParams; + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/NumericCellRenderer.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/NumericCellRenderer.java new file mode 100644 index 000000000..f249b6195 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/NumericCellRenderer.java @@ -0,0 +1,103 @@ +/* + * $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.components.table.renderer; + +import java.text.DecimalFormat; + +import org.apache.struts2.components.table.WebTable; + + +/** + */ +public class NumericCellRenderer extends AbstractCellRenderer { + + DecimalFormat _formater = new DecimalFormat(); + + /** + * this is the format string that DecimalFormat would use. + * + * @see DecimalFormat + */ + String _formatString = null; + + /** + * if set the is the color to use if Number is negative. + */ + String _negativeColor = null; + + /** + * if set this is the color to render if number is positive + */ + String _positiveColor = null; + + + public NumericCellRenderer() { + super(); + } + + + public String getCellValue(WebTable table, Object data, int row, int col) { + StringBuffer retVal = new StringBuffer(128); + + if (data == null) { + return ""; + } + + if (data instanceof Number) { + double cellValue = ((Number) data).doubleValue(); + + if (cellValue >= 0) { + processNumber(retVal, _positiveColor, cellValue); + } else { + processNumber(retVal, _negativeColor, cellValue); + } + + return retVal.toString(); + } + + return data.toString(); + } + + public void setFormatString(String format) { + _formatString = format; + _formater.applyPattern(_formatString); + } + + public void setNegativeColor(String color) { + _negativeColor = color; + } + + public void setPositiveColor(String color) { + _positiveColor = color; + } + + protected void processNumber(StringBuffer buf, String color, double cellValue) { + if (color != null) { + buf.append(" "); + } + + buf.append(_formater.format(cellValue)); + + if (color != null) { + buf.append(""); + } + } +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/package.html b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/package.html new file mode 100644 index 000000000..887a55ccd --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/table/renderer/package.html @@ -0,0 +1,23 @@ + +JSP UI tags for rendering table output in HTML. diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/template/BaseTemplateEngine.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/template/BaseTemplateEngine.java new file mode 100644 index 000000000..de4fd1b9b --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/template/BaseTemplateEngine.java @@ -0,0 +1,110 @@ +/* + * $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.components.template; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.opensymphony.xwork2.util.ClassLoaderUtil; + +/** + * Base class for template engines. + */ +public abstract class BaseTemplateEngine implements TemplateEngine { + + private static final Log LOG = LogFactory.getLog(BaseTemplateEngine.class); + + /** The default theme properties file name. Default is 'theme.properties' */ + public static final String DEFAULT_THEME_PROPERTIES_FILE_NAME = "theme.properties"; + + final Map themeProps = new HashMap(); + + public Map getThemeProps(Template template) { + synchronized (themeProps) { + Properties props = (Properties) themeProps.get(template.getTheme()); + if (props == null) { + String propName = template.getDir() + "/" + template.getTheme() + "/"+getThemePropertiesFileName(); + + // WW-1292 + // let's try getting it from the filesystem + File propFile = new File(propName); + InputStream is = null; + try { + if (propFile.exists()) { + is = new FileInputStream(propFile); + } + } + catch(FileNotFoundException e) { + LOG.warn("Unable to find file in filesystem ["+propFile.getAbsolutePath()+"]"); + } + + if (is == null) { + // if its not in filesystem. let's try the classpath + is = ClassLoaderUtil.getResourceAsStream(propName, getClass()); + } + + props = new Properties(); + + if (is != null) { + try { + props.load(is); + } catch (IOException e) { + LOG.error("Could not load " + propName, e); + } finally { + try { + is.close(); + } catch(IOException io) { + LOG.warn("Unable to close input stream", io); + } + } + } + + themeProps.put(template.getTheme(), props); + } + + return props; + } + } + + protected String getFinalTemplateName(Template template) { + String t = template.toString(); + if (t.indexOf(".") <= 0) { + return t + "." + getSuffix(); + } + + return t; + } + + protected String getThemePropertiesFileName() { + return DEFAULT_THEME_PROPERTIES_FILE_NAME; + } + + protected abstract String getSuffix(); +} diff --git a/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java new file mode 100644 index 000000000..ec3cf7b02 --- /dev/null +++ b/STRUTS_2_0_X/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java @@ -0,0 +1,213 @@ +/* + * $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.components.template; + +import java.io.IOException; +import java.io.Writer; +import java.util.*; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.struts2.ServletActionContext; +import org.apache.struts2.StrutsConstants; +import org.apache.struts2.views.freemarker.FreemarkerManager; + +import com.opensymphony.xwork2.inject.Inject; +import com.opensymphony.xwork2.util.ClassLoaderUtil; +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ActionInvocation; +import com.opensymphony.xwork2.util.ValueStack; + +import freemarker.template.*; + +/** + * Freemarker based template engine. + */ +public class FreemarkerTemplateEngine extends BaseTemplateEngine { + static Class bodyContent = null; + private FreemarkerManager freemarkerManager; + + private final HashMap templates = new HashMap(); + private final HashSet missingTemplates = new HashSet(); + private boolean freemarkerCaching = false; + + static { + try { + bodyContent = ClassLoaderUtil.loadClass("javax.servlet.jsp.tagext.BodyContent", + FreemarkerTemplateEngine.class); + } catch (ClassNotFoundException e) { + // this is OK -- this just means JSP isn't even being used here, which is perfectly fine. + // we need this class in environments that use JSP to know when to wrap the writer + // and ignore flush() calls. In JSP, it is illegal for a BodyContent writer to be flushed(), + // so we have to take caution here. + } + } + + private static final Log LOG = LogFactory.getLog(FreemarkerTemplateEngine.class); + + @Inject + public void setFreemarkerManager(FreemarkerManager mgr) { + this.freemarkerManager = mgr; + } + + public void renderTemplate(TemplateRenderingContext templateContext) throws Exception { + // get the various items required from the stack + ValueStack stack = templateContext.getStack(); + Map context = stack.getContext(); + ServletContext servletContext = (ServletContext) context.get(ServletActionContext.SERVLET_CONTEXT); + HttpServletRequest req = (HttpServletRequest) context.get(ServletActionContext.HTTP_REQUEST); + HttpServletResponse res = (HttpServletResponse) context.get(ServletActionContext.HTTP_RESPONSE); + + // prepare freemarker + Configuration config = freemarkerManager.getConfiguration(servletContext); + + // get the list of templates we can use + List