From da8c7278d522445806cece06e8ed2e306c8603ff Mon Sep 17 00:00:00 2001 From: Peter Hormanns Date: Fri, 10 Jun 2016 19:34:43 +0200 Subject: [PATCH] converted to maven project --- .gitignore | 13 + LICENSE.txt | 661 ++++++++++++++++++ authorization/.gitignore | 13 + authorization/LICENSE.txt | 661 ++++++++++++++++++ authorization/pom.xml | 54 ++ .../de/hsadmin/login/CASTicketValidator.java | 60 ++ .../java/de/hsadmin/login/LoginService.java | 94 +++ .../de/hsadmin/login/LoginServiceLocal.java | 13 + .../java/de/hsadmin/login/RequestContext.java | 21 + .../java/de/hsadmin/login/RequiredScope.java | 14 + .../src/main/java/de/hsadmin/login/Role.java | 7 + .../java/de/hsadmin/login/ScopePolicy.java | 9 + .../de/hsadmin/login/TestTicketValidator.java | 12 + .../de/hsadmin/login/TicketValidator.java | 10 + cli/.gitignore | 13 + cli/LICENSE.txt | 661 ++++++++++++++++++ cli/pom.xml | 52 ++ cli/src/main/java/de/hsadmin/jscli/Main.java | 80 +++ .../main/java/de/hsadmin/jscli/RpcClient.java | 92 +++ .../java/de/hsadmin/jscli/ScriptClient.java | 127 ++++ .../hsadmin/jscli/cas/CASTicketProvider.java | 200 ++++++ .../hsadmin/jscli/conf/CommandlineParser.java | 72 ++ .../java/de/hsadmin/jscli/conf/Config.java | 57 ++ .../hsadmin/jscli/console/ConsoleWrapper.java | 67 ++ .../hsadmin/jscli/console/PasswordReader.java | 9 + .../jscli/exception/JSCliException.java | 16 + .../de/hsadmin/jscli/json/JSONFormatter.java | 104 +++ cli/src/main/resources/js/functions.js | 85 +++ common/.gitignore | 13 + common/LICENSE.txt | 661 ++++++++++++++++++ common/pom.xml | 37 + .../java/de/hsadmin/common/config/Config.java | 62 ++ .../common/error/TechnicalException.java | 15 + .../de/hsadmin/common/error/UserError.java | 54 ++ .../hsadmin/common/error/UserErrorList.java | 38 + .../hsadmin/common/error/UserException.java | 45 ++ .../java/de/hsadmin/common/util/DateUtil.java | 42 ++ .../hsadmin/common/util/ReflectionUtil.java | 65 ++ framework/.gitignore | 13 + framework/LICENSE.txt | 661 ++++++++++++++++++ framework/pom.xml | 70 ++ .../main/java/de/hsadmin/module/Module.java | 25 + .../java/de/hsadmin/module/ValueObject.java | 23 + .../hsadmin/module/impl/AbstractModule.java | 105 +++ .../hsadmin/module/impl/AbstractProperty.java | 135 ++++ .../de/hsadmin/module/impl/AbstractVO.java | 168 +++++ .../module/impl/ValidationDelegate.java | 85 +++ .../module/property/BooleanProperty.java | 31 + .../module/property/ContainsElements.java | 11 + .../hsadmin/module/property/DateProperty.java | 33 + .../de/hsadmin/module/property/Display.java | 15 + .../module/property/DisplayPolicy.java | 7 + .../hsadmin/module/property/ElementsType.java | 16 + .../module/property/IntegerProperty.java | 31 + .../hsadmin/module/property/ListProperty.java | 47 ++ .../de/hsadmin/module/property/Property.java | 38 + .../de/hsadmin/module/property/ReadWrite.java | 14 + .../module/property/ReadWritePolicy.java | 5 + .../de/hsadmin/module/property/Required.java | 14 + .../de/hsadmin/module/property/Search.java | 14 + .../hsadmin/module/property/SearchPolicy.java | 5 + .../module/property/StringProperty.java | 43 ++ .../de/hsadmin/module/property/StringSet.java | 30 + .../module/property/StringSetProperty.java | 84 +++ .../DefaultBooleanParameterMapMapper.java | 39 ++ .../DefaultBooleanPersistentObjectMapper.java | 26 + .../DefaultDateParameterMapMapper.java | 39 ++ .../DefaultDatePersistentObjectMapper.java | 34 + .../DefaultIntegerParameterMapMapper.java | 37 + .../DefaultIntegerPersistentObjectMapper.java | 29 + .../DefaultListParameterMapMapper.java | 65 ++ .../DefaultListPersistentObjectMapper.java | 51 ++ .../DefaultStringParameterMapMapper.java | 27 + .../DefaultStringPersistentObjectMapper.java | 22 + .../DefaultStringSetParameterMapMapper.java | 42 ++ ...efaultStringSetPersistentObjectMapper.java | 35 + .../module/property/mapping/Mapping.java | 15 + .../property/mapping/ParameterMapMapper.java | 14 + .../mapping/PersistentObjectMapper.java | 12 + .../mapping/ReferredPropertyPath.java | 7 + .../ReferredStringPersistentObjectMapper.java | 38 + .../de/hsadmin/module/util/QueryBuilder.java | 74 ++ .../service/property/PropertyRemote.java | 14 + .../service/property/PropertyService.java | 142 ++++ .../property/PropertyServiceLocal.java | 10 + .../hsadmin/service/property/PropertyVO.java | 139 ++++ .../de/hsadmin/xmlrpc/AbstractRemote.java | 179 +++++ .../de/hsadmin/xmlrpc/HSXmlRpcServlet.java | 21 + .../main/java/de/hsadmin/xmlrpc/Remote.java | 34 + .../de/hsadmin/xmlrpc/RemoteException.java | 11 + persistence/.gitignore | 13 + persistence/database/hsdb-bootstrap.sql | 222 ++++++ persistence/database/hsdb-schema.sql | 615 ++++++++++++++++ persistence/database/migrate.sql | 0 persistence/pom.xml | 48 ++ .../java/de/hsadmin/bo/customer/Contact.java | 234 +++++++ .../java/de/hsadmin/bo/customer/Customer.java | 279 ++++++++ .../de/hsadmin/bo/customer/IndicatorVAT.java | 5 + .../hsadmin/bo/customer/SEPADirectDebit.java | 160 +++++ .../java/de/hsadmin/bo/database/Database.java | 118 ++++ .../de/hsadmin/bo/database/DatabaseUser.java | 94 +++ .../de/hsadmin/bo/database/MySqlDatabase.java | 29 + .../de/hsadmin/bo/database/MySqlUser.java | 18 + .../de/hsadmin/bo/database/PgSqlDatabase.java | 29 + .../de/hsadmin/bo/database/PgSqlUser.java | 22 + .../java/de/hsadmin/bo/domain/Domain.java | 121 ++++ .../de/hsadmin/bo/domain/DomainOption.java | 75 ++ .../de/hsadmin/bo/domain/EMailAddress.java | 97 +++ .../java/de/hsadmin/bo/pac/BaseComponent.java | 80 +++ .../main/java/de/hsadmin/bo/pac/BasePac.java | 129 ++++ .../java/de/hsadmin/bo/pac/Component.java | 137 ++++ .../java/de/hsadmin/bo/pac/EMailAlias.java | 82 +++ .../src/main/java/de/hsadmin/bo/pac/Hive.java | 95 +++ .../java/de/hsadmin/bo/pac/INetAddress.java | 68 ++ .../src/main/java/de/hsadmin/bo/pac/Pac.java | 237 +++++++ .../java/de/hsadmin/bo/pac/PacComponent.java | 99 +++ .../de/hsadmin/bo/pac/PacEntityListener.java | 54 ++ .../main/java/de/hsadmin/bo/pac/UnixUser.java | 166 +++++ pom.xml | 45 ++ services/.gitignore | 13 + services/LICENSE.txt | 661 ++++++++++++++++++ services/pom.xml | 80 +++ .../service/customer/ContactRemote.java | 14 + .../service/customer/ContactService.java | 100 +++ .../service/customer/ContactServiceLocal.java | 10 + .../hsadmin/service/customer/ContactVO.java | 246 +++++++ .../service/customer/CustomerRemote.java | 14 + .../service/customer/CustomerService.java | 120 ++++ .../customer/CustomerServiceLocal.java | 10 + .../hsadmin/service/customer/CustomerVO.java | 216 ++++++ .../customer/SEPADirectDebitRemote.java | 14 + .../customer/SEPADirectDebitService.java | 101 +++ .../customer/SEPADirectDebitServiceLocal.java | 10 + .../service/customer/SEPADirectDebitVO.java | 160 +++++ .../de/hsadmin/service/pac/HiveRemote.java | 14 + .../de/hsadmin/service/pac/HiveService.java | 108 +++ .../hsadmin/service/pac/HiveServiceLocal.java | 10 + .../java/de/hsadmin/service/pac/HiveVO.java | 61 ++ .../de/hsadmin/service/pac/INetAddressVO.java | 43 ++ .../hsadmin/service/pac/PacComponentVO.java | 44 ++ .../de/hsadmin/service/pac/PacRemote.java | 14 + .../de/hsadmin/service/pac/PacService.java | 163 +++++ .../hsadmin/service/pac/PacServiceLocal.java | 10 + .../java/de/hsadmin/service/pac/PacVO.java | 149 ++++ web/.gitignore | 13 + web/LICENSE.txt | 661 ++++++++++++++++++ web/pom.xml | 96 +++ .../java/de/hsadmin/model/IMenuOption.java | 23 + .../main/java/de/hsadmin/model/IRemote.java | 36 + .../java/de/hsadmin/model/TicketService.java | 86 +++ .../java/de/hsadmin/rpc/HSAdminSession.java | 15 + .../main/java/de/hsadmin/rpc/ModuleInfo.java | 49 ++ .../java/de/hsadmin/rpc/ModulesManager.java | 143 ++++ .../de/hsadmin/rpc/ModulesManagerFactory.java | 72 ++ .../java/de/hsadmin/rpc/PropertyInfo.java | 108 +++ .../java/de/hsadmin/rpc/RpcException.java | 15 + .../de/hsadmin/rpc/enums/DisplayPolicy.java | 7 + .../de/hsadmin/rpc/enums/ReadWritePolicy.java | 5 + .../de/hsadmin/rpc/enums/SearchPolicy.java | 5 + .../web/AbstractEntryPointsFactory.java | 7 + .../de/hsadmin/web/AbstractPanelFactory.java | 10 + .../de/hsadmin/web/AbstractWindowFactory.java | 11 + .../java/de/hsadmin/web/CustomerPanel.java | 55 ++ .../de/hsadmin/web/DomainOptionsEditor.java | 78 +++ .../main/java/de/hsadmin/web/DomainPanel.java | 48 ++ .../de/hsadmin/web/EMailTargetEditor.java | 285 ++++++++ .../main/java/de/hsadmin/web/EntryPoint.java | 59 ++ .../de/hsadmin/web/EntryPointsFactory.java | 22 + .../de/hsadmin/web/EntryPointsSelector.java | 89 +++ .../java/de/hsadmin/web/FactoryProducer.java | 25 + .../de/hsadmin/web/GenericEditorFactory.java | 202 ++++++ .../main/java/de/hsadmin/web/GenericForm.java | 65 ++ .../de/hsadmin/web/GenericFormWindow.java | 93 +++ .../main/java/de/hsadmin/web/HSAdminUI.java | 47 ++ .../java/de/hsadmin/web/HSConfirmBox.java | 105 +++ .../de/hsadmin/web/HSPacPrefixedField.java | 35 + .../java/de/hsadmin/web/HSPasswordField.java | 21 + .../main/java/de/hsadmin/web/HSSelect.java | 36 + web/src/main/java/de/hsadmin/web/HSTab.java | 163 +++++ .../main/java/de/hsadmin/web/HSTextField.java | 36 + .../main/java/de/hsadmin/web/HelpWindow.java | 38 + web/src/main/java/de/hsadmin/web/I18N.java | 20 + .../java/de/hsadmin/web/IEditorFactory.java | 15 + .../main/java/de/hsadmin/web/IHSEditor.java | 18 + .../main/java/de/hsadmin/web/IHSPanel.java | 12 + .../main/java/de/hsadmin/web/IHSWindow.java | 17 + .../main/java/de/hsadmin/web/InfoWindow.java | 36 + .../main/java/de/hsadmin/web/LoginWindow.java | 108 +++ .../main/java/de/hsadmin/web/MainPanel.java | 18 + .../main/java/de/hsadmin/web/MainToolbar.java | 56 ++ .../main/java/de/hsadmin/web/MainWindow.java | 130 ++++ .../main/java/de/hsadmin/web/NullEditor.java | 32 + .../hsadmin/web/PacNamePrefixValidator.java | 23 + .../java/de/hsadmin/web/PacNamePrefixed.java | 7 + .../java/de/hsadmin/web/PackagePanel.java | 62 ++ .../java/de/hsadmin/web/PanelFactory.java | 27 + .../java/de/hsadmin/web/PanelToolbar.java | 129 ++++ .../de/hsadmin/web/PasswordValidator.java | 62 ++ .../main/java/de/hsadmin/web/ServerPanel.java | 48 ++ .../java/de/hsadmin/web/SubWindowFactory.java | 26 + .../resources/de/hsadmin/web/main.properties | 167 +++++ .../de/hsadmin/web/main_de.properties | 164 +++++ .../de/hsadmin/web/main_es.properties | 164 +++++ web/src/main/resources/log4j.properties | 5 + web/src/main/webapp/META-INF/MANIFEST.MF | 3 + .../VAADIN/themes/hs_admin_peter/addons.scss | 7 + .../themes/hs_admin_peter/hs_admin_peter.scss | 36 + .../VAADIN/themes/hs_admin_peter/styles.scss | 9 + .../webapp/VAADIN/themes/icons/addons.scss | 7 + .../webapp/VAADIN/themes/icons/bars-icon.png | Bin 0 -> 302 bytes .../VAADIN/themes/icons/cancel-icon.png | Bin 0 -> 456 bytes .../webapp/VAADIN/themes/icons/cog-icon.png | Bin 0 -> 699 bytes .../webapp/VAADIN/themes/icons/cog2-icon.png | Bin 0 -> 689 bytes .../webapp/VAADIN/themes/icons/copy-icon.png | Bin 0 -> 576 bytes .../webapp/VAADIN/themes/icons/db-icon.png | Bin 0 -> 931 bytes .../VAADIN/themes/icons/delete-user-icon.png | Bin 0 -> 765 bytes .../VAADIN/themes/icons/download-icon.png | Bin 0 -> 490 bytes .../webapp/VAADIN/themes/icons/edit-icon.png | Bin 0 -> 735 bytes .../webapp/VAADIN/themes/icons/file-icon.png | Bin 0 -> 280 bytes .../webapp/VAADIN/themes/icons/hslogo.png | Bin 0 -> 9411 bytes .../webapp/VAADIN/themes/icons/inbox-icon.png | Bin 0 -> 465 bytes .../VAADIN/themes/icons/mini-edit-icon.png | Bin 0 -> 317 bytes .../webapp/VAADIN/themes/icons/new-icon.png | Bin 0 -> 277 bytes .../VAADIN/themes/icons/new-square-icon.png | Bin 0 -> 402 bytes .../themes/icons/new-square-white-icon.png | Bin 0 -> 425 bytes .../VAADIN/themes/icons/new-user-icon.png | Bin 0 -> 694 bytes .../webapp/VAADIN/themes/icons/new2-icon.png | Bin 0 -> 639 bytes .../webapp/VAADIN/themes/icons/ok-icon.png | Bin 0 -> 878 bytes .../VAADIN/themes/icons/power-off-icon.png | Bin 0 -> 737 bytes .../VAADIN/themes/icons/question-icon.png | Bin 0 -> 753 bytes .../VAADIN/themes/icons/reload-icon.png | Bin 0 -> 713 bytes .../VAADIN/themes/icons/server-icon.png | Bin 0 -> 370 bytes .../VAADIN/themes/icons/settings-icon.png | Bin 0 -> 618 bytes .../webapp/VAADIN/themes/icons/task-icon.png | Bin 0 -> 323 bytes .../webapp/VAADIN/themes/icons/trash-icon.png | Bin 0 -> 433 bytes .../VAADIN/themes/icons/upload-icon.png | Bin 0 -> 414 bytes .../webapp/VAADIN/themes/icons/x-icon.png | Bin 0 -> 458 bytes web/src/main/webapp/WEB-INF/web.xml | 10 + xmlrpc/pom.xml | 102 +++ xmlrpc/src/main/webapp/WEB-INF/web.xml | 22 + .../failsafe-reports/failsafe-summary.xml | 8 + xmlrpc/target/maven-archiver/pom.properties | 5 + xmlrpc/target/xmlrpc-webapp/WEB-INF/web.xml | 22 + 243 files changed, 17385 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE.txt create mode 100644 authorization/.gitignore create mode 100644 authorization/LICENSE.txt create mode 100644 authorization/pom.xml create mode 100644 authorization/src/main/java/de/hsadmin/login/CASTicketValidator.java create mode 100644 authorization/src/main/java/de/hsadmin/login/LoginService.java create mode 100644 authorization/src/main/java/de/hsadmin/login/LoginServiceLocal.java create mode 100644 authorization/src/main/java/de/hsadmin/login/RequestContext.java create mode 100644 authorization/src/main/java/de/hsadmin/login/RequiredScope.java create mode 100644 authorization/src/main/java/de/hsadmin/login/Role.java create mode 100644 authorization/src/main/java/de/hsadmin/login/ScopePolicy.java create mode 100644 authorization/src/main/java/de/hsadmin/login/TestTicketValidator.java create mode 100644 authorization/src/main/java/de/hsadmin/login/TicketValidator.java create mode 100644 cli/.gitignore create mode 100644 cli/LICENSE.txt create mode 100644 cli/pom.xml create mode 100644 cli/src/main/java/de/hsadmin/jscli/Main.java create mode 100644 cli/src/main/java/de/hsadmin/jscli/RpcClient.java create mode 100644 cli/src/main/java/de/hsadmin/jscli/ScriptClient.java create mode 100644 cli/src/main/java/de/hsadmin/jscli/cas/CASTicketProvider.java create mode 100644 cli/src/main/java/de/hsadmin/jscli/conf/CommandlineParser.java create mode 100644 cli/src/main/java/de/hsadmin/jscli/conf/Config.java create mode 100644 cli/src/main/java/de/hsadmin/jscli/console/ConsoleWrapper.java create mode 100644 cli/src/main/java/de/hsadmin/jscli/console/PasswordReader.java create mode 100644 cli/src/main/java/de/hsadmin/jscli/exception/JSCliException.java create mode 100644 cli/src/main/java/de/hsadmin/jscli/json/JSONFormatter.java create mode 100644 cli/src/main/resources/js/functions.js create mode 100644 common/.gitignore create mode 100644 common/LICENSE.txt create mode 100644 common/pom.xml create mode 100644 common/src/main/java/de/hsadmin/common/config/Config.java create mode 100644 common/src/main/java/de/hsadmin/common/error/TechnicalException.java create mode 100644 common/src/main/java/de/hsadmin/common/error/UserError.java create mode 100644 common/src/main/java/de/hsadmin/common/error/UserErrorList.java create mode 100644 common/src/main/java/de/hsadmin/common/error/UserException.java create mode 100644 common/src/main/java/de/hsadmin/common/util/DateUtil.java create mode 100644 common/src/main/java/de/hsadmin/common/util/ReflectionUtil.java create mode 100644 framework/.gitignore create mode 100644 framework/LICENSE.txt create mode 100644 framework/pom.xml create mode 100644 framework/src/main/java/de/hsadmin/module/Module.java create mode 100644 framework/src/main/java/de/hsadmin/module/ValueObject.java create mode 100644 framework/src/main/java/de/hsadmin/module/impl/AbstractModule.java create mode 100644 framework/src/main/java/de/hsadmin/module/impl/AbstractProperty.java create mode 100644 framework/src/main/java/de/hsadmin/module/impl/AbstractVO.java create mode 100644 framework/src/main/java/de/hsadmin/module/impl/ValidationDelegate.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/BooleanProperty.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/ContainsElements.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/DateProperty.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/Display.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/DisplayPolicy.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/ElementsType.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/IntegerProperty.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/ListProperty.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/Property.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/ReadWrite.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/ReadWritePolicy.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/Required.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/Search.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/SearchPolicy.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/StringProperty.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/StringSet.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/StringSetProperty.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/DefaultBooleanParameterMapMapper.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/DefaultBooleanPersistentObjectMapper.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/DefaultDateParameterMapMapper.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/DefaultDatePersistentObjectMapper.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/DefaultIntegerParameterMapMapper.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/DefaultIntegerPersistentObjectMapper.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/DefaultListParameterMapMapper.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/DefaultListPersistentObjectMapper.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringParameterMapMapper.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringPersistentObjectMapper.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringSetParameterMapMapper.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringSetPersistentObjectMapper.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/Mapping.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/ParameterMapMapper.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/PersistentObjectMapper.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/ReferredPropertyPath.java create mode 100644 framework/src/main/java/de/hsadmin/module/property/mapping/ReferredStringPersistentObjectMapper.java create mode 100644 framework/src/main/java/de/hsadmin/module/util/QueryBuilder.java create mode 100644 framework/src/main/java/de/hsadmin/service/property/PropertyRemote.java create mode 100644 framework/src/main/java/de/hsadmin/service/property/PropertyService.java create mode 100644 framework/src/main/java/de/hsadmin/service/property/PropertyServiceLocal.java create mode 100644 framework/src/main/java/de/hsadmin/service/property/PropertyVO.java create mode 100644 framework/src/main/java/de/hsadmin/xmlrpc/AbstractRemote.java create mode 100644 framework/src/main/java/de/hsadmin/xmlrpc/HSXmlRpcServlet.java create mode 100644 framework/src/main/java/de/hsadmin/xmlrpc/Remote.java create mode 100644 framework/src/main/java/de/hsadmin/xmlrpc/RemoteException.java create mode 100644 persistence/.gitignore create mode 100644 persistence/database/hsdb-bootstrap.sql create mode 100644 persistence/database/hsdb-schema.sql create mode 100644 persistence/database/migrate.sql create mode 100644 persistence/pom.xml create mode 100644 persistence/src/main/java/de/hsadmin/bo/customer/Contact.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/customer/Customer.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/customer/IndicatorVAT.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/customer/SEPADirectDebit.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/database/Database.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/database/DatabaseUser.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/database/MySqlDatabase.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/database/MySqlUser.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/database/PgSqlDatabase.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/database/PgSqlUser.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/domain/Domain.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/domain/DomainOption.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/domain/EMailAddress.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/pac/BaseComponent.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/pac/BasePac.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/pac/Component.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/pac/EMailAlias.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/pac/Hive.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/pac/INetAddress.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/pac/Pac.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/pac/PacComponent.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/pac/PacEntityListener.java create mode 100644 persistence/src/main/java/de/hsadmin/bo/pac/UnixUser.java create mode 100644 pom.xml create mode 100644 services/.gitignore create mode 100644 services/LICENSE.txt create mode 100644 services/pom.xml create mode 100644 services/src/main/java/de/hsadmin/service/customer/ContactRemote.java create mode 100644 services/src/main/java/de/hsadmin/service/customer/ContactService.java create mode 100644 services/src/main/java/de/hsadmin/service/customer/ContactServiceLocal.java create mode 100644 services/src/main/java/de/hsadmin/service/customer/ContactVO.java create mode 100644 services/src/main/java/de/hsadmin/service/customer/CustomerRemote.java create mode 100644 services/src/main/java/de/hsadmin/service/customer/CustomerService.java create mode 100644 services/src/main/java/de/hsadmin/service/customer/CustomerServiceLocal.java create mode 100644 services/src/main/java/de/hsadmin/service/customer/CustomerVO.java create mode 100644 services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitRemote.java create mode 100644 services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitService.java create mode 100644 services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitServiceLocal.java create mode 100644 services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitVO.java create mode 100644 services/src/main/java/de/hsadmin/service/pac/HiveRemote.java create mode 100644 services/src/main/java/de/hsadmin/service/pac/HiveService.java create mode 100644 services/src/main/java/de/hsadmin/service/pac/HiveServiceLocal.java create mode 100644 services/src/main/java/de/hsadmin/service/pac/HiveVO.java create mode 100644 services/src/main/java/de/hsadmin/service/pac/INetAddressVO.java create mode 100644 services/src/main/java/de/hsadmin/service/pac/PacComponentVO.java create mode 100644 services/src/main/java/de/hsadmin/service/pac/PacRemote.java create mode 100644 services/src/main/java/de/hsadmin/service/pac/PacService.java create mode 100644 services/src/main/java/de/hsadmin/service/pac/PacServiceLocal.java create mode 100644 services/src/main/java/de/hsadmin/service/pac/PacVO.java create mode 100644 web/.gitignore create mode 100644 web/LICENSE.txt create mode 100644 web/pom.xml create mode 100644 web/src/main/java/de/hsadmin/model/IMenuOption.java create mode 100644 web/src/main/java/de/hsadmin/model/IRemote.java create mode 100644 web/src/main/java/de/hsadmin/model/TicketService.java create mode 100644 web/src/main/java/de/hsadmin/rpc/HSAdminSession.java create mode 100644 web/src/main/java/de/hsadmin/rpc/ModuleInfo.java create mode 100644 web/src/main/java/de/hsadmin/rpc/ModulesManager.java create mode 100644 web/src/main/java/de/hsadmin/rpc/ModulesManagerFactory.java create mode 100644 web/src/main/java/de/hsadmin/rpc/PropertyInfo.java create mode 100644 web/src/main/java/de/hsadmin/rpc/RpcException.java create mode 100644 web/src/main/java/de/hsadmin/rpc/enums/DisplayPolicy.java create mode 100644 web/src/main/java/de/hsadmin/rpc/enums/ReadWritePolicy.java create mode 100644 web/src/main/java/de/hsadmin/rpc/enums/SearchPolicy.java create mode 100644 web/src/main/java/de/hsadmin/web/AbstractEntryPointsFactory.java create mode 100644 web/src/main/java/de/hsadmin/web/AbstractPanelFactory.java create mode 100644 web/src/main/java/de/hsadmin/web/AbstractWindowFactory.java create mode 100644 web/src/main/java/de/hsadmin/web/CustomerPanel.java create mode 100644 web/src/main/java/de/hsadmin/web/DomainOptionsEditor.java create mode 100644 web/src/main/java/de/hsadmin/web/DomainPanel.java create mode 100644 web/src/main/java/de/hsadmin/web/EMailTargetEditor.java create mode 100644 web/src/main/java/de/hsadmin/web/EntryPoint.java create mode 100644 web/src/main/java/de/hsadmin/web/EntryPointsFactory.java create mode 100644 web/src/main/java/de/hsadmin/web/EntryPointsSelector.java create mode 100644 web/src/main/java/de/hsadmin/web/FactoryProducer.java create mode 100644 web/src/main/java/de/hsadmin/web/GenericEditorFactory.java create mode 100644 web/src/main/java/de/hsadmin/web/GenericForm.java create mode 100644 web/src/main/java/de/hsadmin/web/GenericFormWindow.java create mode 100644 web/src/main/java/de/hsadmin/web/HSAdminUI.java create mode 100644 web/src/main/java/de/hsadmin/web/HSConfirmBox.java create mode 100644 web/src/main/java/de/hsadmin/web/HSPacPrefixedField.java create mode 100644 web/src/main/java/de/hsadmin/web/HSPasswordField.java create mode 100644 web/src/main/java/de/hsadmin/web/HSSelect.java create mode 100644 web/src/main/java/de/hsadmin/web/HSTab.java create mode 100644 web/src/main/java/de/hsadmin/web/HSTextField.java create mode 100644 web/src/main/java/de/hsadmin/web/HelpWindow.java create mode 100644 web/src/main/java/de/hsadmin/web/I18N.java create mode 100644 web/src/main/java/de/hsadmin/web/IEditorFactory.java create mode 100644 web/src/main/java/de/hsadmin/web/IHSEditor.java create mode 100644 web/src/main/java/de/hsadmin/web/IHSPanel.java create mode 100644 web/src/main/java/de/hsadmin/web/IHSWindow.java create mode 100644 web/src/main/java/de/hsadmin/web/InfoWindow.java create mode 100644 web/src/main/java/de/hsadmin/web/LoginWindow.java create mode 100644 web/src/main/java/de/hsadmin/web/MainPanel.java create mode 100644 web/src/main/java/de/hsadmin/web/MainToolbar.java create mode 100644 web/src/main/java/de/hsadmin/web/MainWindow.java create mode 100644 web/src/main/java/de/hsadmin/web/NullEditor.java create mode 100644 web/src/main/java/de/hsadmin/web/PacNamePrefixValidator.java create mode 100644 web/src/main/java/de/hsadmin/web/PacNamePrefixed.java create mode 100644 web/src/main/java/de/hsadmin/web/PackagePanel.java create mode 100644 web/src/main/java/de/hsadmin/web/PanelFactory.java create mode 100644 web/src/main/java/de/hsadmin/web/PanelToolbar.java create mode 100644 web/src/main/java/de/hsadmin/web/PasswordValidator.java create mode 100644 web/src/main/java/de/hsadmin/web/ServerPanel.java create mode 100644 web/src/main/java/de/hsadmin/web/SubWindowFactory.java create mode 100644 web/src/main/resources/de/hsadmin/web/main.properties create mode 100644 web/src/main/resources/de/hsadmin/web/main_de.properties create mode 100644 web/src/main/resources/de/hsadmin/web/main_es.properties create mode 100644 web/src/main/resources/log4j.properties create mode 100644 web/src/main/webapp/META-INF/MANIFEST.MF create mode 100644 web/src/main/webapp/VAADIN/themes/hs_admin_peter/addons.scss create mode 100644 web/src/main/webapp/VAADIN/themes/hs_admin_peter/hs_admin_peter.scss create mode 100644 web/src/main/webapp/VAADIN/themes/hs_admin_peter/styles.scss create mode 100644 web/src/main/webapp/VAADIN/themes/icons/addons.scss create mode 100644 web/src/main/webapp/VAADIN/themes/icons/bars-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/cancel-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/cog-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/cog2-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/copy-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/db-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/delete-user-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/download-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/edit-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/file-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/hslogo.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/inbox-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/mini-edit-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/new-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/new-square-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/new-square-white-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/new-user-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/new2-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/ok-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/power-off-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/question-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/reload-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/server-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/settings-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/task-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/trash-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/upload-icon.png create mode 100644 web/src/main/webapp/VAADIN/themes/icons/x-icon.png create mode 100644 web/src/main/webapp/WEB-INF/web.xml create mode 100644 xmlrpc/pom.xml create mode 100644 xmlrpc/src/main/webapp/WEB-INF/web.xml create mode 100644 xmlrpc/target/failsafe-reports/failsafe-summary.xml create mode 100644 xmlrpc/target/maven-archiver/pom.properties create mode 100644 xmlrpc/target/xmlrpc-webapp/WEB-INF/web.xml diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e774414 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +*.class + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +/target +/.settings +/.classpath +/.project diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..dba13ed --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/authorization/.gitignore b/authorization/.gitignore new file mode 100644 index 0000000..e774414 --- /dev/null +++ b/authorization/.gitignore @@ -0,0 +1,13 @@ +*.class + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +/target +/.settings +/.classpath +/.project diff --git a/authorization/LICENSE.txt b/authorization/LICENSE.txt new file mode 100644 index 0000000..dba13ed --- /dev/null +++ b/authorization/LICENSE.txt @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/authorization/pom.xml b/authorization/pom.xml new file mode 100644 index 0000000..685c8dd --- /dev/null +++ b/authorization/pom.xml @@ -0,0 +1,54 @@ + + 4.0.0 + + de.hsadmin + hsadmin-parent + 1.0-SNAPSHOT + + authorization + jar + + HSAdmin Authorization + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + + + + + de.hsadmin + common + 1.0-SNAPSHOT + + + org.apache.geronimo.specs + geronimo-jpa_2.0_spec + 1.1 + provided + + + org.apache.geronimo.specs + geronimo-ejb_3.0_spec + 1.0.1 + provided + + + log4j + log4j + 1.2.17 + + + diff --git a/authorization/src/main/java/de/hsadmin/login/CASTicketValidator.java b/authorization/src/main/java/de/hsadmin/login/CASTicketValidator.java new file mode 100644 index 0000000..40337b9 --- /dev/null +++ b/authorization/src/main/java/de/hsadmin/login/CASTicketValidator.java @@ -0,0 +1,60 @@ +package de.hsadmin.login; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; + +import de.hsadmin.common.config.Config; +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserError; +import de.hsadmin.common.error.UserException; + +public class CASTicketValidator implements TicketValidator { + + private final String proxyValidateURL; + private final String proxyServiceURL; + + public CASTicketValidator() throws TechnicalException { + Config config = Config.getInstance(); + proxyValidateURL = config.getProperty(Config.CAS_VALIDATE_URL); + proxyServiceURL = config.getProperty(Config.CAS_SERVICE_URL); + } + + @Override + public String validate(final String ticket) throws UserException, TechnicalException { + if (proxyServiceURL == null || proxyValidateURL == null) { + throw new TechnicalException("TicketValidator is not initialized."); + } + try { + URL url = new URL(proxyValidateURL + "?service=" + proxyServiceURL + "&ticket=" + ticket); + URLConnection httpConnection = url.openConnection(); + httpConnection.connect(); + InputStream inputStream = httpConnection.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + String nextLine = reader.readLine(); + while (nextLine != null) { + if (nextLine.contains("")) { + String user = extractUser(nextLine); + inputStream.close(); + return user; + } + nextLine = reader.readLine(); + } + inputStream.close(); + throw new UserException(new UserError(UserError.MSG_INVALID_TICKET)); + } catch (IOException e) { + throw new TechnicalException(e); + } + } + + private String extractUser(String nextLine) { + int start = nextLine.indexOf(""); + int end = nextLine.indexOf(""); + String user = nextLine.substring(start + 10, end); + return user; + } + +} diff --git a/authorization/src/main/java/de/hsadmin/login/LoginService.java b/authorization/src/main/java/de/hsadmin/login/LoginService.java new file mode 100644 index 0000000..bca4c1b --- /dev/null +++ b/authorization/src/main/java/de/hsadmin/login/LoginService.java @@ -0,0 +1,94 @@ +package de.hsadmin.login; + +import javax.ejb.Stateless; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import de.hsadmin.common.config.Config; +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserError; +import de.hsadmin.common.error.UserException; + +@Stateless +public class LoginService implements LoginServiceLocal { + + @PersistenceContext(name = "hsar") + private EntityManager entityManager; + + private TicketValidator ticketValidator; + + @Override + public RequestContext createContext(final String ticket, final String runAsUser) throws UserException, TechnicalException { + if (ticket != null && !ticket.isEmpty()) { + final String ticketUser = validateTicket(ticket); + String runAs = runAsUser; + if (runAs == null || runAs.isEmpty()) { + runAs = ticketUser; + } else { + checkRunAsAllowed(ticketUser, runAs); + } + Role scope = findRunAsRole(runAs); + return new RequestContext(runAsUser, scope); + } + throw new UserException(new UserError(UserError.MSG_INVALID_TICKET, ticket)); + } + + private Role findRunAsRole(final String login) throws TechnicalException { + Role resultRole = Role.NONE; + if (hasHostmasterRole(login)) { + resultRole = Role.SYSTEM; + } else { + if (hasCustomerRole(login)) { + resultRole = Role.CUSTOMER; + } else { + if (hasPacAdminRole(login)) { + resultRole = Role.PACKET; + } + } + } + return resultRole; + } + + private boolean hasCustomerRole(final String login) throws TechnicalException { + final String customersPac = Config.getInstance().getProperty(Config.PAC_CUSTOMER_ACCOUNTS); + return login.startsWith(customersPac) && login.length() == 9 && login.charAt(5) == '-'; + } + + private boolean hasHostmasterRole(final String login) throws TechnicalException { + final String hostmastersPac = Config.getInstance().getProperty(Config.PAC_HOSTMASTER_ACCOUNTS); + return login.length() == 2 || ( login.startsWith(hostmastersPac) && login.length() == 8 && login.charAt(5) == '-' ); + } + + private boolean hasPacAdminRole(final String login) throws TechnicalException { + return login.length() == 5; + } + + private void checkRunAsAllowed(final String ticketUser, final String runAsUser) + throws UserException { + assert ticketUser != null && !ticketUser.isEmpty(); + assert runAsUser != null && !runAsUser.isEmpty(); + if (ticketUser.length() != 2 && !runAsUser.startsWith(ticketUser)) { + throw new UserException(new UserError( + UserError.MSG_FORBIDDEN_RUNAS, ticketUser, runAsUser)); + } + } + + private String validateTicket(final String ticket) throws TechnicalException, UserException { + final TicketValidator ticketValidator = getTicketValidator(); + return ticketValidator.validate(ticket); + } + + private TicketValidator getTicketValidator() throws TechnicalException { + if (ticketValidator == null) { + try { + final String property = Config.getInstance().getProperty(Config.TICKETVALIDATOR_CLASS); + final Class validatorClass = Class.forName(property); + ticketValidator = (TicketValidator) validatorClass.newInstance(); + } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { + throw new TechnicalException(e); + } + } + return ticketValidator; + } + +} diff --git a/authorization/src/main/java/de/hsadmin/login/LoginServiceLocal.java b/authorization/src/main/java/de/hsadmin/login/LoginServiceLocal.java new file mode 100644 index 0000000..3a86ee1 --- /dev/null +++ b/authorization/src/main/java/de/hsadmin/login/LoginServiceLocal.java @@ -0,0 +1,13 @@ +package de.hsadmin.login; + +import javax.ejb.Local; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; + +@Local +public interface LoginServiceLocal { + + RequestContext createContext(String ticket, String runAsUser) throws UserException, TechnicalException; + +} diff --git a/authorization/src/main/java/de/hsadmin/login/RequestContext.java b/authorization/src/main/java/de/hsadmin/login/RequestContext.java new file mode 100644 index 0000000..064d6b9 --- /dev/null +++ b/authorization/src/main/java/de/hsadmin/login/RequestContext.java @@ -0,0 +1,21 @@ +package de.hsadmin.login; + +public class RequestContext { + + private final String runAsLogin; + private final Role runAsRole; + + public RequestContext(final String runAs, final Role runAsRole) { + this.runAsLogin = runAs; + this.runAsRole = runAsRole; + } + + public String getLoginUser() { + return runAsLogin; + } + + public Role getLoginRole() { + return runAsRole; + } + +} diff --git a/authorization/src/main/java/de/hsadmin/login/RequiredScope.java b/authorization/src/main/java/de/hsadmin/login/RequiredScope.java new file mode 100644 index 0000000..996a06b --- /dev/null +++ b/authorization/src/main/java/de/hsadmin/login/RequiredScope.java @@ -0,0 +1,14 @@ +package de.hsadmin.login; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface RequiredScope { + + ScopePolicy[] value(); + +} diff --git a/authorization/src/main/java/de/hsadmin/login/Role.java b/authorization/src/main/java/de/hsadmin/login/Role.java new file mode 100644 index 0000000..2fc089b --- /dev/null +++ b/authorization/src/main/java/de/hsadmin/login/Role.java @@ -0,0 +1,7 @@ +package de.hsadmin.login; + +public enum Role { + + SYSTEM, CUSTOMER, HIVE, PACKET, DOMAIN, USER, NONE, ANY + +} diff --git a/authorization/src/main/java/de/hsadmin/login/ScopePolicy.java b/authorization/src/main/java/de/hsadmin/login/ScopePolicy.java new file mode 100644 index 0000000..51894a4 --- /dev/null +++ b/authorization/src/main/java/de/hsadmin/login/ScopePolicy.java @@ -0,0 +1,9 @@ +package de.hsadmin.login; + + +public @interface ScopePolicy { + + Role value(); + String property() default ""; + +} diff --git a/authorization/src/main/java/de/hsadmin/login/TestTicketValidator.java b/authorization/src/main/java/de/hsadmin/login/TestTicketValidator.java new file mode 100644 index 0000000..37a6bf4 --- /dev/null +++ b/authorization/src/main/java/de/hsadmin/login/TestTicketValidator.java @@ -0,0 +1,12 @@ +package de.hsadmin.login; + +public class TestTicketValidator implements TicketValidator { + + @Override + public String validate(final String ticket) { + final int colonPosition = ticket.indexOf(':'); + final String ticketUser = ticket.substring(colonPosition + 1); + return ticketUser; + } + +} diff --git a/authorization/src/main/java/de/hsadmin/login/TicketValidator.java b/authorization/src/main/java/de/hsadmin/login/TicketValidator.java new file mode 100644 index 0000000..616b2a4 --- /dev/null +++ b/authorization/src/main/java/de/hsadmin/login/TicketValidator.java @@ -0,0 +1,10 @@ +package de.hsadmin.login; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; + +public interface TicketValidator { + + String validate(String ticket) throws UserException, TechnicalException; + +} diff --git a/cli/.gitignore b/cli/.gitignore new file mode 100644 index 0000000..e774414 --- /dev/null +++ b/cli/.gitignore @@ -0,0 +1,13 @@ +*.class + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +/target +/.settings +/.classpath +/.project diff --git a/cli/LICENSE.txt b/cli/LICENSE.txt new file mode 100644 index 0000000..dba13ed --- /dev/null +++ b/cli/LICENSE.txt @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/cli/pom.xml b/cli/pom.xml new file mode 100644 index 0000000..101cdb6 --- /dev/null +++ b/cli/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + + de.hsadmin + hsadmin-parent + 1.0-SNAPSHOT + + cli + jar + + HSAdmin Cli + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + + + + + org.apache.xmlrpc + xmlrpc-client + 3.1.3 + + + jline + jline + 1.0 + + + commons-cli + commons-cli + 1.3.1 + + + log4j + log4j + 1.2.17 + + + diff --git a/cli/src/main/java/de/hsadmin/jscli/Main.java b/cli/src/main/java/de/hsadmin/jscli/Main.java new file mode 100644 index 0000000..d9a4840 --- /dev/null +++ b/cli/src/main/java/de/hsadmin/jscli/Main.java @@ -0,0 +1,80 @@ +package de.hsadmin.jscli; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.InputStreamReader; + +import de.hsadmin.jscli.conf.CommandlineParser; +import de.hsadmin.jscli.console.ConsoleWrapper; +import de.hsadmin.jscli.json.JSONFormatter; + + +public class Main { + + public static void main(String[] args) { + final ConsoleWrapper console = new ConsoleWrapper(); + final JSONFormatter formatter = new JSONFormatter(); + try { + final CommandlineParser cmdParser = new CommandlineParser(args); + final String runAs = cmdParser.getRunAs(); + console.open(runAs + "@hsadmin> "); + final String user = cmdParser.getUser(); + final ScriptClient scriptClient = new ScriptClient(console, user, runAs, cmdParser.getArgs()); + final String file = cmdParser.getFile(); + if (file != null && file.length() > 0) { + if ("-".equals(file)) { + scriptClient.execute(new InputStreamReader(System.in)); + console.println(formatter.format(scriptClient.getLastRpcResult())); + } else { + BufferedReader bufferedReader = null; + try { + bufferedReader = new BufferedReader(new FileReader(file)); + String inputLine = bufferedReader.readLine(); + boolean isFirstLine = true; + final StringBuffer scriptFromFile = new StringBuffer(); + while (inputLine != null) { + if (isFirstLine && inputLine.startsWith("#!")) { + scriptFromFile.append("//"); + scriptFromFile.append(inputLine.substring(2)); + } else { + scriptFromFile.append(inputLine); + } + scriptFromFile.append("\n"); + isFirstLine = false; + inputLine = bufferedReader.readLine(); + } + scriptClient.execute(scriptFromFile.toString()); + } catch (FileNotFoundException e) { + System.err.println("File not found: " + file); + } finally { + if (bufferedReader != null) { + bufferedReader.close(); + } + } + } + } + final String expr = cmdParser.getExpression(); + if (expr != null && expr.length() > 0) { + scriptClient.execute(expr); + console.println(formatter.format(scriptClient.getLastRpcResult())); + } + if (cmdParser.isInteractive()) { + String command = console.readInput(); + while (!("bye".equals(command.trim()) || "exit".equals(command.trim()) || "quit".equals(command.trim()))) { + try { + scriptClient.execute(command); + console.println(formatter.format(scriptClient.getLastRpcResult())); + } catch (Exception e) { + console.println("Error: " + e.getLocalizedMessage() + "\n"); + } + command = console.readInput(); + } + } + } catch (Exception e) { + System.err.println(e.getMessage()); + System.exit(-1); + } + } + +} diff --git a/cli/src/main/java/de/hsadmin/jscli/RpcClient.java b/cli/src/main/java/de/hsadmin/jscli/RpcClient.java new file mode 100644 index 0000000..b193b54 --- /dev/null +++ b/cli/src/main/java/de/hsadmin/jscli/RpcClient.java @@ -0,0 +1,92 @@ +package de.hsadmin.jscli; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.client.XmlRpcClient; +import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; + +import de.hsadmin.jscli.cas.CASTicketProvider; +import de.hsadmin.jscli.conf.Config; +import de.hsadmin.jscli.exception.JSCliException; + +public class RpcClient { + + private static final String XMLRPC_URL = "https://config.hostsharing.net:443/hsar/xmlrpc/hsadmin"; + + private final List clientList; + private final Map clientMap; + + public RpcClient(final CASTicketProvider tgt) throws JSCliException { + clientList = new ArrayList(); + clientMap = new HashMap(); + try { + final String xmlrpcURLsString = Config.getInstance().getProperty("xmlrpcURL", XMLRPC_URL); + final String[] xmlrpcURLsArray = xmlrpcURLsString.split(","); + for (final String xmlrpcURL : xmlrpcURLsArray) { + final XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl(); + config.setServerURL(new URL(xmlrpcURL)); + config.setEnabledForExtensions(true); + final XmlRpcClient client = new XmlRpcClient(); + client.setConfig(config); + clientList.add(client); + } + } catch (MalformedURLException e) { + throw new JSCliException(e); + } + } + + public List listMethods() throws JSCliException { + final List methodList = new ArrayList(); + for (final XmlRpcClient client : clientList) { + final List execute = execute(client, "system.listMethods"); + for (final Object obj : execute) { + final String methodString = obj.toString(); + final String[] path = methodString.split("\\."); + if (path.length == 2) { + clientMap.put(path[0], client); + } + methodList.add(methodString); + } + } + return methodList; + } + + private List execute(final XmlRpcClient client, final String method) throws JSCliException { + return execute(client, method, new ArrayList()); + } + + private List execute(final XmlRpcClient client, final String method, final List params) throws JSCliException { + try { + final Object execute = client.execute(method, params); + final ArrayList list = new ArrayList(); + if (execute instanceof Object[]) { + final Object[] resArray = (Object[]) execute; + for (int idx=0; idx < resArray.length; idx++) { + list.add(resArray[idx]); + } + } + if (execute instanceof Map) { + list.add(execute); + } + return list; + } catch (XmlRpcException e) { + throw new JSCliException(e); + } + } + + public List execute(final String method, final List params) throws JSCliException { + final String[] path = method.split("\\."); + if (path.length == 2) { + return execute(clientMap.get(path[0]), method, params); + } else { + throw new JSCliException("method not found: " + method); + } + } + +} diff --git a/cli/src/main/java/de/hsadmin/jscli/ScriptClient.java b/cli/src/main/java/de/hsadmin/jscli/ScriptClient.java new file mode 100644 index 0000000..b4c7870 --- /dev/null +++ b/cli/src/main/java/de/hsadmin/jscli/ScriptClient.java @@ -0,0 +1,127 @@ +package de.hsadmin.jscli; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; + +import de.hsadmin.jscli.cas.CASTicketProvider; +import de.hsadmin.jscli.console.ConsoleWrapper; +import de.hsadmin.jscli.exception.JSCliException; + +public class ScriptClient { + + final private ScriptEngine engine; + final private Set completionStrings; + + public ScriptClient(final ConsoleWrapper console, final String user, final String runAs, final String... arguments) throws JSCliException { + final CASTicketProvider ticketProvider = new CASTicketProvider(console, user, runAs); + final RpcClient rpcClient = new RpcClient(ticketProvider); + final ScriptEngineManager engineManager = new ScriptEngineManager(); + engine = engineManager.getEngineByName("js"); + engine.put("casgrantingticket", ticketProvider); + engine.put("xmlrpcclient", rpcClient); + engine.put("xmlrpcLastResult", null); + completionStrings = new HashSet(); + completionStrings.add("set"); + completionStrings.add("where"); + considerArguments(arguments); + try { + final InputStream inputResource = getClass().getClassLoader().getResourceAsStream("js/functions.js"); + engine.eval(new InputStreamReader(inputResource)); + } catch (ScriptException e) { + throw new JSCliException(e); + } + final List methods = rpcClient.listMethods(); + for (final String method : methods) { + final String[] parts = method.split("\\."); + if (parts.length == 2) { + final String module = parts[0]; + final String function = parts[1]; + if ("system".equals(module) || "getModuleLookup".equals(function) || "createValueObject".equals(function)) { + continue; + } + completionStrings.add(module); + final String jsFunctionIdent; + if ("delete".equals(function)) { + jsFunctionIdent = module + "['remove']"; + completionStrings.add(module + ".remove"); + } else { + jsFunctionIdent = module + "['" + function + "']"; + completionStrings.add(module + "." + function); + } + try { + engine.eval( + "if (typeof " + module + " === 'undefined')" + + " { var " + module + " = { }; };\n" + + jsFunctionIdent + + " = function(json) { return hsaModuleCall('" + module + "', '" + function + "', json); }" + ); + } catch (ScriptException e) { + e.printStackTrace(); + } + } + } + console.codeCompletion(getCodeCompletionStrings()); + } + + public String[] getCodeCompletionStrings() { + final String[] codeCompletionStrings = new String[completionStrings.size()]; + int idx = 0; + for (final String s : completionStrings) { + codeCompletionStrings[idx] = s; + idx++; + } + return codeCompletionStrings; + } + + public Object execute(final String snippet) throws JSCliException { + try { + engine.put("xmlrpcLastResult", null); + return engine.eval(snippet); + } catch (ScriptException e) { + throw new JSCliException(e); + } + } + + public Object execute(final Reader rd) throws JSCliException { + try { + engine.put("xmlrpcLastResult", null); + return engine.eval(rd); + } catch (ScriptException e) { + throw new JSCliException(e); + } + } + + public Object getLastRpcResult() { + return engine.get("xmlrpcLastResult"); + } + + private void considerArguments(final String... arguments) + throws JSCliException { + final StringBuilder argsBuilder = new StringBuilder("var arguments = [ "); + boolean isFirstArg = true; + for (final String arg : arguments) { + if (!isFirstArg) { + argsBuilder.append(", "); + } + argsBuilder.append('\''); + argsBuilder.append(arg); + argsBuilder.append('\''); + isFirstArg = false; + } + argsBuilder.append(" ];"); + try { + engine.eval(argsBuilder.toString()); + } catch (ScriptException e) { + throw new JSCliException(e); + } + } + +} diff --git a/cli/src/main/java/de/hsadmin/jscli/cas/CASTicketProvider.java b/cli/src/main/java/de/hsadmin/jscli/cas/CASTicketProvider.java new file mode 100644 index 0000000..c17cf17 --- /dev/null +++ b/cli/src/main/java/de/hsadmin/jscli/cas/CASTicketProvider.java @@ -0,0 +1,200 @@ +package de.hsadmin.jscli.cas; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.ProtocolException; +import java.net.URL; +import java.net.URLEncoder; +import java.util.Properties; + +import javax.net.ssl.HttpsURLConnection; + +import de.hsadmin.jscli.conf.Config; +import de.hsadmin.jscli.console.PasswordReader; +import de.hsadmin.jscli.exception.JSCliException; + +public class CASTicketProvider { + + private static final String LOGIN_URL = "https://login.hostsharing.net:443/cas/v1/tickets"; + private static final String BACKEND_URL = "https://config.hostsharing.net:443/hsar/backend"; + + final private String loginURL; + final private String backendURL; + final private String runAs; + final private String user; + final private PasswordReader passwordReader; + + private String grantingTicket; + + public CASTicketProvider(final PasswordReader console, final String user, final String runAs) throws JSCliException { + this.passwordReader = console; + this.user = user; + this.runAs = runAs; + final Config config = Config.getInstance(); + backendURL = config.getProperty("backendURL", BACKEND_URL); + loginURL = config.getProperty("loginURL", LOGIN_URL); + if ("TestUmgebung".equals(loginURL)) { + grantingTicket = "ticket:" + user; + } else { + grantingTicket = readFiledGrantingTicket(); + } + } + + public String getTicket() throws JSCliException, FileNotFoundException { + if (grantingTicket != null && grantingTicket.startsWith("ticket:")) { + return grantingTicket.replaceFirst("ticket", "user"); + } + try { + String encodedParams = URLEncoder.encode("service", "UTF-8") + + "=" + URLEncoder.encode(backendURL, "UTF-8"); + return doHttpPost(grantingTicket, encodedParams); + } catch (UnsupportedEncodingException e) { + throw new JSCliException(e); + } + } + + public String getRunAs() { + return runAs; + } + + private String getGrantingTicket() throws JSCliException { + grantingTicket = null; + String password = Config.getInstance().getProperty(user + ".passWord"); + if (password == null || password.length() <= 0) { + password = readPasswordFromConsole(); + } + try { + String encodedParams = URLEncoder.encode("username", "UTF-8") + + "=" + URLEncoder.encode(user, "UTF-8") + + "&" + URLEncoder.encode("password", "UTF-8") + + "=" + URLEncoder.encode(password, "UTF-8"); + grantingTicket = doHttpPost(loginURL, encodedParams); + } catch (UnsupportedEncodingException e) { + throw new JSCliException(e); + } catch (FileNotFoundException e) { + throw new JSCliException("cas server not available: " + loginURL); + } + return grantingTicket; + } + + private String readPasswordFromConsole() throws JSCliException { + return passwordReader.readPassword(); + } + + private String doHttpPost(final String urlString, final String encodedParams) throws JSCliException, FileNotFoundException { + String result = null; + try { + result = extractTicket(urlString, encodedParams); + } catch (FileNotFoundException e) { + grantingTicket = getGrantingTicket(); + saveProperties(grantingTicket, getTicketFile()); + try { + result = extractTicket(grantingTicket, encodedParams); + } catch (IOException e1) { + throw new JSCliException(e1); + } + } catch (IOException e) { + throw new JSCliException(e); + } + return result; + } + + private String extractTicket(final String urlString, + final String encodedParams) throws MalformedURLException, + IOException, ProtocolException { + String result; + final HttpsURLConnection connection = doConnect(urlString, encodedParams); + final String ticket = readTicket(connection); + if (ticket != null && ticket.startsWith("ST-")) { + result = ticket; + } else { + result = connection.getHeaderField("Location"); + } + return result; + } + + private String readTicket(final HttpsURLConnection connection) + throws IOException { + final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + final String ticket = reader.readLine(); + String readLine = null; + do { + readLine = reader.readLine(); + } while (readLine != null); + return ticket; + } + + private HttpsURLConnection doConnect(final String urlString, + final String encodedParams) throws MalformedURLException, + IOException, ProtocolException { + final URL url = new URL(urlString); + final HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded; charset=UTF-8"); + connection.setDoInput(true); + connection.setDoOutput(true); + connection.setUseCaches(false); + connection.setAllowUserInteraction(false); + final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream())); + writer.write(encodedParams); + writer.close(); + return connection; + } + + private String readFiledGrantingTicket() throws JSCliException { + String filedTicket = null; + final File file = getTicketFile(); + final Properties properties = loadProperties(file); + filedTicket = properties.getProperty(user); + if (filedTicket == null) { + filedTicket = getGrantingTicket(); + saveProperties(filedTicket, file); + } + return filedTicket; + } + + private File getTicketFile() { + final String userHome = System.getProperty("user.home"); + final String ticketFileName = userHome + "/.hsadmin.tgt"; + return new File(ticketFileName); + } + + private void saveProperties(final String filedTicket, final File file) throws JSCliException { + final Properties properties = loadProperties(file); + if (filedTicket != null) { + properties.setProperty(user, filedTicket); + try { + properties.store(new FileOutputStream(file), ""); + } catch (IOException e) { + throw new JSCliException(e); + } + } + } + + private Properties loadProperties(final File file) throws JSCliException { + final Properties properties = new Properties(); + if (file.isFile() && file.canRead()) { + try { + properties.load(new FileReader(file)); + } catch (IOException e) { + throw new JSCliException(e); + } + } + return properties; + } + + @Override + public String toString() { + return grantingTicket; + } + +} diff --git a/cli/src/main/java/de/hsadmin/jscli/conf/CommandlineParser.java b/cli/src/main/java/de/hsadmin/jscli/conf/CommandlineParser.java new file mode 100644 index 0000000..b900683 --- /dev/null +++ b/cli/src/main/java/de/hsadmin/jscli/conf/CommandlineParser.java @@ -0,0 +1,72 @@ +package de.hsadmin.jscli.conf; + +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.cli.PosixParser; + +import de.hsadmin.jscli.exception.JSCliException; + +public class CommandlineParser { + + + private CommandLine cmd; + private Options opts; + + public CommandlineParser(String[] args) throws JSCliException { + opts = new Options(); + opts.addOption("h", "help", false, "print this message"); + opts.addOption("u", "user", true, "specify login user"); + opts.addOption("r", "runas", true, "specify run-as user"); + opts.addOption("e", "expr", true, "expression to execute"); + opts.addOption("f", "file", true, "script file to execute"); + opts.addOption("i", "interactive", false, "interactive shell"); + PosixParser parser = new PosixParser(); + try { + if (args.length < 1) { + printHelp(); + System.exit(0); + } + cmd = parser.parse(opts, args); + if (cmd.hasOption("help")) { + printHelp(); + System.exit(0); + } + } catch (ParseException e) { + throw new JSCliException(e); + } + } + + public String getUser() { + final String systemUser = System.getProperty("user.name"); + final String configUser = Config.getInstance().getProperty("userName", systemUser); + return cmd.getOptionValue("user", configUser); + } + + public String getRunAs() { + return cmd.getOptionValue("runas", getUser()); + } + + public String getExpression() { + return cmd.getOptionValue("expr", null); + } + + public String getFile() { + return cmd.getOptionValue("file", null); + } + + public boolean isInteractive() { + return cmd.hasOption("interactive"); + } + + public void printHelp() { + HelpFormatter formatter = new HelpFormatter(); + formatter.printHelp("hsscript", opts); + } + + public String[] getArgs() { + return cmd.getArgs(); + } + +} diff --git a/cli/src/main/java/de/hsadmin/jscli/conf/Config.java b/cli/src/main/java/de/hsadmin/jscli/conf/Config.java new file mode 100644 index 0000000..5b24a65 --- /dev/null +++ b/cli/src/main/java/de/hsadmin/jscli/conf/Config.java @@ -0,0 +1,57 @@ +package de.hsadmin.jscli.conf; + +import java.io.File; +import java.io.FileReader; +import java.util.Properties; + +public class Config { + + private static Config instance; + + private Properties props; + + private Config() { + props = new Properties(); + File file = new File(System.getProperty("user.dir") + "/hsadmin.properties"); + if (!file.canRead()) { + file = new File(System.getProperty("user.dir") + "/conf/hsadmin.properties"); + } + if (!file.canRead()) { + file = new File(System.getProperty("user.home") + "/.hsadmin.properties"); + } + if (!file.canRead()) { + file = new File("/etc/hsadmin.properties"); + } + if (!file.canRead()) { + file = new File("/etc/hsadmin/hsadmin.properties"); + } + if (file.canRead()) { + try { + props.load(new FileReader(file)); + } catch (Exception e) { + // should not happen + e.printStackTrace(); + } + } + } + + public static Config getInstance() { + if (instance == null) { + instance = new Config(); + } + return instance; + } + + public String getProperty(String propertyName) { + String property = props.getProperty(propertyName); + if (property == null) { + return null; + } + return property.trim(); + } + + public String getProperty(String propertyName, String defaultValue) { + return props.getProperty(propertyName, defaultValue).trim(); + } + +} diff --git a/cli/src/main/java/de/hsadmin/jscli/console/ConsoleWrapper.java b/cli/src/main/java/de/hsadmin/jscli/console/ConsoleWrapper.java new file mode 100644 index 0000000..1715ec2 --- /dev/null +++ b/cli/src/main/java/de/hsadmin/jscli/console/ConsoleWrapper.java @@ -0,0 +1,67 @@ +package de.hsadmin.jscli.console; + +import java.io.File; +import java.io.IOException; + +import jline.ConsoleReader; +import jline.History; +import jline.SimpleCompletor; +import de.hsadmin.jscli.exception.JSCliException; + +public class ConsoleWrapper implements PasswordReader { + + private ConsoleReader cons; + private String prompt; + + public void open(final String prompt) throws JSCliException { + this.prompt = prompt; + try { + cons = new ConsoleReader(); + cons.setDefaultPrompt(prompt); + final String userHome = System.getProperty("user.home"); + cons.setHistory(new History(new File(userHome + "/.hsscript_history"))); + } catch (IOException e) { + throw new JSCliException(e); + } + } + + public String readInput() throws JSCliException { + try { + String line = cons.readLine(); + while (line.trim().endsWith("\\")) { + line = line.substring(0, line.length() - 1) + "\n" + cons.readLine(">"); + } + return line; + } catch (IOException e) { + throw new JSCliException(e); + } + } + + public void println(final String text) throws JSCliException { + try { + if (cons != null) { + cons.printString(text); + cons.printNewline(); + } else { + throw new JSCliException("cannot write console"); + } + } catch (IOException e) { + throw new JSCliException(e); + } + } + + public String readPassword() throws JSCliException { + try { + final String pw = cons.readLine("Password: ", new Character('*')); + cons.setDefaultPrompt(prompt); + return pw; + } catch (IOException e) { + throw new JSCliException(e); + } + } + + public void codeCompletion(final String[] candidateStrings) { + cons.addCompletor(new SimpleCompletor(candidateStrings)); + } + +} diff --git a/cli/src/main/java/de/hsadmin/jscli/console/PasswordReader.java b/cli/src/main/java/de/hsadmin/jscli/console/PasswordReader.java new file mode 100644 index 0000000..4a42f3c --- /dev/null +++ b/cli/src/main/java/de/hsadmin/jscli/console/PasswordReader.java @@ -0,0 +1,9 @@ +package de.hsadmin.jscli.console; + +import de.hsadmin.jscli.exception.JSCliException; + +public interface PasswordReader { + + String readPassword() throws JSCliException; + +} diff --git a/cli/src/main/java/de/hsadmin/jscli/exception/JSCliException.java b/cli/src/main/java/de/hsadmin/jscli/exception/JSCliException.java new file mode 100644 index 0000000..ab3cb10 --- /dev/null +++ b/cli/src/main/java/de/hsadmin/jscli/exception/JSCliException.java @@ -0,0 +1,16 @@ +package de.hsadmin.jscli.exception; + + +public class JSCliException extends Exception { + + private static final long serialVersionUID = 1L; + + public JSCliException(Exception e) { + super(e); + } + + public JSCliException(String message) { + super(message); + } + +} diff --git a/cli/src/main/java/de/hsadmin/jscli/json/JSONFormatter.java b/cli/src/main/java/de/hsadmin/jscli/json/JSONFormatter.java new file mode 100644 index 0000000..35a27cb --- /dev/null +++ b/cli/src/main/java/de/hsadmin/jscli/json/JSONFormatter.java @@ -0,0 +1,104 @@ +package de.hsadmin.jscli.json; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class JSONFormatter { + + private int indent = 1; + + public String format(final Object object) { + if (object == null) return ""; + if (object instanceof List) { + return formatList((List) object); + } + if (object instanceof Map) { + return formatMap((Map) object); + } + if (object instanceof String) { + return formatString((String) object); + } + if (object instanceof Boolean) { + return ((Boolean) object).toString(); + } + if (object instanceof Object[]) { + return formatArr((Object[]) object); + } + return "an instance of " + object.getClass().getCanonicalName(); + } + + public String formatMap(final Map map) { + final StringBuffer result = new StringBuffer(); + result.append('{'); + incr(); + result.append(newline()); + final StringBuffer formattedMap = new StringBuffer(); + final List listOfKeys = Arrays.asList(map.keySet().toArray(new String[] {})); + Collections.sort(listOfKeys); + for (final Object key : listOfKeys) { + if (formattedMap.length() > 0) { + formattedMap.append(','); + formattedMap.append(newline()); + } + formattedMap.append(key.toString()); + formattedMap.append(':'); + formattedMap.append(format(map.get(key))); + } + result.append(formattedMap.toString()); + decr(); + result.append(newline()); + result.append('}'); + return result.toString(); + } + + public String formatString(final String str) { + return "'" + str + "'"; + } + + public String formatList(final List list) { + return formatArr(list.toArray()); + } + + public String formatArr(final Object[] arr) { + StringBuffer result = new StringBuffer(); + result.append('['); + incr(); + result.append(newline()); + StringBuffer formattedList = new StringBuffer(); + for (int idx = 0; idx < arr.length; idx ++) { + if (formattedList.length() > 0) { + formattedList.append(','); + formattedList.append(newline()); + } + formattedList.append(format(arr[idx])); + } + result.append(formattedList.toString()); + decr(); + if (formattedList.length() > 0) { + result.append(newline()); + } + result.append(']'); + return result.toString(); + } + + private void incr() { + indent += 3; + } + + private void decr() { + if (indent > 3) { + indent -= 3; + } + } + + private String newline() { + int ind = indent; + if (ind > 52) { + ind = 52; + } + return "\n ".substring(0, indent); + } + +} diff --git a/cli/src/main/resources/js/functions.js b/cli/src/main/resources/js/functions.js new file mode 100644 index 0000000..94dafa3 --- /dev/null +++ b/cli/src/main/resources/js/functions.js @@ -0,0 +1,85 @@ +importClass(java.util.ArrayList); +importClass(java.util.HashMap); + +function hsaParseParam(val) { + if (val instanceof java.util.List) { + return val; + } + if (val instanceof java.util.Map) { + return val; + } + if (typeof val === 'object' && val.constructor === Array) { + return hsaParseParamArray(val); + } + if (typeof val === 'object') { + return hsaParseParamObject(val); + } +} + +function hsaParseParamArray(o) { + var lst = new ArrayList(); + var val = ''; + for (var idx=0; idx < o.length; idx++) { + val = o[idx]; + if (typeof val === 'object' && val.constructor === Array) { + val = hsaParseParamArray(val); + } + else if (typeof val === 'object') { + val = hsaParseParamObject(val); + }; + lst.add(val); + }; + return lst; +} + +function hsaParseParamObject(o) { + var hsh = new HashMap(); + for (var key in o) { + var val = o[key]; + if (typeof val === 'object' && val.constructor === Array) { + val = hsaParseParamArray(val); + } + else if (typeof val === 'object') { + val = hsaParseParamObject(val); + }; + hsh.put(key, val); + }; + return hsh; +} + +function hsaToNativeJSObject(val) { + if (val instanceof java.util.List) { + var res = []; + for (var i = 0; i < val.size(); i++) { + res[i] = hsaToNativeJSObject(val.get(i)); + } + return res; + } + if (val instanceof java.util.Map) { + var res = {}; + var iter = val.keySet().iterator(); + while (iter.hasNext()) { + var key = iter.next(); + res[key] = hsaToNativeJSObject(val.get(key)); + } + return res; + } + return val; +} + +function hsaModuleCall(mod, fct, json) { + var params = new ArrayList(); + params.add(casgrantingticket.getRunAs()); + params.add(casgrantingticket.getTicket()); + if (typeof json === "undefined") { + json = {where:{}, set:{}}; + } + if (fct == "update" || fct == "add") { + params.add(hsaParseParamObject(json["set"])); + } + if (fct == "update" || fct == "delete" || fct == "search") { + params.add(hsaParseParamObject(json["where"])); + } + xmlrpcLastResult = xmlrpcclient.execute(mod + "." + fct, params); + return hsaToNativeJSObject(xmlrpcLastResult); +} diff --git a/common/.gitignore b/common/.gitignore new file mode 100644 index 0000000..e774414 --- /dev/null +++ b/common/.gitignore @@ -0,0 +1,13 @@ +*.class + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +/target +/.settings +/.classpath +/.project diff --git a/common/LICENSE.txt b/common/LICENSE.txt new file mode 100644 index 0000000..dba13ed --- /dev/null +++ b/common/LICENSE.txt @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/common/pom.xml b/common/pom.xml new file mode 100644 index 0000000..cf9d12a --- /dev/null +++ b/common/pom.xml @@ -0,0 +1,37 @@ + + 4.0.0 + + de.hsadmin + hsadmin-parent + 1.0-SNAPSHOT + + common + jar + + HSAdmin Common + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + + + + + log4j + log4j + 1.2.17 + + + diff --git a/common/src/main/java/de/hsadmin/common/config/Config.java b/common/src/main/java/de/hsadmin/common/config/Config.java new file mode 100644 index 0000000..6202bbc --- /dev/null +++ b/common/src/main/java/de/hsadmin/common/config/Config.java @@ -0,0 +1,62 @@ +package de.hsadmin.common.config; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Properties; + +import de.hsadmin.common.error.TechnicalException; + +public class Config { + + public static final String CAS_VALIDATE_URL = "cas.validate.url"; + public static final String CAS_SERVICE_URL = "cas.service.url"; + public static final String PAC_HOSTMASTER_ACCOUNTS = "accountprefix.hostmaster"; + public static final String PAC_CUSTOMER_ACCOUNTS = "accountprefix.customer"; + public static final String PACKET_DOMAINS_POSTFIX = "domainpostfix.pacdomain"; + public static final String TICKETVALIDATOR_CLASS = "ticketvalidator.class"; + + private static Config instance; + + private final Properties props; + + private Config() throws TechnicalException { + props = new Properties(); + File file = new File(System.getProperty("user.dir") + "/hsadmin.properties"); + if (!file.canRead()) { + file = new File(System.getProperty("user.dir") + "/conf/hsadmin.properties"); + } + if (!file.canRead()) { + file = new File(System.getProperty("user.home") + "/.hsadmin.properties"); + } + if (!file.canRead()) { + file = new File("/etc/hsadmin.properties"); + } + if (!file.canRead()) { + file = new File("/etc/hsadmin/hsadmin.properties"); + } + if (file.canRead()) { + try { + props.load(new FileReader(file)); + } catch (IOException e) { + throw new TechnicalException(e); + } + } + } + + public static Config getInstance() throws TechnicalException { + if (instance == null) { + instance = new Config(); + } + return instance; + } + + public String getProperty(final String propertyName) { + return props.getProperty(propertyName); + } + + public String getProperty(final String propertyName, final String defaultValue) { + return props.getProperty(propertyName, defaultValue).trim(); + } + +} diff --git a/common/src/main/java/de/hsadmin/common/error/TechnicalException.java b/common/src/main/java/de/hsadmin/common/error/TechnicalException.java new file mode 100644 index 0000000..8f59d6c --- /dev/null +++ b/common/src/main/java/de/hsadmin/common/error/TechnicalException.java @@ -0,0 +1,15 @@ +package de.hsadmin.common.error; + +public class TechnicalException extends Exception { + + private static final long serialVersionUID = 1L; + + public TechnicalException(Exception e) { + super(e); + } + + public TechnicalException(String message) { + super(message); + } + +} diff --git a/common/src/main/java/de/hsadmin/common/error/UserError.java b/common/src/main/java/de/hsadmin/common/error/UserError.java new file mode 100644 index 0000000..554e7bb --- /dev/null +++ b/common/src/main/java/de/hsadmin/common/error/UserError.java @@ -0,0 +1,54 @@ +package de.hsadmin.common.error; + +public class UserError { + + public static final String MSG_REQUIRED_FIELD = "MSG_REQUIRED_FIELD"; + public static final String MSG_NO_FIELD_WRITEACCESS = "MSG_NO_FIELD_WRITEACCESS"; + public static final String MSG_FIELD_NOT_SEARCHABLE = "MSG_FIELD_NOT_SEARCHABLE"; + public static final String MSG_NOT_IMPLEMENTED = "MSG_NOT_IMPLEMENTED"; + public static final String MSG_FIELD_DOESNOT_EXIST = "MSG_FIELD_DOESNOT_EXIST"; + public static final String MSG_FORBIDDEN_RUNAS = "MSG_FORBIDDEN_RUNAS"; + public static final String MSG_INVALID_TICKET = "MSG_INVALID_TICKET"; + public static final String MSG_MISSING_AUTHORIZATION = "MSG_MISSING_AUTHORIZATION"; + public static final String MSG_INVALID_DATEFORMAT = "MSG_INVALID_DATEFORMAT"; + public static final String MSG_FIELD_REQUIRES_MINLENGTH = "MSG_FIELD_REQUIRES_MINLENGTH"; + public static final String MSG_FIELD_EXCEEDS_MAXLENGTH = "MSG_FIELD_EXCEEDS_MAXLENGTH"; + public static final String MSG_FIELD_DOESNOT_MATCH_REGEXP = "MSG_FIELD_DOESNOT_MATCH_REGEXP"; + public static final String MSG_UNKNOWN_KEY = "MSG_UNKNOWN_KEY"; + public static final String MSG_INT_VALUE_EXPECTED = "MSG_INT_VALUE_EXPECTED"; + public static final String MSG_PAC_NOT_CANCELLED = "MSG_PAC_NOT_CANCELLED"; + public static final String MSG_PAC_CANCEL_DATE_IN_FUTURE = "MSG_PAC_CANCEL_DATE_IN_FUTURE"; + public static final String MSG_CUSTOMER_HAS_PACS = "MSG_CUSTOMER_HAS_PACS"; + public static final String MSG_CUSTOMER_IS_MEMBER = "MSG_CUSTOMER_IS_MEMBER"; + public static final String MSG_CUSTOMER_DELETE_DEADLINE_NOT_EXPIRED = "MSG_CUSTOMER_DELETE_DEADLINE_NOT_EXPIRED"; + public static final String MSG_ENTITY_EXISTS = "MSG_ENTITY_EXISTS"; + public static final String MSG_BOOLEAN_VALUE_EXPECTED = "MSG_BOOLEAN_VALUE_EXPECTED"; + public static final String MSG_DATE_VALUE_EXPECTED = "MSG_DATE_VALUE_EXPECTED"; + public static final String MSG_STRING_VALUE_EXPECTED = "MSG_STRING_VALUE_EXPECTED"; + public static final String MSG_HASHMAP_VALUE_EXPECTED = "MSG_HASHMAP_VALUE_EXPECTED"; + public static final String MSG_FIELD_DOESNOT_VALIDATE = "MSG_FIELD_DOESNOT_VALIDATE"; + + private final String message; + private final String[] parameters; + + public UserError(String msgKey, String... params) { + this.message = msgKey; + this.parameters = params; + } + + public String getLocalizedMessage() { + final StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(message); + stringBuilder.append(": "); + for (String p : parameters) { + stringBuilder.append(p); + stringBuilder.append(", "); + } + return stringBuilder.substring(0, stringBuilder.length() - 2); + } + + public String getMessageKey() { + return message; + } + +} diff --git a/common/src/main/java/de/hsadmin/common/error/UserErrorList.java b/common/src/main/java/de/hsadmin/common/error/UserErrorList.java new file mode 100644 index 0000000..0229309 --- /dev/null +++ b/common/src/main/java/de/hsadmin/common/error/UserErrorList.java @@ -0,0 +1,38 @@ +package de.hsadmin.common.error; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class UserErrorList { + + private final List errors; + + public UserErrorList() { + errors = new ArrayList<>(); + } + + public String buildMessage() { + final StringBuilder stringBuilder = new StringBuilder(); + final String lineSeparator = System.getProperty("line.separator"); + for (UserError err : errors) { + stringBuilder.append(err.getLocalizedMessage()); + stringBuilder.append(lineSeparator); + } + return stringBuilder.toString(); + } + + public void add(String messageId, String... params) { + errors.add(new UserError(messageId, params)); + } + + public void raiseException() throws UserException { + if (!errors.isEmpty()) { + throw new UserException(this); + } + } + + public Iterator errors() { + return errors.iterator(); + } +} diff --git a/common/src/main/java/de/hsadmin/common/error/UserException.java b/common/src/main/java/de/hsadmin/common/error/UserException.java new file mode 100644 index 0000000..ac350d1 --- /dev/null +++ b/common/src/main/java/de/hsadmin/common/error/UserException.java @@ -0,0 +1,45 @@ +package de.hsadmin.common.error; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + + +public class UserException extends Exception { + + private static final long serialVersionUID = 1L; + + private final List errors; + + public UserException(final Exception e) { + super(e); + errors = new ArrayList<>(); + } + + public UserException(final UserErrorList errorList) { + super(errorList.buildMessage()); + errors = new ArrayList<>(); + final Iterator iterator = errorList.errors(); + while (iterator.hasNext()) { + UserError err = iterator.next(); + errors.add(err); + } + } + + public UserException(final UserError userError) { + super(userError.getLocalizedMessage()); + errors = new ArrayList<>(); + errors.add(userError); + } + + public boolean hasError(final String errorMessageKey) { + boolean listContainsError = false; + for (UserError err : errors) { + if (err.getMessageKey().equals(errorMessageKey)) { + listContainsError = true; + } + } + return listContainsError; + } + +} diff --git a/common/src/main/java/de/hsadmin/common/util/DateUtil.java b/common/src/main/java/de/hsadmin/common/util/DateUtil.java new file mode 100644 index 0000000..a8e2b3f --- /dev/null +++ b/common/src/main/java/de/hsadmin/common/util/DateUtil.java @@ -0,0 +1,42 @@ +package de.hsadmin.common.util; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +public class DateUtil { + + final static public DateFormat DEFAULT_DATEFORMAT = new SimpleDateFormat("dd.MM.yy"); + + private final Calendar instance; + + private DateUtil() { + instance = Calendar.getInstance(); + setTimeToNull(instance); + } + + public static DateUtil getInstance(final Date dateValue) { + final DateUtil dateUtil = new DateUtil(); + dateUtil.setDate(dateValue); + return dateUtil; + } + + public void setDate(final Date dateValue) { + instance.setTime(dateValue); + setTimeToNull(instance); + } + + public Date yearsLater(final int years) { + instance.add(Calendar.YEAR, years); + return instance.getTime(); + } + + private void setTimeToNull(final Calendar calendar) { + calendar.set(Calendar.HOUR_OF_DAY, 0); + calendar.set(Calendar.MINUTE, 0); + calendar.set(Calendar.SECOND, 0); + calendar.set(Calendar.MILLISECOND, 0); + } + +} diff --git a/common/src/main/java/de/hsadmin/common/util/ReflectionUtil.java b/common/src/main/java/de/hsadmin/common/util/ReflectionUtil.java new file mode 100644 index 0000000..33e7bb8 --- /dev/null +++ b/common/src/main/java/de/hsadmin/common/util/ReflectionUtil.java @@ -0,0 +1,65 @@ +package de.hsadmin.common.util; + +import java.beans.IntrospectionException; +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserError; +import de.hsadmin.common.error.UserException; + +public class ReflectionUtil { + + public static boolean hasProperty(final Class clasz, final String propertyName) throws UserException { + try { + final PropertyDescriptor propertyDescriptor = new PropertyDescriptor(propertyName, clasz); + return propertyDescriptor.getReadMethod() != null; + } catch (IllegalArgumentException | IntrospectionException e) { + throw new UserException(new UserError(UserError.MSG_FIELD_DOESNOT_EXIST, propertyName)); + } + } + + public static Annotation getAnnotation(final Class clasz, final String propertyName, Class annotationClass) throws TechnicalException { + try { + final Field field = clasz.getDeclaredField(propertyName); + if (field != null) { + return field.getAnnotation(annotationClass); + } + return null; + } catch (NoSuchFieldException | SecurityException e) { + throw new TechnicalException(e); + } + } + + public static Object invokeGetter(final Object anObject, final String propertyName) throws TechnicalException { + try { + final PropertyDescriptor propertyDescriptor = new PropertyDescriptor(propertyName, anObject.getClass()); + return propertyDescriptor.getReadMethod().invoke(anObject); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | IntrospectionException e) { + throw new TechnicalException(e); + } + } + + public static void invokeSetter(final Object anObject, final String propertyName, final Object value) throws TechnicalException { + try { + PropertyDescriptor propertyDescriptor = new PropertyDescriptor(propertyName, anObject.getClass()); + propertyDescriptor.getWriteMethod().invoke(anObject, value); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | IntrospectionException e) { + throw new TechnicalException(e); + } + } + + public static Object newInstance(final Object anObject, String propertyName) throws TechnicalException { + try { + final PropertyDescriptor propertyDescriptor = new PropertyDescriptor(propertyName, anObject.getClass()); + final Object newInstance = propertyDescriptor.getReadMethod().getReturnType().newInstance(); + invokeSetter(anObject, propertyName, newInstance); + return newInstance; + } catch (InstantiationException | IllegalAccessException | IntrospectionException | TechnicalException e) { + throw new TechnicalException(e); + } + } + +} diff --git a/framework/.gitignore b/framework/.gitignore new file mode 100644 index 0000000..e774414 --- /dev/null +++ b/framework/.gitignore @@ -0,0 +1,13 @@ +*.class + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +/target +/.settings +/.classpath +/.project diff --git a/framework/LICENSE.txt b/framework/LICENSE.txt new file mode 100644 index 0000000..dba13ed --- /dev/null +++ b/framework/LICENSE.txt @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/framework/pom.xml b/framework/pom.xml new file mode 100644 index 0000000..14097e7 --- /dev/null +++ b/framework/pom.xml @@ -0,0 +1,70 @@ + + 4.0.0 + + de.hsadmin + hsadmin-parent + 1.0-SNAPSHOT + + framework + jar + + HSAdmin Framework + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + + + + + de.hsadmin + common + 1.0-SNAPSHOT + + + de.hsadmin + authorization + 1.0-SNAPSHOT + + + org.apache.geronimo.specs + geronimo-jpa_2.0_spec + 1.1 + provided + + + org.apache.geronimo.specs + geronimo-ejb_3.0_spec + 1.0.1 + provided + + + org.apache.geronimo.specs + geronimo-validation_1.0_spec + 1.1 + provided + + + org.apache.xmlrpc + xmlrpc-server + 3.1.3 + + + log4j + log4j + 1.2.17 + + + diff --git a/framework/src/main/java/de/hsadmin/module/Module.java b/framework/src/main/java/de/hsadmin/module/Module.java new file mode 100644 index 0000000..0932183 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/Module.java @@ -0,0 +1,25 @@ +package de.hsadmin.module; + +import java.util.List; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.login.RequestContext; + +public interface Module { + + public VO create(RequestContext requestContext, VO prototype) + throws UserException, TechnicalException; + + public List read(RequestContext requestContext, VO criteria) + throws UserException, TechnicalException; + + public List update(RequestContext requestContext, VO criteria, VO prototype) + throws UserException, TechnicalException; + + public void delete(RequestContext requestContext, VO criteria) + throws UserException, TechnicalException; + + public VO buildVO() throws TechnicalException; + +} diff --git a/framework/src/main/java/de/hsadmin/module/ValueObject.java b/framework/src/main/java/de/hsadmin/module/ValueObject.java new file mode 100644 index 0000000..403b49f --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/ValueObject.java @@ -0,0 +1,23 @@ +package de.hsadmin.module; + +import java.util.List; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.module.property.Property; + +public interface ValueObject { + + public List> properties() throws UserException, TechnicalException; + + public Property get(String propertyName) throws UserException; + + public boolean hasProperty(String propertyName) throws UserException; + + public void copyPropertiesToPersistentObject(Object persistentObject) + throws UserException, TechnicalException; + + public void copyPropertiesFromPersistentObject(Object persistentObject) + throws UserException, TechnicalException; + +} diff --git a/framework/src/main/java/de/hsadmin/module/impl/AbstractModule.java b/framework/src/main/java/de/hsadmin/module/impl/AbstractModule.java new file mode 100644 index 0000000..2bd2af4 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/impl/AbstractModule.java @@ -0,0 +1,105 @@ +package de.hsadmin.module.impl; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserError; +import de.hsadmin.common.error.UserException; +import de.hsadmin.login.RequestContext; +import de.hsadmin.login.RequiredScope; +import de.hsadmin.login.Role; +import de.hsadmin.login.ScopePolicy; +import de.hsadmin.module.Module; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.property.Property; +import de.hsadmin.module.property.StringProperty; + +public abstract class AbstractModule implements Module { + + private final ValidationDelegate validationDelegate; + + public AbstractModule() { + validationDelegate = new ValidationDelegate<>(); + } + + @Override + public VO create(final RequestContext requestContext, final VO prototype) + throws UserException, TechnicalException { + checkScopePolicy(requestContext, "create"); + validationDelegate.checkPrototypeIsCreateable(prototype); + return prototype; + } + + @Override + public List read(final RequestContext requestContext, final VO criteria) + throws UserException, TechnicalException { + checkScopePolicy(requestContext, "read", criteria); + validationDelegate.checkCriteriaIsSearchable(criteria); + final List readValueObjects = new ArrayList<>(); + return readValueObjects; + } + + @Override + public List update(final RequestContext requestContext, final VO criteria, + final VO prototype) throws UserException, TechnicalException { + checkScopePolicy(requestContext, "update", criteria); + validationDelegate.checkCriteriaIsSearchable(criteria); + validationDelegate.checkPrototypeIsUpdateable(prototype); + final List valueObjectsForUpdate = read(requestContext, criteria); + return valueObjectsForUpdate; + } + + @Override + public void delete(final RequestContext requestContext, final VO criteria) + throws UserException, TechnicalException { + checkScopePolicy(requestContext, "delete", criteria); + validationDelegate.checkCriteriaIsSearchable(criteria); + } + + protected void checkScopePolicy(final RequestContext requestContext, final String methodName, + final VO criteria) throws TechnicalException, UserException { + final String scopeAttribute = checkScopePolicy(requestContext, methodName); + if (scopeAttribute != null && !scopeAttribute.isEmpty()) { + final Property property = criteria.get(scopeAttribute); + if (property.valueIsNullOrEmpty() && property instanceof StringProperty) { + ((StringProperty) property).setValue(requestContext.getLoginUser()); + } else { + if (!requestContext.getLoginUser().equals(property.getValue())) { + throw new UserException(new UserError(UserError.MSG_MISSING_AUTHORIZATION, methodName)); + } + } + } + } + + protected String checkScopePolicy(final RequestContext requestContext, final String methodName) + throws TechnicalException, UserException { + try { + Method method = null; + final Class valueClass = buildVO().getClass(); + if ("update".equals(methodName)) { + method = getClass().getMethod(methodName, RequestContext.class, valueClass, valueClass); + } else { + method = getClass().getMethod(methodName, RequestContext.class, valueClass); + } + if (method == null) { + throw new UserException(new UserError(UserError.MSG_MISSING_AUTHORIZATION, methodName)); + } + final RequiredScope annotation = method.getAnnotation(RequiredScope.class); + if (annotation == null) { + throw new UserException(new UserError(UserError.MSG_MISSING_AUTHORIZATION, methodName)); + } + final ScopePolicy[] scopePolicies = annotation.value(); + for (ScopePolicy policy : scopePolicies) { + if (policy.value() == requestContext.getLoginRole() || policy.value() == Role.ANY) { + return policy.property(); + } + } + throw new UserException(new UserError(UserError.MSG_MISSING_AUTHORIZATION, methodName)); + } catch (NoSuchMethodException | SecurityException e) { + throw new TechnicalException(e); + } + } + +} diff --git a/framework/src/main/java/de/hsadmin/module/impl/AbstractProperty.java b/framework/src/main/java/de/hsadmin/module/impl/AbstractProperty.java new file mode 100644 index 0000000..1df5309 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/impl/AbstractProperty.java @@ -0,0 +1,135 @@ +package de.hsadmin.module.impl; + +import java.util.Map; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.common.util.ReflectionUtil; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.property.Property; +import de.hsadmin.module.property.ReadWritePolicy; +import de.hsadmin.module.property.SearchPolicy; +import de.hsadmin.module.property.mapping.ParameterMapMapper; +import de.hsadmin.module.property.mapping.PersistentObjectMapper; + +public abstract class AbstractProperty implements Property { + + private final ValueObject owningVO; + private final String name; + private final ReadWritePolicy policy; + private final SearchPolicy search; + private final boolean required; + + private PersistentObjectMapper persistentObjectMapper; + private ParameterMapMapper parameterMapMapper; + + public AbstractProperty( + final ValueObject owner, + final String propertyName, + final ReadWritePolicy readWritePolicy, + final SearchPolicy searchPolicy, + final boolean required) { + this.owningVO = owner; + this.name = propertyName; + this.policy = readWritePolicy; + this.search = searchPolicy; + this.required = required; + } + + protected PersistentObjectMapper getPersistentObjectMapper() { + return persistentObjectMapper; + } + + protected ParameterMapMapper getParameterMapMapper() { + return parameterMapMapper; + } + + @SuppressWarnings("unchecked") + protected void setPersistentObjectMapper(final PersistentObjectMapper mapper) { + persistentObjectMapper = (PersistentObjectMapper) mapper; + } + + @SuppressWarnings("unchecked") + protected void setParameterMapMapper(ParameterMapMapper mapper) { + parameterMapMapper = (ParameterMapMapper) mapper; + } + + @Override + public String getName() { + return name; + } + + @Override + public ReadWritePolicy access() { + return policy; + } + + @Override + public SearchPolicy search() { + return search; + } + + @Override + public boolean required() { + return required; + } + + @SuppressWarnings("unchecked") + public Class> getPropertyType() { + return (Class>) getClass(); + } + + @SuppressWarnings("unchecked") + @Override + public T getValue() throws TechnicalException { + return (T) ReflectionUtil.invokeGetter(owningVO, getName()); + } + + @Override + public void setValue(T value) throws TechnicalException { + ReflectionUtil.invokeSetter(owningVO, getName(), value); + } + + @Override + public boolean valueIsNullOrEmpty() { + try { + return getValue() == null; + } catch (TechnicalException e) { + return true; + } + } + + @Override + public String toString() { + try { + return "Property " + name + ": " + getValue(); + } catch (TechnicalException e) { + return "Property " + name; + } + } + + @Override + public void copyValueFromPersistentObject(Object persistentObject) throws TechnicalException, UserException { + setValue(getPersistentObjectMapper().readValueFromPersistentObject(persistentObject, getName())); + } + + @Override + public void copyValueToPersistentObject(Object persistentObject) throws TechnicalException, UserException { + T newValue = getValue(); + if (newValue != null) { + getPersistentObjectMapper().writeValueToPersistentObject(persistentObject, getName(), newValue); + } + } + + @Override + public void copyValueToParameterMap(Map rpcParameter) + throws TechnicalException, UserException { + getParameterMapMapper().writeValueToParameterMap(rpcParameter, getName(), getValue()); + } + + @Override + public void copyValueFromParameterMap(Map rpcParameter) throws TechnicalException, UserException { + setValue(getParameterMapMapper().readValueFromParameterMap(rpcParameter, getName())); + } + +} diff --git a/framework/src/main/java/de/hsadmin/module/impl/AbstractVO.java b/framework/src/main/java/de/hsadmin/module/impl/AbstractVO.java new file mode 100644 index 0000000..6326160 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/impl/AbstractVO.java @@ -0,0 +1,168 @@ +package de.hsadmin.module.impl; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.common.util.ReflectionUtil; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.property.ContainsElements; +import de.hsadmin.module.property.ElementsType; +import de.hsadmin.module.property.Property; +import de.hsadmin.module.property.ReadWrite; +import de.hsadmin.module.property.ReadWritePolicy; +import de.hsadmin.module.property.Required; +import de.hsadmin.module.property.Search; +import de.hsadmin.module.property.SearchPolicy; +import de.hsadmin.module.property.mapping.Mapping; +import de.hsadmin.module.property.mapping.ParameterMapMapper; +import de.hsadmin.module.property.mapping.PersistentObjectMapper; +import de.hsadmin.module.property.mapping.ReferredPropertyPath; + +public abstract class AbstractVO implements ValueObject { + + private final Map> propertiesMap; + + public AbstractVO() throws TechnicalException { + propertiesMap = new HashMap<>(); + final Field[] fields = getClass().getDeclaredFields(); + for (Field f : fields) { + if (isPropertyField(f)) { + initializeProperty(f); + } + } + } + + @Override + public List> properties() throws UserException, TechnicalException { + final List> result = new ArrayList<>(); + try { + final Field[] fields = getClass().getDeclaredFields(); + for (Field f : fields) { + if (isPropertyField(f)) { + result.add(get(f.getName())); + } + } + } catch (IllegalArgumentException e) { + throw new TechnicalException(e); + } + return result; + } + + @Override + public Property get(final String propertyName) throws UserException { + assert propertyName != null && propertyName.length() > 0; + return propertiesMap.get(propertyName); + } + + @Override + public boolean hasProperty(final String propertyName) throws UserException { + assert propertyName != null && propertyName.length() > 0; + return ReflectionUtil.hasProperty(getClass(), propertyName); + } + + @Override + public void copyPropertiesToPersistentObject(final Object persistentObject) throws UserException, TechnicalException { + assert persistentObject != null; + final List> properties = properties(); + for (Property p : properties) { + p.copyValueToPersistentObject(persistentObject); + } + } + + @Override + public void copyPropertiesFromPersistentObject(final Object persistentObject) throws UserException, TechnicalException { + assert persistentObject != null; + final List> properties = properties(); + for (Property p : properties) { + p.copyValueFromPersistentObject(persistentObject); + } + } + + private boolean isPropertyField(final Field f) { + ReadWrite annotation = f.getAnnotation(ReadWrite.class); + return annotation != null; + } + + private void initializeProperty(final Field f) throws TechnicalException { + try { + String simplePropertyClassName = f.getType().getSimpleName(); + if ("int".equals(simplePropertyClassName)) { + simplePropertyClassName = "Integer"; + } + if ("boolean".equals(simplePropertyClassName)) { + simplePropertyClassName = "Boolean"; + } + final Class type = Class.forName("de.hsadmin.module.property." + simplePropertyClassName + "Property"); + final Constructor constructor = type.getConstructor(ValueObject.class, String.class, ReadWritePolicy.class, SearchPolicy.class, boolean.class); + final Property newInstance = (Property) constructor.newInstance(this, f.getName(), getReadWritePolicy(f), getSearchPolicy(f), isRequired(f)); + set(f.getName(), newInstance); + if (ContainsElements.class.isAssignableFrom(type)) { + ContainsElements container = (ContainsElements) newInstance; + container.setElementsType(getElementsType(f)); + } + Mapping mapping = f.getAnnotation(Mapping.class); + if (mapping != null && newInstance instanceof AbstractProperty) { + AbstractProperty prop = (AbstractProperty) newInstance; + PersistentObjectMapper persistentObjectMapper = mapping.boMapping().newInstance(); + ParameterMapMapper parameterMapMapper = mapping.rpcMapping().newInstance(); + prop.setParameterMapMapper(parameterMapMapper); + prop.setPersistentObjectMapper(persistentObjectMapper); + if (persistentObjectMapper instanceof ReferredPropertyPath) { + ((ReferredPropertyPath) persistentObjectMapper).setPropertyPath(mapping.boMappingPath());; + } + } + } catch (IllegalArgumentException | IllegalAccessException | InstantiationException | InvocationTargetException + | NoSuchMethodException | SecurityException | UserException | ClassNotFoundException e) { + throw new TechnicalException(e); + } + } + + private void set(final String propertyName, final Property propertyInstance) throws UserException { + assert propertyName != null && propertyName.length() > 0; + assert propertyInstance != null; + propertiesMap.put(propertyName, propertyInstance); + } + + private SearchPolicy getSearchPolicy(final Field f) { + final Search search = f.getAnnotation(Search.class); + SearchPolicy searchPolicy = SearchPolicy.NONE; + if (search != null) { + searchPolicy = search.value(); + } + return searchPolicy; + } + + private Class getElementsType(final Field f) throws TechnicalException { + final ElementsType annotation = f.getAnnotation(ElementsType.class); + if (annotation != null) { + return annotation.value(); + } + throw new TechnicalException("annotation ElementsType required"); + } + + private boolean isRequired(final Field f) { + final Required requiredAnn = f.getAnnotation(Required.class); + boolean required = false; + if (requiredAnn != null) { + required = requiredAnn.value(); + } + return required; + } + + private ReadWritePolicy getReadWritePolicy(final Field f) { + final ReadWrite readWrite = f.getAnnotation(ReadWrite.class); + ReadWritePolicy rwPolicy = ReadWritePolicy.NONE; + if (readWrite != null) { + rwPolicy = readWrite.value(); + } + return rwPolicy; + } + +} diff --git a/framework/src/main/java/de/hsadmin/module/impl/ValidationDelegate.java b/framework/src/main/java/de/hsadmin/module/impl/ValidationDelegate.java new file mode 100644 index 0000000..d7be660 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/impl/ValidationDelegate.java @@ -0,0 +1,85 @@ +package de.hsadmin.module.impl; + +import java.util.List; +import java.util.Set; + +import javax.validation.ConstraintViolation; +import javax.validation.Validation; +import javax.validation.ValidatorFactory; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserError; +import de.hsadmin.common.error.UserErrorList; +import de.hsadmin.common.error.UserException; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.property.Property; +import de.hsadmin.module.property.ReadWritePolicy; +import de.hsadmin.module.property.SearchPolicy; + +public class ValidationDelegate { + + private static final ValidatorFactory vf; + + static { + vf = Validation.buildDefaultValidatorFactory(); + } + + public void checkPrototypeIsCreateable(final T prototype) throws UserException, TechnicalException { + final UserErrorList errors = new UserErrorList(); + final List> properties = prototype.properties(); + for (Property p : properties) { + if (p.valueIsNullOrEmpty()) { + if (p.required()) { + errors.add(UserError.MSG_REQUIRED_FIELD, p.getName()); + } + } else { + final ReadWritePolicy rwPolicy = p.access(); + if (rwPolicy != ReadWritePolicy.READWRITE && rwPolicy != ReadWritePolicy.WRITEONCE) { + errors.add(UserError.MSG_NO_FIELD_WRITEACCESS, p.getName()); + } else { + Set> validateResults = vf.getValidator().validate(prototype); + if (!validateResults.isEmpty()) { + for (ConstraintViolation violation: validateResults) { + errors.add(UserError.MSG_FIELD_DOESNOT_VALIDATE, violation.getMessage(), violation.getPropertyPath().toString(), violation.getInvalidValue().toString()); + } + } + } + } + } + errors.raiseException(); + } + + public void checkPrototypeIsUpdateable(final T prototype) throws UserException, TechnicalException { + final List> properties = prototype.properties(); + final UserErrorList errors = new UserErrorList(); + for (Property p : properties) { + final ReadWritePolicy rwPolicy = p.access(); + if (!p.valueIsNullOrEmpty()) { + if (rwPolicy != ReadWritePolicy.READWRITE) { + errors.add(UserError.MSG_NO_FIELD_WRITEACCESS, p.getName()); + } else { + Set> validateResults = vf.getValidator().validate(prototype); + if (!validateResults.isEmpty()) { + for (ConstraintViolation violation: validateResults) { + errors.add(UserError.MSG_FIELD_DOESNOT_VALIDATE, violation.getMessage(), violation.getPropertyPath().toString(), violation.getInvalidValue().toString()); + } + } + } + } + } + errors.raiseException(); + } + + public void checkCriteriaIsSearchable(final T criteria) throws UserException, TechnicalException { + final UserErrorList errors = new UserErrorList(); + final List> properties = criteria.properties(); + for (Property p : properties) { + final SearchPolicy searchPolicy = p.search(); + if (!p.valueIsNullOrEmpty() && searchPolicy != SearchPolicy.COMPARE && searchPolicy != SearchPolicy.EQUALS && searchPolicy != SearchPolicy.LIKE) { + errors.add(UserError.MSG_FIELD_NOT_SEARCHABLE, p.getName()); + } + } + errors.raiseException(); + } + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/BooleanProperty.java b/framework/src/main/java/de/hsadmin/module/property/BooleanProperty.java new file mode 100644 index 0000000..7c05b4a --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/BooleanProperty.java @@ -0,0 +1,31 @@ +package de.hsadmin.module.property; + +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractProperty; +import de.hsadmin.module.property.mapping.DefaultBooleanParameterMapMapper; +import de.hsadmin.module.property.mapping.DefaultBooleanPersistentObjectMapper; +import de.hsadmin.module.property.mapping.ParameterMapMapper; +import de.hsadmin.module.property.mapping.PersistentObjectMapper; + +public class BooleanProperty extends AbstractProperty implements Property { + + private static final PersistentObjectMapper defaultPersistentObjectMapper; + private static final ParameterMapMapper defaultParameterMapMapper; + + static { + defaultPersistentObjectMapper = new DefaultBooleanPersistentObjectMapper(); + defaultParameterMapMapper = new DefaultBooleanParameterMapMapper(); + } + + public BooleanProperty(final ValueObject ownerVO, final String propertyName, final ReadWritePolicy readWritePolicy, final SearchPolicy searchPolicy, final boolean required) { + super(ownerVO, propertyName, readWritePolicy, searchPolicy, required); + setParameterMapMapper(defaultParameterMapMapper); + setPersistentObjectMapper(defaultPersistentObjectMapper); + } + + @Override + public Class getValueType() { + return Boolean.class; + } + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/ContainsElements.java b/framework/src/main/java/de/hsadmin/module/property/ContainsElements.java new file mode 100644 index 0000000..5eb38d0 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/ContainsElements.java @@ -0,0 +1,11 @@ +package de.hsadmin.module.property; + +import de.hsadmin.module.ValueObject; + +public interface ContainsElements { + + public Class getElementsType(); + + public void setElementsType(Class elementsType); + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/DateProperty.java b/framework/src/main/java/de/hsadmin/module/property/DateProperty.java new file mode 100644 index 0000000..f693e9f --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/DateProperty.java @@ -0,0 +1,33 @@ +package de.hsadmin.module.property; + +import java.util.Date; + +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractProperty; +import de.hsadmin.module.property.mapping.DefaultDateParameterMapMapper; +import de.hsadmin.module.property.mapping.DefaultDatePersistentObjectMapper; +import de.hsadmin.module.property.mapping.ParameterMapMapper; +import de.hsadmin.module.property.mapping.PersistentObjectMapper; + +public class DateProperty extends AbstractProperty implements Property { + + private static final PersistentObjectMapper defaultPersistentObjectMapper; + private static final ParameterMapMapper defaultParameterMapMapper; + + static { + defaultPersistentObjectMapper = new DefaultDatePersistentObjectMapper(); + defaultParameterMapMapper = new DefaultDateParameterMapMapper(); + } + + public DateProperty(final ValueObject ownerVO, final String propertyName, final ReadWritePolicy readWritePolicy, final SearchPolicy searchPolicy, final boolean required) { + super(ownerVO, propertyName, readWritePolicy, searchPolicy, required); + setPersistentObjectMapper(defaultPersistentObjectMapper); + setParameterMapMapper(defaultParameterMapMapper); + } + + @Override + public Class getValueType() { + return Date.class; + } + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/Display.java b/framework/src/main/java/de/hsadmin/module/property/Display.java new file mode 100644 index 0000000..de72277 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/Display.java @@ -0,0 +1,15 @@ +package de.hsadmin.module.property; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Display { + + int sequence() default 9999; + DisplayPolicy visible() default DisplayPolicy.ALWAYS; + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/DisplayPolicy.java b/framework/src/main/java/de/hsadmin/module/property/DisplayPolicy.java new file mode 100644 index 0000000..f15175b --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/DisplayPolicy.java @@ -0,0 +1,7 @@ +package de.hsadmin.module.property; + +public enum DisplayPolicy { + + ALWAYS, OPTIONAL, NEVER + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/ElementsType.java b/framework/src/main/java/de/hsadmin/module/property/ElementsType.java new file mode 100644 index 0000000..f291153 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/ElementsType.java @@ -0,0 +1,16 @@ +package de.hsadmin.module.property; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import de.hsadmin.module.ValueObject; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface ElementsType { + + Class value(); + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/IntegerProperty.java b/framework/src/main/java/de/hsadmin/module/property/IntegerProperty.java new file mode 100644 index 0000000..76e81c9 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/IntegerProperty.java @@ -0,0 +1,31 @@ +package de.hsadmin.module.property; + +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractProperty; +import de.hsadmin.module.property.mapping.DefaultIntegerParameterMapMapper; +import de.hsadmin.module.property.mapping.DefaultIntegerPersistentObjectMapper; +import de.hsadmin.module.property.mapping.ParameterMapMapper; +import de.hsadmin.module.property.mapping.PersistentObjectMapper; + +public class IntegerProperty extends AbstractProperty implements Property { + + private static final PersistentObjectMapper defaultPersistentObjectMapper; + private static final ParameterMapMapper defaultParameterMapMapper; + + static { + defaultPersistentObjectMapper = new DefaultIntegerPersistentObjectMapper(); + defaultParameterMapMapper = new DefaultIntegerParameterMapMapper(); + } + + public IntegerProperty(final ValueObject ownerVO, final String propertyName, final ReadWritePolicy readWritePolicy, final SearchPolicy searchPolicy, final boolean required) { + super(ownerVO, propertyName, readWritePolicy, searchPolicy, required); + setPersistentObjectMapper(defaultPersistentObjectMapper); + setParameterMapMapper(defaultParameterMapMapper); + } + + @Override + public Class getValueType() { + return Integer.class; + } + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/ListProperty.java b/framework/src/main/java/de/hsadmin/module/property/ListProperty.java new file mode 100644 index 0000000..549a1e4 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/ListProperty.java @@ -0,0 +1,47 @@ +package de.hsadmin.module.property; + +import java.util.List; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractProperty; +import de.hsadmin.module.property.mapping.DefaultListParameterMapMapper; +import de.hsadmin.module.property.mapping.DefaultListPersistentObjectMapper; + +public class ListProperty extends AbstractProperty> implements Property>, ContainsElements { + + private Class elementsType; + + public ListProperty(final ValueObject ownerVO, final String propertyName, final ReadWritePolicy readWritePolicy, final SearchPolicy searchPolicy, final boolean required) { + super(ownerVO, propertyName, readWritePolicy, searchPolicy, required); + } + + @Override + public Class getValueType() { + return List.class; + } + + @Override + public boolean valueIsNullOrEmpty() { + List val = null; + try { + val = getValue(); + } catch (TechnicalException e) { + return true; + } + return val == null || val.isEmpty(); + } + + @Override + public Class getElementsType() { + return elementsType; + } + + @Override + public void setElementsType(final Class elementsType) { + this.elementsType = elementsType; + setPersistentObjectMapper(new DefaultListPersistentObjectMapper(elementsType)); + setParameterMapMapper(new DefaultListParameterMapMapper(elementsType)); + } + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/Property.java b/framework/src/main/java/de/hsadmin/module/property/Property.java new file mode 100644 index 0000000..ac99264 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/Property.java @@ -0,0 +1,38 @@ +package de.hsadmin.module.property; + +import java.util.Map; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; + +public interface Property { + + public String getName(); + + public T getValue() throws TechnicalException; + + public void setValue(T value) throws TechnicalException; + + public Class> getPropertyType(); + + public Class getValueType(); + + public ReadWritePolicy access(); + + public SearchPolicy search(); + + public boolean required(); + + public boolean valueIsNullOrEmpty(); + + public void copyValueFromPersistentObject(final Object persistentObject) throws TechnicalException, UserException; + + public void copyValueToPersistentObject(final Object persistentObject) throws TechnicalException, UserException; + + public void copyValueToParameterMap(final Map rpcParameter) throws TechnicalException, UserException; + + public void copyValueFromParameterMap(final Map rpcParameter) throws TechnicalException, UserException; + +} + + diff --git a/framework/src/main/java/de/hsadmin/module/property/ReadWrite.java b/framework/src/main/java/de/hsadmin/module/property/ReadWrite.java new file mode 100644 index 0000000..802b9a0 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/ReadWrite.java @@ -0,0 +1,14 @@ +package de.hsadmin.module.property; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface ReadWrite { + + ReadWritePolicy value(); + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/ReadWritePolicy.java b/framework/src/main/java/de/hsadmin/module/property/ReadWritePolicy.java new file mode 100644 index 0000000..dd9dbb5 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/ReadWritePolicy.java @@ -0,0 +1,5 @@ +package de.hsadmin.module.property; + +public enum ReadWritePolicy { + READ, READWRITE, WRITEONCE, NONE +} diff --git a/framework/src/main/java/de/hsadmin/module/property/Required.java b/framework/src/main/java/de/hsadmin/module/property/Required.java new file mode 100644 index 0000000..bb75fe9 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/Required.java @@ -0,0 +1,14 @@ +package de.hsadmin.module.property; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Required { + + boolean value(); + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/Search.java b/framework/src/main/java/de/hsadmin/module/property/Search.java new file mode 100644 index 0000000..5d8c827 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/Search.java @@ -0,0 +1,14 @@ +package de.hsadmin.module.property; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Search { + + SearchPolicy value(); + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/SearchPolicy.java b/framework/src/main/java/de/hsadmin/module/property/SearchPolicy.java new file mode 100644 index 0000000..6ba37ed --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/SearchPolicy.java @@ -0,0 +1,5 @@ +package de.hsadmin.module.property; + +public enum SearchPolicy { + EQUALS, LIKE, COMPARE, NONE +} diff --git a/framework/src/main/java/de/hsadmin/module/property/StringProperty.java b/framework/src/main/java/de/hsadmin/module/property/StringProperty.java new file mode 100644 index 0000000..19bb38e --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/StringProperty.java @@ -0,0 +1,43 @@ +package de.hsadmin.module.property; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractProperty; +import de.hsadmin.module.property.mapping.DefaultStringParameterMapMapper; +import de.hsadmin.module.property.mapping.DefaultStringPersistentObjectMapper; +import de.hsadmin.module.property.mapping.ParameterMapMapper; +import de.hsadmin.module.property.mapping.PersistentObjectMapper; + +public class StringProperty extends AbstractProperty implements Property { + + private static final PersistentObjectMapper defaultPersistentObjectMapper; + private static final ParameterMapMapper defaultParameterMapMapper; + + static { + defaultPersistentObjectMapper = new DefaultStringPersistentObjectMapper(); + defaultParameterMapMapper = new DefaultStringParameterMapMapper(); + } + + public StringProperty(final ValueObject ownerVO, final String propertyName, final ReadWritePolicy readWritePolicy, final SearchPolicy searchPolicy, final boolean required) { + super(ownerVO, propertyName, readWritePolicy, searchPolicy, required); + setParameterMapMapper(defaultParameterMapMapper); + setPersistentObjectMapper(defaultPersistentObjectMapper); + } + + @Override + public Class getValueType() { + return String.class; + } + + @Override + public boolean valueIsNullOrEmpty() { + String val = null; + try { + val = getValue(); + } catch (TechnicalException e) { + return true; + } + return val == null || val.isEmpty(); + } + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/StringSet.java b/framework/src/main/java/de/hsadmin/module/property/StringSet.java new file mode 100644 index 0000000..3fe410f --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/StringSet.java @@ -0,0 +1,30 @@ +package de.hsadmin.module.property; + +import java.util.Arrays; +import java.util.Set; +import java.util.TreeSet; + +public class StringSet { + + private Set stringSet; + + public StringSet() { + stringSet = null; + } + + public String[] getStrings() { + if (stringSet == null) { + return null; + } + return stringSet.toArray(new String[] { } ); + } + + public void setStrings(final String[] changedStringSet) { + stringSet = null; + if (changedStringSet != null) { + stringSet = new TreeSet(); + stringSet.addAll(Arrays.asList(changedStringSet)); + } + } + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/StringSetProperty.java b/framework/src/main/java/de/hsadmin/module/property/StringSetProperty.java new file mode 100644 index 0000000..b638272 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/StringSetProperty.java @@ -0,0 +1,84 @@ +package de.hsadmin.module.property; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.common.util.ReflectionUtil; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractProperty; +import de.hsadmin.module.property.mapping.DefaultStringSetParameterMapMapper; +import de.hsadmin.module.property.mapping.DefaultStringSetPersistentObjectMapper; +import de.hsadmin.module.property.mapping.ParameterMapMapper; +import de.hsadmin.module.property.mapping.PersistentObjectMapper; + +public class StringSetProperty extends AbstractProperty { + + private static final PersistentObjectMapper defaultPersistentObjectMapper; + private static final ParameterMapMapper defaultParameterMapMapper; + + static { + defaultPersistentObjectMapper = new DefaultStringSetPersistentObjectMapper(); + defaultParameterMapMapper = new DefaultStringSetParameterMapMapper(); + } + + private final ValueObject owningVO; + + public StringSetProperty(final ValueObject owner, final String propertyName, + final ReadWritePolicy readWritePolicy, final SearchPolicy searchPolicy, + final boolean required) { + super(owner, propertyName, readWritePolicy, searchPolicy, required); + owningVO = owner; + setParameterMapMapper(defaultParameterMapMapper); + setPersistentObjectMapper(defaultPersistentObjectMapper); + } + + @Override + public Class getValueType() { + return StringSet.class; + } + + @Override + public void setValue(final StringSet value) throws TechnicalException { + ReflectionUtil.invokeSetter(owningVO, getName(), value.getStrings()); + } + + @Override + public StringSet getValue() throws TechnicalException { + final StringSet value = new StringSet(); + final Object stringList = ReflectionUtil.invokeGetter(owningVO, getName()); + if (stringList instanceof String[]) { + value.setStrings(((String[]) stringList)); + } + return value; + } + + @Override + public boolean valueIsNullOrEmpty() { + try { + final Object stringList = ReflectionUtil.invokeGetter(owningVO, getName()); + if (stringList == null) { + return true; + } + if (stringList instanceof String[]) { + return ((String[]) stringList).length == 0; + } + return false; + } catch (TechnicalException e) { + return false; + } + } + + @Override + public void copyValueFromPersistentObject(Object persistentObject) + throws TechnicalException, UserException { + // TODO Auto-generated method stub + super.copyValueFromPersistentObject(persistentObject); + } + + @Override + public void copyValueToPersistentObject(Object persistentObject) + throws TechnicalException, UserException { + // TODO Auto-generated method stub + super.copyValueToPersistentObject(persistentObject); + } + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultBooleanParameterMapMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultBooleanParameterMapMapper.java new file mode 100644 index 0000000..741d6b0 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultBooleanParameterMapMapper.java @@ -0,0 +1,39 @@ +package de.hsadmin.module.property.mapping; + +import java.util.Map; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserError; +import de.hsadmin.common.error.UserException; + +public class DefaultBooleanParameterMapMapper implements + ParameterMapMapper { + @Override + public void writeValueToParameterMap(final Map rpcParameter, + final String propertyName, final Boolean value) + throws TechnicalException, UserException { + if (value != null) { + rpcParameter.put(propertyName, value.toString()); + } + } + + @Override + public Boolean readValueFromParameterMap(final Map rpcParameter, + final String propertyName) throws TechnicalException, UserException { + final Object value = rpcParameter.get(propertyName); + if (value instanceof Boolean) { + return (Boolean) value; + } + if (value instanceof String) { + String stringValue = (String) value; + if ("true".equalsIgnoreCase(stringValue)) { + return Boolean.TRUE; + } + if ("false".equalsIgnoreCase(stringValue)) { + return Boolean.FALSE; + } + throw new UserException(new UserError(UserError.MSG_BOOLEAN_VALUE_EXPECTED, propertyName, stringValue)); + } + return null; + } +} \ No newline at end of file diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultBooleanPersistentObjectMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultBooleanPersistentObjectMapper.java new file mode 100644 index 0000000..015fe6f --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultBooleanPersistentObjectMapper.java @@ -0,0 +1,26 @@ +package de.hsadmin.module.property.mapping; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.util.ReflectionUtil; + +public class DefaultBooleanPersistentObjectMapper implements PersistentObjectMapper { + + @Override + public void writeValueToPersistentObject(final Object persistentObject, final String propertyName, final Boolean value) throws TechnicalException { + ReflectionUtil.invokeSetter(persistentObject, propertyName, value); + } + + @Override + public Boolean readValueFromPersistentObject(final Object persistentObject, final String propertyName) throws TechnicalException { + final Object object = ReflectionUtil.invokeGetter(persistentObject, propertyName); + if (object instanceof Boolean) { + return (Boolean) object; + } else { + if (object instanceof String) { + return Boolean.parseBoolean((String) object); + } else { + return Boolean.FALSE; + } + } + } +} \ No newline at end of file diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultDateParameterMapMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultDateParameterMapMapper.java new file mode 100644 index 0000000..7c77c98 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultDateParameterMapMapper.java @@ -0,0 +1,39 @@ +package de.hsadmin.module.property.mapping; + +import java.text.ParseException; +import java.util.Date; +import java.util.Map; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserError; +import de.hsadmin.common.error.UserException; +import de.hsadmin.common.util.DateUtil; + +public class DefaultDateParameterMapMapper implements ParameterMapMapper { + + @Override + public void writeValueToParameterMap(final Map rpcParameter, + final String propertyName, final Date value) + throws TechnicalException, UserException { + if (value != null) { + rpcParameter.put(propertyName, DateUtil.DEFAULT_DATEFORMAT.format(value)); + } + } + + @Override + public Date readValueFromParameterMap(final Map rpcParameter, + final String propertyName) throws TechnicalException, UserException { + final Object value = rpcParameter.get(propertyName); + if (value instanceof Date) { + return (Date) value; + } + if (value instanceof String) { + try { + return DateUtil.DEFAULT_DATEFORMAT.parse((String) value); + } catch (ParseException e) { + throw new UserException(new UserError(UserError.MSG_INVALID_DATEFORMAT, propertyName, (String) value)); + } + } + return null; + } +} \ No newline at end of file diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultDatePersistentObjectMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultDatePersistentObjectMapper.java new file mode 100644 index 0000000..389c607 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultDatePersistentObjectMapper.java @@ -0,0 +1,34 @@ +package de.hsadmin.module.property.mapping; + +import java.text.ParseException; +import java.util.Date; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.util.DateUtil; +import de.hsadmin.common.util.ReflectionUtil; + +public class DefaultDatePersistentObjectMapper implements PersistentObjectMapper { + + @Override + public void writeValueToPersistentObject(final Object persistentObject, final String propertyName, final Date value) throws TechnicalException { + ReflectionUtil.invokeSetter(persistentObject, propertyName, value); + } + + @Override + public Date readValueFromPersistentObject(final Object persistentObject, final String propertyName) throws TechnicalException { + final Object object = ReflectionUtil.invokeGetter(persistentObject, propertyName); + if (object instanceof Date) { + return (Date) object; + } else { + if (object instanceof String) { + try { + return DateUtil.DEFAULT_DATEFORMAT.parse((String) object); + } catch (ParseException e) { + throw new TechnicalException(e); + } + } else { + return null; + } + } + } +} \ No newline at end of file diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultIntegerParameterMapMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultIntegerParameterMapMapper.java new file mode 100644 index 0000000..b19b343 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultIntegerParameterMapMapper.java @@ -0,0 +1,37 @@ +package de.hsadmin.module.property.mapping; + +import java.util.Map; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserError; +import de.hsadmin.common.error.UserException; + +public class DefaultIntegerParameterMapMapper implements ParameterMapMapper { + + @Override + public void writeValueToParameterMap(final Map rpcParameter, + final String propertyName, Integer value) + throws TechnicalException, UserException { + if (value != null) { + rpcParameter.put(propertyName, value.toString()); + } + } + + @Override + public Integer readValueFromParameterMap(final Map rpcParameter, + final String propertyName) + throws TechnicalException, UserException { + final Object value = rpcParameter.get(propertyName); + if (value instanceof Integer) { + return (Integer) value; + } + if (value instanceof String) { + try { + return Integer.parseInt((String) value); + } catch (NumberFormatException e) { + throw new UserException(new UserError(UserError.MSG_INT_VALUE_EXPECTED, propertyName, (String) value)); + } + } + return null; + } +} \ No newline at end of file diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultIntegerPersistentObjectMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultIntegerPersistentObjectMapper.java new file mode 100644 index 0000000..9e20cff --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultIntegerPersistentObjectMapper.java @@ -0,0 +1,29 @@ +package de.hsadmin.module.property.mapping; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.util.ReflectionUtil; + +public class DefaultIntegerPersistentObjectMapper implements PersistentObjectMapper { + @Override + public void writeValueToPersistentObject(final Object persistentObject, final String propertyName, final Integer value) throws TechnicalException { + ReflectionUtil.invokeSetter(persistentObject, propertyName, value); + } + + @Override + public Integer readValueFromPersistentObject(final Object persistentObject, final String propertyName) throws TechnicalException { + final Object object = ReflectionUtil.invokeGetter(persistentObject, propertyName); + if (object instanceof Integer) { + return (Integer) object; + } else { + if (object instanceof String) { + try { + return Integer.parseInt((String) object); + } catch (NumberFormatException e) { + throw new TechnicalException(e); + } + } else { + return null; + } + } + } +} \ No newline at end of file diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultListParameterMapMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultListParameterMapMapper.java new file mode 100644 index 0000000..2148e82 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultListParameterMapMapper.java @@ -0,0 +1,65 @@ +package de.hsadmin.module.property.mapping; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.property.Property; + +public class DefaultListParameterMapMapper implements ParameterMapMapper> { + + final private Class elementsType; + + public DefaultListParameterMapMapper(Class elementsType) { + this.elementsType = elementsType; + } + + @Override + public void writeValueToParameterMap(Map rpcParameter, String propertyName, List value) + throws TechnicalException, UserException { + List> list = new ArrayList<>(); + for (Object o : value) { + assert o instanceof ValueObject; + ValueObject vo = (ValueObject) o; + Map map = new HashMap<>(); + List> properties = vo.properties(); + for (Property p : properties) { + p.copyValueToParameterMap(map); + } + list.add(map); + } + rpcParameter.put(propertyName, list); + } + + @SuppressWarnings("unchecked") + @Override + public List readValueFromParameterMap(Map rpcParameter, String propertyName) + throws TechnicalException, UserException { + final List value = new ArrayList<>(); + final Object list = rpcParameter.get(propertyName); + try { + if (list instanceof Object[]) { + for (Object obj : (Object[])list) { + if (obj instanceof Map) { + final VO vo = (VO) elementsType.newInstance(); + final Map map = (Map) obj; + for (Object key : map.keySet()) { + if (key instanceof String) { + final Property property = vo.get((String)key); + property.copyValueFromParameterMap((Map) map); + } + } + value.add(vo); + } + } + } + } catch (InstantiationException | IllegalAccessException e) { + throw new TechnicalException(e); + } + return value; + } +} \ No newline at end of file diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultListPersistentObjectMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultListPersistentObjectMapper.java new file mode 100644 index 0000000..60d1c08 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultListPersistentObjectMapper.java @@ -0,0 +1,51 @@ +package de.hsadmin.module.property.mapping; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.common.util.ReflectionUtil; +import de.hsadmin.module.ValueObject; + +public class DefaultListPersistentObjectMapper implements PersistentObjectMapper> { + + private final Class elementsType; + + public DefaultListPersistentObjectMapper(Class elementsType) { + this.elementsType = elementsType; + } + + @Override + public void writeValueToPersistentObject(Object persistentObject, String propertyName, List value) throws TechnicalException, UserException { + final List valueFromPersistentObject = readValueFromPersistentObject(persistentObject, propertyName); + valueFromPersistentObject.clear(); +// for (final VO elem : value) { +// valueFromPersistentObject.add(elem); +// elem. +// } +// ReflectionUtil.invokeSetter(persistentObject, propertyName, ???; + } + + @Override + public List readValueFromPersistentObject(Object persistentObject, String propertyName) throws TechnicalException, UserException { + final Object object = ReflectionUtil.invokeGetter(persistentObject, propertyName); + if (object instanceof Collection) { + final List valueList = new ArrayList<>(); + final Collection coll = (Collection) object; + for (Object o : coll) { + try { + final VO newInstance = elementsType.newInstance(); + newInstance.copyPropertiesFromPersistentObject(o); + valueList.add(newInstance); + } catch (InstantiationException | IllegalAccessException e) { + throw new TechnicalException(e); + } + } + return valueList; + } else { + return null; + } + } +} \ No newline at end of file diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringParameterMapMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringParameterMapMapper.java new file mode 100644 index 0000000..27943e0 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringParameterMapMapper.java @@ -0,0 +1,27 @@ +package de.hsadmin.module.property.mapping; + +import java.util.Map; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; + +public class DefaultStringParameterMapMapper implements ParameterMapMapper { + @Override + public void writeValueToParameterMap(final Map rpcParameter, + final String propertyName, final String value) + throws TechnicalException, UserException { + if (value != null) { + rpcParameter.put(propertyName, value); + } + } + + @Override + public String readValueFromParameterMap(final Map rpcParameter, + final String propertyName) throws TechnicalException, UserException { + final Object value = rpcParameter.get(propertyName); + if (value instanceof String) { + return (String) value; + } + return null; + } +} \ No newline at end of file diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringPersistentObjectMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringPersistentObjectMapper.java new file mode 100644 index 0000000..ce8d007 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringPersistentObjectMapper.java @@ -0,0 +1,22 @@ +package de.hsadmin.module.property.mapping; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.util.ReflectionUtil; + +public class DefaultStringPersistentObjectMapper implements + PersistentObjectMapper { + @Override + public void writeValueToPersistentObject(final Object persistentObject, final String propertyName, final String value) throws TechnicalException { + ReflectionUtil.invokeSetter(persistentObject, propertyName, value); + } + + @Override + public String readValueFromPersistentObject(final Object persistentObject, final String propertyName) throws TechnicalException { + final Object object = ReflectionUtil.invokeGetter(persistentObject, propertyName); + if (object instanceof String) { + return (String) object; + } else { + return null; + } + } +} \ No newline at end of file diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringSetParameterMapMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringSetParameterMapMapper.java new file mode 100644 index 0000000..b581926 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringSetParameterMapMapper.java @@ -0,0 +1,42 @@ +package de.hsadmin.module.property.mapping; + +import java.util.Arrays; +import java.util.Map; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.module.property.StringSet; + +public class DefaultStringSetParameterMapMapper implements + ParameterMapMapper { + + @Override + public void writeValueToParameterMap(final Map rpcParameter, + final String propertyName, final StringSet value) throws TechnicalException, + UserException { + final String[] strings = value.getStrings(); + if (strings != null) { + rpcParameter.put(propertyName, Arrays.asList(strings)); + } + } + + @Override + public StringSet readValueFromParameterMap( + final Map rpcParameter, final String propertyName) + throws TechnicalException, UserException { + final Object rpcParam = rpcParameter.get(propertyName); + final StringSet value = new StringSet(); + String[] strings = new String[] { }; + if (rpcParam instanceof Object[]) { + strings = new String[((Object[]) rpcParam).length]; + int idx = 0; + for (final Object o : (Object[]) rpcParam) { + strings[idx] = (String) o; + idx++; + } + } + value.setStrings(strings); + return value; + } + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringSetPersistentObjectMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringSetPersistentObjectMapper.java new file mode 100644 index 0000000..9c5f1ee --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/DefaultStringSetPersistentObjectMapper.java @@ -0,0 +1,35 @@ +package de.hsadmin.module.property.mapping; + +import java.util.Arrays; +import java.util.Collection; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.common.util.ReflectionUtil; +import de.hsadmin.module.property.StringSet; + +public class DefaultStringSetPersistentObjectMapper implements + PersistentObjectMapper { + + @SuppressWarnings("unchecked") + @Override + public StringSet readValueFromPersistentObject(final Object persistentObject, + final String propertyName) throws TechnicalException, UserException { + final Object strings = ReflectionUtil.invokeGetter(persistentObject, propertyName); + final StringSet value = new StringSet(); + if (strings instanceof Collection) { + value.setStrings(((Collection) strings).toArray(new String[] { })); + } + return value; + } + + @Override + public void writeValueToPersistentObject(final Object persistentObject, + final String propertyName, final StringSet value) throws TechnicalException { + final String[] strings = value.getStrings(); + if (strings != null) { + ReflectionUtil.invokeSetter(persistentObject, propertyName, Arrays.asList(strings)); + } + } + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/Mapping.java b/framework/src/main/java/de/hsadmin/module/property/mapping/Mapping.java new file mode 100644 index 0000000..90941c9 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/Mapping.java @@ -0,0 +1,15 @@ +package de.hsadmin.module.property.mapping; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Mapping { + + Class> boMapping(); + Class> rpcMapping(); + String boMappingPath() default ""; +} diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/ParameterMapMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/ParameterMapMapper.java new file mode 100644 index 0000000..36996cb --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/ParameterMapMapper.java @@ -0,0 +1,14 @@ +package de.hsadmin.module.property.mapping; + +import java.util.Map; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; + +public interface ParameterMapMapper { + + void writeValueToParameterMap(Map rpcParameter, String propertyName, T value) throws TechnicalException, UserException; + + T readValueFromParameterMap(Map rpcParameter, String propertyName) throws TechnicalException, UserException; + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/PersistentObjectMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/PersistentObjectMapper.java new file mode 100644 index 0000000..1e4f73b --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/PersistentObjectMapper.java @@ -0,0 +1,12 @@ +package de.hsadmin.module.property.mapping; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; + +public interface PersistentObjectMapper { + + T readValueFromPersistentObject(Object persistentObject, String propertyName) throws TechnicalException, UserException; + + void writeValueToPersistentObject(Object persistentObject, String propertyName, T value) throws TechnicalException, UserException; + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/ReferredPropertyPath.java b/framework/src/main/java/de/hsadmin/module/property/mapping/ReferredPropertyPath.java new file mode 100644 index 0000000..73d74b9 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/ReferredPropertyPath.java @@ -0,0 +1,7 @@ +package de.hsadmin.module.property.mapping; + +public interface ReferredPropertyPath { + + void setPropertyPath(String path); + +} diff --git a/framework/src/main/java/de/hsadmin/module/property/mapping/ReferredStringPersistentObjectMapper.java b/framework/src/main/java/de/hsadmin/module/property/mapping/ReferredStringPersistentObjectMapper.java new file mode 100644 index 0000000..385e68f --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/property/mapping/ReferredStringPersistentObjectMapper.java @@ -0,0 +1,38 @@ +package de.hsadmin.module.property.mapping; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.common.util.ReflectionUtil; + +public class ReferredStringPersistentObjectMapper implements PersistentObjectMapper, ReferredPropertyPath { + + private String propertyPath; + + @Override + public void setPropertyPath(final String path) { + propertyPath = path; + } + + @Override + public String readValueFromPersistentObject(final Object persistentObject, final String propertyName) throws TechnicalException, UserException { + String path = propertyName; + if (propertyPath != null) { + path = propertyPath; + } + final String[] strings = path.split("\\."); + Object pathObject = persistentObject; + for (int idx = 0; idx < strings.length && pathObject != null; idx++) { + final String propName = strings[idx]; + pathObject = ReflectionUtil.invokeGetter(pathObject, propName); + } + return pathObject instanceof String ? (String) pathObject : null; + } + + @Override + public void writeValueToPersistentObject(final Object persistentObject, + final String propertyName, final String value) throws TechnicalException { + // TODO Auto-generated method stub + + } + +} diff --git a/framework/src/main/java/de/hsadmin/module/util/QueryBuilder.java b/framework/src/main/java/de/hsadmin/module/util/QueryBuilder.java new file mode 100644 index 0000000..c4a1606 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/module/util/QueryBuilder.java @@ -0,0 +1,74 @@ +package de.hsadmin.module.util; + +import java.util.ArrayList; +import java.util.List; + +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Join; +import javax.persistence.criteria.ParameterExpression; +import javax.persistence.criteria.Path; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.common.util.ReflectionUtil; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.property.Property; +import de.hsadmin.module.property.mapping.Mapping; + +public class QueryBuilder { + + final private EntityManager em; + final private Class clasz; + + private QueryBuilder(final EntityManager em, final Class clasz) { + this.em = em; + this.clasz = clasz; + } + + public static QueryBuilder newBuilder(final EntityManager em, final Class clasz) { + return new QueryBuilder(em, clasz); + } + + public List getResultList(final ValueObject criteria) + throws UserException, TechnicalException { + final CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); + final CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(clasz); + final Root root = criteriaQuery.from(clasz); + final List predicates = new ArrayList<>(); + for (Property p : criteria.properties()) { + if (!p.valueIsNullOrEmpty()) { + Mapping mappingAnnotation = (Mapping) ReflectionUtil.getAnnotation(criteria.getClass(), p.getName(), Mapping.class); + final String mapping = mappingAnnotation != null ? mappingAnnotation.boMappingPath() : p.getName(); + int pos = 0; + Join join = null; + while (mapping.substring(pos).contains(".")) { + join = join == null ? + root.join(mapping.substring(0, mapping.indexOf('.', pos))) + : join.join(mapping.substring(0, mapping.indexOf('.', pos))); + pos = mapping.indexOf('.') + 1; + } + final Path path = join == null ? + root.get(mapping.substring(pos)) + : join.get(mapping.substring(pos)); + final ParameterExpression parameter = criteriaBuilder.parameter(p.getValueType(), p.getName()); + predicates.add(criteriaBuilder.equal(path, parameter)); + } + } + if (predicates.size() > 0) { + criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()])); + } + final TypedQuery query = em.createQuery(criteriaQuery); + for (Property p : criteria.properties()) { + if (!p.valueIsNullOrEmpty()) { + query.setParameter(p.getName(), p.getValue()); + } + } + return query.getResultList(); + } + +} diff --git a/framework/src/main/java/de/hsadmin/service/property/PropertyRemote.java b/framework/src/main/java/de/hsadmin/service/property/PropertyRemote.java new file mode 100644 index 0000000..b973341 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/service/property/PropertyRemote.java @@ -0,0 +1,14 @@ +package de.hsadmin.service.property; + +import de.hsadmin.xmlrpc.AbstractRemote; +import de.hsadmin.xmlrpc.Remote; + + +public class PropertyRemote extends AbstractRemote implements Remote { + + @Override + protected String getModuleLookup() { + return "PropertyServiceLocal"; + } + +} diff --git a/framework/src/main/java/de/hsadmin/service/property/PropertyService.java b/framework/src/main/java/de/hsadmin/service/property/PropertyService.java new file mode 100644 index 0000000..fff838d --- /dev/null +++ b/framework/src/main/java/de/hsadmin/service/property/PropertyService.java @@ -0,0 +1,142 @@ +package de.hsadmin.service.property; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.Enumeration; +import java.util.List; +import java.util.Properties; + +import javax.ejb.Stateless; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.login.RequestContext; +import de.hsadmin.login.RequiredScope; +import de.hsadmin.login.Role; +import de.hsadmin.login.ScopePolicy; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractModule; +import de.hsadmin.module.property.Display; +import de.hsadmin.module.property.DisplayPolicy; +import de.hsadmin.module.property.ReadWrite; +import de.hsadmin.module.property.ReadWritePolicy; +import de.hsadmin.module.property.Search; +import de.hsadmin.module.property.SearchPolicy; +import de.hsadmin.xmlrpc.AbstractRemote; + +@Stateless +public class PropertyService extends AbstractModule implements PropertyServiceLocal { + + @PersistenceContext(name="hsar") + private EntityManager entityManager; + + @Override + public PropertyVO buildVO() throws TechnicalException { + return new PropertyVO(); + } + + @Override + @RequiredScope({@ScopePolicy(Role.NONE)}) + public PropertyVO create(final RequestContext requestContext, final PropertyVO prototype) + throws UserException, TechnicalException { + return null; + } + + @Override + @RequiredScope({@ScopePolicy(Role.ANY)}) + public List read(final RequestContext requestContext, final PropertyVO criteria) + throws UserException, TechnicalException { + final List emptyList = super.read(requestContext, criteria); + final Properties remoteServicesProperties = new Properties(); + final String requestedModuleName = criteria.getModule(); + try { + remoteServicesProperties.load(getClass().getClassLoader().getResourceAsStream("org/apache/xmlrpc/webserver/XmlRpcServlet.properties")); + final Enumeration propertyNames = remoteServicesProperties.propertyNames(); + while (propertyNames.hasMoreElements()) { + final String properyName = (String) propertyNames.nextElement(); + if (requestedModuleName != null && !requestedModuleName.equals(properyName)) { + continue; + } + final Class serviceRemoteClass = Class.forName(remoteServicesProperties.getProperty(properyName)); + @SuppressWarnings("unchecked") + final AbstractRemote serviceRemote = (AbstractRemote) serviceRemoteClass.newInstance(); + final ValueObject valueObject = serviceRemote.createValueObject(); + final Field[] declaredFields = valueObject.getClass().getDeclaredFields(); + for (Field f : declaredFields) { + final PropertyVO vo = buildVO(); + vo.setModule(properyName); + vo.setName(f.getName()); + final ReadWrite readWrite = f.getAnnotation(ReadWrite.class); + if (readWrite == null) { + vo.setReadwriteable(ReadWritePolicy.NONE.name().toLowerCase()); + } else { + vo.setReadwriteable(readWrite.value().name().toLowerCase()); + } + final Search search = f.getAnnotation(Search.class); + if (search == null) { + vo.setSearchable(SearchPolicy.NONE.name().toLowerCase()); + } else { + vo.setSearchable(search.value().name().toLowerCase()); + } + final Display sequence = f.getAnnotation(Display.class); + if (sequence == null) { + vo.setDisplaySequence(Integer.valueOf(9999)); + vo.setDisplayVisible(DisplayPolicy.ALWAYS.name().toLowerCase());; + } else { + vo.setDisplaySequence(sequence.sequence()); + vo.setDisplayVisible(sequence.visible().name().toLowerCase());; + } + final Pattern pattern = f.getAnnotation(Pattern.class); + if (pattern == null) { + vo.setValidationRegexp("[a-zA-Z0-9\\_\\-\\.\\,\\ ]*"); + } else { + vo.setValidationRegexp(pattern.regexp()); + } + final Size size = f.getAnnotation(Size.class); + if (size == null) { + vo.setMinLength(Integer.valueOf(0)); + vo.setMaxLength(Integer.valueOf(999)); + } else { + vo.setMinLength(size.min()); + vo.setMaxLength(size.max()); + } + vo.setType(printableTypeName(valueObject.get(f.getName()).getValueType())); + emptyList.add(vo); + } + } + } catch (IOException | ClassNotFoundException | InstantiationException | IllegalAccessException e) { + throw new TechnicalException(e); + } + return emptyList; + } + + private String printableTypeName(Class type) { + String name = type.getName().toLowerCase(); + if (name.indexOf('.') >= 0) { + final int lastDot = name.lastIndexOf('.'); + name = name.substring(lastDot + 1); + } + if ("arraylist".equals(name)) { + name = "array"; + } + return name; + } + + @Override + @RequiredScope({@ScopePolicy(Role.NONE)}) + public List update(RequestContext requestContext, PropertyVO criteria, PropertyVO prototype) + throws UserException, TechnicalException { + return null; + } + + @Override + @RequiredScope({@ScopePolicy(Role.NONE)}) + public void delete(RequestContext requestContext, PropertyVO criteria) + throws UserException, TechnicalException { + } + +} diff --git a/framework/src/main/java/de/hsadmin/service/property/PropertyServiceLocal.java b/framework/src/main/java/de/hsadmin/service/property/PropertyServiceLocal.java new file mode 100644 index 0000000..a99b556 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/service/property/PropertyServiceLocal.java @@ -0,0 +1,10 @@ +package de.hsadmin.service.property; + +import javax.ejb.Local; + +import de.hsadmin.module.Module; + +@Local +public interface PropertyServiceLocal extends Module{ + +} diff --git a/framework/src/main/java/de/hsadmin/service/property/PropertyVO.java b/framework/src/main/java/de/hsadmin/service/property/PropertyVO.java new file mode 100644 index 0000000..054872a --- /dev/null +++ b/framework/src/main/java/de/hsadmin/service/property/PropertyVO.java @@ -0,0 +1,139 @@ +package de.hsadmin.service.property; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractVO; +import de.hsadmin.module.property.ReadWrite; +import de.hsadmin.module.property.ReadWritePolicy; +import de.hsadmin.module.property.Search; +import de.hsadmin.module.property.SearchPolicy; +import de.hsadmin.module.property.Display; + +public class PropertyVO extends AbstractVO implements ValueObject { + + @Display(sequence = 10) + @Search(SearchPolicy.EQUALS) + @ReadWrite(ReadWritePolicy.READ) + private String module; + + @Display(sequence = 20) + @ReadWrite(ReadWritePolicy.READ) + private String name; + + @Display(sequence = 50) + @ReadWrite(ReadWritePolicy.READ) + private String searchable; + + @Display(sequence = 40) + @ReadWrite(ReadWritePolicy.READ) + private String readwriteable; + + @Display(sequence = 30) + @ReadWrite(ReadWritePolicy.READ) + private String type; + + @Display(sequence = 60) + @ReadWrite(ReadWritePolicy.READ) + private Integer displaySequence; + + @Display(sequence = 70) + @ReadWrite(ReadWritePolicy.READ) + private String displayVisible; + + @Display(sequence = 80) + @ReadWrite(ReadWritePolicy.READ) + private Integer minLength; + + @Display(sequence = 81) + @ReadWrite(ReadWritePolicy.READ) + private Integer maxLength; + + @Display(sequence = 90) + @ReadWrite(ReadWritePolicy.READ) + private String validationRegexp; + + public PropertyVO() throws TechnicalException { + super(); + } + + public String getModule() { + return module; + } + + public void setModule(String module) { + this.module = module; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSearchable() { + return searchable; + } + + public void setSearchable(String searchable) { + this.searchable = searchable; + } + + public String getReadwriteable() { + return readwriteable; + } + + public void setReadwriteable(String readwriteable) { + this.readwriteable = readwriteable; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Integer getDisplaySequence() { + return displaySequence; + } + + public void setDisplaySequence(Integer sequence) { + this.displaySequence = sequence; + } + + public String getDisplayVisible() { + return displayVisible; + } + + public void setDisplayVisible(String displayVisible) { + this.displayVisible = displayVisible; + } + + public Integer getMinLength() { + return minLength; + } + + public Integer getMaxLength() { + return maxLength; + } + + public String getValidationRegexp() { + return validationRegexp; + } + + public void setMinLength(Integer minLength) { + this.minLength = minLength; + } + + public void setMaxLength(Integer maxLength) { + this.maxLength = maxLength; + } + + public void setValidationRegexp(String validationRegexp) { + this.validationRegexp = validationRegexp; + } + +} diff --git a/framework/src/main/java/de/hsadmin/xmlrpc/AbstractRemote.java b/framework/src/main/java/de/hsadmin/xmlrpc/AbstractRemote.java new file mode 100644 index 0000000..a1bb35e --- /dev/null +++ b/framework/src/main/java/de/hsadmin/xmlrpc/AbstractRemote.java @@ -0,0 +1,179 @@ +package de.hsadmin.xmlrpc; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import javax.ejb.EJBException; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.persistence.EntityExistsException; +import javax.persistence.PersistenceException; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserError; +import de.hsadmin.common.error.UserErrorList; +import de.hsadmin.common.error.UserException; +import de.hsadmin.login.LoginServiceLocal; +import de.hsadmin.login.RequestContext; +import de.hsadmin.module.Module; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.property.Property; + +public abstract class AbstractRemote implements Remote { + + final private LoginServiceLocal login; + final private Module module; + + @SuppressWarnings("unchecked") + public AbstractRemote() { + final Properties props = new Properties(); + props.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.core.LocalInitialContextFactory"); + Context ctx = null; + try { + ctx = new InitialContext(props); + login = (LoginServiceLocal) ctx.lookup("LoginServiceLocal"); + module = (Module) ctx.lookup(getModuleLookup()); + } catch (NamingException e) { + throw new RuntimeException(e); + } finally { + if (ctx != null) { + try { ctx.close(); } catch (NamingException e) { } + } + } + } + + @Override + public List> search(final String runAsUser, final String ticket, + final Map whereParams) throws RemoteException { + try { + final RequestContext requestContext = login.createContext(ticket, runAsUser); + final VO queryValue = module.buildVO(); + mapXmlRpc2VO(whereParams, queryValue); + final List list = module.read(requestContext, queryValue); + final List> resultList = new ArrayList<>(); + for (VO value : list) { + final Map resultValue = new HashMap<>(); + mapVO2XmlRpc(value, resultValue); + resultList.add(resultValue); + } + return resultList; + } catch (UserException | TechnicalException | EJBException e) { + if (e instanceof EJBException && e.getCause() != null) { + analyzeEJBException(e.getCause()); + } + throw new RemoteException(e); + } + } + + @Override + public Map add(final String runAsUser, final String ticket, + final Map setParams) throws RemoteException { + try { + final RequestContext requestContext = login.createContext(ticket, runAsUser); + final VO setValue = module.buildVO(); + mapXmlRpc2VO(setParams, setValue); + final VO newValue = module.create(requestContext, setValue); + final Map resultValue = new HashMap<>(); + mapVO2XmlRpc(newValue, resultValue); + return resultValue; + } catch (UserException | TechnicalException | EJBException e) { + if (e instanceof EJBException && e.getCause() != null) { + throw analyzeEJBException(e.getCause()); + } + throw new RemoteException(e); + } + } + + @Override + public List> update(final String runAsUser, final String ticket, + final Map setParams, final Map whereParams) + throws RemoteException { + try { + final RequestContext requestContext = login.createContext(ticket, runAsUser); + final VO queryValue = module.buildVO(); + mapXmlRpc2VO(whereParams, queryValue); + final VO setValue = module.buildVO(); + mapXmlRpc2VO(setParams, setValue); + final List list = module.update(requestContext, queryValue, setValue); + final List> resultList = new ArrayList<>(); + for (VO value : list) { + final Map resultValue = new HashMap<>(); + mapVO2XmlRpc(value, resultValue); + resultList.add(resultValue); + } + return resultList; + } catch (UserException | TechnicalException | EJBException e) { + if (e instanceof EJBException && e.getCause() != null) { + analyzeEJBException(e.getCause()); + } + throw new RemoteException(e); + } + } + + @Override + public void delete(final String runAsUser, final String ticket, + final Map whereParams) throws RemoteException { + try { + final RequestContext requestContext = login.createContext(ticket, runAsUser); + final VO queryValue = module.buildVO(); + mapXmlRpc2VO(whereParams, queryValue); + module.delete(requestContext, queryValue); + } catch (UserException | TechnicalException | EJBException e) { + if (e instanceof EJBException && e.getCause() != null) { + throw analyzeEJBException(e.getCause()); + } + throw new RemoteException(e); + } + } + + protected abstract String getModuleLookup(); + + public ValueObject createValueObject() throws TechnicalException { + return module.buildVO(); + } + + private RemoteException analyzeEJBException(final Throwable cause) { + final TechnicalException analyzedException = new TechnicalException("EJBException: " + cause.getMessage()); + if (cause instanceof EntityExistsException) { + return new RemoteException(new UserException(new UserError(UserError.MSG_ENTITY_EXISTS))); + } + if (cause instanceof PersistenceException) { + final Throwable cause2 = ((PersistenceException)cause).getCause(); + if (cause2 instanceof EntityExistsException) { + return new RemoteException(new UserException(new UserError(UserError.MSG_ENTITY_EXISTS))); + } + } + return new RemoteException(analyzedException); + } + + private void mapVO2XmlRpc(final ValueObject valueObject, final Map resultValue) + throws UserException, TechnicalException { + final UserErrorList errors = new UserErrorList(); + final List> props = valueObject.properties(); + for (Property p : props) { + p.copyValueToParameterMap(resultValue); + } + errors.raiseException(); + } + + private void mapXmlRpc2VO(final Map paramsMap, + final VO valueObject) throws UserException, TechnicalException { + final UserErrorList errors = new UserErrorList(); + final Set keySet = paramsMap.keySet(); + for (String key : keySet) { + if (valueObject.hasProperty(key)) { + final Property property = valueObject.get(key); + property.copyValueFromParameterMap(paramsMap); + } else { + errors.add(UserError.MSG_FIELD_DOESNOT_EXIST, key); + } + } + errors.raiseException(); + } + +} diff --git a/framework/src/main/java/de/hsadmin/xmlrpc/HSXmlRpcServlet.java b/framework/src/main/java/de/hsadmin/xmlrpc/HSXmlRpcServlet.java new file mode 100644 index 0000000..39da9d2 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/xmlrpc/HSXmlRpcServlet.java @@ -0,0 +1,21 @@ +package de.hsadmin.xmlrpc; + +import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.metadata.XmlRpcSystemImpl; +import org.apache.xmlrpc.server.PropertyHandlerMapping; +import org.apache.xmlrpc.server.XmlRpcHandlerMapping; +import org.apache.xmlrpc.webserver.XmlRpcServlet; + +public class HSXmlRpcServlet extends XmlRpcServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected XmlRpcHandlerMapping newXmlRpcHandlerMapping() + throws XmlRpcException { + XmlRpcHandlerMapping handlerMapping = super.newXmlRpcHandlerMapping(); + XmlRpcSystemImpl.addSystemHandler((PropertyHandlerMapping) handlerMapping); + return handlerMapping; + } + +} diff --git a/framework/src/main/java/de/hsadmin/xmlrpc/Remote.java b/framework/src/main/java/de/hsadmin/xmlrpc/Remote.java new file mode 100644 index 0000000..1e5e678 --- /dev/null +++ b/framework/src/main/java/de/hsadmin/xmlrpc/Remote.java @@ -0,0 +1,34 @@ +package de.hsadmin.xmlrpc; + +import java.util.List; +import java.util.Map; + + +public interface Remote { + + public abstract List> search( + String runAsUser, + String ticket, + Map whereParams + ) throws RemoteException; + + public abstract Map add( + String runAsUser, + String ticket, + Map setParams + ) throws RemoteException; + + public abstract void delete( + String runAsUser, + String ticket, + Map whereParams + ) throws RemoteException; + + public abstract List> update( + String runAsUser, + String ticket, + Map setParams, + Map whereParams + ) throws RemoteException; + +} \ No newline at end of file diff --git a/framework/src/main/java/de/hsadmin/xmlrpc/RemoteException.java b/framework/src/main/java/de/hsadmin/xmlrpc/RemoteException.java new file mode 100644 index 0000000..d7a6ddc --- /dev/null +++ b/framework/src/main/java/de/hsadmin/xmlrpc/RemoteException.java @@ -0,0 +1,11 @@ +package de.hsadmin.xmlrpc; + +public class RemoteException extends Exception { + + private static final long serialVersionUID = 1L; + + public RemoteException(Exception e) { + super(e); + } + +} diff --git a/persistence/.gitignore b/persistence/.gitignore new file mode 100644 index 0000000..e774414 --- /dev/null +++ b/persistence/.gitignore @@ -0,0 +1,13 @@ +*.class + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +/target +/.settings +/.classpath +/.project diff --git a/persistence/database/hsdb-bootstrap.sql b/persistence/database/hsdb-bootstrap.sql new file mode 100644 index 0000000..396ea9a --- /dev/null +++ b/persistence/database/hsdb-bootstrap.sql @@ -0,0 +1,222 @@ +-- +-- Table: basepacket +-- +INSERT INTO basepacket (basepacket_code, description, sorting, valid, article_number) + VALUES ('PAC/DW', 'Dynamic-Web/Base', 300, true, 100); +INSERT INTO basepacket (basepacket_code, description, sorting, valid, article_number) + VALUES ('PAC/SW', 'Static-Web/Base', 400, true, 200); +INSERT INTO basepacket (basepacket_code, description, sorting, valid, article_number) + VALUES ('PAC/WEB', 'Web/Base', 100, true, 300); +INSERT INTO basepacket (basepacket_code, description, sorting, valid, article_number) + VALUES ('SRV/MGD', 'Managed Server', 200, true, 400); + +-- +-- Table: basecomponent +-- +INSERT INTO basecomponent (basecomponent_code, description, sorting, valid) + VALUES ('MULTI', 'Accounts', 100, true); +INSERT INTO basecomponent (basecomponent_code, description, sorting, valid) + VALUES ('TRAFFIC', 'Monatliches Datenvolumen in GB', 200, true); +INSERT INTO basecomponent (basecomponent_code, description, sorting, valid) + VALUES ('QUOTA', 'Festplattenspeicherplatz in MB', 300, true); +INSERT INTO basecomponent (basecomponent_code, description, sorting, valid) + VALUES ('DAEMON', 'Nutzung eines eigenen Servers/Daemons', 400, true); +INSERT INTO basecomponent (basecomponent_code, description, sorting, valid) + VALUES ('MIRROR', 'Echtzeitspiegelung der Daten', 500, true); +INSERT INTO basecomponent (basecomponent_code, description, sorting, valid) + VALUES ('BACKUP', 'Nächtliches Backup', 600, true); +INSERT INTO basecomponent (basecomponent_code, description, sorting, valid) + VALUES ('DISK', 'Nächtliches Backup', 700, true); +INSERT INTO basecomponent (basecomponent_code, description, sorting, valid) + VALUES ('CPU', 'Nächtliches Backup', 800, true); + +-- +-- Table: component +-- +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 1, 10, 1, 1, 1, false, 100 FROM basepacket, basecomponent WHERE basepacket_code='PAC/DW' AND basecomponent_code='MULTI'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 1, 10, 1, 1, 1, false, 200 FROM basepacket, basecomponent WHERE basepacket_code='PAC/SW' AND basecomponent_code='MULTI'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 1, 10, 1, 1, 1, false, 300 FROM basepacket, basecomponent WHERE basepacket_code='PAC/WEB' AND basecomponent_code='MULTI'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 128, 40960, 128, 128, 128, false, 101 FROM basepacket, basecomponent WHERE basepacket_code='PAC/DW' AND basecomponent_code='QUOTA'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 512, 40960, 512, 512, 512, false, 201 FROM basepacket, basecomponent WHERE basepacket_code='PAC/SW' AND basecomponent_code='QUOTA'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 512, 40960, 512, 512, 0, false, 301 FROM basepacket, basecomponent WHERE basepacket_code='PAC/WEB' AND basecomponent_code='QUOTA'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 2, 40960, 2, 2, 2, false, 102 FROM basepacket, basecomponent WHERE basepacket_code='PAC/DW' AND basecomponent_code='TRAFFIC'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 4, 40960, 4, 4, 4, false, 202 FROM basepacket, basecomponent WHERE basepacket_code='PAC/SW' AND basecomponent_code='TRAFFIC'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 5, 40960, 5, 5, 0, false, 302 FROM basepacket, basecomponent WHERE basepacket_code='PAC/WEB' AND basecomponent_code='TRAFFIC'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 0, 4, 0, 1, 0, false, 103 FROM basepacket, basecomponent WHERE basepacket_code='PAC/DW' AND basecomponent_code='DAEMON'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 0, 4, 0, 1, 0, false, 303 FROM basepacket, basecomponent WHERE basepacket_code='PAC/WEB' AND basecomponent_code='DAEMON'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 0, 1, 1, 1, 1, false, 104 FROM basepacket, basecomponent WHERE basepacket_code='PAC/DW' AND basecomponent_code='MIRROR'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 0, 1, 1, 1, 1, false, 204 FROM basepacket, basecomponent WHERE basepacket_code='PAC/SW' AND basecomponent_code='MIRROR'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 0, 1, 1, 1, 1, false, 304 FROM basepacket, basecomponent WHERE basepacket_code='PAC/WEB' AND basecomponent_code='MIRROR'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 0, 1, 1, 1, 1, false, 105 FROM basepacket, basecomponent WHERE basepacket_code='PAC/DW' AND basecomponent_code='BACKUP'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 0, 1, 1, 1, 1, false, 205 FROM basepacket, basecomponent WHERE basepacket_code='PAC/SW' AND basecomponent_code='BACKUP'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 0, 1, 1, 1, 1, false, 305 FROM basepacket, basecomponent WHERE basepacket_code='PAC/WEB' AND basecomponent_code='BACKUP'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 25, 100, 25, 25, 0, false, 410 FROM basepacket, basecomponent WHERE basepacket_code='SRV/MGD' AND basecomponent_code='DISK'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 1, 16, 1, 1, 0, false, 420 FROM basepacket, basecomponent WHERE basepacket_code='SRV/MGD' AND basecomponent_code='CPU'; +INSERT INTO component (basepacket_id, basecomponent_id, min_quantity, max_quantity, default_quantity, increment_quantity, include_quantity, admin_only, article_number) + SELECT basepacket_id, basecomponent_id, 10, 1000, 10, 10, 0, false, 430 FROM basepacket, basecomponent WHERE basepacket_code='SRV/MGD' AND basecomponent_code='TRAFFIC'; + +-- +-- Table: role +-- +INSERT INTO role (role_name) VALUES ('billing'); +INSERT INTO role (role_name) VALUES ('operation'); + +-- +-- Table: business_partner +-- +INSERT INTO business_partner (member_id, member_code, member_since, shares_signed, free, indicator_vat, exempt_vat) + VALUES (10000, 'hsh00-hsh', current_date, 0, TRUE, 'NET', FALSE); + +-- +-- table: contact +-- +INSERT INTO contact (bp_id, salut, first_name, last_name, firma, email) + SELECT bp_id, 'Herr', 'Sigi', 'Superb', 'Hosting Inc.', 'info@example.com' FROM business_partner WHERE member_id=10000; + +-- +-- table: contactrole_ref +-- +INSERT INTO contactrole_ref ( contact_id, role ) + SELECT contact_id, 'billing' FROM contact WHERE email='info@example.com'; +INSERT INTO contactrole_ref ( contact_id, role ) + SELECT contact_id, 'operation' FROM contact WHERE email='info@example.com'; + +-- +-- Table: inet_addr +-- +INSERT INTO inet_addr (inet_addr, description) + VALUES (inet '176.9.242.67', 'address 67'); +INSERT INTO inet_addr (inet_addr, description) + VALUES (inet '176.9.242.72', 'address 72'); +INSERT INTO inet_addr (inet_addr, description) + VALUES (inet '176.9.242.73', 'address 73'); +INSERT INTO inet_addr (inet_addr, description) + VALUES (inet '176.9.242.74', 'address 74'); +INSERT INTO inet_addr (inet_addr, description) + VALUES (inet '176.9.242.75', 'address 75'); +INSERT INTO inet_addr (inet_addr, description) + VALUES (inet '176.9.242.76', 'address 76'); +INSERT INTO inet_addr (inet_addr, description) + VALUES (inet '176.9.242.77', 'address 77'); +INSERT INTO inet_addr (inet_addr, description) + VALUES (inet '176.9.242.78', 'address 78'); + +-- +-- Table: Hive +-- +INSERT INTO hive (hive_name, inet_addr_id, description) + SELECT 'h99', inet_addr_id, 'Test Hive h99' FROM inet_addr WHERE inet_addr = inet '176.9.242.67'; + +-- +-- table: packet +-- +INSERT INTO packet (packet_name, bp_id, hive_id, created, cur_inet_addr_id, free, basepacket_id) + SELECT 'hsh00', business_partner.bp_id, hive.hive_id, current_date, inet_addr.inet_addr_id, true, basepacket.basepacket_id + FROM business_partner, hive, inet_addr, basepacket + WHERE hive_name='h99' AND inet_addr = inet '176.9.242.72' AND member_id = 10000 AND basepacket.basepacket_code='PAC/DW'; +INSERT INTO packet (packet_name, bp_id, hive_id, created, cur_inet_addr_id, free, basepacket_id) + SELECT 'hsh01', business_partner.bp_id, hive.hive_id, current_date, inet_addr.inet_addr_id, true, basepacket.basepacket_id + FROM business_partner, hive, inet_addr, basepacket + WHERE hive_name='h99' AND inet_addr = inet '176.9.242.73' AND member_id = 10000 AND basepacket.basepacket_code='PAC/DW'; + +-- +-- table: packet_component +-- +INSERT INTO packet_component (basecomponent_id, packet_id, quantity, created) + SELECT 1, packet.packet_id, 2, current_date FROM packet + WHERE packet.packet_name = 'hsh00'; +INSERT INTO packet_component (basecomponent_id, packet_id, quantity, created) + SELECT 2, packet.packet_id, 128, current_date FROM packet + WHERE packet.packet_name = 'hsh00'; +INSERT INTO packet_component (basecomponent_id, packet_id, quantity, created) + SELECT 3, packet.packet_id, 1, current_date FROM packet + WHERE packet.packet_name = 'hsh00'; +INSERT INTO packet_component (basecomponent_id, packet_id, quantity, created) + SELECT 4, packet.packet_id, 1, current_date FROM packet + WHERE packet.packet_name = 'hsh00'; +INSERT INTO packet_component (basecomponent_id, packet_id, quantity, created) + SELECT 5, packet.packet_id, 1, current_date FROM packet + WHERE packet.packet_name = 'hsh00'; +INSERT INTO packet_component (basecomponent_id, packet_id, quantity, created) + SELECT 1, packet.packet_id, 2, current_date FROM packet + WHERE packet.packet_name = 'hsh01'; +INSERT INTO packet_component (basecomponent_id, packet_id, quantity, created) + SELECT 2, packet.packet_id, 128, current_date FROM packet + WHERE packet.packet_name = 'hsh01'; +INSERT INTO packet_component (basecomponent_id, packet_id, quantity, created) + SELECT 3, packet.packet_id, 1, current_date FROM packet + WHERE packet.packet_name = 'hsh01'; +INSERT INTO packet_component (basecomponent_id, packet_id, quantity, created) + SELECT 4, packet.packet_id, 1, current_date FROM packet + WHERE packet.packet_name = 'hsh01'; +INSERT INTO packet_component (basecomponent_id, packet_id, quantity, created) + SELECT 5, packet.packet_id, 1, current_date FROM packet + WHERE packet.packet_name = 'hsh01'; + +-- +-- table: unixuser +-- +INSERT INTO unixuser (name, comment, shell, homedir, locked, packet_id, userid) + SELECT 'hsh00', 'packet hsh00', '/bin/bash', '/home/pacs/hsh00', FALSE, packet_id, 10001 FROM packet + WHERE packet_name='hsh00'; +INSERT INTO unixuser (name, comment, shell, homedir, locked, packet_id, userid) + SELECT 'hsh01', 'packet hsh01', '/bin/bash', '/home/pacs/hsh01', FALSE, packet_id, 10002 FROM packet + WHERE packet_name='hsh01'; +INSERT INTO unixuser (name, comment, shell, homedir, locked, packet_id, userid) + SELECT 'hsh01-ad', 'hostmaster ad', '/bin/bash', '/home/pacs/hsh01/users/ad', FALSE, packet_id, 10003 FROM packet + WHERE packet_name='hsh01'; + +-- +-- table: domain +-- +INSERT INTO domain (domain_name, domain_since, domain_dns_master, domain_owner) + SELECT 'hostsharing.net', current_date, 'dns.hostsharing.net', unixuser_id FROM unixuser + WHERE unixuser.name='hsh00'; + + -- +-- table: domain_option +-- +INSERT INTO domain_option (domain_option_name) + VALUES ('backupmxforexternalmx'); +INSERT INTO domain_option (domain_option_name) + VALUES ('greylisting'); +INSERT INTO domain_option (domain_option_name) + VALUES ('htdocsfallback'); +INSERT INTO domain_option (domain_option_name) + VALUES ('includes'); +INSERT INTO domain_option (domain_option_name) + VALUES ('indexes'); +INSERT INTO domain_option (domain_option_name) + VALUES ('multiviews'); +INSERT INTO domain_option (domain_option_name) + VALUES ('php'); + +-- +-- table: price_list +-- +INSERT INTO price_list VALUES (1, 'Default Price List'); + +-- +-- table: customer_price_list_mapping +-- +INSERT INTO pricelist_ref (SELECT bp_id, 'Default Price List' FROM business_partner); + diff --git a/persistence/database/hsdb-schema.sql b/persistence/database/hsdb-schema.sql new file mode 100644 index 0000000..c197418 --- /dev/null +++ b/persistence/database/hsdb-schema.sql @@ -0,0 +1,615 @@ +CREATE SEQUENCE bank_account_bank_account_i_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE SEQUENCE bank_account_bank_account_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE TABLE basecomponent ( + basecomponent_id integer DEFAULT nextval(('"basecomponent_basecomponent_seq"'::text)::regclass) NOT NULL, + basecomponent_code character varying(10) NOT NULL, + description character varying(100) NOT NULL, + sorting integer NOT NULL, + valid boolean NOT NULL +); + +CREATE SEQUENCE basecomponent_basecomponent_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE TABLE basepacket ( + basepacket_id integer DEFAULT nextval(('"basepacket_basepacket_id_seq"'::text)::regclass) NOT NULL, + basepacket_code character varying(10) NOT NULL, + description character varying(100) NOT NULL, + sorting integer NOT NULL, + valid boolean NOT NULL, + article_number integer NOT NULL +); + +CREATE SEQUENCE basepacket_basepacket_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE SEQUENCE billdata_billdata_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE TABLE business_partner ( + bp_id integer DEFAULT nextval(('"business_partner_bp_id_seq"'::text)::regclass) NOT NULL, + member_id integer NOT NULL, + member_code character varying(20) NOT NULL, + member_since date, + member_until date, + member_role character varying(100), + author_contract date, + nondisc_contract date, + shares_updated date, + shares_signed integer NOT NULL, + uid_vat character varying(20), + free boolean DEFAULT false NOT NULL, + indicator_vat character varying(20) DEFAULT 'GROSS'::character varying NOT NULL, + exempt_vat boolean DEFAULT false NOT NULL, + CONSTRAINT ckc_member_id_business CHECK (((member_id >= 10000) AND (member_id <= 99999))), + CONSTRAINT ckc_shares_signed_business CHECK ((shares_signed >= 0)), + CONSTRAINT ckt_business_partner CHECK ((((((member_since IS NULL) AND (member_until IS NULL)) OR ((member_since IS NOT NULL) AND (member_until IS NULL))) OR (((member_since IS NOT NULL) AND (member_until IS NOT NULL)) AND (member_since < member_until))) AND ((member_code)::text ~~ 'hsh00-%'::text))) +); + +CREATE SEQUENCE business_partner_bp_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE TABLE contact ( + contact_id integer DEFAULT nextval(('"contact_contact_id_seq"'::text)::regclass) NOT NULL, + bp_id integer NOT NULL, + salut character varying(30), + first_name character varying(40) NOT NULL, + last_name character varying(40) NOT NULL, + title character varying(20), + firma character varying(120), + co character varying(50), + street character varying(50), + zipcode character varying(10), + city character varying(40), + country character varying(30), + phone_private character varying(30), + phone_office character varying(30), + phone_mobile character varying(30), + fax character varying(30), + email character varying(100) NOT NULL, + CONSTRAINT ckc_email_contact CHECK (((email)::text ~~ '%@%.%'::text)) +); + +CREATE VIEW business_partner_ticket AS + SELECT (business_partner.member_id)::character varying(20) AS member_id, "substring"((business_partner.member_code)::text, 7) AS member_code, contact.salut, contact.first_name, contact.last_name, contact.title, contact.firma, contact.co, contact.street, contact.zipcode, contact.city, contact.country, contact.phone_private, contact.phone_office, contact.phone_mobile, contact.fax, contact.email, ((COALESCE(to_char((business_partner.member_since)::timestamp with time zone, 'YYYY-DD-MM'::text), '-'::text) || ' / '::text) || COALESCE(to_char((business_partner.member_until)::timestamp with time zone, 'YYYY-DD-MM'::text), '-'::text)) AS comment, 1 AS valid FROM (business_partner LEFT JOIN contact ON ((contact.bp_id = business_partner.bp_id))) ORDER BY (business_partner.member_id)::character varying(20); + +CREATE TABLE component ( + basepacket_id integer NOT NULL, + basecomponent_id integer NOT NULL, + min_quantity integer NOT NULL, + max_quantity integer NOT NULL, + default_quantity integer NOT NULL, + increment_quantity integer NOT NULL, + include_quantity integer NOT NULL, + admin_only boolean NOT NULL, + article_number integer NOT NULL, + component_id integer DEFAULT nextval(('"component_id_seq"'::text)::regclass) NOT NULL, + CONSTRAINT ckt_component CHECK ((((((((((0 <= min_quantity) AND (min_quantity <= default_quantity)) AND (default_quantity <= max_quantity)) AND (include_quantity <= default_quantity)) AND (0 <= include_quantity)) AND (mod(min_quantity, increment_quantity) = 0)) AND (mod(max_quantity, increment_quantity) = 0)) AND (mod(default_quantity, increment_quantity) = 0)) AND (mod(include_quantity, increment_quantity) = 0))) +); + +CREATE SEQUENCE component_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE SEQUENCE contact_contact_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE TABLE contactrole_ref ( + contact_id integer NOT NULL, + role character varying(40) NOT NULL +); + +CREATE SEQUENCE database_database_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE TABLE database ( + database_id integer DEFAULT nextval('database_database_id_seq'::regclass) NOT NULL, + engine character varying(12) NOT NULL, + packet_id integer NOT NULL, + name character varying(64) NOT NULL, + owner character varying(24) NOT NULL, + encoding character varying(12) NOT NULL +); + +CREATE SEQUENCE dbuser_dbuser_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE TABLE database_user ( + dbuser_id integer DEFAULT nextval('dbuser_dbuser_id_seq'::regclass) NOT NULL, + engine character varying(12) NOT NULL, + packet_id integer NOT NULL, + name character varying(64) NOT NULL +); + +CREATE SEQUENCE domain_domain_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE TABLE domain ( + domain_name character varying(256) NOT NULL, + domain_since date, + domain_dns_master character varying(64), + domain_id integer DEFAULT nextval('domain_domain_id_seq'::regclass) NOT NULL, + domain_owner integer NOT NULL +); + +CREATE TABLE domain__domain_option ( + domain_option_id integer NOT NULL, + domain_id integer NOT NULL +); + +CREATE TABLE domain_option ( + domain_option_id integer DEFAULT nextval(('"domain_option_id_seq"'::text)::regclass) NOT NULL, + domain_option_name character varying(50) NOT NULL +); + +CREATE SEQUENCE domain_option_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE SEQUENCE emailaddr_emailaddr_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE TABLE emailaddr ( + emailaddr_id integer DEFAULT nextval('emailaddr_emailaddr_id_seq'::regclass) NOT NULL, + localpart character varying(64) NOT NULL, + domain_id integer NOT NULL, + target text, + subdomain character varying(64) +); + +CREATE SEQUENCE emailalias_emailalias_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE TABLE emailalias ( + emailalias_id integer DEFAULT nextval('emailalias_emailalias_id_seq'::regclass) NOT NULL, + pac_id integer NOT NULL, + target text NOT NULL, + name character varying(96) NOT NULL +); + +CREATE TABLE hive ( + hive_id integer DEFAULT nextval(('"hive_hive_id_seq"'::text)::regclass) NOT NULL, + hive_name character varying(3) NOT NULL, + inet_addr_id integer NOT NULL, + description character varying(100) +); + +CREATE SEQUENCE hive_hive_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE TABLE inet_addr ( + inet_addr_id integer DEFAULT nextval(('"inet_addr_inet_addr_id_seq"'::text)::regclass) NOT NULL, + inet_addr inet NOT NULL, + description character varying(100), + CONSTRAINT ckc_inet_addr_inet_add CHECK ((masklen(inet_addr) = 32)) +); + +CREATE SEQUENCE inet_addr_inet_addr_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE SEQUENCE member_id_seq + START WITH 10200 + INCREMENT BY 1 + MINVALUE 10200 + MAXVALUE 99999 + CACHE 1; + +CREATE TABLE packet ( + packet_id integer DEFAULT nextval(('"packet_packet_id_seq"'::text)::regclass) NOT NULL, + packet_name character varying(5) NOT NULL, + bp_id integer NOT NULL, + hive_id integer NOT NULL, + created date NOT NULL, + cancelled date, + cur_inet_addr_id integer, + old_inet_addr_id integer, + free boolean DEFAULT false NOT NULL, + basepacket_id integer, + CONSTRAINT ckt_packet CHECK (((cancelled IS NULL) OR (cancelled > created))) +); + +CREATE TABLE packet_component ( + basecomponent_id integer NOT NULL, + packet_id integer NOT NULL, + quantity integer NOT NULL, + created date, + cancelled date, + packet_component_id integer DEFAULT nextval(('"packet_component_id_seq"'::text)::regclass) NOT NULL, + CONSTRAINT ckt_packet_component CHECK (((cancelled IS NULL) OR (cancelled > created))) +); + +CREATE SEQUENCE packet_component_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE SEQUENCE packet_packet_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE TABLE price ( + id integer NOT NULL, + article_number integer NOT NULL, + price numeric(10,2) NOT NULL, + vat numeric(4,2) NOT NULL, + price_list integer +); + +CREATE SEQUENCE price_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +ALTER SEQUENCE price_id_seq OWNED BY price.id; + +CREATE TABLE price_list ( + id integer NOT NULL, + name character varying(20) +); + +CREATE SEQUENCE price_list_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +ALTER SEQUENCE price_list_id_seq OWNED BY price_list.id; + +CREATE TABLE pricelist_ref ( + bp_id integer NOT NULL, + price_list character varying(40) NOT NULL +); + +CREATE TABLE queue ( + queue_entry_id integer DEFAULT nextval(('"queue_queue_entry_id_seq"'::text)::regclass) NOT NULL, + user_id integer NOT NULL, + started timestamp without time zone NOT NULL, + finished timestamp without time zone, + title character varying(192), + details text, + CONSTRAINT ckt_queue CHECK (((finished IS NULL) OR (finished >= started))) +); + +CREATE SEQUENCE queue_queue_entry_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE TABLE queue_task ( + task_id integer DEFAULT nextval(('"queue_task_id_seq"'::text)::regclass) NOT NULL, + proc bytea, + exception text, + started timestamp without time zone NOT NULL, + finished timestamp without time zone, + title character varying(192), + details text, + user_id integer +); + +CREATE SEQUENCE queue_task_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE TABLE role ( + role_name character varying(40) NOT NULL +); + +CREATE TABLE sepa_mandat ( + sepa_mandat_id integer DEFAULT nextval(('"sepa_mandat_id_seq"'::text)::regclass) NOT NULL, + bp_id integer NOT NULL, + bank_customer character varying(50) NOT NULL, + bank_name character varying(50), + bank_iban character varying(40) NOT NULL, + bank_bic character varying(40) NOT NULL, + mandat_ref character varying(40) NOT NULL, + mandat_signed date NOT NULL, + mandat_since date NOT NULL, + mandat_used date, + mandat_until date, + CONSTRAINT dateschk1 CHECK (((mandat_signed <= mandat_since) AND (mandat_since <= mandat_until))), + CONSTRAINT dateschk2 CHECK ((((mandat_since <= mandat_until) AND (mandat_since <= mandat_used)) AND (mandat_used <= mandat_until))) +); + +CREATE SEQUENCE sepa_mandat_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE SEQUENCE unixuser_unixuser_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + +CREATE TABLE unixuser ( + unixuser_id integer DEFAULT nextval('unixuser_unixuser_id_seq'::regclass) NOT NULL, + name character varying(64) NOT NULL, + comment character varying(128), + shell character varying(64) NOT NULL, + homedir character varying(128) NOT NULL, + locked boolean NOT NULL, + packet_id integer NOT NULL, + quota_softlimit integer DEFAULT 0 NOT NULL, + userid integer NOT NULL, + quota_hardlimit integer DEFAULT 0, + CONSTRAINT unixuser_userid CHECK ((userid >= 10000)) +); + +ALTER TABLE ONLY price ALTER COLUMN id SET DEFAULT nextval('price_id_seq'::regclass); + +ALTER TABLE ONLY price_list ALTER COLUMN id SET DEFAULT nextval('price_list_id_seq'::regclass); + +ALTER TABLE ONLY business_partner + ADD CONSTRAINT business_partner_bp_id_key UNIQUE (bp_id); + +ALTER TABLE ONLY database + ADD CONSTRAINT database_uniq UNIQUE (engine, name); + +ALTER TABLE ONLY database_user + ADD CONSTRAINT database_user_uniq UNIQUE (engine, name); + +ALTER TABLE ONLY emailaddr + ADD CONSTRAINT emailaddr_uniq UNIQUE (localpart, subdomain, domain_id); + +ALTER TABLE ONLY emailalias + ADD CONSTRAINT emailalias_pkey PRIMARY KEY (emailalias_id); + +ALTER TABLE ONLY emailalias + ADD CONSTRAINT emailalias_uniq UNIQUE (name); + +ALTER TABLE ONLY basecomponent + ADD CONSTRAINT pk_basecomponent PRIMARY KEY (basecomponent_id); + +ALTER TABLE ONLY basepacket + ADD CONSTRAINT pk_basepacket PRIMARY KEY (basepacket_id); + +ALTER TABLE ONLY business_partner + ADD CONSTRAINT pk_business_partner PRIMARY KEY (bp_id); + +ALTER TABLE ONLY component + ADD CONSTRAINT pk_component PRIMARY KEY (component_id); + +ALTER TABLE ONLY contact + ADD CONSTRAINT pk_contact PRIMARY KEY (contact_id); + +ALTER TABLE ONLY contactrole_ref + ADD CONSTRAINT pk_contactrole_ref PRIMARY KEY (contact_id, role); + +ALTER TABLE ONLY database + ADD CONSTRAINT pk_database PRIMARY KEY (database_id); + +ALTER TABLE ONLY database_user + ADD CONSTRAINT pk_database_user PRIMARY KEY (dbuser_id); + +ALTER TABLE ONLY domain__domain_option + ADD CONSTRAINT pk_domain__domain_option PRIMARY KEY (domain_option_id, domain_id); + +ALTER TABLE ONLY domain_option + ADD CONSTRAINT pk_domain_option PRIMARY KEY (domain_option_id); + +ALTER TABLE ONLY hive + ADD CONSTRAINT pk_hive PRIMARY KEY (hive_id); + +ALTER TABLE ONLY inet_addr + ADD CONSTRAINT pk_inet_addr PRIMARY KEY (inet_addr_id); + +ALTER TABLE ONLY packet + ADD CONSTRAINT pk_packet PRIMARY KEY (packet_id); + +ALTER TABLE ONLY packet_component + ADD CONSTRAINT pk_packet_component PRIMARY KEY (packet_component_id); + +ALTER TABLE ONLY role + ADD CONSTRAINT pk_role PRIMARY KEY (role_name); + +ALTER TABLE ONLY sepa_mandat + ADD CONSTRAINT pk_sepa_mandat PRIMARY KEY (sepa_mandat_id); + +ALTER TABLE ONLY unixuser + ADD CONSTRAINT pk_unixuser PRIMARY KEY (unixuser_id); + +ALTER TABLE ONLY price_list + ADD CONSTRAINT price_list_pkey PRIMARY KEY (id); + +ALTER TABLE ONLY price_list + ADD CONSTRAINT price_list_uniq_name UNIQUE (name); + +ALTER TABLE ONLY price + ADD CONSTRAINT price_pkey PRIMARY KEY (id); + +ALTER TABLE ONLY unixuser + ADD CONSTRAINT unixuser_name_key UNIQUE (name); + +CREATE UNIQUE INDEX basecomponent_in_1 ON basecomponent USING btree (basecomponent_code); + +CREATE UNIQUE INDEX basepacket_in_1 ON basepacket USING btree (basepacket_code); + +CREATE INDEX component_in_1 ON component USING btree (basecomponent_id); + +CREATE INDEX contact_in_1 ON contact USING btree (bp_id); + +CREATE UNIQUE INDEX customer_in_1 ON business_partner USING btree (member_code); + +CREATE UNIQUE INDEX customer_in_2 ON business_partner USING btree (member_id); + +CREATE UNIQUE INDEX database_unique_owner ON database_user USING btree (name, engine); + +CREATE UNIQUE INDEX domain_option_name_idx ON domain_option USING btree (domain_option_name); + +CREATE UNIQUE INDEX domain_unique_id ON domain USING btree (domain_id); + +CREATE UNIQUE INDEX domain_unique_name ON domain USING btree (domain_name); + +CREATE UNIQUE INDEX emailaddr_uniq2 ON emailaddr USING btree (localpart, domain_id) WHERE (subdomain IS NULL); + +CREATE UNIQUE INDEX hive_in_1 ON hive USING btree (hive_name); + +CREATE UNIQUE INDEX inet_addr_in_1 ON inet_addr USING btree (inet_addr); + +CREATE INDEX packet_component_in_1 ON packet_component USING btree (packet_id); + +CREATE INDEX packet_component_in_2 ON packet_component USING btree (basecomponent_id); + +CREATE UNIQUE INDEX packet_in_1 ON packet USING btree (packet_name); + +CREATE INDEX packet_in_2 ON packet USING btree (bp_id); + +ALTER TABLE ONLY packet + ADD CONSTRAINT base_packet_ref FOREIGN KEY (basepacket_id) REFERENCES basepacket(basepacket_id); + +ALTER TABLE ONLY database + ADD CONSTRAINT database_owner FOREIGN KEY (owner, engine) REFERENCES database_user(name, engine); + +ALTER TABLE ONLY database + ADD CONSTRAINT database_packet_id_fkey FOREIGN KEY (packet_id) REFERENCES packet(packet_id) DEFERRABLE; + +ALTER TABLE ONLY database_user + ADD CONSTRAINT dbuser_packet_id_fkey FOREIGN KEY (packet_id) REFERENCES packet(packet_id) DEFERRABLE; + +ALTER TABLE ONLY domain__domain_option + ADD CONSTRAINT domain_id_fkey FOREIGN KEY (domain_id) REFERENCES domain(domain_id) DEFERRABLE; + +ALTER TABLE ONLY domain__domain_option + ADD CONSTRAINT domain_option_id_fkey FOREIGN KEY (domain_option_id) REFERENCES domain_option(domain_option_id) DEFERRABLE; + +ALTER TABLE ONLY domain + ADD CONSTRAINT domain_owner_chk FOREIGN KEY (domain_owner) REFERENCES unixuser(unixuser_id) MATCH FULL; + +ALTER TABLE ONLY emailaddr + ADD CONSTRAINT email_domain FOREIGN KEY (domain_id) REFERENCES domain(domain_id); + +ALTER TABLE ONLY emailalias + ADD CONSTRAINT emailalias_pac_id_fkey FOREIGN KEY (pac_id) REFERENCES packet(packet_id) DEFERRABLE; + +ALTER TABLE ONLY sepa_mandat + ADD CONSTRAINT fk_bank_acc_reference_business FOREIGN KEY (bp_id) REFERENCES business_partner(bp_id) ON UPDATE RESTRICT ON DELETE RESTRICT; + +ALTER TABLE ONLY component + ADD CONSTRAINT fk_bcomp_bpack FOREIGN KEY (basepacket_id) REFERENCES basepacket(basepacket_id) ON UPDATE RESTRICT ON DELETE RESTRICT; + +ALTER TABLE ONLY packet_component + ADD CONSTRAINT fk_comp_pack FOREIGN KEY (packet_id) REFERENCES packet(packet_id) ON UPDATE RESTRICT ON DELETE RESTRICT; + +ALTER TABLE ONLY contact + ADD CONSTRAINT fk_contact_reference_business FOREIGN KEY (bp_id) REFERENCES business_partner(bp_id) ON UPDATE RESTRICT ON DELETE RESTRICT; + +ALTER TABLE ONLY contactrole_ref + ADD CONSTRAINT fk_contactrole_ref_contact FOREIGN KEY (contact_id) REFERENCES contact(contact_id); + +ALTER TABLE ONLY contactrole_ref + ADD CONSTRAINT fk_contactrole_ref_role FOREIGN KEY (role) REFERENCES role(role_name); + +ALTER TABLE ONLY hive + ADD CONSTRAINT fk_hive_inet FOREIGN KEY (inet_addr_id) REFERENCES inet_addr(inet_addr_id) ON UPDATE RESTRICT ON DELETE RESTRICT; + +ALTER TABLE ONLY packet + ADD CONSTRAINT fk_pac_cur_inet FOREIGN KEY (cur_inet_addr_id) REFERENCES inet_addr(inet_addr_id) ON UPDATE RESTRICT ON DELETE RESTRICT; + +ALTER TABLE ONLY packet + ADD CONSTRAINT fk_pac_old_inet FOREIGN KEY (old_inet_addr_id) REFERENCES inet_addr(inet_addr_id) ON UPDATE RESTRICT ON DELETE RESTRICT; + +ALTER TABLE ONLY packet + ADD CONSTRAINT fk_packet_bp FOREIGN KEY (bp_id) REFERENCES business_partner(bp_id) ON UPDATE RESTRICT ON DELETE RESTRICT; + +ALTER TABLE ONLY packet + ADD CONSTRAINT fk_packet_hive FOREIGN KEY (hive_id) REFERENCES hive(hive_id) ON UPDATE RESTRICT ON DELETE RESTRICT; + +ALTER TABLE ONLY pricelist_ref + ADD CONSTRAINT fk_pricelist_ref_bp FOREIGN KEY (bp_id) REFERENCES business_partner(bp_id) ON UPDATE RESTRICT ON DELETE CASCADE; + +ALTER TABLE ONLY pricelist_ref + ADD CONSTRAINT fk_pricelist_ref_pricelist FOREIGN KEY (price_list) REFERENCES price_list(name) ON UPDATE RESTRICT ON DELETE CASCADE; + +ALTER TABLE ONLY component + ADD CONSTRAINT fk_reference_13 FOREIGN KEY (basecomponent_id) REFERENCES basecomponent(basecomponent_id) ON UPDATE RESTRICT ON DELETE RESTRICT; + +ALTER TABLE ONLY price + ADD CONSTRAINT price_price_list_fkey FOREIGN KEY (price_list) REFERENCES price_list(id); + +ALTER TABLE ONLY queue_task + ADD CONSTRAINT queue_task_user_id_fkey FOREIGN KEY (user_id) REFERENCES unixuser(unixuser_id) ON DELETE SET NULL; + +ALTER TABLE ONLY queue + ADD CONSTRAINT queue_user_id_fkey FOREIGN KEY (user_id) REFERENCES unixuser(unixuser_id) DEFERRABLE; diff --git a/persistence/database/migrate.sql b/persistence/database/migrate.sql new file mode 100644 index 0000000..e69de29 diff --git a/persistence/pom.xml b/persistence/pom.xml new file mode 100644 index 0000000..1417fdc --- /dev/null +++ b/persistence/pom.xml @@ -0,0 +1,48 @@ + + 4.0.0 + + de.hsadmin + hsadmin-parent + 1.0-SNAPSHOT + + persistence + jar + + HSAdmin Persistence + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + + + + + de.hsadmin + common + 1.0-SNAPSHOT + + + org.apache.geronimo.specs + geronimo-jpa_2.0_spec + 1.1 + provided + + + log4j + log4j + 1.2.17 + + + diff --git a/persistence/src/main/java/de/hsadmin/bo/customer/Contact.java b/persistence/src/main/java/de/hsadmin/bo/customer/Contact.java new file mode 100644 index 0000000..cc75b63 --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/customer/Contact.java @@ -0,0 +1,234 @@ +package de.hsadmin.bo.customer; + +import static javax.persistence.FetchType.EAGER; + +import java.io.Serializable; +import java.util.List; + +import javax.persistence.CollectionTable; +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.Table; + +@Entity(name = "Contact") +@Table(name = "contact") +public class Contact implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "contact_id", columnDefinition = "integer") + private long id; + + @JoinColumn(name = "bp_id", columnDefinition = "integer") + @ManyToOne(fetch = EAGER) + private Customer customer; + + @Column(name = "salut", columnDefinition = "character varying(30)") + private String salut; + + @Column(name = "first_name", columnDefinition = "character varying(40)") + private String firstName; + + @Column(name = "last_name", columnDefinition = "character varying(40)") + private String lastName; + + @Column(name = "title", columnDefinition = "character varying(20)") + private String title; + + @Column(name = "firma", columnDefinition = "character varying(120)") + private String firma; + + @Column(name = "co", columnDefinition = "character varying(50)") + private String co; + + @Column(name = "street", columnDefinition = "character varying(50)") + private String street; + + @Column(name = "zipcode", columnDefinition = "character varying(10)") + private String zipCode; + + @Column(name = "city", columnDefinition = "character varying(40)") + private String city; + + @Column(name = "country", columnDefinition = "character varying(30)") + private String country; + + @Column(name = "phone_private", columnDefinition = "character varying(30)") + private String phonePrivate; + + @Column(name = "phone_office", columnDefinition = "character varying(30)") + private String phoneOffice; + + @Column(name = "phone_mobile", columnDefinition = "character varying(30)") + private String phoneMobile; + + @Column(name = "fax", columnDefinition = "character varying(30)") + private String fax; + + @Column(name = "email", columnDefinition = "character varying(50)") + private String email; + + @ElementCollection(fetch = EAGER) + @CollectionTable( + name="contactrole_ref", + joinColumns=@JoinColumn(name="contact_id") + ) + @Column(name="role") + private List roles; + + public Contact() { + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public Customer getCustomer() { + return customer; + } + + public void setCustomer(final Customer customer) { + this.customer = customer; + } + + public String getSalut() { + return salut; + } + + public void setSalut(final String salut) { + this.salut = salut; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(final String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(final String lastName) { + this.lastName = lastName; + } + + public String getTitle() { + return title; + } + + public void setTitle(final String title) { + this.title = title; + } + + public String getFirma() { + return firma; + } + + public void setFirma(final String firma) { + this.firma = firma; + } + + public String getCo() { + return co; + } + + public void setCo(final String co) { + this.co = co; + } + + public String getStreet() { + return street; + } + + public void setStreet(final String street) { + this.street = street; + } + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(final String zipCode) { + this.zipCode = zipCode; + } + + public String getCity() { + return city; + } + + public void setCity(final String city) { + this.city = city; + } + + public String getCountry() { + return country; + } + + public void setCountry(final String country) { + this.country = country; + } + + public String getPhonePrivate() { + return phonePrivate; + } + + public void setPhonePrivate(final String phonePrivate) { + this.phonePrivate = phonePrivate; + } + + public String getPhoneOffice() { + return phoneOffice; + } + + public void setPhoneOffice(final String phoneOffice) { + this.phoneOffice = phoneOffice; + } + + public String getPhoneMobile() { + return phoneMobile; + } + + public void setPhoneMobile(final String phoneMobile) { + this.phoneMobile = phoneMobile; + } + + public String getFax() { + return fax; + } + + public void setFax(final String fax) { + this.fax = fax; + } + + public String getEmail() { + return email; + } + + public void setEmail(final String email) { + this.email = email; + } + + public List getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/customer/Customer.java b/persistence/src/main/java/de/hsadmin/bo/customer/Customer.java new file mode 100644 index 0000000..1185ab9 --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/customer/Customer.java @@ -0,0 +1,279 @@ +package de.hsadmin.bo.customer; + +import static javax.persistence.CascadeType.ALL; +import static javax.persistence.FetchType.EAGER; +import static javax.persistence.FetchType.LAZY; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.persistence.Basic; +import javax.persistence.CollectionTable; +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToMany; +import javax.persistence.OrderBy; +import javax.persistence.Table; +import javax.persistence.Temporal; + +import de.hsadmin.bo.pac.Pac; + + +@Entity(name = "Customer") +@Table(name = "business_partner") +public class Customer implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "bp_id", columnDefinition = "integer") + private long id; + + @Column(name = "member_id", columnDefinition = "integer") + private int memberNo; + + @Column(name = "member_code", columnDefinition = "character varying(20)") + private String name; + + @Column(name = "member_since", columnDefinition = "date", nullable = true) + private Date memberSince; + + @Column(name = "member_until", columnDefinition = "date", nullable = true) + @Temporal(javax.persistence.TemporalType.DATE) + private Date memberUntil; + + @Column(name = "member_role", columnDefinition = "character varying(100)", nullable = true) + private String memberRole; + + @Column(name = "author_contract", columnDefinition = "date", nullable = true) + @Temporal(javax.persistence.TemporalType.DATE) + private Date authorContract; + + @Column(name = "nondisc_contract", columnDefinition = "date", nullable = true) + @Temporal(javax.persistence.TemporalType.DATE) + private Date nonDiscContract; + + @Column(name = "shares_updated", columnDefinition = "date", nullable = true) + @Temporal(javax.persistence.TemporalType.DATE) + private Date sharesUpdated; + + @Column(name = "shares_signed", columnDefinition = "integer") + private int sharesSigned; + + @Column(name = "free", nullable = false) + private boolean free = false; + + @Column(name = "exempt_vat", nullable = false) + private boolean exemptVAT = false; + + @Column(name = "indicator_vat", nullable = false) + @Basic + @Enumerated(EnumType.STRING) + private IndicatorVAT indicatorVAT = IndicatorVAT.GROSS; + + @Column(name = "uid_vat", columnDefinition = "character varying(20)", nullable = true) + private String uidVAT; + + @OneToMany(fetch = EAGER, cascade = ALL, mappedBy = "customer") + private Set contacts; + + @ElementCollection(fetch = EAGER) + @CollectionTable( + name="pricelist_ref", + joinColumns=@JoinColumn(name="bp_id") + ) + @Column(name="price_list") + private List priceLists; + + @OneToMany(fetch = LAZY, cascade = ALL, mappedBy = "customer") + @OrderBy("mandatSigned") + private Set sepaDirectDebits; + + @OneToMany(fetch = LAZY, cascade = ALL, mappedBy = "customer") + @OrderBy("name") + private Set pacs; + + public Customer() { + contacts = new HashSet<>(); + pacs = new HashSet<>(); + priceLists = new ArrayList<>(); + sepaDirectDebits = new HashSet<>(); + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public int getMemberNo() { + return memberNo; + } + + public void setMemberNo(final int memberNo) { + this.memberNo = memberNo; + } + + public String getName() { + return name; + } + + public void setName(final String memberCode) { + this.name = memberCode; + } + + public Date getMemberSince() { + return memberSince; + } + + public void setMemberSince(final Date memberSince) { + this.memberSince = memberSince; + } + + public Date getMemberUntil() { + return memberUntil; + } + + public void setMemberUntil(final Date memberUntil) { + this.memberUntil = memberUntil; + } + + public String getMemberRole() { + return memberRole; + } + + public void setMemberRole(final String memberRole) { + this.memberRole = memberRole; + } + + public Date getAuthorContract() { + return authorContract; + } + + public void setAuthorContract(final Date authorContract) { + this.authorContract = authorContract; + } + + public Date getNonDiscContract() { + return nonDiscContract; + } + + public void setNonDiscContract(final Date nonDiscContract) { + this.nonDiscContract = nonDiscContract; + } + + public Date getSharesUpdated() { + return sharesUpdated; + } + + public void setSharesUpdated(final Date sharesUpdated) { + this.sharesUpdated = sharesUpdated; + } + + public int getSharesSigned() { + return sharesSigned; + } + + public void setSharesSigned(final int sharesSigned) { + this.sharesSigned = sharesSigned; + } + + public String getUidVAT() { + return uidVAT; + } + + public void setUidVAT(final String uidVAT) { + this.uidVAT = uidVAT; + } + + public Set getContacts() { + return contacts; + } + + public void setContacts(final Set contacts) { + if (contacts == null) { + this.contacts.clear(); + } else { + this.contacts = contacts; + } + } + + public Set getPacs() { + return pacs; + } + + public void setPacs(final Set pacs) { + if (pacs == null) { + this.pacs.clear(); + } else { + this.pacs = pacs; + } + } + + public boolean isFree() { + return free; + } + + public boolean getFree() { + return free; + } + + public void setFree(final boolean free) { + this.free = free; + } + + public IndicatorVAT getIndicatorVAT() { + return indicatorVAT; + } + + public void setIndicatorVAT(final IndicatorVAT indicatorVAT) { + this.indicatorVAT = indicatorVAT; + } + + public boolean isExemptVAT() { + return exemptVAT; + } + + public boolean getExemptVAT() { + return exemptVAT; + } + + public void setExemptVAT(final boolean exemptVAT) { + this.exemptVAT = exemptVAT; + } + + public List getPriceLists() { + return priceLists; + } + + public void setPriceLists(final List priceLists) { + if (priceLists == null) { + this.priceLists.clear(); + } else { + this.priceLists = priceLists; + } + } + + public Set getSepaDirectDebits() { + return sepaDirectDebits; + } + + public void setSepaDirectDebits(final Set sepaDirectDebits) { + this.sepaDirectDebits = sepaDirectDebits; + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/customer/IndicatorVAT.java b/persistence/src/main/java/de/hsadmin/bo/customer/IndicatorVAT.java new file mode 100644 index 0000000..0b4ecbb --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/customer/IndicatorVAT.java @@ -0,0 +1,5 @@ +package de.hsadmin.bo.customer; + +public enum IndicatorVAT { + NET, GROSS +} diff --git a/persistence/src/main/java/de/hsadmin/bo/customer/SEPADirectDebit.java b/persistence/src/main/java/de/hsadmin/bo/customer/SEPADirectDebit.java new file mode 100644 index 0000000..b3d6a49 --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/customer/SEPADirectDebit.java @@ -0,0 +1,160 @@ +package de.hsadmin.bo.customer; + +import static javax.persistence.FetchType.EAGER; + +import java.io.Serializable; +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToOne; +import javax.persistence.Table; +import javax.persistence.Temporal; + +@Entity(name = "SEPADirectDebit") +@Table(name = "sepa_mandat") +public class SEPADirectDebit implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "sepa_mandat_id", columnDefinition = "integer") + private long id; + + @JoinColumn(name = "bp_id", columnDefinition = "integer") + @OneToOne(fetch = EAGER) + private Customer customer; + + @Column(name = "bank_customer", columnDefinition = "character varying(50)", nullable = false) + private String bankCustomer; + + @Column(name = "bank_name", columnDefinition = "character varying(50)") + private String bankName; + + @Column(name = "bank_iban", columnDefinition = "character varying(34)", nullable = false) + private String bankIBAN; + + @Column(name = "bank_bic", columnDefinition = "character varying(11)", nullable = false) + private String bankBIC; + + @Column(name = "mandat_ref", columnDefinition = "character varying(10)", nullable = false) + private String mandatRef; + + @Column(name = "mandat_signed", columnDefinition = "date", nullable = false) + @Temporal(javax.persistence.TemporalType.DATE) + private Date mandatSigned; + + @Column(name = "mandat_since", columnDefinition = "date", nullable = true) + @Temporal(javax.persistence.TemporalType.DATE) + private Date mandatSince; + + @Column(name = "mandat_until", columnDefinition = "date", nullable = true) + @Temporal(javax.persistence.TemporalType.DATE) + private Date mandatUntil; + + @Column(name = "mandat_used", columnDefinition = "date", nullable = true) + @Temporal(javax.persistence.TemporalType.DATE) + private Date mandatUsed; + + public SEPADirectDebit() { + this.customer = null; + } + + public SEPADirectDebit(final Customer customer) { + this.customer = customer; + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public Customer getCustomer() { + return customer; + } + + public void setCustomer(final Customer customer) { + this.customer = customer; + } + + public String getBankCustomer() { + return bankCustomer; + } + + public void setBankCustomer(final String bankCustomer) { + this.bankCustomer = bankCustomer; + } + + public String getBankName() { + return bankName; + } + + public void setBankName(final String bankName) { + this.bankName = bankName; + } + + public String getBankIBAN() { + return bankIBAN; + } + + public void setBankIBAN(final String bankIBAN) { + this.bankIBAN = bankIBAN; + } + + public String getBankBIC() { + return bankBIC; + } + + public void setBankBIC(final String bankBIC) { + this.bankBIC = bankBIC; + } + + public String getMandatRef() { + return mandatRef; + } + + public void setMandatRef(String mandatRef) { + this.mandatRef = mandatRef; + } + + public Date getMandatSigned() { + return mandatSigned; + } + + public void setMandatSigned(Date mandatSigned) { + this.mandatSigned = mandatSigned; + } + + public Date getMandatSince() { + return mandatSince; + } + + public void setMandatSince(Date mandatSince) { + this.mandatSince = mandatSince; + } + + public Date getMandatUntil() { + return mandatUntil; + } + + public void setMandatUntil(Date mandatUntil) { + this.mandatUntil = mandatUntil; + } + + public Date getMandatUsed() { + return mandatUsed; + } + + public void setMandatUsed(Date mandatUsed) { + this.mandatUsed = mandatUsed; + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/database/Database.java b/persistence/src/main/java/de/hsadmin/bo/database/Database.java new file mode 100644 index 0000000..8115db3 --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/database/Database.java @@ -0,0 +1,118 @@ +package de.hsadmin.bo.database; + +import static javax.persistence.FetchType.EAGER; +import static javax.persistence.GenerationType.SEQUENCE; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.DiscriminatorColumn; +import javax.persistence.DiscriminatorType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; + +import de.hsadmin.bo.pac.Pac; + +@Entity +@Table(name = "database") +@Inheritance(strategy=InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn(name="engine", discriminatorType=DiscriminatorType.STRING) +@SequenceGenerator(name = "DatabaseSeqGen", sequenceName = "database_database_id_seq") +public abstract class Database implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = SEQUENCE, generator = "DatabaseSeqGen") + @Column(name = "database_id", columnDefinition = "integer", updatable=false, insertable=false) + private long id; + + @Column(name = "engine", columnDefinition = "character varying(12)", updatable=false) + private String instance; + + @Column(name = "name", columnDefinition = "character varying(24)", updatable=false) + private String name; + + @Column(name = "owner", columnDefinition = "character varying(24)") + private String owner; + + @JoinColumn(name = "packet_id", columnDefinition = "integer", updatable=false) + @ManyToOne(fetch = EAGER) + private Pac pac; + + @Column(name = "encoding", columnDefinition = "character varying(24)", updatable=false) + private String encoding; + + protected Database() { + encoding = "UTF-8"; + } + + protected Database(String instance, Pac pac, String name, String owner, + String encoding) { + this.instance = instance; + this.pac = pac; + this.name = name; + this.owner = owner; + this.encoding = encoding; + } + + public abstract String getSystemEncoding(); + + public abstract Class getSqlUserClass(); + + public long getId() { + return id; + } + + protected void setId(long id) { + this.id = id; + } + + public String getInstance() { + return instance; + } + + public void setInstance(String instance) { + this.instance = instance; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public Pac getPac() { + return pac; + } + + public void setPac(Pac pac) { + this.pac = pac; + } + + public String getEncoding() { + return encoding; + } + + public void setEncoding(String encoding) { + this.encoding = encoding; + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/database/DatabaseUser.java b/persistence/src/main/java/de/hsadmin/bo/database/DatabaseUser.java new file mode 100644 index 0000000..b3804ee --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/database/DatabaseUser.java @@ -0,0 +1,94 @@ +package de.hsadmin.bo.database; + +import static javax.persistence.FetchType.EAGER; +import static javax.persistence.GenerationType.SEQUENCE; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.DiscriminatorColumn; +import javax.persistence.DiscriminatorType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; +import javax.persistence.Transient; + +import de.hsadmin.bo.pac.Pac; + +@Entity +@Table(name = "database_user") +@Inheritance(strategy=InheritanceType.SINGLE_TABLE) +@DiscriminatorColumn(name="engine", discriminatorType=DiscriminatorType.STRING) +@SequenceGenerator(name = "DatabaseUserSeqGen", sequenceName = "dbuser_dbuser_id_seq") +public abstract class DatabaseUser implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = SEQUENCE, generator = "DatabaseUserSeqGen") + @Column(name = "dbuser_id", columnDefinition = "integer", updatable=false, insertable=false) + private long id; + + @Column(name = "name", columnDefinition = "character varying(24)", updatable=false) + private String name; + + @Transient + private String password; + + @Column(name = "engine", columnDefinition = "character varying(12)", updatable=false) + protected String instance; + + @JoinColumn(name = "packet_id", columnDefinition = "integer", updatable=false) + @ManyToOne(fetch = EAGER) + protected Pac pac; + + protected DatabaseUser() { + } + + public long getId() { + return id; + } + + protected void setId(long id) { + this.id = id; + } + + public String getInstance() { + return instance; + } + + public void setInstance(String instance) { + this.instance = instance; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public Pac getPac() { + return pac; + } + + public void setPac(Pac pac) { + this.pac = pac; + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/database/MySqlDatabase.java b/persistence/src/main/java/de/hsadmin/bo/database/MySqlDatabase.java new file mode 100644 index 0000000..2acf80a --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/database/MySqlDatabase.java @@ -0,0 +1,29 @@ +package de.hsadmin.bo.database; + +import java.io.Serializable; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + +@Entity(name = "MySqlDatabase") +@DiscriminatorValue("mysql") +public class MySqlDatabase extends Database implements Serializable { + + private static final long serialVersionUID = 1L; + + public MySqlDatabase() { + setInstance("mysql"); + setEncoding("UTF-8"); + } + + public String getSystemEncoding() { + String sysEnc = getEncoding().toLowerCase().replaceAll("-", ""); + return sysEnc; + } + + @Override + public Class getSqlUserClass() { + return MySqlUser.class; + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/database/MySqlUser.java b/persistence/src/main/java/de/hsadmin/bo/database/MySqlUser.java new file mode 100644 index 0000000..6b08c65 --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/database/MySqlUser.java @@ -0,0 +1,18 @@ +package de.hsadmin.bo.database; + +import java.io.Serializable; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + +@Entity(name = "MySqlUser") +@DiscriminatorValue("mysql") +public class MySqlUser extends DatabaseUser implements Serializable { + + private static final long serialVersionUID = 1L; + + public MySqlUser() { + setInstance("mysql"); + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/database/PgSqlDatabase.java b/persistence/src/main/java/de/hsadmin/bo/database/PgSqlDatabase.java new file mode 100644 index 0000000..cbb2a2a --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/database/PgSqlDatabase.java @@ -0,0 +1,29 @@ +package de.hsadmin.bo.database; + +import java.io.Serializable; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + +@Entity(name = "PgSqlDatabase") +@DiscriminatorValue("pgsql") +public class PgSqlDatabase extends Database implements Serializable { + + private static final long serialVersionUID = 1L; + + public PgSqlDatabase() { + setInstance("pgsql"); + setEncoding("UTF-8"); + } + + @Override + public Class getSqlUserClass() { + return PgSqlUser.class; + } + + public String getSystemEncoding() { + return getEncoding(); + } + +} + diff --git a/persistence/src/main/java/de/hsadmin/bo/database/PgSqlUser.java b/persistence/src/main/java/de/hsadmin/bo/database/PgSqlUser.java new file mode 100644 index 0000000..0638291 --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/database/PgSqlUser.java @@ -0,0 +1,22 @@ +package de.hsadmin.bo.database; + +import java.io.Serializable; + +import javax.persistence.DiscriminatorValue; +import javax.persistence.Entity; + +@Entity(name = "PgSqlUser") +@DiscriminatorValue("pgsql") +public class PgSqlUser extends DatabaseUser implements Serializable { + + private static final long serialVersionUID = 1L; + + public static String createQueryFromStringKey(String humanKey) { + return "obj.name='" + humanKey + "' AND obj.instance='pgsql'"; + } + + public PgSqlUser() { + setInstance("pgsql"); + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/domain/Domain.java b/persistence/src/main/java/de/hsadmin/bo/domain/Domain.java new file mode 100644 index 0000000..174b478 --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/domain/Domain.java @@ -0,0 +1,121 @@ +package de.hsadmin.bo.domain; + +import static javax.persistence.FetchType.EAGER; +import static javax.persistence.GenerationType.SEQUENCE; + +import java.util.Date; +import java.util.Set; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.ManyToOne; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; +import javax.persistence.Temporal; + +import de.hsadmin.bo.pac.UnixUser; +import de.hsadmin.common.config.Config; +import de.hsadmin.common.error.TechnicalException; + +@Entity(name = "Domain") +@Table(name = "domain") +@SequenceGenerator(name = "DomainsSeqGen", sequenceName = "domain_domain_id_seq") +public class Domain { + + @Id + @Column(name = "domain_id", columnDefinition = "integer") + @GeneratedValue(strategy = SEQUENCE, generator = "DomainsSeqGen") + private long id; + + @Column(name = "domain_name", columnDefinition = "character varying(256)", nullable = false) + private String name; + + @JoinColumn(name = "domain_owner", columnDefinition = "integer", nullable = false) + @ManyToOne(fetch = EAGER) + private UnixUser user; + + @Column(name = "domain_since", columnDefinition = "date") + @Temporal(javax.persistence.TemporalType.DATE) + private Date since; + + @Column(name = "domain_dns_master", columnDefinition = "character varying(64)") + private String dnsMaster; + + @ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.PERSIST) + @JoinTable(name="domain__domain_option", + joinColumns={@JoinColumn(name="domain_id", referencedColumnName="domain_id")}, + inverseJoinColumns={@JoinColumn(name="domain_option_id", referencedColumnName="domain_option_id")}) + private Set domainoptions; + + public Domain() { + } + + 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 UnixUser getUser() { + return user; + } + + public void setUser(UnixUser user) { + this.user = user; + } + + public Date getSince() { + return since; + } + + public void setSince(Date since) { + this.since = since; + } + + public String getDnsMaster() { + return dnsMaster; + } + + public void setDnsMaster(String dnsMaster) { + this.dnsMaster = dnsMaster; + } + + public boolean isPacDomain() { + if (getUser() != null && getUser().getPac() != null) { + String pacDomName = getUser().getPac().getName(); + try { + final String pacDomainPostfix = Config.getInstance().getProperty(Config.PACKET_DOMAINS_POSTFIX, "example.com"); + pacDomName = pacDomName + "." + pacDomainPostfix; + } catch (TechnicalException e) { + } + return pacDomName.equals(getName()); + } + return false; + } + + public Set getDomainoptions() { + return domainoptions; + } + + public void setDomainoptions(Set domainOptions) { + this.domainoptions = domainOptions; + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/domain/DomainOption.java b/persistence/src/main/java/de/hsadmin/bo/domain/DomainOption.java new file mode 100644 index 0000000..9e84f0e --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/domain/DomainOption.java @@ -0,0 +1,75 @@ +package de.hsadmin.bo.domain; + +import static javax.persistence.GenerationType.SEQUENCE; + +import java.util.List; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.ManyToMany; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; + +@Table(name="domain_option") +@Entity(name="DomainOption") +@SequenceGenerator(name = "DomainOptionSeqGen", sequenceName = "domain_option_id_seq") +public class DomainOption { + + @Id + @Column(name = "domain_option_id", columnDefinition = "integer") + @GeneratedValue(strategy = SEQUENCE, generator = "DomainOptionSeqGen") + private long id; + + @Column(name = "domain_option_name", columnDefinition = "character varying(256)", nullable = false) + private String name; + + @ManyToMany(mappedBy="domainoptions", fetch=FetchType.LAZY) + private List domains; + + 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; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof DomainOption) { + DomainOption opt = (DomainOption) obj; + return getName().equals(opt.getName()); + } + return false; + } + + @Override + public int hashCode() { + return getName().hashCode(); + } + + @Override + public String toString() { + return getName(); + } + + public List getDomains() { + return domains; + } + + public void setDomains(List domains) { + this.domains = domains; + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/domain/EMailAddress.java b/persistence/src/main/java/de/hsadmin/bo/domain/EMailAddress.java new file mode 100644 index 0000000..52fb7d2 --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/domain/EMailAddress.java @@ -0,0 +1,97 @@ +package de.hsadmin.bo.domain; + +import static javax.persistence.FetchType.EAGER; +import static javax.persistence.GenerationType.SEQUENCE; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; + + +@Entity(name = "EMailAddress") +@Table(name = "emailaddr") +@SequenceGenerator(name = "EMailAddressesSeqGen", sequenceName = "emailaddr_emailaddr_id_seq") +public class EMailAddress implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = SEQUENCE, generator = "EMailAddressesSeqGen") + @Column(name = "emailaddr_id", columnDefinition = "integer") + private long id; + + @Column(name = "localpart", updatable = false, nullable= false) + private String localpart = ""; + + @Column(name = "subdomain") + private String subdomain; + + @ManyToOne(fetch = EAGER) + @JoinColumn(name = "domain_id", columnDefinition = "integer", updatable = false) + private Domain domain; + + @Column(name = "target", nullable= false) + private String target; + + public EMailAddress() { + } + + public long getId() { + return id; + } + + protected void setId(long id) { + this.id = id; + } + + public String getLocalpart() { + return localpart == null ? "" : localpart; + } + + public void setLocalpart(String localpart) { + this.localpart = localpart; + } + + public String getSubdomain() { + return subdomain == null || subdomain.length() == 0 ? null : subdomain; + } + + public void setSubdomain(String subdomain) { + this.subdomain = subdomain; + } + + public Domain getDomain() { + return domain; + } + + public void setDomain(Domain domain) { + this.domain = domain; + } + + public String getTarget() { + return target; + } + + public void setTarget(String target) { + this.target = target; + } + + public String toString() { + if (localpart != null && target != null && domain != null) { + String local = super.toString() + "{ id=" + id + "; address=" + localpart + "@"; + if (subdomain != null) { local += "." + subdomain; } + return local + domain + "; target=" + target + " }"; + } else { + return super.toString(); + } + } + + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/pac/BaseComponent.java b/persistence/src/main/java/de/hsadmin/bo/pac/BaseComponent.java new file mode 100644 index 0000000..56e9e9b --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/pac/BaseComponent.java @@ -0,0 +1,80 @@ +package de.hsadmin.bo.pac; + +import static javax.persistence.GenerationType.SEQUENCE; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; + +@Entity(name = "BaseComponent") +@Table(name = "basecomponent") +@SequenceGenerator(name = "BaseComponentsSeqGen", sequenceName = "basecomponent_basecomponent_seq") +public class BaseComponent implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = SEQUENCE, generator = "BaseComponentsSeqGen") + @Column(name = "basecomponent_id", columnDefinition = "integer") + private long baseComponentId; + + @Column(name = "basecomponent_code", columnDefinition = "character varying(10)") + private String feature; + + @Column(name = "description", columnDefinition = "character varying(100)") + private String description; + + @Column(name = "sorting", columnDefinition = "integer") + private int sorting; + + @Column(name = "valid", columnDefinition = "boolean") + private boolean valid; + + public BaseComponent() { + } + + public String getFeature() { + return feature; + } + + public void setFeature(final String code) { + this.feature = code; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } + + public int getSorting() { + return sorting; + } + + public void setSorting(final int sorting) { + this.sorting = sorting; + } + + public boolean getValid() { + return valid; + } + + public void setValid(final boolean valid) { + this.valid = valid; + } + + public void setBaseComponentId(final long baseComponentId) { + this.baseComponentId = baseComponentId; + } + + public long getBaseComponentId() { + return baseComponentId; + } +} diff --git a/persistence/src/main/java/de/hsadmin/bo/pac/BasePac.java b/persistence/src/main/java/de/hsadmin/bo/pac/BasePac.java new file mode 100644 index 0000000..a230dab --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/pac/BasePac.java @@ -0,0 +1,129 @@ +package de.hsadmin.bo.pac; + +import static javax.persistence.CascadeType.ALL; +import static javax.persistence.GenerationType.SEQUENCE; + +import java.io.Serializable; +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; + +@Entity(name = "BasePac") +@Table(name = "basepacket") +@SequenceGenerator(name = "BasePacsSeqGen", sequenceName = "basepacket_basepacket_id_seq") +public class BasePac implements Serializable { + + private static final long serialVersionUID = 1L; + + public BasePac() { + components = new HashSet(); + } + + @Id + @GeneratedValue(strategy = SEQUENCE, generator = "BasePacsSeqGen") + @Column(name = "basepacket_id", columnDefinition = "integer") + private long basePacId; + + @Column(name = "basepacket_code", columnDefinition = "character varying(10)") + private String name; + + @Column(name = "description", columnDefinition = "character varying(100)") + private String description; + + @Column(name = "article_number", columnDefinition = "integer", nullable=false) + private int articleNumber; + + @Column(name = "sorting", columnDefinition = "integer") + private int sorting; + + @Column(name = "valid", columnDefinition = "boolean") + private boolean valid; + + @OneToMany(fetch = FetchType.LAZY, cascade=ALL, mappedBy="basePacket") + private Set components; + + public long getBasePacId() { + return basePacId; + } + + public void setBasePacId(final long id) { + this.basePacId = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } + + public int getSorting() { + return sorting; + } + + public void setSorting(final int sorting) { + this.sorting = sorting; + } + + public boolean isValid() { + return valid; + } + + public void setValid(final boolean valid) { + this.valid = valid; + } + + public Set getComponents() { + return components != null ? components + : (components = new HashSet()); + } + + public void setComponents(final Set components) { + this.components = components; + } + + public Component getComponent(final String feature) { + for (Component comp : getComponents()) + if (feature.equals(comp.getBaseComponent().getFeature())) + return comp; + return null; + } + + public void addComponent(final Component comp) { + getComponents().add(comp); + } + + public void removeComponent(final Component comp) { + getComponents().remove(comp); + } + + public int getArticleNumber() { + return articleNumber; + } + + public void setArticleNumber(final int articleNumber) { + this.articleNumber = articleNumber; + } + + @Override + public String toString() { + return "BasePac \"" + getName() + "\""; + } +} diff --git a/persistence/src/main/java/de/hsadmin/bo/pac/Component.java b/persistence/src/main/java/de/hsadmin/bo/pac/Component.java new file mode 100644 index 0000000..d781967 --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/pac/Component.java @@ -0,0 +1,137 @@ +package de.hsadmin.bo.pac; + +import static javax.persistence.GenerationType.SEQUENCE; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; + +@Entity(name = "Component") +@Table(name = "component") +@SequenceGenerator(name = "CompSeqGen", sequenceName = "component_id_seq") +public class Component implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = SEQUENCE, generator = "CompSeqGen") + @Column(name = "component_id", columnDefinition = "integer") + private long componentId; + + @ManyToOne + @JoinColumn(name="basecomponent_id") + private BaseComponent baseComponent; + + @ManyToOne + @JoinColumn(name="basepacket_id") + private BasePac basePacket; + + @Column(name = "article_number", columnDefinition = "integer", nullable=false) + private int articleNumber; + + @Column(name = "min_quantity", columnDefinition = "integer") + private int minimumQuantity; + + @Column(name = "max_quantity", columnDefinition = "integer") + private int maximimumQuantity; + + @Column(name = "default_quantity", columnDefinition = "integer") + private int defaultQuantity; + + @Column(name = "increment_quantity", columnDefinition = "integer") + private int incrementQuantity; + + @Column(name = "include_quantity", columnDefinition = "integer") + private int includedQuantity; + + @Column(name = "admin_only", columnDefinition = "boolean") + private boolean adminOnly; + + public BaseComponent getBaseComponent() { + return baseComponent; + } + + public void setBaseComponent(final BaseComponent baseComponent) { + this.baseComponent = baseComponent; + } + + public int getMinimumQuantity() { + return minimumQuantity; + } + + public void setMinimumQuantity(final int minimumQuantity) { + this.minimumQuantity = minimumQuantity; + } + + public int getMaximimumQuantity() { + return maximimumQuantity; + } + + public void setMaximimumQuantity(final int maximimumQuantity) { + this.maximimumQuantity = maximimumQuantity; + } + + public int getDefaultQuantity() { + return defaultQuantity; + } + + public void setDefaultQuantity(final int defiautoQuantity) { + this.defaultQuantity = defiautoQuantity; + } + + public int getIncrementQuantity() { + return incrementQuantity; + } + + public void setIncrementQuantity(final int incrementQuantity) { + this.incrementQuantity = incrementQuantity; + } + + public int getIncludedQuantity() { + return includedQuantity; + } + + public void setIncludedQuantity(final int includedQuantity) { + this.includedQuantity = includedQuantity; + } + + public boolean isAdminOnly() { + return adminOnly; + } + + public void setAdminOnly(final boolean adminOnly) { + this.adminOnly = adminOnly; + } + + public int getArticleNumber() { + return articleNumber; + } + + public void setArticleNumber(final int articleNumber) { + this.articleNumber = articleNumber; + } + + public long getComponentId() { + return componentId; + } + + public void setComponentId(final long componentId) { + this.componentId = componentId; + } + + public BasePac getBasePacket() { + return basePacket; + } + + public void setBasePacket(final BasePac basePacket) { + this.basePacket = basePacket; + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/pac/EMailAlias.java b/persistence/src/main/java/de/hsadmin/bo/pac/EMailAlias.java new file mode 100644 index 0000000..5516812 --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/pac/EMailAlias.java @@ -0,0 +1,82 @@ +package de.hsadmin.bo.pac; + +import static javax.persistence.GenerationType.SEQUENCE; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; + +@javax.persistence.Entity(name = "EMailAliases") +@Table(name = "emailalias") +@SequenceGenerator(name = "EMailAliasesSeqGen", sequenceName = "emailalias_emailalias_id_seq") +public class EMailAlias implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = SEQUENCE, generator = "EMailAliasesSeqGen") + @Column(name = "emailalias_id", columnDefinition = "integer", insertable=false, updatable=false) + private long id; + + @ManyToOne() + @JoinColumn(name = "pac_id", columnDefinition = "integer") + private Pac pac; + + @Column(updatable=false) + private String name; + + @Column + private String target; + + public EMailAlias() { + } + + public EMailAlias(Pac pac, String name, String target) { + this.pac = pac; + this.name = name; + this.target = target; + } + + public static String createQueryFromStringKey(String humanKey) { + return "obj.name='" + humanKey + "'"; + } + + public long getId() { + return id; + } + + protected void setId(long id) { + this.id = id; + } + + public Pac getPac() { + return pac; + } + + public void setPac(Pac pac) { + this.pac = pac; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getTarget() { + return target; + } + + public void setTarget(String target) { + this.target = target; + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/pac/Hive.java b/persistence/src/main/java/de/hsadmin/bo/pac/Hive.java new file mode 100644 index 0000000..8e564df --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/pac/Hive.java @@ -0,0 +1,95 @@ +package de.hsadmin.bo.pac; + +import static javax.persistence.CascadeType.ALL; +import static javax.persistence.FetchType.EAGER; +import static javax.persistence.FetchType.LAZY; +import static javax.persistence.GenerationType.SEQUENCE; + +import java.io.Serializable; +import java.util.Set; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.OrderBy; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; + +@Entity(name = "Hive") +@Table(name = "hive") +@SequenceGenerator(name = "HivesSeqGen", sequenceName = "hive_hive_id_seq") +public class Hive implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = SEQUENCE, generator = "HivesSeqGen") + @Column(name = "hive_id") + private long id; + + @Column(name = "hive_name", columnDefinition = "character varying(3)", unique = true) + private String name; + + @JoinColumn(name = "inet_addr_id") + @ManyToOne(fetch = EAGER) + private INetAddress inetAddr; + + @Column(name = "description", columnDefinition = "character varying(100)") + private String description; + + @OneToMany(fetch = LAZY, cascade = ALL, mappedBy = "hive") + @OrderBy("name") + private Set pacs; + + public Hive() { + } + + public Hive(final INetAddress inetAddr) { + this.inetAddr = inetAddr; + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String hiveName) { + this.name = hiveName; + } + + public INetAddress getInetAddr() { + return inetAddr; + } + + public void setInetAddr(final INetAddress inetAddr) { + this.inetAddr = inetAddr; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } + + public Set getPacs() { + return pacs; + } + + public void setPacs(final Set pacs) { + this.pacs = pacs; + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/pac/INetAddress.java b/persistence/src/main/java/de/hsadmin/bo/pac/INetAddress.java new file mode 100644 index 0000000..e939c6c --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/pac/INetAddress.java @@ -0,0 +1,68 @@ +package de.hsadmin.bo.pac; + +import static javax.persistence.GenerationType.SEQUENCE; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; + +@Entity(name = "INetAddress") +@Table(name = "inet_addr") +@SequenceGenerator(name = "INetAddressesSeqGen", sequenceName = "inet_addr_inet_addr_id_seq") +public class INetAddress implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = SEQUENCE, generator = "INetAddressesSeqGen") + @Column(name = "inet_addr_id") + private long id; + + @Column(name = "inet_addr", unique = true, length=-1) + private String inetAddr; + + @Column(name = "description", columnDefinition = "character varying(100)") + private String description; + + public INetAddress() { + } + + public INetAddress(final String inetAddr) { + this.inetAddr = inetAddr; + } + + public INetAddress(final String inetAddr, final String desc) { + this(inetAddr); + description = desc; + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + + public String getInetAddr() { + return inetAddr; + } + + public void setInetAddr(final String inetAddr) { + this.inetAddr = inetAddr; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/pac/Pac.java b/persistence/src/main/java/de/hsadmin/bo/pac/Pac.java new file mode 100644 index 0000000..8fbd981 --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/pac/Pac.java @@ -0,0 +1,237 @@ +package de.hsadmin.bo.pac; + +import static javax.persistence.CascadeType.ALL; +import static javax.persistence.FetchType.EAGER; +import static javax.persistence.FetchType.LAZY; +import static javax.persistence.GenerationType.SEQUENCE; + +import java.io.Serializable; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EntityListeners; +import javax.persistence.EntityManager; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Query; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +import de.hsadmin.bo.customer.Customer; + +@Entity(name = "Pac") +@Table(name = "packet") +@SequenceGenerator(name = "PacsSeqGen", sequenceName = "packet_packet_id_seq") +@EntityListeners({PacEntityListener.class}) +public class Pac implements Serializable { + + private static final long serialVersionUID = 1L; + + public static final int UNDEFINED_QUANTITY = -1; + + @Id + @GeneratedValue(strategy = SEQUENCE, generator = "PacsSeqGen") + @Column(name = "packet_id", columnDefinition = "integer") + private long id; + + @Column(name = "packet_name", unique = true) + private String name; + + @JoinColumn(name = "bp_id") + @ManyToOne(fetch = LAZY) + private Customer customer; + + @JoinColumn(name = "basepacket_id") + @ManyToOne(fetch = EAGER) + private BasePac basePac; + + @JoinColumn(name = "hive_id") + @ManyToOne(fetch = EAGER) + private Hive hive; + + @Column(name = "created") + @Temporal(TemporalType.DATE) + private Date created; + + @Column(name = "cancelled", nullable = true) + @Temporal(TemporalType.DATE) + private Date cancelled; + + @Column(name = "free", nullable = false) + private Boolean free = false; + + @JoinColumn(name = "cur_inet_addr_id", nullable = true) + @ManyToOne(fetch = EAGER) + private INetAddress curINetAddr; + + @JoinColumn(name = "old_inet_addr_id", nullable = true) + @ManyToOne(fetch = EAGER) + private INetAddress oldINetAddr; + + @OneToMany(fetch = EAGER, cascade = ALL, mappedBy="pac") + private Set pacComponents; + + @OneToMany(fetch = LAZY, cascade = ALL, mappedBy="pac") + private Set unixUser; + + public void initPacComponents(final EntityManager em, final BasePac aBasepac, final boolean setDefaults) { + final Query qAttachedBasepac = em.createQuery("SELECT b FROM BasePac b WHERE b.valid = :valid AND b.name = :name"); + qAttachedBasepac.setParameter("valid", Boolean.TRUE); + qAttachedBasepac.setParameter("name", aBasepac.getName()); + basePac = (BasePac) qAttachedBasepac.getSingleResult(); + pacComponents = new HashSet(); + final Date today = new Date(); + for (Component comp : basePac.getComponents()) { + final PacComponent pacComp = new PacComponent(); + pacComp.setCreated(today); + pacComp.setBaseComponent(comp.getBaseComponent()); + pacComp.setPac(this); + if (setDefaults) { + pacComp.setQuantity(comp.getDefaultQuantity()); + } else { + pacComp.setQuantity(UNDEFINED_QUANTITY); + } + pacComponents.add(pacComp); + } + } + + public long getId() { + return id; + } + + protected void setId(final long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public Customer getCustomer() { + return customer; + } + + public void setCustomer(final Customer customer) { + this.customer = customer; + } + + public Hive getHive() { + return hive; + } + + public void setHive(final Hive hive) { + this.hive = hive; + } + + public Date getCreated() { + return created; + } + + public void setCreated(final Date created) { + this.created = created; + } + + public Date getCancelled() { + return cancelled; + } + + public void setCancelled(final Date cancelled) { + this.cancelled = cancelled; + } + + public INetAddress getCurINetAddr() { + return curINetAddr; + } + + public void setCurINetAddr(final INetAddress curINetAddr) { + this.curINetAddr = curINetAddr; + } + + public INetAddress getOldINetAddr() { + if (oldINetAddr == null) { + return getCurINetAddr(); + } + return oldINetAddr; + } + + public void setOldINetAddr(final INetAddress oldINetAddr) { + this.oldINetAddr = oldINetAddr; + } + + public BasePac getBasePac() { + return basePac; + } + + public void setBasePac(final BasePac basepac) { + this.basePac = basepac; + } + + public Set getPacComponents() { + return pacComponents; + } + + public void setPacComponents(final Set pacComponents) { + this.pacComponents = pacComponents; + } + + public PacComponent getPacComponent(final String feature) { + if (pacComponents != null) { + for (PacComponent pc : pacComponents) { + if (feature.equals(pc.getBaseComponent().getFeature())) { + return pc; + } + } + } + return null; + } + + public Set getUnixUser() { + return unixUser; + } + + public void setUnixUser(Set unixUser) { + this.unixUser = unixUser; + } + + public String toString() { + return super.toString() + "{ name=" + name + " }"; + } + + public Boolean isFree() { + return free; + } + + public Boolean getFree() { + return free; + } + + public void setFree(final Boolean free) { + if (free == null) { + this.free = Boolean.FALSE; + } else { + this.free = free; + } + } + + public int getQuantityByComponentName(final String componentName) { + PacComponent multi = getPacComponent(componentName); + if (multi == null) { + return 0; + } else { + return multi.getQuantity(); + } + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/pac/PacComponent.java b/persistence/src/main/java/de/hsadmin/bo/pac/PacComponent.java new file mode 100644 index 0000000..98c5d19 --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/pac/PacComponent.java @@ -0,0 +1,99 @@ +package de.hsadmin.bo.pac; + +import static javax.persistence.GenerationType.SEQUENCE; + +import java.io.Serializable; +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; + +@Entity(name = "PacComponents") +@Table(name = "packet_component") +@SequenceGenerator(name = "PacCompSeqGen", sequenceName = "packet_component_id_seq") +public class PacComponent implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = SEQUENCE, generator = "PacCompSeqGen") + @Column(name = "packet_component_id") + private long pacComponentId; + + @ManyToOne + @JoinColumn(name = "packet_id") + private Pac pac; + + @ManyToOne + @JoinColumn(name = "basecomponent_id") + private BaseComponent baseComponent; + + @Column(name = "quantity", columnDefinition = "integer") + private int quantity; + + @Column(name = "created", columnDefinition = "date", nullable = true) + @Temporal(TemporalType.DATE) + private Date created; + + @Column(name = "cancelled", columnDefinition = "date", nullable = true) + @Temporal(TemporalType.DATE) + private Date cancelled; + + public BasePac getBasePac() { + return pac.getBasePac(); + } + + public BaseComponent getBaseComponent() { + return baseComponent; + } + + public void setBaseComponent(final BaseComponent baseComponent) { + this.baseComponent = baseComponent; + } + + public Pac getPac() { + return pac; + } + + public void setPac(final Pac pac) { + this.pac = pac; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(final int quantity) { + this.quantity = quantity; + } + + public Date getCreated() { + return created; + } + + public void setCreated(Date created) { + this.created = created; + } + + public Date getCancelled() { + return cancelled; + } + + public void setCancelled(final Date cancelled) { + this.cancelled = cancelled; + } + + @Override + public String toString() { + return "pac=" + pac.getName() + ";comp=" + getBaseComponent().getFeature() + ";quantity=" + getQuantity(); + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/pac/PacEntityListener.java b/persistence/src/main/java/de/hsadmin/bo/pac/PacEntityListener.java new file mode 100644 index 0000000..d21ab58 --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/pac/PacEntityListener.java @@ -0,0 +1,54 @@ +package de.hsadmin.bo.pac; + +import javax.persistence.PostLoad; +import javax.persistence.PrePersist; +import javax.persistence.PreRemove; +import javax.persistence.PreUpdate; + +public class PacEntityListener { + + public PacEntityListener() { + System.out.println("PacEntityListener()"); + } + + @PostLoad + public void onLoad(Object pacObject) { + System.out.println("onLoad"); + if (pacObject instanceof Pac) { + Pac pac = (Pac) pacObject; + System.out.println("Pac: " + pac.getName() + " free:" + pac.isFree()); + } + System.out.println(" from: " + this.toString()); + } + + @PrePersist + public void onCreate(Object pacObject) { + System.out.println("onCreate"); + if (pacObject instanceof Pac) { + Pac pac = (Pac) pacObject; + System.out.println("Pac: " + pac.getName() + " free:" + pac.isFree()); + } + System.out.println(" from: " + this.toString()); + } + + @PreUpdate + public void onUpdate(Object pacObject) { + System.out.println("onUpdate"); + if (pacObject instanceof Pac) { + Pac pac = (Pac) pacObject; + System.out.println("Pac: " + pac.getName() + " free:" + pac.isFree()); + } + System.out.println(" from: " + this.toString()); + } + + @PreRemove + public void onDelete(Object pacObject) { + System.out.println("onDelete"); + if (pacObject instanceof Pac) { + Pac pac = (Pac) pacObject; + System.out.println("Pac: " + pac.getName() + " free:" + pac.isFree()); + } + System.out.println(" from: " + this.toString()); + } + +} diff --git a/persistence/src/main/java/de/hsadmin/bo/pac/UnixUser.java b/persistence/src/main/java/de/hsadmin/bo/pac/UnixUser.java new file mode 100644 index 0000000..ea1d63f --- /dev/null +++ b/persistence/src/main/java/de/hsadmin/bo/pac/UnixUser.java @@ -0,0 +1,166 @@ +package de.hsadmin.bo.pac; + +import static javax.persistence.GenerationType.SEQUENCE; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; +import javax.persistence.Transient; + + +@Entity(name = "UnixUsers") +@Table(name = "unixuser") +@SequenceGenerator(name = "UnixUsersSeqGen", sequenceName = "unixuser_unixuser_id_seq") +public class UnixUser implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @GeneratedValue(strategy = SEQUENCE, generator = "UnixUsersSeqGen") + @Column(name="unixuser_id", columnDefinition="integer", updatable=false, insertable=false) + private long id; + + @Column(name="userid", columnDefinition="integer", nullable=false, updatable=false) + private long userId; + + @Column(name="name", columnDefinition = "character varying(24)", unique=true, updatable=false) + private String name; + + @Transient + private String password; + + @JoinColumn(name = "packet_id", columnDefinition = "integer", updatable=false) + @ManyToOne(fetch = FetchType.LAZY) + private Pac pac; + + @Column(name = "comment", columnDefinition = "character varying(128)") + private String comment; + + @Column(name = "shell", columnDefinition = "character varying(32)") + private String shell; + + @Column(name = "homedir", columnDefinition = "character varying(48)", updatable=false) + private String homedir; + + @Column(name = "locked", columnDefinition = "boolean") + private boolean locked; + + @Column(name = "quota_softlimit", columnDefinition = "integer") + private Integer quotaSoftlimit; + + @Column(name = "quota_hardlimit", columnDefinition = "integer") + private Integer quotaHardlimit; + + public UnixUser() { + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public long getUserId() { + return userId; + } + + public void setUserId(long userId) { + this.userId = userId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + + public Pac getPac() { + return pac; + } + + public void setPac(Pac pac) { + this.pac = pac; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + + public String getShell() { + return shell; + } + + public void setShell(String shell) { + this.shell = shell; + } + + public String getHomedir() { + return homedir; + } + + public void setHomedir(String homedir) { + this.homedir = homedir; + } + + public boolean isDefaultHomedir() { + return getHomedir().equals(getDefaultHomedir()); + } + + private String getDefaultHomedir() { + String pacName = pac.getName(); + if (name.equals(pacName)) { + return "/home/pacs/" + pacName; + } + else { + return "/home/pacs/" + pacName + "/users/" + name.substring(pacName.length() + 1); + } + } + + public boolean isLocked() { + return locked; + } + + public void setLocked(boolean locked) { + this.locked = locked; + } + + public Integer getQuotaSoftlimit() { + return quotaSoftlimit; + } + + public void setQuotaSoftlimit(Integer quota) { + this.quotaSoftlimit = quota; + } + + public void setQuotaHardlimit(Integer quotaLimit) { + this.quotaHardlimit = quotaLimit; + } + + public Integer getQuotaHardlimit() { + return quotaHardlimit; + } + +} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..f236b01 --- /dev/null +++ b/pom.xml @@ -0,0 +1,45 @@ + + 4.0.0 + + de.hsadmin + hsadmin-parent + pom + 1.0-SNAPSHOT + HSAdmin Parent Project + + + authorization + common + framework + persistence + services + xmlrpc + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.7 + 1.7 + + + + + + + + + junit + junit + 4.12 + test + + + diff --git a/services/.gitignore b/services/.gitignore new file mode 100644 index 0000000..e774414 --- /dev/null +++ b/services/.gitignore @@ -0,0 +1,13 @@ +*.class + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +/target +/.settings +/.classpath +/.project diff --git a/services/LICENSE.txt b/services/LICENSE.txt new file mode 100644 index 0000000..dba13ed --- /dev/null +++ b/services/LICENSE.txt @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/services/pom.xml b/services/pom.xml new file mode 100644 index 0000000..d855541 --- /dev/null +++ b/services/pom.xml @@ -0,0 +1,80 @@ + + 4.0.0 + + de.hsadmin + hsadmin-parent + 1.0-SNAPSHOT + + services + jar + + HSAdmin Services + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + + + + + de.hsadmin + framework + 1.0-SNAPSHOT + + + de.hsadmin + persistence + 1.0-SNAPSHOT + + + de.hsadmin + common + 1.0-SNAPSHOT + + + de.hsadmin + authorization + 1.0-SNAPSHOT + + + org.apache.geronimo.specs + geronimo-jpa_2.0_spec + 1.1 + provided + + + org.apache.geronimo.specs + geronimo-ejb_3.0_spec + 1.0.1 + provided + + + org.apache.geronimo.specs + geronimo-validation_1.0_spec + 1.1 + provided + + + org.apache.xmlrpc + xmlrpc-server + 3.1.3 + + + log4j + log4j + 1.2.17 + + + diff --git a/services/src/main/java/de/hsadmin/service/customer/ContactRemote.java b/services/src/main/java/de/hsadmin/service/customer/ContactRemote.java new file mode 100644 index 0000000..ccb7a79 --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/customer/ContactRemote.java @@ -0,0 +1,14 @@ +package de.hsadmin.service.customer; + +import de.hsadmin.xmlrpc.AbstractRemote; +import de.hsadmin.xmlrpc.Remote; + + +public class ContactRemote extends AbstractRemote implements Remote { + + @Override + protected String getModuleLookup() { + return "ContactServiceLocal"; + } + +} diff --git a/services/src/main/java/de/hsadmin/service/customer/ContactService.java b/services/src/main/java/de/hsadmin/service/customer/ContactService.java new file mode 100644 index 0000000..f4ab674 --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/customer/ContactService.java @@ -0,0 +1,100 @@ +package de.hsadmin.service.customer; + +import java.util.List; + +import javax.ejb.Stateless; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; + +import de.hsadmin.bo.customer.Contact; +import de.hsadmin.bo.customer.Customer; +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.login.RequestContext; +import de.hsadmin.login.RequiredScope; +import de.hsadmin.login.Role; +import de.hsadmin.login.ScopePolicy; +import de.hsadmin.module.impl.AbstractModule; +import de.hsadmin.module.util.QueryBuilder; + +@Stateless +public class ContactService extends AbstractModule implements ContactServiceLocal { + + @PersistenceContext(name="hsar") + private EntityManager entityManager; + + @Override + public ContactVO buildVO() throws TechnicalException { + return new ContactVO(); + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM)}) + public ContactVO create(final RequestContext requestContext, final ContactVO prototype) + throws UserException, TechnicalException { + final ContactVO vo = super.create(requestContext, prototype); + final Contact bo = new Contact(); + bo.setCustomer(findCustomerByName(prototype.getCustomer())); + vo.copyPropertiesToPersistentObject(bo); + entityManager.persist(bo); + final Contact newBO = findContactByNames(vo); + final ContactVO newVO = new ContactVO(); + newVO.copyPropertiesFromPersistentObject(newBO); + return newVO; + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM), @ScopePolicy(value=Role.CUSTOMER, property="customer")}) + public List read(final RequestContext requestContext, final ContactVO criteria) + throws UserException, TechnicalException { + final List emptyList = super.read(requestContext, criteria); + final List list = QueryBuilder.newBuilder(entityManager, Contact.class).getResultList(criteria); + for (Contact c : list) { + ContactVO vo = new ContactVO(); + vo.copyPropertiesFromPersistentObject(c); + emptyList.add(vo); + } + return emptyList; + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM)}) + public List update(final RequestContext requestContext, final ContactVO criteria, final ContactVO prototype) + throws UserException, TechnicalException { + final List contactsForUpdate = super.update(requestContext, criteria, prototype); + for (ContactVO vo : contactsForUpdate) { + final Contact bo = findContactByNames(vo); + prototype.copyPropertiesToPersistentObject(bo); + vo.copyPropertiesFromPersistentObject(bo); + } + return contactsForUpdate; + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM)}) + public void delete(final RequestContext requestContext, final ContactVO criteria) + throws UserException, TechnicalException { + super.delete(requestContext, criteria); + final List list = QueryBuilder.newBuilder(entityManager, Contact.class).getResultList(criteria); + for (Contact c : list) { + entityManager.remove(c); + } + } + + private Contact findContactByNames(final ContactVO prototype) throws UserException, TechnicalException { + final Query query = entityManager.createQuery("SELECT c FROM Contact c WHERE c.firstName = :firstname AND c.lastName = :lastname AND c.customer.name = :customer AND c.email = :email"); + query.setParameter("firstname", prototype.get("firstName").getValue()); + query.setParameter("lastname", prototype.get("lastName").getValue()); + query.setParameter("customer", prototype.get("customer").getValue()); + query.setParameter("email", prototype.get("email").getValue()); + return (Contact) query.getSingleResult(); + } + + private Customer findCustomerByName(final String customer) throws UserException { + final Query query = entityManager.createQuery("SELECT c FROM Customer c WHERE c.name = :name"); + query.setParameter("name", customer); + return (Customer) query.getSingleResult(); + } + +} diff --git a/services/src/main/java/de/hsadmin/service/customer/ContactServiceLocal.java b/services/src/main/java/de/hsadmin/service/customer/ContactServiceLocal.java new file mode 100644 index 0000000..3cd3e19 --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/customer/ContactServiceLocal.java @@ -0,0 +1,10 @@ +package de.hsadmin.service.customer; + +import javax.ejb.Local; + +import de.hsadmin.module.Module; + +@Local +public interface ContactServiceLocal extends Module { + +} diff --git a/services/src/main/java/de/hsadmin/service/customer/ContactVO.java b/services/src/main/java/de/hsadmin/service/customer/ContactVO.java new file mode 100644 index 0000000..b29562a --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/customer/ContactVO.java @@ -0,0 +1,246 @@ +package de.hsadmin.service.customer; + +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractVO; +import de.hsadmin.module.property.ReadWrite; +import de.hsadmin.module.property.ReadWritePolicy; +import de.hsadmin.module.property.Required; +import de.hsadmin.module.property.Search; +import de.hsadmin.module.property.SearchPolicy; +import de.hsadmin.module.property.StringSet; +import de.hsadmin.module.property.mapping.DefaultStringParameterMapMapper; +import de.hsadmin.module.property.mapping.Mapping; +import de.hsadmin.module.property.mapping.ReferredStringPersistentObjectMapper; + +public class ContactVO extends AbstractVO implements ValueObject { + + @Mapping(boMapping=ReferredStringPersistentObjectMapper.class, + rpcMapping=DefaultStringParameterMapMapper.class, + boMappingPath="customer.name") + @ReadWrite(ReadWritePolicy.WRITEONCE) + @Required(true) + @Search(SearchPolicy.EQUALS) + private String customer; + + @Pattern(regexp="[A-Za-z]*") + @Size(min=0,max=16) + @ReadWrite(ReadWritePolicy.READWRITE) + private String salut; + + @Pattern(regexp="[\\p{L}\\p{Nd}\\-\\ ]*") + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.LIKE) + private String firstName; + + @Pattern(regexp="[\\p{L}\\p{Nd}\\-\\ ]*") + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.LIKE) + private String lastName; + + @Pattern(regexp="[\\p{L}\\p{Nd}\\-\\ ]*") + @ReadWrite(ReadWritePolicy.READWRITE) + private String title; + + @Pattern(regexp="[\\p{L}\\p{Nd}\\-\\ \\.\\/\\&]*") + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.LIKE) + private String firma; + + @Pattern(regexp="[\\p{L}\\p{Nd}\\-\\ ]*") + @ReadWrite(ReadWritePolicy.READWRITE) + private String co; + + @Pattern(regexp="[\\p{L}\\p{Nd}\\-\\ \\.\\/]*") + @ReadWrite(ReadWritePolicy.READWRITE) + private String street; + + @Pattern(regexp="\\d+") + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.LIKE) + private String zipCode; + + @Pattern(regexp="[\\p{L}\\p{Nd}\\-\\ \\(\\)\\/]*") + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.LIKE) + private String city; + + @Pattern(regexp="[\\p{L}\\p{Nd}\\-\\ ]*") + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.LIKE) + private String country; + + @Pattern(regexp="[\\+\\d\\-\\ \\(\\)\\/]*") + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.LIKE) + private String phonePrivate; + + @Pattern(regexp="[\\+\\d\\-\\ \\(\\)\\/]*") + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.LIKE) + private String phoneOffice; + + @Pattern(regexp="[\\+\\d\\-\\ \\(\\)\\/]*") + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.LIKE) + private String phoneMobile; + + @Pattern(regexp="[\\+\\d\\-\\ \\(\\)\\/]*") + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.LIKE) + private String fax; + + @Pattern(regexp="[a-zA-Z0-9\\.\\-\\_]*@[a-z0-9äöüß\\.\\-]*") + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.EQUALS) + @Required(true) + private String email; + + @ReadWrite(ReadWritePolicy.READWRITE) + private final StringSet roles; + + public ContactVO() throws TechnicalException { + super(); + roles = new StringSet(); + } + + public String getCustomer() { + return customer; + } + + public void setCustomer(String customer) { + this.customer = customer; + } + + public String getSalut() { + return salut; + } + + public void setSalut(String salut) { + this.salut = salut; + } + + 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 getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getFirma() { + return firma; + } + + public void setFirma(String firma) { + this.firma = firma; + } + + public String getCo() { + return co; + } + + public void setCo(String co) { + this.co = co; + } + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + + public String getZipCode() { + return zipCode; + } + + public void setZipCode(String zipCode) { + this.zipCode = zipCode; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getPhonePrivate() { + return phonePrivate; + } + + public void setPhonePrivate(String phonePrivate) { + this.phonePrivate = phonePrivate; + } + + public String getPhoneOffice() { + return phoneOffice; + } + + public void setPhoneOffice(String phoneOffice) { + this.phoneOffice = phoneOffice; + } + + public String getPhoneMobile() { + return phoneMobile; + } + + public void setPhoneMobile(String phoneMobile) { + this.phoneMobile = phoneMobile; + } + + public String getFax() { + return fax; + } + + public void setFax(String fax) { + this.fax = fax; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String[] getRoles() { + return roles.getStrings(); + } + + public void setRoles(String[] changedRoles) { + roles.setStrings(changedRoles); + } + +} diff --git a/services/src/main/java/de/hsadmin/service/customer/CustomerRemote.java b/services/src/main/java/de/hsadmin/service/customer/CustomerRemote.java new file mode 100644 index 0000000..2bce2ae --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/customer/CustomerRemote.java @@ -0,0 +1,14 @@ +package de.hsadmin.service.customer; + +import de.hsadmin.xmlrpc.AbstractRemote; +import de.hsadmin.xmlrpc.Remote; + + +public class CustomerRemote extends AbstractRemote implements Remote { + + @Override + protected String getModuleLookup() { + return "CustomerServiceLocal"; + } + +} diff --git a/services/src/main/java/de/hsadmin/service/customer/CustomerService.java b/services/src/main/java/de/hsadmin/service/customer/CustomerService.java new file mode 100644 index 0000000..dd33a02 --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/customer/CustomerService.java @@ -0,0 +1,120 @@ +package de.hsadmin.service.customer; + +import java.util.Date; +import java.util.List; +import java.util.Set; + +import javax.ejb.Stateless; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; + +import de.hsadmin.bo.customer.Customer; +import de.hsadmin.bo.pac.Pac; +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserError; +import de.hsadmin.common.error.UserErrorList; +import de.hsadmin.common.error.UserException; +import de.hsadmin.common.util.DateUtil; +import de.hsadmin.login.RequestContext; +import de.hsadmin.login.RequiredScope; +import de.hsadmin.login.Role; +import de.hsadmin.login.ScopePolicy; +import de.hsadmin.module.impl.AbstractModule; +import de.hsadmin.module.util.QueryBuilder; + +@Stateless +public class CustomerService extends AbstractModule implements CustomerServiceLocal { + + @PersistenceContext(name="hsar") + private EntityManager entityManager; + + @Override + public CustomerVO buildVO() throws TechnicalException { + return new CustomerVO(); + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM)}) + public CustomerVO create(final RequestContext requestContext, final CustomerVO prototype) + throws UserException, TechnicalException { + final CustomerVO customerVO = super.create(requestContext, prototype); + final String[] priceLists = customerVO.getPriceLists(); + if (priceLists == null) { + customerVO.setPriceLists(new String[] { "Standard" }); + } + final Customer customerBO = new Customer(); + customerVO.copyPropertiesToPersistentObject(customerBO); + entityManager.persist(customerBO); + final Customer newBO = findCustomerByName(prototype); + final CustomerVO newVO = new CustomerVO(); + newVO.copyPropertiesFromPersistentObject(newBO); + return newVO; + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM), @ScopePolicy(value=Role.CUSTOMER, property="name")}) + public List read(final RequestContext requestContext, final CustomerVO criteria) throws UserException, TechnicalException { + final List emptyList = super.read(requestContext, criteria); + final List list = QueryBuilder.newBuilder(entityManager, Customer.class).getResultList(criteria); + for (Customer c : list) { + final CustomerVO vo = new CustomerVO(); + vo.copyPropertiesFromPersistentObject(c); + emptyList.add(vo); + } + return emptyList; + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM)}) + public List update(final RequestContext requestContext, final CustomerVO criteria, final CustomerVO prototype) + throws UserException, TechnicalException { + final List customersForUpdate = super.update(requestContext, criteria, prototype); + for (CustomerVO vo : customersForUpdate) { + final Customer customer = findCustomerByName(vo); + prototype.copyPropertiesToPersistentObject(customer); + vo.copyPropertiesFromPersistentObject(customer); + } + return customersForUpdate; + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM)}) + public void delete(final RequestContext requestContext, final CustomerVO criteria) + throws UserException, TechnicalException { + super.delete(requestContext, criteria); + final List list = QueryBuilder.newBuilder(entityManager, Customer.class).getResultList(criteria); + for (Customer cust : list) { + checkDeleteConditions(cust); + entityManager.remove(cust); + } + } + + private void checkDeleteConditions(Customer customer) throws UserException { + UserErrorList errors = new UserErrorList(); + Set pacs = customer.getPacs(); + if (!pacs.isEmpty()) { + errors.add(UserError.MSG_CUSTOMER_HAS_PACS, Integer.toString(pacs.size())); + } + Date memberSince = customer.getMemberSince(); + if (memberSince != null) { + Date memberUntil = customer.getMemberUntil(); + if (memberUntil == null) { + errors.add(UserError.MSG_CUSTOMER_IS_MEMBER, customer.getName()); + } else { + Date earliestDeleteDate = DateUtil.getInstance(memberUntil).yearsLater(4); + if (earliestDeleteDate.getTime() > System.currentTimeMillis()) { + errors.add(UserError.MSG_CUSTOMER_DELETE_DEADLINE_NOT_EXPIRED, customer.getName()); + } + } + } + errors.raiseException(); + } + + private Customer findCustomerByName(final CustomerVO prototype) throws UserException, TechnicalException { + final Query query = entityManager.createQuery("SELECT c FROM Customer c WHERE c.name = :name"); + query.setParameter("name", prototype.get("name").getValue()); + return (Customer) query.getSingleResult(); + } + +} diff --git a/services/src/main/java/de/hsadmin/service/customer/CustomerServiceLocal.java b/services/src/main/java/de/hsadmin/service/customer/CustomerServiceLocal.java new file mode 100644 index 0000000..e58f861 --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/customer/CustomerServiceLocal.java @@ -0,0 +1,10 @@ +package de.hsadmin.service.customer; + +import javax.ejb.Local; + +import de.hsadmin.module.Module; + +@Local +public interface CustomerServiceLocal extends Module { + +} diff --git a/services/src/main/java/de/hsadmin/service/customer/CustomerVO.java b/services/src/main/java/de/hsadmin/service/customer/CustomerVO.java new file mode 100644 index 0000000..7f343a6 --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/customer/CustomerVO.java @@ -0,0 +1,216 @@ +package de.hsadmin.service.customer; + +import java.util.Date; +import java.util.List; + +import javax.validation.constraints.Pattern; +import javax.validation.constraints.Size; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.module.impl.AbstractVO; +import de.hsadmin.module.property.Display; +import de.hsadmin.module.property.DisplayPolicy; +import de.hsadmin.module.property.ElementsType; +import de.hsadmin.module.property.ReadWrite; +import de.hsadmin.module.property.ReadWritePolicy; +import de.hsadmin.module.property.Required; +import de.hsadmin.module.property.Search; +import de.hsadmin.module.property.SearchPolicy; +import de.hsadmin.module.property.StringSet; + +public class CustomerVO extends AbstractVO { + + @ReadWrite(ReadWritePolicy.WRITEONCE) + @Required(true) + @Search(SearchPolicy.LIKE) + @Pattern(regexp="hsh00\\-[a-z0-9]{3}") + @Size(min=9,max=9) + private String name; + + @ReadWrite(ReadWritePolicy.WRITEONCE) + @Required(true) + @Search(SearchPolicy.EQUALS) + private Integer memberNo; + + @ReadWrite(ReadWritePolicy.READWRITE) + private String memberRole; + + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.COMPARE) + private Date memberSince; + + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.COMPARE) + private Date memberUntil; + + @ReadWrite(ReadWritePolicy.READWRITE) + private Date authorContract; + + @ReadWrite(ReadWritePolicy.READWRITE) + private Date nonDiscContract; + + @ReadWrite(ReadWritePolicy.READWRITE) + private Date sharesUpdated; + + @ReadWrite(ReadWritePolicy.READWRITE) + private Integer sharesSigned; + + @ReadWrite(ReadWritePolicy.READWRITE) + private Boolean free; + + @ReadWrite(ReadWritePolicy.READWRITE) + private Boolean exemptVAT; + + @ReadWrite(ReadWritePolicy.READWRITE) + private String indicatorVAT; + + @ReadWrite(ReadWritePolicy.READWRITE) + private String uidVAT; + + @ElementsType(ContactVO.class) + @ReadWrite(ReadWritePolicy.READ) + @Display(visible=DisplayPolicy.OPTIONAL) + private List contacts; + + @ElementsType(SEPADirectDebitVO.class) + @ReadWrite(ReadWritePolicy.READ) + @Display(visible=DisplayPolicy.NEVER) + private List sepaDirectDebits; + + @ReadWrite(ReadWritePolicy.READWRITE) + private final StringSet priceLists; + + public CustomerVO() throws TechnicalException { + super(); + priceLists = new StringSet(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getMemberNo() { + return memberNo; + } + + public void setMemberNo(Integer memberNo) { + this.memberNo = memberNo; + } + + public String getMemberRole() { + return memberRole; + } + + public void setMemberRole(String memberRole) { + this.memberRole = memberRole; + } + + public Date getMemberSince() { + return memberSince; + } + + public void setMemberSince(Date memberSince) { + this.memberSince = memberSince; + } + + public Date getMemberUntil() { + return memberUntil; + } + + public void setMemberUntil(Date memberUntil) { + this.memberUntil = memberUntil; + } + + public Date getAuthorContract() { + return authorContract; + } + + public void setAuthorContract(Date authorContract) { + this.authorContract = authorContract; + } + + public Date getNonDiscContract() { + return nonDiscContract; + } + + public void setNonDiscContract(Date nonDiscContract) { + this.nonDiscContract = nonDiscContract; + } + + public Date getSharesUpdated() { + return sharesUpdated; + } + + public void setSharesUpdated(Date sharesUpdated) { + this.sharesUpdated = sharesUpdated; + } + + public Integer getSharesSigned() { + return sharesSigned; + } + + public void setSharesSigned(Integer sharesSigned) { + this.sharesSigned = sharesSigned; + } + + public Boolean getFree() { + return free; + } + + public void setFree(Boolean free) { + this.free = free; + } + + public Boolean getExemptVAT() { + return exemptVAT; + } + + public void setExemptVAT(Boolean exemptVAT) { + this.exemptVAT = exemptVAT; + } + + public String getIndicatorVAT() { + return indicatorVAT; + } + + public void setIndicatorVAT(String indicatorVAT) { + this.indicatorVAT = indicatorVAT; + } + + public String getUidVAT() { + return uidVAT; + } + + public void setUidVAT(String uidVAT) { + this.uidVAT = uidVAT; + } + + public List getContacts() { + return contacts; + } + + public void setContacts(List contacts) { + this.contacts = contacts; + } + + public String[] getPriceLists() { + return priceLists.getStrings(); + } + + public void setPriceLists(String[] priceLists) { + this.priceLists.setStrings(priceLists); + } + + public List getSepaDirectDebits() { + return sepaDirectDebits; + } + + public void setSepaDirectDebits(List sepaDirectDebits) { + this.sepaDirectDebits = sepaDirectDebits; + } + +} diff --git a/services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitRemote.java b/services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitRemote.java new file mode 100644 index 0000000..875733c --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitRemote.java @@ -0,0 +1,14 @@ +package de.hsadmin.service.customer; + +import de.hsadmin.xmlrpc.AbstractRemote; +import de.hsadmin.xmlrpc.Remote; + + +public class SEPADirectDebitRemote extends AbstractRemote implements Remote { + + @Override + protected String getModuleLookup() { + return "SEPADirectDebitServiceLocal"; + } + +} diff --git a/services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitService.java b/services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitService.java new file mode 100644 index 0000000..987635f --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitService.java @@ -0,0 +1,101 @@ +package de.hsadmin.service.customer; + +import java.util.List; + +import javax.ejb.Stateless; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; + +import de.hsadmin.bo.customer.Contact; +import de.hsadmin.bo.customer.Customer; +import de.hsadmin.bo.customer.SEPADirectDebit; +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.login.RequestContext; +import de.hsadmin.login.RequiredScope; +import de.hsadmin.login.Role; +import de.hsadmin.login.ScopePolicy; +import de.hsadmin.module.impl.AbstractModule; +import de.hsadmin.module.util.QueryBuilder; + +@Stateless +public class SEPADirectDebitService extends AbstractModule implements SEPADirectDebitServiceLocal { + + @PersistenceContext(name="hsar") + private EntityManager entityManager; + + @Override + public SEPADirectDebitVO buildVO() throws TechnicalException { + return new SEPADirectDebitVO(); + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM)}) + public SEPADirectDebitVO create(final RequestContext requestContext, final SEPADirectDebitVO prototype) + throws UserException, TechnicalException { + final SEPADirectDebitVO vo = super.create(requestContext, prototype); + final SEPADirectDebit bo = new SEPADirectDebit(); + bo.setCustomer(findCustomerByName(prototype.getCustomer())); + vo.copyPropertiesToPersistentObject(bo); + entityManager.persist(bo); + final SEPADirectDebit newBO = findMandatByValues(vo); + final SEPADirectDebitVO newVO = new SEPADirectDebitVO(); + newVO.copyPropertiesFromPersistentObject(newBO); + return newVO; + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM), @ScopePolicy(value=Role.CUSTOMER, property="customer")}) + public List read(final RequestContext requestContext, final SEPADirectDebitVO criteria) + throws UserException, TechnicalException { + final List emptyList = super.read(requestContext, criteria); + final List list = QueryBuilder.newBuilder(entityManager, SEPADirectDebit.class).getResultList(criteria); + for (SEPADirectDebit c : list) { + final SEPADirectDebitVO vo = new SEPADirectDebitVO(); + vo.copyPropertiesFromPersistentObject(c); + emptyList.add(vo); + } + return emptyList; + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM)}) + public List update(final RequestContext requestContext, final SEPADirectDebitVO criteria, final SEPADirectDebitVO prototype) + throws UserException, TechnicalException { + final List mandantsForUpdate = super.update(requestContext, criteria, prototype); + for (SEPADirectDebitVO vo : mandantsForUpdate) { + final SEPADirectDebit bo = findMandatByValues(vo); + prototype.copyPropertiesToPersistentObject(bo); + vo.copyPropertiesFromPersistentObject(bo); + } + return mandantsForUpdate; + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM)}) + public void delete(final RequestContext requestContext, final SEPADirectDebitVO criteria) + throws UserException, TechnicalException { + super.delete(requestContext, criteria); + final List list = QueryBuilder.newBuilder(entityManager, Contact.class).getResultList(criteria); + for (Contact c : list) { + entityManager.remove(c); + } + } + + private SEPADirectDebit findMandatByValues(final SEPADirectDebitVO prototype) throws UserException, TechnicalException { + final Query query = entityManager.createQuery("SELECT m FROM SEPADirectDebit m WHERE m.bankIBAN = :bankIBAN AND m.bankBIC = :bankBIC AND m.customer.name = :customer AND m.mandatSigned = :mandatSigned"); + query.setParameter("bankIBAN", prototype.get("bankIBAN").getValue()); + query.setParameter("bankBIC", prototype.get("bankBIC").getValue()); + query.setParameter("customer", prototype.get("customer").getValue()); + query.setParameter("mandatSigned", prototype.get("mandatSigned").getValue()); + return (SEPADirectDebit) query.getSingleResult(); + } + + private Customer findCustomerByName(final String customer) throws UserException { + final Query query = entityManager.createQuery("SELECT c FROM Customer c WHERE c.name = :name"); + query.setParameter("name", customer); + return (Customer) query.getSingleResult(); + } + +} diff --git a/services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitServiceLocal.java b/services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitServiceLocal.java new file mode 100644 index 0000000..bc59751 --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitServiceLocal.java @@ -0,0 +1,10 @@ +package de.hsadmin.service.customer; + +import javax.ejb.Local; + +import de.hsadmin.module.Module; + +@Local +public interface SEPADirectDebitServiceLocal extends Module { + +} diff --git a/services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitVO.java b/services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitVO.java new file mode 100644 index 0000000..fccc80d --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/customer/SEPADirectDebitVO.java @@ -0,0 +1,160 @@ +package de.hsadmin.service.customer; + +import java.util.Date; + +import javax.validation.constraints.Pattern; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractVO; +import de.hsadmin.module.property.ReadWrite; +import de.hsadmin.module.property.ReadWritePolicy; +import de.hsadmin.module.property.Required; +import de.hsadmin.module.property.Search; +import de.hsadmin.module.property.SearchPolicy; +import de.hsadmin.module.property.mapping.DefaultStringParameterMapMapper; +import de.hsadmin.module.property.mapping.Mapping; +import de.hsadmin.module.property.mapping.ReferredStringPersistentObjectMapper; + +public class SEPADirectDebitVO extends AbstractVO implements ValueObject { + + @Mapping(boMapping=ReferredStringPersistentObjectMapper.class, + rpcMapping=DefaultStringParameterMapMapper.class, + boMappingPath="customer.name") + @ReadWrite(ReadWritePolicy.WRITEONCE) + @Required(true) + @Search(SearchPolicy.EQUALS) + private String customer; + + @Pattern(regexp="[\\p{L}\\p{Nd}\\-\\ ]*") + @ReadWrite(ReadWritePolicy.READWRITE) + @Required(true) + @Search(SearchPolicy.LIKE) + private String bankCustomer; + + @Pattern(regexp="[\\p{L}\\p{Nd}\\-\\ \\.\\/\\&]*") + @ReadWrite(ReadWritePolicy.READWRITE) + @Required(false) + @Search(SearchPolicy.LIKE) + private String bankName; + + @Pattern(regexp="[A-Z0-9]*") + @ReadWrite(ReadWritePolicy.WRITEONCE) + @Required(true) + @Search(SearchPolicy.LIKE) + private String bankIBAN; + + @Pattern(regexp="[A-Z0-9]*") + @ReadWrite(ReadWritePolicy.WRITEONCE) + @Required(true) + @Search(SearchPolicy.LIKE) + private String bankBIC; + + @ReadWrite(ReadWritePolicy.WRITEONCE) + @Required(true) + @Search(SearchPolicy.LIKE) + private String mandatRef; + + @ReadWrite(ReadWritePolicy.WRITEONCE) + @Required(true) + @Search(SearchPolicy.COMPARE) + private Date mandatSigned; + + @ReadWrite(ReadWritePolicy.WRITEONCE) + @Required(true) + @Search(SearchPolicy.COMPARE) + private Date mandatSince; + + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.COMPARE) + private Date mandatUntil; + + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.COMPARE) + private Date mandatUsed; + + public SEPADirectDebitVO() throws TechnicalException { + super(); + } + + public String getCustomer() { + return customer; + } + + public void setCustomer(String customer) { + this.customer = customer; + } + + public String getBankCustomer() { + return bankCustomer; + } + + public void setBankCustomer(String bankCustomer) { + this.bankCustomer = bankCustomer; + } + + public String getBankName() { + return bankName; + } + + public void setBankName(String bankName) { + this.bankName = bankName; + } + + public String getBankIBAN() { + return bankIBAN; + } + + public void setBankIBAN(String bankIBAN) { + this.bankIBAN = bankIBAN; + } + + public String getBankBIC() { + return bankBIC; + } + + public void setBankBIC(String bankBIC) { + this.bankBIC = bankBIC; + } + + public String getMandatRef() { + return mandatRef; + } + + public void setMandatRef(String mandatRef) { + this.mandatRef = mandatRef; + } + + public Date getMandatSigned() { + return mandatSigned; + } + + public void setMandatSigned(Date mandatSigned) { + this.mandatSigned = mandatSigned; + } + + public Date getMandatSince() { + return mandatSince; + } + + public void setMandatSince(Date mandatSince) { + this.mandatSince = mandatSince; + } + + public Date getMandatUntil() { + return mandatUntil; + } + + public void setMandatUntil(Date mandatUntil) { + this.mandatUntil = mandatUntil; + } + + public Date getMandatUsed() { + return mandatUsed; + } + + public void setMandatUsed(Date mandatUsed) { + this.mandatUsed = mandatUsed; + } + +} diff --git a/services/src/main/java/de/hsadmin/service/pac/HiveRemote.java b/services/src/main/java/de/hsadmin/service/pac/HiveRemote.java new file mode 100644 index 0000000..d2e5d5f --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/pac/HiveRemote.java @@ -0,0 +1,14 @@ +package de.hsadmin.service.pac; + +import de.hsadmin.xmlrpc.AbstractRemote; +import de.hsadmin.xmlrpc.Remote; + + +public class HiveRemote extends AbstractRemote implements Remote { + + @Override + protected String getModuleLookup() { + return "HiveServiceLocal"; + } + +} diff --git a/services/src/main/java/de/hsadmin/service/pac/HiveService.java b/services/src/main/java/de/hsadmin/service/pac/HiveService.java new file mode 100644 index 0000000..a03eb16 --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/pac/HiveService.java @@ -0,0 +1,108 @@ +package de.hsadmin.service.pac; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.List; + +import javax.ejb.Stateless; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; + +import de.hsadmin.bo.pac.Hive; +import de.hsadmin.bo.pac.INetAddress; +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserException; +import de.hsadmin.login.RequestContext; +import de.hsadmin.login.RequiredScope; +import de.hsadmin.login.Role; +import de.hsadmin.login.ScopePolicy; +import de.hsadmin.module.impl.AbstractModule; +import de.hsadmin.module.property.Property; +import de.hsadmin.module.property.StringProperty; +import de.hsadmin.module.util.QueryBuilder; + +@Stateless +public class HiveService extends AbstractModule implements HiveServiceLocal { + + @PersistenceContext(name="hsar") + private EntityManager entityManager; + + @Override + public HiveVO buildVO() throws TechnicalException { + return new HiveVO(); + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM)}) + public HiveVO create(final RequestContext requestContext, final HiveVO prototype) + throws UserException, TechnicalException { + final HiveVO vo = super.create(requestContext, prototype); + final Hive bo = new Hive(); + final Property inetAddressProperty = prototype.get("inetAddress"); + assert inetAddressProperty instanceof StringProperty; + bo.setInetAddr(findInetAddress(((StringProperty) inetAddressProperty).getValue())); + vo.copyPropertiesToPersistentObject(bo); + entityManager.persist(bo); + final Hive newBO = findHiveByName(vo); + final HiveVO newVO = new HiveVO(); + newVO.copyPropertiesFromPersistentObject(newBO); + return newVO; + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM), @ScopePolicy(value=Role.HIVE, property="name")}) + public List read(final RequestContext requestContext, final HiveVO criteria) + throws UserException, TechnicalException { + final List emptyList = super.read(requestContext, criteria); + final List list = QueryBuilder.newBuilder(entityManager, Hive.class).getResultList(criteria); + for (Hive c : list) { + HiveVO vo = new HiveVO(); + vo.copyPropertiesFromPersistentObject(c); + emptyList.add(vo); + } + return emptyList; + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM)}) + public List update(final RequestContext requestContext, final HiveVO criteria, final HiveVO prototype) + throws UserException, TechnicalException { + final List hivesForUpdate = super.update(requestContext, criteria, prototype); + for (HiveVO vo : hivesForUpdate) { + final Hive bo = findHiveByName(vo); + prototype.copyPropertiesToPersistentObject(bo); + vo.copyPropertiesFromPersistentObject(bo); + } + return hivesForUpdate; + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM)}) + public void delete(final RequestContext requestContext, final HiveVO criteria) + throws UserException, TechnicalException { + super.delete(requestContext, criteria); + final List list = QueryBuilder.newBuilder(entityManager, Hive.class).getResultList(criteria); + for (Hive c : list) { + entityManager.remove(c); + } + } + + private Hive findHiveByName(final HiveVO prototype) throws UserException, TechnicalException { + final Query query = entityManager.createQuery("SELECT h FROM Hive h WHERE h.name = :name"); + query.setParameter("name", prototype.get("name").getValue()); + return (Hive) query.getSingleResult(); + } + + private INetAddress findInetAddress(final String inetAddr) throws UserException, TechnicalException { + final String trimmedINetAddress = inetAddr.trim(); + try { + InetAddress.getByName(trimmedINetAddress); + } catch (UnknownHostException e) { + throw new UserException(e); + } + final Query query = entityManager.createNativeQuery("SELECT * FROM inet_addr WHERE inet_addr = inet '" + trimmedINetAddress + "'", INetAddress.class); + return (INetAddress) query.getSingleResult(); + } + +} diff --git a/services/src/main/java/de/hsadmin/service/pac/HiveServiceLocal.java b/services/src/main/java/de/hsadmin/service/pac/HiveServiceLocal.java new file mode 100644 index 0000000..8ecfdb0 --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/pac/HiveServiceLocal.java @@ -0,0 +1,10 @@ +package de.hsadmin.service.pac; + +import javax.ejb.Local; + +import de.hsadmin.module.Module; + +@Local +public interface HiveServiceLocal extends Module{ + +} diff --git a/services/src/main/java/de/hsadmin/service/pac/HiveVO.java b/services/src/main/java/de/hsadmin/service/pac/HiveVO.java new file mode 100644 index 0000000..b707746 --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/pac/HiveVO.java @@ -0,0 +1,61 @@ +package de.hsadmin.service.pac; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractVO; +import de.hsadmin.module.property.ReadWrite; +import de.hsadmin.module.property.ReadWritePolicy; +import de.hsadmin.module.property.Required; +import de.hsadmin.module.property.Search; +import de.hsadmin.module.property.SearchPolicy; +import de.hsadmin.module.property.mapping.DefaultStringParameterMapMapper; +import de.hsadmin.module.property.mapping.Mapping; +import de.hsadmin.module.property.mapping.ReferredStringPersistentObjectMapper; + +public class HiveVO extends AbstractVO implements ValueObject { + + @Required(true) + @ReadWrite(ReadWritePolicy.WRITEONCE) + @Search(SearchPolicy.EQUALS) + private String name; + + @Required(true) + @ReadWrite(ReadWritePolicy.WRITEONCE) + @Mapping( + boMapping=ReferredStringPersistentObjectMapper.class, + rpcMapping=DefaultStringParameterMapMapper.class, + boMappingPath="inetAddr.inetAddr") + private String inetAddress; + + @ReadWrite(ReadWritePolicy.READWRITE) + private String description; + + public HiveVO() throws TechnicalException { + super(); + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getInetAddress() { + return inetAddress; + } + + public void setInetAddress(final String inetAddress) { + this.inetAddress = inetAddress; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } + +} diff --git a/services/src/main/java/de/hsadmin/service/pac/INetAddressVO.java b/services/src/main/java/de/hsadmin/service/pac/INetAddressVO.java new file mode 100644 index 0000000..c034087 --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/pac/INetAddressVO.java @@ -0,0 +1,43 @@ +package de.hsadmin.service.pac; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractVO; +import de.hsadmin.module.property.ReadWrite; +import de.hsadmin.module.property.ReadWritePolicy; +import de.hsadmin.module.property.Required; +import de.hsadmin.module.property.Search; +import de.hsadmin.module.property.SearchPolicy; + +public class INetAddressVO extends AbstractVO implements ValueObject { + + @Required(true) + @ReadWrite(ReadWritePolicy.WRITEONCE) + @Search(SearchPolicy.EQUALS) + private String inetAddr; + + @ReadWrite(ReadWritePolicy.READWRITE) + private String description; + + + public INetAddressVO() throws TechnicalException { + super(); + } + + public String getInetAddr() { + return inetAddr; + } + + public void setInetAddr(final String inetAddr) { + this.inetAddr = inetAddr; + } + + public String getDescription() { + return description; + } + + public void setDescription(final String description) { + this.description = description; + } + +} diff --git a/services/src/main/java/de/hsadmin/service/pac/PacComponentVO.java b/services/src/main/java/de/hsadmin/service/pac/PacComponentVO.java new file mode 100644 index 0000000..c22174a --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/pac/PacComponentVO.java @@ -0,0 +1,44 @@ +package de.hsadmin.service.pac; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractVO; +import de.hsadmin.module.property.ReadWrite; +import de.hsadmin.module.property.ReadWritePolicy; +import de.hsadmin.module.property.mapping.DefaultStringParameterMapMapper; +import de.hsadmin.module.property.mapping.Mapping; +import de.hsadmin.module.property.mapping.ReferredStringPersistentObjectMapper; + +public class PacComponentVO extends AbstractVO implements ValueObject { + + @Mapping( + boMapping=ReferredStringPersistentObjectMapper.class, + rpcMapping=DefaultStringParameterMapMapper.class, + boMappingPath="baseComponent.feature") + @ReadWrite(ReadWritePolicy.READ) + private String feature; + + @ReadWrite(ReadWritePolicy.READWRITE) + private Integer quantity; + + public PacComponentVO() throws TechnicalException { + super(); + } + + public String getFeature() { + return feature; + } + + public void setFeature(final String feature) { + this.feature = feature; + } + + public Integer getQuantity() { + return quantity; + } + + public void setQuantity(final Integer quantity) { + this.quantity = quantity; + } + +} diff --git a/services/src/main/java/de/hsadmin/service/pac/PacRemote.java b/services/src/main/java/de/hsadmin/service/pac/PacRemote.java new file mode 100644 index 0000000..cb082b9 --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/pac/PacRemote.java @@ -0,0 +1,14 @@ +package de.hsadmin.service.pac; + +import de.hsadmin.xmlrpc.AbstractRemote; +import de.hsadmin.xmlrpc.Remote; + + +public class PacRemote extends AbstractRemote implements Remote { + + @Override + protected String getModuleLookup() { + return "PacServiceLocal"; + } + +} diff --git a/services/src/main/java/de/hsadmin/service/pac/PacService.java b/services/src/main/java/de/hsadmin/service/pac/PacService.java new file mode 100644 index 0000000..fa14032 --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/pac/PacService.java @@ -0,0 +1,163 @@ +package de.hsadmin.service.pac; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Date; +import java.util.List; + +import javax.ejb.Stateless; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; + +import de.hsadmin.bo.customer.Customer; +import de.hsadmin.bo.pac.BasePac; +import de.hsadmin.bo.pac.Hive; +import de.hsadmin.bo.pac.INetAddress; +import de.hsadmin.bo.pac.Pac; +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.common.error.UserError; +import de.hsadmin.common.error.UserErrorList; +import de.hsadmin.common.error.UserException; +import de.hsadmin.common.util.DateUtil; +import de.hsadmin.login.RequestContext; +import de.hsadmin.login.RequiredScope; +import de.hsadmin.login.Role; +import de.hsadmin.login.ScopePolicy; +import de.hsadmin.module.impl.AbstractModule; +import de.hsadmin.module.util.QueryBuilder; + +@Stateless +public class PacService extends AbstractModule implements PacServiceLocal { + + @PersistenceContext(name="hsar") + private EntityManager entityManager; + + @Override + public PacVO buildVO() throws TechnicalException { + return new PacVO(); + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM)}) + public PacVO create(final RequestContext requestContext, final PacVO prototype) + throws UserException, TechnicalException { + final PacVO vo = super.create(requestContext, prototype); + final Pac bo = new Pac(); + final String inetAddressProperty = prototype.getInetAddress(); + assert inetAddressProperty != null; + bo.setCurINetAddr(findInetAddress(inetAddressProperty)); + final String hiveProperty = prototype.getHive(); + assert hiveProperty != null; + bo.setHive(findHiveByName(hiveProperty)); + final String basePacProperty = prototype.getBasePac(); + assert basePacProperty != null; + bo.setBasePac(findBasePacByName(basePacProperty)); + final String customerProperty = prototype.getCustomer(); + assert customerProperty != null; + bo.setCustomer(findCustomerByName(customerProperty)); + vo.copyPropertiesToPersistentObject(bo); + if (bo.getCreated() == null) { + bo.setCreated(new Date()); + } + bo.initPacComponents(entityManager, bo.getBasePac(), true); + entityManager.persist(bo); + final Pac newBO = findPacByName(vo.getName()); + final PacVO newVO = new PacVO(); + newVO.copyPropertiesFromPersistentObject(newBO); + return newVO; + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM), @ScopePolicy(value=Role.HIVE, property="name")}) + public List read(final RequestContext requestContext, final PacVO criteria) + throws UserException, TechnicalException { + final List emptyList = super.read(requestContext, criteria); + final List list = QueryBuilder.newBuilder(entityManager, Pac.class).getResultList(criteria); + for (Pac c : list) { + PacVO vo = new PacVO(); + vo.copyPropertiesFromPersistentObject(c); + emptyList.add(vo); + } + return emptyList; + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM)}) + public List update(final RequestContext requestContext, final PacVO criteria, final PacVO prototype) + throws UserException, TechnicalException { + final List pacsForUpdate = super.update(requestContext, criteria, prototype); + for (PacVO vo : pacsForUpdate) { + final Pac bo = findPacByName(vo.getName()); + final String customerName = prototype.getCustomer(); + if (customerName != null && !customerName.isEmpty()) { + Customer customer = findCustomerByName(customerName); + bo.setCustomer(customer); + } + prototype.copyPropertiesToPersistentObject(bo); + vo.copyPropertiesFromPersistentObject(bo); + } + return pacsForUpdate; + } + + @Override + @RequiredScope({@ScopePolicy(Role.SYSTEM)}) + public void delete(final RequestContext requestContext, final PacVO criteria) + throws UserException, TechnicalException { + super.delete(requestContext, criteria); + final List list = QueryBuilder.newBuilder(entityManager, Pac.class).getResultList(criteria); + for (Pac pac : list) { + checkDeleteConditions(pac); + entityManager.remove(pac); + } + } + + private void checkDeleteConditions(Pac pac) throws UserException { + UserErrorList errors = new UserErrorList(); + Date cancelledDate = pac.getCancelled(); + if (cancelledDate == null) { + errors.add(UserError.MSG_PAC_NOT_CANCELLED, pac.getName()); + } else { + if (cancelledDate.getTime() > System.currentTimeMillis()) { + errors.add(UserError.MSG_PAC_CANCEL_DATE_IN_FUTURE, pac.getName(), DateUtil.DEFAULT_DATEFORMAT.format(cancelledDate)); + } + } + errors.raiseException(); + } + + private Hive findHiveByName(final String hiveName) throws UserException { + final Query query = entityManager.createQuery("SELECT h FROM Hive h WHERE h.name = :name"); + query.setParameter("name", hiveName); + return (Hive) query.getSingleResult(); + } + + private Pac findPacByName(final String pacName) throws UserException { + final Query query = entityManager.createQuery("SELECT p FROM Pac p WHERE p.name = :name"); + query.setParameter("name", pacName); + return (Pac) query.getSingleResult(); + } + + private INetAddress findInetAddress(final String inetAddr) throws UserException, TechnicalException { + final String trimmedINetAddress = inetAddr.trim(); + try { + InetAddress.getByName(trimmedINetAddress); + } catch (UnknownHostException e) { + throw new UserException(e); + } + final Query query = entityManager.createNativeQuery("SELECT * FROM inet_addr WHERE inet_addr = inet '" + trimmedINetAddress + "'", INetAddress.class); + return (INetAddress) query.getSingleResult(); + } + + private BasePac findBasePacByName(final String value) { + final Query query = entityManager.createQuery("SELECT p FROM BasePac p WHERE p.name = :name"); + query.setParameter("name", value); + return (BasePac) query.getSingleResult(); + } + + private Customer findCustomerByName(final String value) { + final Query query = entityManager.createQuery("SELECT c FROM Customer c WHERE c.name = :name"); + query.setParameter("name", value); + return (Customer) query.getSingleResult(); + } + +} diff --git a/services/src/main/java/de/hsadmin/service/pac/PacServiceLocal.java b/services/src/main/java/de/hsadmin/service/pac/PacServiceLocal.java new file mode 100644 index 0000000..1f872b2 --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/pac/PacServiceLocal.java @@ -0,0 +1,10 @@ +package de.hsadmin.service.pac; + +import javax.ejb.Local; + +import de.hsadmin.module.Module; + +@Local +public interface PacServiceLocal extends Module{ + +} diff --git a/services/src/main/java/de/hsadmin/service/pac/PacVO.java b/services/src/main/java/de/hsadmin/service/pac/PacVO.java new file mode 100644 index 0000000..ed270b6 --- /dev/null +++ b/services/src/main/java/de/hsadmin/service/pac/PacVO.java @@ -0,0 +1,149 @@ +package de.hsadmin.service.pac; + +import java.util.Date; +import java.util.List; + +import de.hsadmin.common.error.TechnicalException; +import de.hsadmin.module.ValueObject; +import de.hsadmin.module.impl.AbstractVO; +import de.hsadmin.module.property.ElementsType; +import de.hsadmin.module.property.ReadWrite; +import de.hsadmin.module.property.ReadWritePolicy; +import de.hsadmin.module.property.Required; +import de.hsadmin.module.property.Search; +import de.hsadmin.module.property.SearchPolicy; +import de.hsadmin.module.property.mapping.DefaultStringParameterMapMapper; +import de.hsadmin.module.property.mapping.Mapping; +import de.hsadmin.module.property.mapping.ReferredStringPersistentObjectMapper; + +public class PacVO extends AbstractVO implements ValueObject { + + @Required(true) + @ReadWrite(ReadWritePolicy.WRITEONCE) + @Search(SearchPolicy.LIKE) + private String name; + + @Required(true) + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.EQUALS) + @Mapping( + boMapping=ReferredStringPersistentObjectMapper.class, + rpcMapping=DefaultStringParameterMapMapper.class, + boMappingPath="customer.name") + private String customer; + + @Required(true) + @ReadWrite(ReadWritePolicy.READWRITE) + @Search(SearchPolicy.EQUALS) + @Mapping( + boMapping=ReferredStringPersistentObjectMapper.class, + rpcMapping=DefaultStringParameterMapMapper.class, + boMappingPath="basePac.name") + private String basePac; + + @Required(true) + @ReadWrite(ReadWritePolicy.WRITEONCE) + @Search(SearchPolicy.EQUALS) + @Mapping( + boMapping=ReferredStringPersistentObjectMapper.class, + rpcMapping=DefaultStringParameterMapMapper.class, + boMappingPath="hive.name") + private String hive; + + @ReadWrite(ReadWritePolicy.READWRITE) + private Date created; + + @ReadWrite(ReadWritePolicy.READWRITE) + private Date cancelled; + + @ReadWrite(ReadWritePolicy.READWRITE) + private Boolean free; + + @Required(true) + @ReadWrite(ReadWritePolicy.WRITEONCE) + @Mapping( + boMapping=ReferredStringPersistentObjectMapper.class, + rpcMapping=DefaultStringParameterMapMapper.class, + boMappingPath="curINetAddr.inetAddr") + private String inetAddress; + + @ReadWrite(ReadWritePolicy.READWRITE) + @ElementsType(PacComponentVO.class) + private List pacComponents; + + public PacVO() throws TechnicalException { + super(); + } + + public String getName() { + return name; + } + + public void setName(final String name) { + this.name = name; + } + + public String getCustomer() { + return customer; + } + + public void setCustomer(final String customer) { + this.customer = customer; + } + + public String getBasePac() { + return basePac; + } + + public void setBasePac(final String basePac) { + this.basePac = basePac; + } + + public String getHive() { + return hive; + } + + public void setHive(final String hive) { + this.hive = hive; + } + + public Date getCreated() { + return created; + } + + public void setCreated(final Date created) { + this.created = created; + } + + public Date getCancelled() { + return cancelled; + } + + public void setCancelled(final Date cancelled) { + this.cancelled = cancelled; + } + + public Boolean getFree() { + return free; + } + + public void setFree(final Boolean free) { + this.free = free; + } + + public String getInetAddress() { + return inetAddress; + } + + public void setInetAddress(final String inetAddress) { + this.inetAddress = inetAddress; + } + + public List getPacComponents() { + return pacComponents; + } + + public void setPacComponents(List pacComponents) { + this.pacComponents = pacComponents; + } +} diff --git a/web/.gitignore b/web/.gitignore new file mode 100644 index 0000000..e774414 --- /dev/null +++ b/web/.gitignore @@ -0,0 +1,13 @@ +*.class + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +/target +/.settings +/.classpath +/.project diff --git a/web/LICENSE.txt b/web/LICENSE.txt new file mode 100644 index 0000000..dba13ed --- /dev/null +++ b/web/LICENSE.txt @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/web/pom.xml b/web/pom.xml new file mode 100644 index 0000000..ca5ff23 --- /dev/null +++ b/web/pom.xml @@ -0,0 +1,96 @@ + + + 4.0.0 + net.hostsharing + hs.hsadmin.web + war + 0.0.1-SNAPSHOT + hs.hsadmin.web + + + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + + org.apache.xmlrpc + xmlrpc-client + 3.1.3 + + + + com.vaadin + vaadin-server + 7.6.4 + + + + com.vaadin + vaadin-themes + 7.6.4 + + + + com.vaadin + vaadin-client-compiled + 7.6.4 + + + + net.kencochrane.raven + raven-log4j + 6.0.0 + + + + log4j + log4j + 1.2.17 + + + + org.slf4j + slf4j-log4j12 + 1.7.7 + + + + junit + junit + 4.12 + test + + + + + + + + + maven-compiler-plugin + 3.3 + + 1.7 + 1.7 + + + + + org.apache.tomcat.maven + tomcat7-maven-plugin + 2.2 + + / + + + + + admin + + + diff --git a/web/src/main/java/de/hsadmin/model/IMenuOption.java b/web/src/main/java/de/hsadmin/model/IMenuOption.java new file mode 100644 index 0000000..85f3ce2 --- /dev/null +++ b/web/src/main/java/de/hsadmin/model/IMenuOption.java @@ -0,0 +1,23 @@ +package de.hsadmin.model; + +/** + * This Interface has the names of the available options + * in hostsharing + * @author druiz + */ +public interface IMenuOption { + + public static final String UNIX_USERS = "user"; + public static final String EMAIL_ADDRESSES = "emailaddress"; + public static final String EMAIL_ALIASES = "emailalias"; + public static final String MYSQL_DB = "mysqldb"; + public static final String MYSQL_USER = "mysqluser"; + public static final String POSTGRES_DB = "postgresqldb"; + public static final String POSTGRES_USER = "postgresqluser"; + public static final String QUEUED_TASKS = "q"; + public static final String DOMAINS = "domain"; + public static final String PACKAGE = "pac"; + public static final String MANAGED_SERVERS = "hive"; + public static final String CUSTOMER = "customer"; + +} diff --git a/web/src/main/java/de/hsadmin/model/IRemote.java b/web/src/main/java/de/hsadmin/model/IRemote.java new file mode 100644 index 0000000..c3617ff --- /dev/null +++ b/web/src/main/java/de/hsadmin/model/IRemote.java @@ -0,0 +1,36 @@ +package de.hsadmin.model; + +import java.util.List; +import java.util.Map; + +import org.apache.xmlrpc.XmlRpcException; + + +public interface IRemote { + + public abstract List> search( + String runAsUser, + String ticket, + Map whereParams + ) throws XmlRpcException; + + public abstract Map add( + String runAsUser, + String ticket, + Map setParams + ) throws XmlRpcException; + + public abstract void delete( + String runAsUser, + String ticket, + Map whereParams + ) throws XmlRpcException; + + public abstract List> update( + String runAsUser, + String ticket, + Map setParams, + Map whereParams + ) throws XmlRpcException; + +} diff --git a/web/src/main/java/de/hsadmin/model/TicketService.java b/web/src/main/java/de/hsadmin/model/TicketService.java new file mode 100644 index 0000000..34efd97 --- /dev/null +++ b/web/src/main/java/de/hsadmin/model/TicketService.java @@ -0,0 +1,86 @@ +package de.hsadmin.model; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Serializable; +import java.net.URL; +import java.net.URLEncoder; + +import javax.net.ssl.HttpsURLConnection; + +import de.hsadmin.rpc.RpcException; + +/** + * Helper for service tickets. + * Hostsharing uses the CAS authentication service to authenticate + * users of hostsharing services. This class is used to create a + * "ticket granting ticket" for a session and service ticket for + * individual service calls. + */ +public class TicketService implements Serializable { + + public static final String SERVICE_URL = "https://config.hostsharing.net:443/hsar/backend"; + public static final String CAS_URL = "https://login.hostsharing.net/cas/v1/tickets"; + + private static final long serialVersionUID = 1L; + + public String getGrantingTicket(final String user, final String password) throws RpcException { + String ticket = null; + try { + String userParam = "username=" + URLEncoder.encode(user, "UTF-8"); + String passwordParam = "password=" + URLEncoder.encode(password, "UTF-8"); + String encodedData = userParam + "&" + passwordParam; + URL url = new URL(CAS_URL); + + final HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded; charset=UTF-8"); + connection.setDoInput(true); + connection.setDoOutput(true); + connection.setUseCaches(false); + connection.setAllowUserInteraction(false); + final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream())); + writer.write(encodedData); + writer.close(); + connection.connect(); + ticket = connection.getHeaderField("Location"); + } catch (Exception e) { + throw new RpcException(e); + } + + return ticket; + } + + public String getServiceTicket(String grantingTicket) throws RpcException { + String ticket = null; + try { + String serviceParam = "service=" + URLEncoder.encode(SERVICE_URL, "UTF-8"); + URL url = new URL(grantingTicket); + + final HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded; charset=UTF-8"); + connection.setDoInput(true); + connection.setDoOutput(true); + connection.setUseCaches(false); + connection.setAllowUserInteraction(false); + final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream())); + writer.write(serviceParam); + writer.close(); + connection.connect(); + final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + ticket = reader.readLine(); + String readLine = reader.readLine(); + do { + readLine = reader.readLine(); + } while (readLine != null); + } catch (Exception e) { + throw new RpcException(e); + } + + return ticket; + } + +} diff --git a/web/src/main/java/de/hsadmin/rpc/HSAdminSession.java b/web/src/main/java/de/hsadmin/rpc/HSAdminSession.java new file mode 100644 index 0000000..03e9f5a --- /dev/null +++ b/web/src/main/java/de/hsadmin/rpc/HSAdminSession.java @@ -0,0 +1,15 @@ +package de.hsadmin.rpc; + +import de.hsadmin.model.TicketService; + +public interface HSAdminSession { + + public String getGrantingTicket(); + + public TicketService getTicketService(); + + public ModulesManager getModulesManager(); + + public String getUser(); + +} diff --git a/web/src/main/java/de/hsadmin/rpc/ModuleInfo.java b/web/src/main/java/de/hsadmin/rpc/ModuleInfo.java new file mode 100644 index 0000000..7226813 --- /dev/null +++ b/web/src/main/java/de/hsadmin/rpc/ModuleInfo.java @@ -0,0 +1,49 @@ +package de.hsadmin.rpc; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +public class ModuleInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + final private String name; + final private Map propertiesByName; + final private SortedMap propertiesBySequence; + + public ModuleInfo(final String name) { + this.name = name; + this.propertiesByName = new HashMap(); + this.propertiesBySequence = new TreeMap(); + } + + public String getName() { + return name; + } + + public boolean hasProperty(final String name) { + return propertiesByName.containsKey(name); + } + + public PropertyInfo propertyInfo(final String name) { + return propertiesByName.get(name); + } + + public Iterator properties() { + return propertiesBySequence.values().iterator(); + } + + void add(final PropertyInfo propInfo) { + propertiesByName.put(propInfo.getName(), propInfo); + int displaySequence = propInfo.getDisplaySequence(); + while (propertiesBySequence.containsKey(displaySequence)) { + displaySequence++; + } + propertiesBySequence.put(displaySequence, propInfo); + } + +} diff --git a/web/src/main/java/de/hsadmin/rpc/ModulesManager.java b/web/src/main/java/de/hsadmin/rpc/ModulesManager.java new file mode 100644 index 0000000..3015ce7 --- /dev/null +++ b/web/src/main/java/de/hsadmin/rpc/ModulesManager.java @@ -0,0 +1,143 @@ +package de.hsadmin.rpc; + +import java.io.Serializable; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.client.XmlRpcClient; +import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; + +import de.hsadmin.model.IRemote; + + +public class ModulesManager implements Serializable { + + private static final long serialVersionUID = 1L; + + private static final Logger LOG = Logger.getLogger(ModulesManager.class); + + private final Map modulesRepository; + private final Map serviceRepository; + + public ModulesManager() { + modulesRepository = new HashMap(); + serviceRepository = new HashMap(); + } + + public boolean hasModule(final String name) { + return modulesRepository.containsKey(name); + } + + void add(final ModuleInfo module, final URL serverURL) { + modulesRepository.put(module.getName(), module); + serviceRepository.put(module.getName(), serverURL); + } + + public ModuleInfo module(String moduleName) { + return modulesRepository.get(moduleName); + } + + public String[] entryPointColumns(String moduleName) { + if (hasModule(moduleName) && "customer".equals(moduleName)) { + return new String[] { "name", "memberNo" }; + } + if (hasModule(moduleName) && "hive".equals(moduleName)) { + return new String[] { "name", "description" }; + } + if (hasModule(moduleName) && "domain".equals(moduleName)) { + return new String[] { "name", "user" }; + } + if (hasModule(moduleName) && "pac".equals(moduleName)) { + return new String[] { "name", "customer" }; + } + return new String[] { "name" }; + } + + public IRemote proxy(final String moduleName) { + return new IRemote() { + + @SuppressWarnings("unchecked") + @Override + public List> search(final String runAsUser, final String ticket, final Map whereParams) throws XmlRpcException + { + LOG.info("RPC Call: " + moduleName + ".search - user " + runAsUser); + final XmlRpcClient rpcClient = rpcClient(moduleName); + final List xmlRpcParamsList = new ArrayList(); + xmlRpcParamsList.add(runAsUser); + xmlRpcParamsList.add(ticket); + xmlRpcParamsList.add(whereParams); + final Object[] rpcResult = (Object[]) rpcClient.execute(moduleName + ".search", xmlRpcParamsList); + final List> resultList = new ArrayList>(); + for (final Object obj : rpcResult) { + if (obj instanceof Map) { + resultList.add((Map) obj); + } + } + return resultList; + } + + @SuppressWarnings("unchecked") + @Override + public Map add(final String runAsUser, final String ticket, final Map setParams) throws XmlRpcException + { + LOG.info("RPC Call: " + moduleName + ".add - user " + runAsUser); + final XmlRpcClient rpcClient = rpcClient(moduleName); + final List xmlRpcParamsList = new ArrayList(); + xmlRpcParamsList.add(runAsUser); + xmlRpcParamsList.add(ticket); + xmlRpcParamsList.add(setParams); + return (Map) rpcClient.execute(moduleName + ".add", xmlRpcParamsList); + } + + @SuppressWarnings("unchecked") + @Override + public List> update(final String runAsUser, final String ticket, final Map setParams, final Map whereParams) + throws XmlRpcException + { + LOG.info("RPC Call: " + moduleName + ".update - user " + runAsUser); + final XmlRpcClient rpcClient = rpcClient(moduleName); + final List xmlRpcParamsList = new ArrayList(); + xmlRpcParamsList.add(runAsUser); + xmlRpcParamsList.add(ticket); + xmlRpcParamsList.add(setParams); + xmlRpcParamsList.add(whereParams); + final Object[] rpcResult = (Object[]) rpcClient.execute(moduleName + ".update", xmlRpcParamsList); + final List> resultList = new ArrayList>(); + for (final Object obj : rpcResult) { + if (obj instanceof Map) { + resultList.add((Map) obj); + } + } + return resultList; + } + + @Override + public void delete(final String runAsUser, final String ticket, final Map whereParams) throws XmlRpcException + { + LOG.info("RPC Call: " + moduleName + ".delete - user " + runAsUser); + final XmlRpcClient rpcClient = rpcClient(moduleName); + final List xmlRpcParamsList = new ArrayList(); + xmlRpcParamsList.add(runAsUser); + xmlRpcParamsList.add(ticket); + xmlRpcParamsList.add(whereParams); + rpcClient.execute(moduleName + ".delete", xmlRpcParamsList); + } + + private XmlRpcClient rpcClient(final String moduleName) + { + final XmlRpcClient rpcClient = new XmlRpcClient(); + final XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl(); + config.setServerURL(serviceRepository.get(moduleName)); + config.setEnabledForExtensions(true); + rpcClient.setConfig(config); + return rpcClient; + } + }; + } + +} diff --git a/web/src/main/java/de/hsadmin/rpc/ModulesManagerFactory.java b/web/src/main/java/de/hsadmin/rpc/ModulesManagerFactory.java new file mode 100644 index 0000000..ed79a8b --- /dev/null +++ b/web/src/main/java/de/hsadmin/rpc/ModulesManagerFactory.java @@ -0,0 +1,72 @@ +package de.hsadmin.rpc; + +import java.io.Serializable; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.client.XmlRpcClient; +import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; + +import de.hsadmin.model.TicketService; + +public class ModulesManagerFactory { + + private final String ticketGrantingTicket; + private final String runAsUser; + + public ModulesManagerFactory(final String ticketGrantingTicket, final String runAsUser) { + this.ticketGrantingTicket = ticketGrantingTicket; + this.runAsUser = runAsUser; + } + + public ModulesManager newModulesManager(final String... serverURLs) throws RpcException { + final ModulesManager moduleManager = new ModulesManager(); + final TicketService ticketService = new TicketService(); + try { + for (final String servername : serverURLs) + { + final XmlRpcClient rpcClient = new XmlRpcClient(); + final XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl(); + final URL serverURL = new URL(servername); + config.setServerURL(serverURL); + config.setEnabledForExtensions(true); + rpcClient.setConfig(config); + final List xmlRpcParamsList = new ArrayList(); + xmlRpcParamsList.add(runAsUser); + xmlRpcParamsList.add(ticketService.getServiceTicket(ticketGrantingTicket)); + final HashMap whereParamsMap = new HashMap(); + xmlRpcParamsList.add(whereParamsMap); + final Object[] rpcResult = (Object[]) rpcClient.execute("property.search", xmlRpcParamsList); + for (final Object resObject : rpcResult) { + @SuppressWarnings("unchecked") + final Map propertyData = (Map) resObject; + final String moduleName = (String) propertyData.get("module"); + if (!moduleManager.hasModule(moduleName)) { + moduleManager.add(new ModuleInfo(moduleName), serverURL); + } + final PropertyInfo propInfo = new PropertyInfo(); + propInfo.setDisplaySequence(Integer.parseInt((String) propertyData.get("displaySequence"))); + propInfo.setDisplayVisible((String) propertyData.get("displayVisible")); + propInfo.setMaxLength(Integer.parseInt((String) propertyData.get("maxLength"))); + propInfo.setMinLength(Integer.parseInt((String) propertyData.get("minLength"))); + propInfo.setModule(moduleName); + propInfo.setName((String) propertyData.get("name")); + propInfo.setReadwriteable((String) propertyData.get("readwriteable")); + propInfo.setSearchable((String) propertyData.get("searchable")); + propInfo.setType((String) propertyData.get("type")); + propInfo.setValidationRegexp((String) propertyData.get("validationRegexp")); + moduleManager.module(moduleName).add(propInfo); + } + } + } catch (MalformedURLException | XmlRpcException e) { + throw new RpcException(e); + } + return moduleManager; + } + +} diff --git a/web/src/main/java/de/hsadmin/rpc/PropertyInfo.java b/web/src/main/java/de/hsadmin/rpc/PropertyInfo.java new file mode 100644 index 0000000..80ad89a --- /dev/null +++ b/web/src/main/java/de/hsadmin/rpc/PropertyInfo.java @@ -0,0 +1,108 @@ +package de.hsadmin.rpc; + +import java.io.Serializable; + +import de.hsadmin.rpc.enums.DisplayPolicy; +import de.hsadmin.rpc.enums.ReadWritePolicy; +import de.hsadmin.rpc.enums.SearchPolicy; + +public class PropertyInfo implements Serializable { + + private static final long serialVersionUID = 1L; + + private String module; + private String name; + private String type; + private int minLength; + private int maxLength; + private String validationRegexp; + private int displaySequence; + private DisplayPolicy displayVisible; + private ReadWritePolicy readwriteable; + private SearchPolicy searchable; + + public String getModule() { + return module; + } + + void setModule(String module) { + this.module = module; + } + + public String getName() { + return name; + } + + void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + void setType(String type) { + this.type = type; + } + + public int getMinLength() { + return minLength; + } + + void setMinLength(int minLength) { + this.minLength = minLength; + } + + public int getMaxLength() { + return maxLength; + } + + void setMaxLength(int maxLength) { + this.maxLength = maxLength; + } + + public String getValidationRegexp() { + return validationRegexp; + } + + void setValidationRegexp(String validationRegexp) { + this.validationRegexp = validationRegexp; + } + + public int getDisplaySequence() { + return displaySequence; + } + + void setDisplaySequence(int displaySequence) { + this.displaySequence = displaySequence; + } + + public DisplayPolicy getDisplayVisible() { + return displayVisible; + } + + void setDisplayVisible(final String displayVisible) { + this.displayVisible = DisplayPolicy.valueOf(displayVisible.toUpperCase()); + } + + public ReadWritePolicy getReadwriteable() { + return readwriteable; + } + + void setReadwriteable(final String readwriteable) { + this.readwriteable = ReadWritePolicy.valueOf(readwriteable.toUpperCase()); + } + + public SearchPolicy getSearchable() { + return searchable; + } + + void setSearchable(final String searchable) { + this.searchable = SearchPolicy.valueOf(searchable.toUpperCase()); + } + + @Override + public String toString() { + return "PropertyInfo " + module + "." + name; + } +} diff --git a/web/src/main/java/de/hsadmin/rpc/RpcException.java b/web/src/main/java/de/hsadmin/rpc/RpcException.java new file mode 100644 index 0000000..a807f6b --- /dev/null +++ b/web/src/main/java/de/hsadmin/rpc/RpcException.java @@ -0,0 +1,15 @@ +package de.hsadmin.rpc; + + +public class RpcException extends Exception { + + private static final long serialVersionUID = 1L; + + public RpcException(final Exception e) { + super(e); + } + + public RpcException(final String message) { + super(message); + } +} diff --git a/web/src/main/java/de/hsadmin/rpc/enums/DisplayPolicy.java b/web/src/main/java/de/hsadmin/rpc/enums/DisplayPolicy.java new file mode 100644 index 0000000..0f5cfb7 --- /dev/null +++ b/web/src/main/java/de/hsadmin/rpc/enums/DisplayPolicy.java @@ -0,0 +1,7 @@ +package de.hsadmin.rpc.enums; + +public enum DisplayPolicy { + + ALWAYS, OPTIONAL, NEVER + +} diff --git a/web/src/main/java/de/hsadmin/rpc/enums/ReadWritePolicy.java b/web/src/main/java/de/hsadmin/rpc/enums/ReadWritePolicy.java new file mode 100644 index 0000000..bfca20e --- /dev/null +++ b/web/src/main/java/de/hsadmin/rpc/enums/ReadWritePolicy.java @@ -0,0 +1,5 @@ +package de.hsadmin.rpc.enums; + +public enum ReadWritePolicy { + READ, READWRITE, WRITEONCE, NONE +} diff --git a/web/src/main/java/de/hsadmin/rpc/enums/SearchPolicy.java b/web/src/main/java/de/hsadmin/rpc/enums/SearchPolicy.java new file mode 100644 index 0000000..1c51edb --- /dev/null +++ b/web/src/main/java/de/hsadmin/rpc/enums/SearchPolicy.java @@ -0,0 +1,5 @@ +package de.hsadmin.rpc.enums; + +public enum SearchPolicy { + EQUALS, LIKE, COMPARE, NONE +} diff --git a/web/src/main/java/de/hsadmin/web/AbstractEntryPointsFactory.java b/web/src/main/java/de/hsadmin/web/AbstractEntryPointsFactory.java new file mode 100644 index 0000000..190bda9 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/AbstractEntryPointsFactory.java @@ -0,0 +1,7 @@ +package de.hsadmin.web; + +public abstract class AbstractEntryPointsFactory { + + public abstract String[] getEntryPointNames(String role); + +} diff --git a/web/src/main/java/de/hsadmin/web/AbstractPanelFactory.java b/web/src/main/java/de/hsadmin/web/AbstractPanelFactory.java new file mode 100644 index 0000000..789c170 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/AbstractPanelFactory.java @@ -0,0 +1,10 @@ +package de.hsadmin.web; + +import de.hsadmin.rpc.HSAdminSession; +import de.hsadmin.rpc.RpcException; + +public abstract class AbstractPanelFactory { + + public abstract IHSPanel getPanel(String panelType, HSAdminSession mainWindow, Object itemId) throws RpcException; + +} diff --git a/web/src/main/java/de/hsadmin/web/AbstractWindowFactory.java b/web/src/main/java/de/hsadmin/web/AbstractWindowFactory.java new file mode 100644 index 0000000..0d11628 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/AbstractWindowFactory.java @@ -0,0 +1,11 @@ +package de.hsadmin.web; + +import com.vaadin.ui.Window; + +import de.hsadmin.rpc.HSAdminSession; + +public abstract class AbstractWindowFactory { + + public abstract Window getSubWindow(HSTab parent, String type, String action, HSAdminSession session); + +} diff --git a/web/src/main/java/de/hsadmin/web/CustomerPanel.java b/web/src/main/java/de/hsadmin/web/CustomerPanel.java new file mode 100644 index 0000000..bcae029 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/CustomerPanel.java @@ -0,0 +1,55 @@ +package de.hsadmin.web; + +import com.vaadin.ui.Component; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.Panel; +import com.vaadin.ui.TabSheet; +import com.vaadin.ui.TabSheet.SelectedTabChangeEvent; +import com.vaadin.ui.TabSheet.SelectedTabChangeListener; + +import de.hsadmin.rpc.HSAdminSession; +import de.hsadmin.rpc.RpcException; + +public class CustomerPanel extends CustomComponent implements IHSPanel, SelectedTabChangeListener { + + private static final long serialVersionUID = 1L; + + private final HSAdminSession session; + + public CustomerPanel(HSAdminSession session, Object itemId) throws RpcException { + this.session = session; + final Panel panel = new Panel(); + panel.setSizeFull(); + final TabSheet tabsheet = createTabs(itemId); + tabsheet.setSizeFull(); + panel.setContent(tabsheet); + setCompositionRoot(panel); + } + + @Override + public TabSheet createTabs(Object itemId) throws RpcException + { + final TabSheet tabsheet = new TabSheet(); + tabsheet.setSizeFull(); + tabsheet.addSelectedTabChangeListener(this); + tabsheet.addSelectedTabChangeListener(this); + tabsheet.addTab(new GenericForm("customer", session, itemId, "name"), I18N.getText("customer")); + final HSTab usersTab = new HSTab("contact", session, "customer", itemId, "email"); + usersTab.fillTable(); + tabsheet.addTab(usersTab, I18N.getText("contact")); + HSTab aliasTab = new HSTab("mandat", session, "customer", itemId, "mandatRef"); + tabsheet.addTab(aliasTab, I18N.getText("mandat")); + HSTab pacTab = new HSTab("pac", session, "customer", itemId, "name"); + tabsheet.addTab(pacTab, I18N.getText("pac")); + return tabsheet; + } + + @Override + public void selectedTabChange(SelectedTabChangeEvent event) { + final Component tab = event.getTabSheet().getSelectedTab(); + if (tab instanceof HSTab) { + ((HSTab) tab).fillTable(); + } + } + +} diff --git a/web/src/main/java/de/hsadmin/web/DomainOptionsEditor.java b/web/src/main/java/de/hsadmin/web/DomainOptionsEditor.java new file mode 100644 index 0000000..a422a4a --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/DomainOptionsEditor.java @@ -0,0 +1,78 @@ +package de.hsadmin.web; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.vaadin.data.Validator; +import com.vaadin.ui.CheckBox; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.VerticalLayout; + +import de.hsadmin.rpc.HSAdminSession; +import de.hsadmin.rpc.PropertyInfo; + +public class DomainOptionsEditor extends CustomComponent implements IHSEditor { + + private static final long serialVersionUID = 1L; + + private static final String[] OPTIONS = new String[] { "greylisting", "multiviews", "indexes", "htdocsfallback", "includes", "backupmxforexternalmx" }; + + private final PropertyInfo propertyInfo; + private final VerticalLayout layout; + private final Map checkboxes; + + public DomainOptionsEditor(final PropertyInfo propertyInfo, final HSAdminSession session, final Map whereContext) { + this.checkboxes = new HashMap<>(); + this.propertyInfo = propertyInfo; + this.setCaption(I18N.getText(propertyInfo.getName())); + layout = new VerticalLayout(); + for (String opt : OPTIONS) { + final CheckBox checkBox = new CheckBox(I18N.getText("domainoption." + opt)); + checkboxes.put(opt, checkBox); + layout.addComponent(checkBox); + } + layout.setCaption(I18N.getText(propertyInfo.getName())); + setCompositionRoot(layout); + } + + @Override + public void setValues(final Map valuesMap) { + final Object optionsObject = valuesMap.get(propertyInfo.getName()); + if (optionsObject == null) { + for (String opt : OPTIONS) { + checkboxes.get(opt).setValue(!"backupmxforexternalmx".equals(opt)); + } + } + if (optionsObject instanceof Object[]) { + final List options = Arrays.asList((Object[]) optionsObject); + for (String opt : OPTIONS) { + checkboxes.get(opt).setValue(options.contains(opt)); + } + } + } + + @Override + public Object getValue() { + final List values = new ArrayList<>(); + for (final String opt : OPTIONS) { + if (checkboxes.get(opt).getValue()) { + values.add(opt); + } + } + return values.toArray(); + } + + @Override + public void addValidator(Validator validator) { + + } + + @Override + public boolean isValid() { + return true; + } + +} diff --git a/web/src/main/java/de/hsadmin/web/DomainPanel.java b/web/src/main/java/de/hsadmin/web/DomainPanel.java new file mode 100644 index 0000000..c352dab --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/DomainPanel.java @@ -0,0 +1,48 @@ +package de.hsadmin.web; + +import com.vaadin.ui.Component; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.Panel; +import com.vaadin.ui.TabSheet; +import com.vaadin.ui.TabSheet.SelectedTabChangeEvent; +import com.vaadin.ui.TabSheet.SelectedTabChangeListener; + +import de.hsadmin.rpc.HSAdminSession; +import de.hsadmin.rpc.RpcException; + +public class DomainPanel extends CustomComponent implements IHSPanel, SelectedTabChangeListener { + + private static final long serialVersionUID = 1L; + + private final HSAdminSession session; + + public DomainPanel(HSAdminSession session, Object itemId) throws RpcException { + this.session = session; + final Panel panel = new Panel(); + panel.setSizeFull(); + final TabSheet tabsheet = createTabs(itemId); + tabsheet.setSizeFull(); + panel.setContent(tabsheet); + setCompositionRoot(panel); + } + + @Override + public TabSheet createTabs(Object itemId) throws RpcException + { + final TabSheet tabsheet = new TabSheet(); + tabsheet.addTab(new GenericForm("domain", session, itemId, "name"), I18N.getText("domain")); + HSTab emailTab = new HSTab("emailaddress", session, "domain", itemId, "id"); + emailTab.fillTable(); + tabsheet.addTab(emailTab, I18N.getText("emailaddress")); + return tabsheet; + } + + @Override + public void selectedTabChange(SelectedTabChangeEvent event) { + Component tab = event.getTabSheet().getSelectedTab(); + if (tab instanceof HSTab) { + ((HSTab) tab).fillTable(); + } + } + +} \ No newline at end of file diff --git a/web/src/main/java/de/hsadmin/web/EMailTargetEditor.java b/web/src/main/java/de/hsadmin/web/EMailTargetEditor.java new file mode 100644 index 0000000..ee73347 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/EMailTargetEditor.java @@ -0,0 +1,285 @@ +package de.hsadmin.web; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.xmlrpc.XmlRpcException; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.data.Validator; +import com.vaadin.data.Validator.InvalidValueException; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.AbstractOrderedLayout; +import com.vaadin.ui.Alignment; +import com.vaadin.ui.Component; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.NativeSelect; +import com.vaadin.ui.TextField; +import com.vaadin.ui.VerticalLayout; + +import de.hsadmin.model.IRemote; +import de.hsadmin.model.TicketService; +import de.hsadmin.rpc.HSAdminSession; +import de.hsadmin.rpc.ModulesManager; +import de.hsadmin.rpc.PropertyInfo; +import de.hsadmin.rpc.RpcException; + +public class EMailTargetEditor extends CustomComponent implements IHSEditor, ValueChangeListener { + + private static final long serialVersionUID = 1L; + + private final boolean isEditAble; + private final PropertyInfo propertyInfo; + private final List validators; + private final AbstractOrderedLayout layout; + private final List aliases; + private final List postboxes; + + + public EMailTargetEditor(final String action, final PropertyInfo propertyInfo, final HSAdminSession session, final Map whereContext) { + this.isEditAble = PanelToolbar.ACTION_EDIT.equals(action) || PanelToolbar.ACTION_NEW.equals(action); + this.propertyInfo = propertyInfo; + this.validators = new ArrayList<>(); + this.setCaption(I18N.getText(propertyInfo.getName())); + this.aliases = targetsSelect("emailalias", session, whereContext); + this.postboxes = targetsSelect("user", session, whereContext); + postboxes.removeAll(aliases); + layout = new VerticalLayout(); + layout.setCaption(I18N.getText(propertyInfo.getName())); + setCompositionRoot(layout); + } + + @Override + public void setValues(Map valuesMap) { + final Object targetValues = valuesMap.get(propertyInfo.getName()); + if (targetValues instanceof Object[]) { + final Object[] targetsArray = (Object[]) targetValues; + layout.removeAllComponents(); + for (final Object singleTarget : targetsArray) { + final String target = singleTarget.toString(); + layout.addComponent(new TargetRow(this, target)); + } + } + assertLastTargetRowIsEmpty(); + } + + public void assertLastTargetRowIsEmpty() { + final int rowsCount = layout.getComponentCount(); + if (isEditAble) { + if (rowsCount > 0) { + final Component component = layout.getComponent(rowsCount - 1); + if (! ((TargetRow) component).valueIsEmpty()) { + layout.addComponent(new TargetRow(this)); + } + } else { + layout.addComponent(new TargetRow(this)); + } + } + } + + @Override + public Object getValue() { + final int numberOfChildren = layout.getComponentCount(); + final List targetsList = new ArrayList<>(); + for (int idx = 0; idx < numberOfChildren; idx++) { + final Component child = layout.getComponent(idx); + if (child instanceof AbstractOrderedLayout) { + final Component grandChild = ((AbstractOrderedLayout) child).getComponent(1); + if (grandChild instanceof TextField) { + targetsList.add(((TextField) grandChild).getValue()); + } + if (grandChild instanceof NativeSelect) { + targetsList.add(((NativeSelect) grandChild).getValue().toString()); + } + } + } + return targetsList.toArray(new String[] { }); + } + + @Override + public void addValidator(Validator validator) { + validators.add(validator); + } + + @Override + public boolean isValid() { + for (Validator vldr : validators) { + try { + vldr.validate(getValue()); + } catch (InvalidValueException e) { + return false; + } + } + return true; + } + + @Override + public void valueChange(ValueChangeEvent event) { + assertLastTargetRowIsEmpty(); + } + + private List targetsSelect(final String type, final HSAdminSession session, final Map whereContext) { + final List selectList = new ArrayList<>(); + try { + String pac = whereContext.get("pac"); + if (pac == null) { + final Map domainContext = new HashMap<>(); + domainContext.put("name", whereContext.get("domain")); + final List> domainResult = search("domain", session, domainContext); + pac = (String) domainResult.get(0).get("pac"); + } + final Map pacContext = new HashMap<>(); + pacContext.put("pac", pac); + final List> list = search(type, session, pacContext); + for (Map usr : list) { + selectList.add(usr.get("name").toString()); + } + } catch (RpcException | XmlRpcException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return selectList; + } + + private List> search(final String type, + final HSAdminSession session, + final Map whereContext) throws RpcException, XmlRpcException + { + final String grantingTicket = session.getGrantingTicket(); + final TicketService ticketService = session.getTicketService(); + final String serviceTicket = ticketService.getServiceTicket(grantingTicket); + final ModulesManager modulesManager = session.getModulesManager(); + final IRemote proxy = modulesManager.proxy(type); + final String user = session.getUser(); + return proxy.search(user, serviceTicket, whereContext); + } + + private class TargetRow extends HorizontalLayout { + + private static final long serialVersionUID = 1L; + + private TargetRow(final EMailTargetEditor editor, final String target) { + setWidth("100%"); + setSpacing(true); + final NativeSelect targetTypeSelect = new NativeSelect(); + targetTypeSelect.addItems(new Object[] { I18N.getText("emailtarget.email"), I18N.getText("emailtarget.postbox"), I18N.getText("emailtarget.alias") }); + targetTypeSelect.setWidth("6.0em"); + targetTypeSelect.setValue(""); + addComponent(targetTypeSelect); + setComponentAlignment(targetTypeSelect, Alignment.MIDDLE_LEFT); + setExpandRatio(targetTypeSelect, 0.0f); + AbstractComponent targetField = null; + NativeSelect sel = null; + if (aliases.contains(target)) { + targetTypeSelect.setValue(I18N.getText("emailtarget.alias")); + sel = new NativeSelect(); + sel.addItems(aliases); + sel.setValue(target); + sel.addValueChangeListener(editor); + sel.setEnabled(isEditAble); + targetField = sel; + } else { + if (postboxes.contains(target)) { + targetTypeSelect.setValue(I18N.getText("emailtarget.postbox")); + sel = new NativeSelect(); + sel.addItems(postboxes); + sel.setValue(target); + sel.addValueChangeListener(editor); + sel.setEnabled(isEditAble); + targetField = sel; + } else { + targetTypeSelect.setValue(I18N.getText("emailtarget.email")); + targetField = new TextField(); + targetField.setEnabled(isEditAble); + ((TextField) targetField).setValue(target); + ((TextField) targetField).addValueChangeListener(editor); + } + } + final AbstractComponent field = targetField; + targetTypeSelect.setImmediate(true); + targetTypeSelect.addValueChangeListener(new ValueChangeListener() { + + private static final long serialVersionUID = 1L; + + @Override + public void valueChange(ValueChangeEvent event) { + final TargetRow targetRow = (TargetRow) targetTypeSelect.getParent(); + final Object newValueObject = event.getProperty().getValue(); + if (targetRow.getComponentCount() == 2) { + final Component component = targetRow.getComponent(1); + targetRow.removeComponent(component); + } + if (newValueObject == null) { + layout.removeComponent(targetRow); + } else + { + final String newValue = newValueObject.toString(); + if (targetRow.getComponentCount() == 1) { + AbstractComponent comp = null; + if (I18N.getText("emailtarget.email").equals(newValue)) { + final TextField textField = new TextField(); + textField.addValueChangeListener(editor); + textField.setImmediate(true); + textField.setEnabled(isEditAble); + comp = textField; + } else { + if (I18N.getText("emailtarget.alias").equals(newValue) || I18N.getText("emailtarget.postbox").equals(newValue)) { + final NativeSelect select = new NativeSelect(); + if (I18N.getText("emailtarget.alias").equals(newValue)) { + select.addItems(aliases); + } else { + select.addItems(postboxes); + } + select.addValueChangeListener(editor); + select.setImmediate(true); + select.setEnabled(isEditAble); + comp = select; + } else { + final TextField textField = new TextField(); + textField.addValueChangeListener(editor); + textField.setImmediate(true); + textField.setEnabled(isEditAble); + comp = textField; + } + } + comp.setWidth("100%"); + targetRow.addComponent(comp); + targetRow.setComponentAlignment(comp, Alignment.MIDDLE_RIGHT); + targetRow.setExpandRatio(comp, 1.0f); + } + } + } + + }); + targetTypeSelect.setEnabled(isEditAble); + field.setWidth("100%"); + addComponent(field); + setComponentAlignment(field, Alignment.MIDDLE_RIGHT); + setExpandRatio(field, 1.0f); + } + + public TargetRow(final EMailTargetEditor eMailTargetEditor) { + this(eMailTargetEditor, ""); + } + + private boolean valueIsEmpty() { + if (getComponentCount() == 2) { + final Component component = getComponent(1); + if (component instanceof TextField) { + final String value = ((TextField) component).getValue(); + return value == null || value.isEmpty(); + } + if (component instanceof NativeSelect) { + final Object value = ((NativeSelect) component).getValue(); + return value == null || value.toString().isEmpty(); + } + } + return true; + } + } + +} diff --git a/web/src/main/java/de/hsadmin/web/EntryPoint.java b/web/src/main/java/de/hsadmin/web/EntryPoint.java new file mode 100644 index 0000000..6771dac --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/EntryPoint.java @@ -0,0 +1,59 @@ +package de.hsadmin.web; + +import java.util.List; + +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.Table; +import com.vaadin.ui.Table.ColumnHeaderMode; +import com.vaadin.ui.VerticalLayout; + +public class EntryPoint extends CustomComponent { + + private static final long serialVersionUID = 1L; + + final private String module; + final private EntryPointsSelector parent; + final private Table selectTable; + + public EntryPoint(EntryPointsSelector parent, String name) { + this.module = name; + this.parent = parent; + setCaption(name); + final VerticalLayout tab = new VerticalLayout(); + selectTable = new Table(); + selectTable.setData(name); + final MainWindow mainWindow = parent.getMainWindow(); + final String[] entryPointColumns = mainWindow.entryPointColumns(name); + if (entryPointColumns != null && entryPointColumns.length > 0) { + for (String col : entryPointColumns) { + selectTable.addContainerProperty(col, String.class, null); + } + } + selectTable.setPageLength(0); + selectTable.setColumnHeaderMode(ColumnHeaderMode.HIDDEN); + selectTable.addItemClickListener(parent); + selectTable.setSelectable(true); + selectTable.setImmediate(true); + selectTable.setSizeFull(); + tab.addComponent(selectTable); + tab.setSizeFull(); + setCompositionRoot(tab); + } + + public void fillTable() { + selectTable.removeAllItems(); + final MainWindow mainWindow = parent.getMainWindow(); + final String[] entryPointColumns = mainWindow.entryPointColumns(module); + final List list = mainWindow.list(module, entryPointColumns); + for (Object[] row : list) { + selectTable.addItem(row, row[0]); + } + selectTable.setSortContainerPropertyId(entryPointColumns[0]); + selectTable.sort(); + selectTable.setColumnHeaderMode(ColumnHeaderMode.HIDDEN); + selectTable.setSelectable(true); + selectTable.setImmediate(true); + selectTable.setSizeFull(); + } + +} diff --git a/web/src/main/java/de/hsadmin/web/EntryPointsFactory.java b/web/src/main/java/de/hsadmin/web/EntryPointsFactory.java new file mode 100644 index 0000000..61efa20 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/EntryPointsFactory.java @@ -0,0 +1,22 @@ +package de.hsadmin.web; + +public class EntryPointsFactory extends AbstractEntryPointsFactory { + + @Override + public String[] getEntryPointNames(final String role) { + if ("HOSTMASTER".equals(role)) { + return new String[] { "customer", "pac", "domain" }; + } + if ("CUSTOMER".equals(role)) { + return new String[] { "customer", "pac", "domain" }; + } + if ("PAC_ADMIN_DW".equals(role)) { + return new String[] { "pac", "domain" }; + } + if ("DOM_ADMIN".equals(role)) { + return new String[] { "domain" }; + } + return new String[] { }; + } + +} diff --git a/web/src/main/java/de/hsadmin/web/EntryPointsSelector.java b/web/src/main/java/de/hsadmin/web/EntryPointsSelector.java new file mode 100644 index 0000000..b5ae0d2 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/EntryPointsSelector.java @@ -0,0 +1,89 @@ +package de.hsadmin.web; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.xmlrpc.XmlRpcException; + +import com.vaadin.event.ItemClickEvent; +import com.vaadin.event.ItemClickEvent.ItemClickListener; +import com.vaadin.ui.Accordion; +import com.vaadin.ui.Component; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.Panel; +import com.vaadin.ui.TabSheet.SelectedTabChangeEvent; +import com.vaadin.ui.TabSheet.SelectedTabChangeListener; +import com.vaadin.ui.Table; + +import de.hsadmin.model.IRemote; +import de.hsadmin.model.TicketService; +import de.hsadmin.rpc.RpcException; + +public class EntryPointsSelector extends CustomComponent implements ItemClickListener, SelectedTabChangeListener { + + private static final long serialVersionUID = 1L; + private final MainWindow mainWindow; + + private Accordion accordion; + + public EntryPointsSelector(final MainWindow mainWindow) throws RpcException { + this.mainWindow = mainWindow; + final Panel panel = new Panel(); + accordion = new Accordion(); + accordion.setSizeFull(); + createTabs(); + panel.setContent(accordion); + panel.setSizeFull(); + setCompositionRoot(panel); + accordion.addSelectedTabChangeListener(this); + } + + private void createTabs() throws RpcException { + final String role = getRole(); + final AbstractEntryPointsFactory entryPointsFactory = FactoryProducer.getEntryPointsFactory("default"); + boolean hasFirstTab = false; + for(String tabName : entryPointsFactory.getEntryPointNames(role)) { + accordion.addTab(new EntryPoint(this, tabName), I18N.getText(tabName)); + hasFirstTab = true; + } + if (hasFirstTab) { + final Component component = accordion.getTab(0).getComponent(); + if (component instanceof EntryPoint) { + ((EntryPoint) component).fillTable(); + } + } + } + + public String getRole() throws RpcException { + final IRemote rolesProxy = mainWindow.getModulesManager().proxy("role"); + final String user = mainWindow.getUser(); + final TicketService ticketService = mainWindow.getTicketService(); + final String grantingTicket = mainWindow.getGrantingTicket(); + final String serviceTicket = ticketService.getServiceTicket(grantingTicket); + try { + final List> list = rolesProxy.search(user, serviceTicket, new HashMap()); + return (String) list.get(0).get("role"); + } catch (XmlRpcException e) { + throw new RpcException(e); + } + } + + @Override + public void itemClick(ItemClickEvent event) { + Table table = (Table) event.getSource(); + mainWindow.setCenterPanel((String) table.getData(), event.getItemId()); + } + + @Override + public void selectedTabChange(SelectedTabChangeEvent event) { + final Component selectedTab = event.getTabSheet().getSelectedTab(); + if (selectedTab instanceof EntryPoint) { + ((EntryPoint) selectedTab).fillTable(); + } + } + + public MainWindow getMainWindow() { + return mainWindow; + } +} \ No newline at end of file diff --git a/web/src/main/java/de/hsadmin/web/FactoryProducer.java b/web/src/main/java/de/hsadmin/web/FactoryProducer.java new file mode 100644 index 0000000..2a0fd2a --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/FactoryProducer.java @@ -0,0 +1,25 @@ +package de.hsadmin.web; + + +public class FactoryProducer { + + public static AbstractPanelFactory getPanelFactory(String choice) + { + return new PanelFactory(); + } + + public static AbstractWindowFactory getWindowFactory(String choice) + { + return new SubWindowFactory(); + } + + public static IEditorFactory getEditorFactory(String choice) + { + return new GenericEditorFactory(); + } + + public static AbstractEntryPointsFactory getEntryPointsFactory(String choice) { + return new EntryPointsFactory(); + } + +} diff --git a/web/src/main/java/de/hsadmin/web/GenericEditorFactory.java b/web/src/main/java/de/hsadmin/web/GenericEditorFactory.java new file mode 100644 index 0000000..4d76118 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/GenericEditorFactory.java @@ -0,0 +1,202 @@ +package de.hsadmin.web; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.apache.xmlrpc.XmlRpcException; + +import com.vaadin.data.Validator; + +import de.hsadmin.model.IRemote; +import de.hsadmin.model.TicketService; +import de.hsadmin.rpc.HSAdminSession; +import de.hsadmin.rpc.ModulesManager; +import de.hsadmin.rpc.PropertyInfo; +import de.hsadmin.rpc.RpcException; +import de.hsadmin.rpc.enums.ReadWritePolicy; + +public class GenericEditorFactory implements IEditorFactory, Serializable { + + private static final long serialVersionUID = 1L; + + @Override + public IHSEditor getEditor(final String action, final PropertyInfo propertyInfo, final HSAdminSession session, final Map whereContext) + { + final String inputName = propertyInfo.getName(); + final String module = propertyInfo.getModule(); + if ("domain".equals(module)) { + if ("user".equals(inputName)) { + return getSelectFromRemote(action, propertyInfo, session, "user", whereContext); + } + if ("domainoptions".equals(inputName)) { + return getDomainOptionsEditor(action, propertyInfo, session, whereContext); + } + } + if ("emailaddress".equals(module) || "emailalias".equals(module)) { + if ("target".equals(inputName)) { + return getEMailTargetEditor(action, propertyInfo, session, whereContext); + } + } + if ("mysqldb".equals(module)) { + if ("owner".equals(inputName)) { + return getSelectFromRemote(action, propertyInfo, session, "mysqluser", whereContext); + } + } + if ("postgresqldb".equals(module)) { + if ("owner".equals(inputName)) { + return getSelectFromRemote(action, propertyInfo, session, "postgresqluser", whereContext); + } + } + return getEditor(action, propertyInfo); + } + + + private IHSEditor getDomainOptionsEditor(final String action, final PropertyInfo propertyInfo, final HSAdminSession session, final Map whereContext) { + return PanelToolbar.ACTION_EDIT.equals(action) ? new DomainOptionsEditor(propertyInfo, session, whereContext) : new NullEditor(); + } + + + private IHSEditor getEMailTargetEditor(final String action, final PropertyInfo propertyInfo, final HSAdminSession session, final Map whereContext) + { + return new EMailTargetEditor(action, propertyInfo, session, whereContext); + } + + + @Override + public IHSEditor getEditor(final String action, final PropertyInfo propertyInfo) + { + final String inputName = propertyInfo.getName(); + if ("password".equals(inputName)) { + return getPasswordField(action, propertyInfo); + } + if ("shell".equals(inputName)) { + return getShellSelect(action, propertyInfo); + } + final String module = propertyInfo.getModule(); + if ("user".equals(module) || "emailalias".equals(module)) { + if ("name".equals(inputName)) { + return getPacPrefixedField(action, propertyInfo, '-'); + } + } + if ("mysqluser".equals(module) || "postgresqluser".equals(module)) { + if ("name".equals(inputName)) { + return getPacPrefixedField(action, propertyInfo, '_'); + } + } + if ("mysqldb".equals(module) || "postgresqldb".equals(module)) { + if ("name".equals(inputName)) { + return getPacPrefixedField(action, propertyInfo, '_'); + } + if ("encoding".equals(inputName)) { + return getSelectField(action, propertyInfo, "UTF8", "LATIN1"); + } + } + return getTextField(action, propertyInfo); + } + + private IHSEditor getSelectField(final String action, final PropertyInfo propertyInfo, final String... items) + { + final HSSelect field = new HSSelect(propertyInfo.getName(), Arrays.asList(items)); + field.setWidth("100%"); + field.setEnabled(isWriteAble(propertyInfo, action)); + return field; + } + + + private IHSEditor getPacPrefixedField(final String action, final PropertyInfo propertyInfo, final char delimiter) + { + final HSPacPrefixedField field = new HSPacPrefixedField(propertyInfo.getName(), delimiter); + field.setWidth("100%"); + field.setValue("xyz00-"); + enableAndValidate(action, propertyInfo, field); + return field; + } + + private IHSEditor getShellSelect(final String action, final PropertyInfo propertyInfo) + { + final String[] items = new String[] { "/bin/false", "/bin/bash", "/bin/csh", "/bin/dash", "/bin/ksh", "/bin/tcsh", "/bin/zsh", "/usr/bin/passwd", "/usr/bin/scponly" }; + final HSSelect field = new HSSelect(propertyInfo.getName(), 7, Arrays.asList(items)); + field.setWidth("100%"); + field.setEnabled(isWriteAble(propertyInfo, action)); + return field; + } + + private IHSEditor getSelectFromRemote(final String action, final PropertyInfo propertyInfo, final HSAdminSession session, final String module, final Map whereContext) + { + final List selectList = new ArrayList<>(); + try { + final String grantingTicket = session.getGrantingTicket(); + final TicketService ticketService = session.getTicketService(); + final String serviceTicket = ticketService.getServiceTicket(grantingTicket); + final ModulesManager modulesManager = session.getModulesManager(); + final IRemote proxy = modulesManager.proxy(module); + final String user = session.getUser(); + final List> list = proxy.search(user, serviceTicket, whereContext); + for (Map usr : list) { + selectList.add(usr.get("name").toString()); + } + } catch (RpcException | XmlRpcException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + final HSSelect field = new HSSelect(propertyInfo.getName(), selectList); + field.setEnabled(isWriteAble(propertyInfo, action)); + field.setWidth("100%"); + return field; + } + + private IHSEditor getPasswordField(final String action, final PropertyInfo propertyInfo) + { + final HSPasswordField field = new HSPasswordField(propertyInfo.getName(), "new".equals(action)); + field.setWidth("100%"); + field.setEnabled("new".equals(action) || "edit".equals(action)); + return field; + } + + private IHSEditor getTextField(final String action, final PropertyInfo propertyInfo) + { + final HSTextField field = new HSTextField(propertyInfo.getName()); + field.setWidth("100%"); + enableAndValidate(action, propertyInfo, field); + return field; + } + + private void enableAndValidate(final String action, final PropertyInfo propertyInfo, final IHSEditor field) + { + if (isWriteAble(propertyInfo, action)) { + final String regexp = propertyInfo.getValidationRegexp(); + final int minLength = propertyInfo.getMinLength(); + final int maxLength = propertyInfo.getMaxLength(); + field.addValidator(new Validator() { + private static final long serialVersionUID = 1L; + @Override + public void validate(Object value) throws InvalidValueException { + final String inputString = (String) value; + if (inputString == null || !inputString.matches(regexp)) { + throw new InvalidValueException("input must match " + regexp); + } + if (inputString.length() < minLength) { + throw new InvalidValueException("minimal length is " + minLength); + } + if (inputString.length() > maxLength) { + throw new InvalidValueException("maximal length is " + maxLength); + } + } + }); + } else { + field.setEnabled(false); + } + } + + private boolean isWriteAble(PropertyInfo propertyInfo, String action) { + if (PanelToolbar.ACTION_VIEW.equals(action)) { + return false; + } + return (ReadWritePolicy.WRITEONCE.equals(propertyInfo.getReadwriteable()) && PanelToolbar.ACTION_NEW.equals(action)) || + (ReadWritePolicy.READWRITE.equals(propertyInfo.getReadwriteable()) && ( PanelToolbar.ACTION_EDIT.equals(action) || PanelToolbar.ACTION_NEW.equals(action) )); + } + +} diff --git a/web/src/main/java/de/hsadmin/web/GenericForm.java b/web/src/main/java/de/hsadmin/web/GenericForm.java new file mode 100644 index 0000000..de48645 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/GenericForm.java @@ -0,0 +1,65 @@ +package de.hsadmin.web; + +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.xmlrpc.XmlRpcException; + +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.FormLayout; + +import de.hsadmin.model.IRemote; +import de.hsadmin.model.TicketService; +import de.hsadmin.rpc.HSAdminSession; +import de.hsadmin.rpc.PropertyInfo; +import de.hsadmin.rpc.RpcException; + +public class GenericForm extends CustomComponent { + + private static final long serialVersionUID = 1L; + + final private FormLayout formLayout; + final private Map inputFields; + + public GenericForm(final String module, final HSAdminSession session, final Object itemId, final String selectPropertyName) throws RpcException { + formLayout = new FormLayout(); + formLayout.setMargin(true); + inputFields = new HashMap(); + final Iterator iterator = session.getModulesManager().module(module).properties(); + while (iterator.hasNext()) { + final PropertyInfo propertyInfo = iterator.next(); + final String inputName = propertyInfo.getName(); + final IEditorFactory editorFactory = FactoryProducer.getEditorFactory(module); + final IHSEditor field = editorFactory.getEditor("view", propertyInfo); + inputFields.put(inputName, field); + formLayout.addComponent(field); + } + setCompositionRoot(formLayout); + + final Hashtable whereParams = new Hashtable(); + whereParams.put(selectPropertyName, itemId.toString()); + + try { + final String grantingTicket = session.getGrantingTicket(); + final TicketService ticketService = session.getTicketService(); + final String user = session.getUser(); + final String serviceTicket = ticketService.getServiceTicket(grantingTicket); + final IRemote proxy = session.getModulesManager().proxy(module); + final List> list = proxy.search(user, serviceTicket, whereParams); + + final Set keySet = inputFields.keySet(); + for (String key : keySet) { + inputFields.get(key).setValues(list.get(0)); + } + } catch (XmlRpcException e) { + throw new RpcException(e); + } + + + } + +} diff --git a/web/src/main/java/de/hsadmin/web/GenericFormWindow.java b/web/src/main/java/de/hsadmin/web/GenericFormWindow.java new file mode 100644 index 0000000..14b5062 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/GenericFormWindow.java @@ -0,0 +1,93 @@ +package de.hsadmin.web; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import com.vaadin.ui.FormLayout; +import com.vaadin.ui.Window; + +import de.hsadmin.rpc.HSAdminSession; +import de.hsadmin.rpc.PropertyInfo; +import de.hsadmin.rpc.enums.ReadWritePolicy; + +public class GenericFormWindow extends Window implements IHSWindow { + + private static final long serialVersionUID = 1L; + + final private FormLayout contentForm; + final private Map inputFields; + final private HSTab parent; + + private Map uniqueRecordSelect; + + public GenericFormWindow(final HSTab parent, final String module, final String action, final HSAdminSession session, final Map whereContext) + { + super(I18N.getText(action) + " " + I18N.getText(module)); + this.parent = parent; + center(); + setModal(true); + setWidth("640px"); + inputFields = new HashMap(); + contentForm = new FormLayout(); + contentForm.setMargin(true); + + final Iterator iterator = session.getModulesManager().module(module).properties(); + while (iterator.hasNext()) { + final PropertyInfo propertyInfo = iterator.next(); + if ("new".equals(action) && ReadWritePolicy.READ.equals(propertyInfo.getReadwriteable())) { + continue; + } + final String inputName = propertyInfo.getName(); + final IEditorFactory editorFactory = FactoryProducer.getEditorFactory(module); + final IHSEditor field = editorFactory.getEditor(action, propertyInfo, session, whereContext); + inputFields.put(inputName, field); + contentForm.addComponent(field); + } + contentForm.addComponent(new HSConfirmBox(this, module, action, session)); + setContent(contentForm); + } + + @Override + public void setFormData(final Map valuesMap, final Map uniqueWhereSelector) { + this.uniqueRecordSelect = uniqueWhereSelector; + final Set keySet = inputFields.keySet(); + for (final String key : keySet) { + inputFields.get(key).setValues(valuesMap); + } + } + + @Override + public Map getFormData() { + Map formData = new HashMap(); + final Set keySet = inputFields.keySet(); + for (String key : keySet) { + final IHSEditor ihsEditor = inputFields.get(key); + if (ihsEditor.isEnabled()) { + formData.put(key, ihsEditor.getValue()); + } + } + return formData; + } + + @Override + public Map getUniqueWhereSelector() { + return uniqueRecordSelect; + } + + @Override + public void reload() { + parent.fillTable(); + } + + @Override + public boolean isValid() { + boolean valid = true; + for (IHSEditor editor : inputFields.values()) { + valid &= editor.isValid(); + } + return valid; + } + +} diff --git a/web/src/main/java/de/hsadmin/web/HSAdminUI.java b/web/src/main/java/de/hsadmin/web/HSAdminUI.java new file mode 100644 index 0000000..3202f71 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/HSAdminUI.java @@ -0,0 +1,47 @@ +package de.hsadmin.web; + +import javax.servlet.annotation.WebServlet; + +import com.vaadin.annotations.Theme; +import com.vaadin.annotations.Title; +import com.vaadin.annotations.VaadinServletConfiguration; +import com.vaadin.server.VaadinRequest; +import com.vaadin.server.VaadinServlet; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; + +import de.hsadmin.model.TicketService; + +@Title("HSAdmin Web") +@Theme("valo") +public class HSAdminUI extends UI { + + private static final long serialVersionUID = 1L; + + @WebServlet(value = "/*", asyncSupported = true) + @VaadinServletConfiguration(productionMode = false, ui = HSAdminUI.class) + public static class Servlet extends VaadinServlet { + + private static final long serialVersionUID = 1L; + + } + + private VerticalLayout layout; + private TicketService ticketService; + + @Override + protected void init(VaadinRequest request) { + setSizeFull(); + layout = new VerticalLayout(); + layout.setSizeFull(); + + ticketService = new TicketService(); + UI.getCurrent().addWindow(new LoginWindow(this, ticketService)); + + setContent(layout); + } + + public void setGrantingTicket(String grantingTicket, String username) { + layout.addComponent(new MainWindow(ticketService, grantingTicket, username)); + } +} \ No newline at end of file diff --git a/web/src/main/java/de/hsadmin/web/HSConfirmBox.java b/web/src/main/java/de/hsadmin/web/HSConfirmBox.java new file mode 100644 index 0000000..a99b648 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/HSConfirmBox.java @@ -0,0 +1,105 @@ +package de.hsadmin.web; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.vaadin.event.ShortcutAction.KeyCode; +import com.vaadin.server.ErrorMessage; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Window; +import com.vaadin.ui.themes.ValoTheme; + +import de.hsadmin.model.IRemote; +import de.hsadmin.model.TicketService; +import de.hsadmin.rpc.HSAdminSession; +import de.hsadmin.rpc.RpcException; + +public class HSConfirmBox extends HorizontalLayout { + + private static final long serialVersionUID = 1L; + + private static final Logger LOG = Logger.getLogger(HSConfirmBox.class); + + private Button okButton, cancelButton; + + public HSConfirmBox(final GenericFormWindow parent, final String module, final String action, final HSAdminSession session) { + okButton = new Button("OK"); + okButton.setStyleName(ValoTheme.BUTTON_PRIMARY); + okButton.setClickShortcut(KeyCode.ENTER); + okButton.addClickListener(new ClickListener() + { + private static final long serialVersionUID = 1L; + + public void buttonClick(ClickEvent event) + { + final IRemote iRemote = session.getModulesManager().proxy(module); + final String runAsUser = session.getUser(); + final TicketService ticketService = session.getTicketService(); + boolean success = false; + try { + if (!parent.isValid()) { + throw new RpcException("validation error"); + } + final String ticket = ticketService.getServiceTicket(session.getGrantingTicket()); + try { + if ("new".equals(action)) { + iRemote.add(runAsUser, ticket, parent.getFormData()); + parent.reload(); + success = true; + } + if ("edit".equals(action)) { + iRemote.update(runAsUser, ticket, parent.getFormData(), parent.getUniqueWhereSelector()); + parent.reload(); + success = true; + } + if ("delete".equals(action)) { + iRemote.delete(runAsUser, ticket, parent.getUniqueWhereSelector()); + parent.reload(); + success = true; + } + } catch (final XmlRpcException e) { + LOG.info("RPC Error", e); + throw new RpcException(e); + } + } catch (final RpcException e) { + final ErrorMessage componentError = new ErrorMessage() { + private static final long serialVersionUID = 1L; + @Override + public ErrorLevel getErrorLevel() { + return ErrorLevel.CRITICAL; + } + @Override + public String getFormattedHtmlMessage() { + return "

Error

" + e.getLocalizedMessage() + "

"; + } + }; + parent.setComponentError(componentError); + final Button btn = event.getButton(); + btn.setComponentError(componentError); + } + if (success) { + ((Window) parent).close(); + } + } + }); + cancelButton = new Button(I18N.getText("cancel")); + cancelButton.setClickShortcut(KeyCode.ESCAPE); + cancelButton.addClickListener(new ClickListener() + { + private static final long serialVersionUID = 1L; + + public void buttonClick(ClickEvent event) + { + ((Window) parent).close(); + } + }); + + setSpacing(true); + addComponent(okButton); + addComponent(cancelButton); + } + +} diff --git a/web/src/main/java/de/hsadmin/web/HSPacPrefixedField.java b/web/src/main/java/de/hsadmin/web/HSPacPrefixedField.java new file mode 100644 index 0000000..7668543 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/HSPacPrefixedField.java @@ -0,0 +1,35 @@ +package de.hsadmin.web; + +import java.util.Map; + + +public class HSPacPrefixedField extends HSTextField implements PacNamePrefixed { + + private static final long serialVersionUID = 1L; + + private final char delimiter; + + private String pacName; + + public HSPacPrefixedField(final String name, final char delimiter) { + super(name); + pacName = "xyz00"; + this.delimiter = delimiter; + addValidator(new PacNamePrefixValidator(this)); + } + + @Override + public String getPacName() { + return pacName; + } + + @Override + public void setValues(final Map valuesMap) { + super.setValues(valuesMap); + pacName = (String) valuesMap.get("pac"); + final String currentValue = getValue(); + if (currentValue == null || currentValue.isEmpty()) { + setValue(pacName + delimiter); + } + } +} diff --git a/web/src/main/java/de/hsadmin/web/HSPasswordField.java b/web/src/main/java/de/hsadmin/web/HSPasswordField.java new file mode 100644 index 0000000..0460c9b --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/HSPasswordField.java @@ -0,0 +1,21 @@ +package de.hsadmin.web; + +import java.util.Map; + +import com.vaadin.ui.PasswordField; + +public class HSPasswordField extends PasswordField implements IHSEditor { + + private static final long serialVersionUID = 1L; + + public HSPasswordField(final String name, final boolean passwordRequired) { + super(I18N.getText(name)); + addValidator(new PasswordValidator(passwordRequired)); + } + + @Override + public void setValues(final Map valuesMap) { + setValue(""); + } + +} diff --git a/web/src/main/java/de/hsadmin/web/HSSelect.java b/web/src/main/java/de/hsadmin/web/HSSelect.java new file mode 100644 index 0000000..3edefb8 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/HSSelect.java @@ -0,0 +1,36 @@ +package de.hsadmin.web; + +import java.util.List; +import java.util.Map; + +import com.vaadin.ui.NativeSelect; + +public class HSSelect extends NativeSelect implements IHSEditor { + + private static final long serialVersionUID = 1L; + + private final String propertyName; + + public HSSelect(final String label, final List values) { + this(label, 0, values); + } + + public HSSelect(final String label, final int defaultIndex, final List values) { + super(I18N.getText(label)); + this.propertyName = label; + super.addItems(values); + if (values != null && values.size() > defaultIndex) { + super.setValue(values.get(defaultIndex)); + } + super.setMultiSelect(false); + super.setNullSelectionAllowed(false); + } + + @Override + public void setValues(final Map valuesMap) { + final Object newValue = valuesMap.get(propertyName); + if (newValue != null) { + setValue(newValue); + } + } +} diff --git a/web/src/main/java/de/hsadmin/web/HSTab.java b/web/src/main/java/de/hsadmin/web/HSTab.java new file mode 100644 index 0000000..6a8fe1a --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/HSTab.java @@ -0,0 +1,163 @@ +package de.hsadmin.web; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.xmlrpc.XmlRpcException; + +import com.vaadin.ui.Alignment; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Table; +import com.vaadin.ui.VerticalLayout; + +import de.hsadmin.model.TicketService; +import de.hsadmin.rpc.HSAdminSession; +import de.hsadmin.rpc.ModuleInfo; +import de.hsadmin.rpc.ModulesManager; +import de.hsadmin.rpc.PropertyInfo; +import de.hsadmin.rpc.RpcException; +import de.hsadmin.rpc.enums.DisplayPolicy; +import de.hsadmin.rpc.enums.ReadWritePolicy; + +public class HSTab extends CustomComponent { + + private static final long serialVersionUID = 1L; + + private final HSAdminSession session; + private final String module; + private final Object selectPropertyValue; + private final String selectPropertyName; + private final String rowIdPropertyName; + private final HorizontalLayout panelToolbar; + + private Table grid; + + + public HSTab(final String source, final HSAdminSession session, final String selectPropertyName, final Object selectPropertyValue, final String rowIdPropertyName) { + super(); + setSizeFull(); + this.module = source; + this.session = session; + this.selectPropertyName = selectPropertyName; + this.selectPropertyValue = selectPropertyValue; + this.rowIdPropertyName = rowIdPropertyName; + final Table dataTable = getGrid(session.getModulesManager().module(source)); + panelToolbar = new PanelToolbar(source, session, this); + final VerticalLayout layout = new VerticalLayout(); + layout.setSizeFull(); + layout.addComponent(panelToolbar); + layout.setComponentAlignment(panelToolbar, Alignment.TOP_RIGHT); + layout.addComponent(dataTable); + layout.setExpandRatio(dataTable, 1.0f); + dataTable.setHeight("100%"); + setCompositionRoot(layout); + } + + public void fillTable() + { + grid.removeAllItems(); + Object firstId = null; + try { + final ModulesManager modulesManager = session.getModulesManager(); + final String grantingTicket = session.getGrantingTicket(); + final TicketService ticketService = session.getTicketService(); + final String serviceTicket = ticketService.getServiceTicket(grantingTicket); + final String user = session.getUser(); + final HashMap whereParams = new HashMap(); + whereParams.put(selectPropertyName, selectPropertyValue.toString()); + try { + final List> objectsList = modulesManager.proxy(module).search(user, serviceTicket, whereParams); + for (Map objectHash : objectsList) + { + final Iterator properties = session.getModulesManager().module(module).properties(); + final List itemsList = new ArrayList(); + while (properties.hasNext()) { + final PropertyInfo propertyInfo = properties.next(); + if (showColumnInTable(propertyInfo)) { + final Object value = objectHash.get(propertyInfo.getName()); + if (value == null) { + itemsList.add(""); + } else { + if (value instanceof Object[]) { + final StringBuffer buff = new StringBuffer(); + final Object[] items = (Object[]) value; + if (items.length > 0) { + buff.append(items[0].toString()); + } + for (int idx=1; idx < items.length; idx++) { + buff.append(", "); + buff.append(items[idx].toString()); + } + itemsList.add(buff.toString()); + } else { + itemsList.add(value.toString()); + } + } + } + } + final Object rowId = objectHash.get(rowIdPropertyName); + if (firstId == null) { + firstId = rowId; + } + grid.addItem(itemsList.toArray(), rowId); + } + } catch (UnsupportedOperationException | XmlRpcException e) { + throw new RpcException(e); + } + } catch (RpcException e) { + // FIXME error handling + } +// grid.setPageLength(0); + grid.setSelectable(true); + grid.setImmediate(true); + grid.setSizeFull(); + if (grid.size() == 1) { + grid.select(firstId); + } + } + + public Object getSelection() { + return grid.getValue(); + } + + public String getRowIdName() { + return rowIdPropertyName; + } + + private boolean showColumnInTable(final PropertyInfo propertyInfo) + { + final DisplayPolicy displayVisible = propertyInfo.getDisplayVisible(); + final ReadWritePolicy readwriteable = propertyInfo.getReadwriteable(); + return DisplayPolicy.ALWAYS.equals(displayVisible) && + ( ! ReadWritePolicy.NONE.equals(readwriteable) ); + } + + private Table getGrid(ModuleInfo moduleInfo) + { + grid = new Table(); + final Iterator properties = moduleInfo.properties(); + while (properties.hasNext()) { + final PropertyInfo propertyInfo = properties.next(); + if (showColumnInTable(propertyInfo)) { + grid.addContainerProperty(I18N.getText(propertyInfo.getModule() + "." + propertyInfo.getName()), String.class, ""); + } + } + grid.setSelectable(true); + grid.setImmediate(true); + grid.setSizeFull(); + return grid; + } + + public Object getSelectPropertyValue() { + return selectPropertyValue; + } + + public String getSelectPropertyName() { + return selectPropertyName; + } + +} diff --git a/web/src/main/java/de/hsadmin/web/HSTextField.java b/web/src/main/java/de/hsadmin/web/HSTextField.java new file mode 100644 index 0000000..e925c87 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/HSTextField.java @@ -0,0 +1,36 @@ +package de.hsadmin.web; + +import java.util.Map; + +import com.vaadin.ui.TextField; + +public class HSTextField extends TextField implements IHSEditor { + + private static final long serialVersionUID = 1L; + + private final String propertyName; + + public HSTextField(final String name) { + super(I18N.getText(name)); + this.propertyName = name; + } + + @Override + public void setValues(final Map valuesMap) { + String newValue = ""; + final Object valObject = valuesMap.get(propertyName); + if (valObject instanceof String) { + newValue = (String) valObject; + } + if (valObject instanceof Integer) { + ((Integer) valObject).toString(); + } + if (valObject instanceof Boolean) { + ((Boolean) valObject).toString(); + } + if (newValue != null) { + setValue(newValue); + } + } + +} diff --git a/web/src/main/java/de/hsadmin/web/HelpWindow.java b/web/src/main/java/de/hsadmin/web/HelpWindow.java new file mode 100644 index 0000000..fd60faa --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/HelpWindow.java @@ -0,0 +1,38 @@ +package de.hsadmin.web; + +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Window; + +public class HelpWindow extends Window { + + private static final long serialVersionUID = 1L; + + private static final String HELP_HTML_SNIPPET = "Contact us in case of further questions"; + + public HelpWindow() { + // Create a sub-window and set the content + super("Help Window"); + // Center it in the browser window + center(); + + VerticalLayout subContent = new VerticalLayout(); + subContent.setMargin(true); + + subContent.addComponent(new Label(HELP_HTML_SNIPPET)); + Button ok = new Button("OK"); + ok.addClickListener(new ClickListener() { + private static final long serialVersionUID = -6121701552072481416L; + + public void buttonClick(ClickEvent event) { + close(); // Close the sub-window + } + }); + subContent.addComponent(ok); + + setContent(subContent); + } +} \ No newline at end of file diff --git a/web/src/main/java/de/hsadmin/web/I18N.java b/web/src/main/java/de/hsadmin/web/I18N.java new file mode 100644 index 0000000..df14604 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/I18N.java @@ -0,0 +1,20 @@ +package de.hsadmin.web; + +import java.util.MissingResourceException; +import java.util.ResourceBundle; + +public class I18N { + + private static final ResourceBundle TEXTS = ResourceBundle.getBundle("de.hsadmin.web.main"); + + public static String getText(final String textProperty) { + String textValue; + try{ + textValue = I18N.TEXTS.getString(textProperty); + }catch(MissingResourceException e){ + textValue = "./. " + textProperty; + } + return textValue; + } + +} diff --git a/web/src/main/java/de/hsadmin/web/IEditorFactory.java b/web/src/main/java/de/hsadmin/web/IEditorFactory.java new file mode 100644 index 0000000..614068a --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/IEditorFactory.java @@ -0,0 +1,15 @@ +package de.hsadmin.web; + +import java.util.Map; + +import de.hsadmin.rpc.HSAdminSession; +import de.hsadmin.rpc.PropertyInfo; + + +public interface IEditorFactory { + + public abstract IHSEditor getEditor(String action, PropertyInfo propertyInfo); + + public abstract IHSEditor getEditor(String action, PropertyInfo propertyInfo, HSAdminSession session, Map whereContext); + +} diff --git a/web/src/main/java/de/hsadmin/web/IHSEditor.java b/web/src/main/java/de/hsadmin/web/IHSEditor.java new file mode 100644 index 0000000..aaf026b --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/IHSEditor.java @@ -0,0 +1,18 @@ +package de.hsadmin.web; + +import java.util.Map; + +import com.vaadin.data.Validator; +import com.vaadin.ui.Component; + +public interface IHSEditor extends Component { + + public void setValues(Map valuesMap); + + public Object getValue(); + + public void addValidator(Validator validator); + + public boolean isValid(); + +} diff --git a/web/src/main/java/de/hsadmin/web/IHSPanel.java b/web/src/main/java/de/hsadmin/web/IHSPanel.java new file mode 100644 index 0000000..e615dea --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/IHSPanel.java @@ -0,0 +1,12 @@ +package de.hsadmin.web; + +import com.vaadin.ui.Component; +import com.vaadin.ui.TabSheet; + +import de.hsadmin.rpc.RpcException; + +public interface IHSPanel extends Component{ + + public TabSheet createTabs(Object itemId) throws RpcException; + +} \ No newline at end of file diff --git a/web/src/main/java/de/hsadmin/web/IHSWindow.java b/web/src/main/java/de/hsadmin/web/IHSWindow.java new file mode 100644 index 0000000..810048e --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/IHSWindow.java @@ -0,0 +1,17 @@ +package de.hsadmin.web; + +import java.util.Map; + +public interface IHSWindow { + + public void setFormData(Map value, Map selector); + + public Map getFormData(); + + public Map getUniqueWhereSelector(); + + public void reload(); + + public boolean isValid(); + +} diff --git a/web/src/main/java/de/hsadmin/web/InfoWindow.java b/web/src/main/java/de/hsadmin/web/InfoWindow.java new file mode 100644 index 0000000..98525ae --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/InfoWindow.java @@ -0,0 +1,36 @@ +package de.hsadmin.web; + +import com.vaadin.event.ShortcutAction.KeyCode; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.themes.ValoTheme; +import com.vaadin.ui.Label; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.Window; + +public class InfoWindow extends Window { + + private static final long serialVersionUID = 1L; + + public InfoWindow(final String info) + { + super("Info"); + center(); + final VerticalLayout subContent = new VerticalLayout(); + subContent.setMargin(true); + subContent.addComponent(new Label(info)); + final Button ok = new Button("OK"); + ok.setClickShortcut(KeyCode.ENTER); + ok.setStyleName(ValoTheme.BUTTON_PRIMARY); + ok.addClickListener(new ClickListener() + { + private static final long serialVersionUID = 1L; + public void buttonClick(ClickEvent event) { + close(); + } + }); + subContent.addComponent(ok); + setContent(subContent); + } +} \ No newline at end of file diff --git a/web/src/main/java/de/hsadmin/web/LoginWindow.java b/web/src/main/java/de/hsadmin/web/LoginWindow.java new file mode 100644 index 0000000..1241300 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/LoginWindow.java @@ -0,0 +1,108 @@ +package de.hsadmin.web; + +import java.util.HashMap; +import java.util.Map; + +import com.vaadin.event.ShortcutAction.KeyCode; +import com.vaadin.server.ExternalResource; +import com.vaadin.ui.AbstractTextField; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.Component; +import com.vaadin.ui.FormLayout; +import com.vaadin.ui.HasComponents; +import com.vaadin.ui.Label; +import com.vaadin.ui.Link; +import com.vaadin.ui.PasswordField; +import com.vaadin.ui.TextField; +import com.vaadin.ui.Window; +import com.vaadin.ui.themes.ValoTheme; + +import de.hsadmin.model.TicketService; +import de.hsadmin.rpc.RpcException; + +public class LoginWindow extends Window { + + private static final long serialVersionUID = 1L; + + public LoginWindow(final HSAdminUI parent, final TicketService ticketService) { + super(I18N.getText("login.title")); + center(); + setModal(true); + setWidth("480px"); + + final FormLayout subContent = new FormLayout(); + subContent.setMargin(true); + + final TextField login = new TextField(I18N.getText("user.name")); + login.setWidth("100%"); + subContent.addComponent(login); + login.focus(); + final PasswordField password = new PasswordField(I18N.getText("password")); + password.setWidth("100%"); + subContent.addComponent(password); + final Label feedback = new Label(""); + feedback.setWidth("100%"); + feedback.setVisible(false); + subContent.addComponent(feedback); + feedback.setStyleName(ValoTheme.LABEL_FAILURE); + + final Button okButton = new Button(I18N.getText("login.button")); + okButton.setStyleName(ValoTheme.BUTTON_PRIMARY); + okButton.setClickShortcut(KeyCode.ENTER); + okButton.addClickListener(new ClickListener() + { + private static final long serialVersionUID = 1L; + + public void buttonClick(ClickEvent event) { + final HasComponents formLayout = okButton.getParent(); + if (formLayout != null) { + + final FormLayout form = (FormLayout) formLayout; + final int count = form.getComponentCount(); + final Map credentials = new HashMap(); + for (int idx=0; idx < count; idx++) { + final Component component = form.getComponent(idx); + if (component instanceof AbstractTextField) { + final AbstractTextField tf = (AbstractTextField) component; + if (tf.isEnabled() && tf.isValid()) { + final String key = tf.getCaption(); + final String value = tf.getValue(); + credentials.put(key, value); + } + } + } + try { + final String user = credentials.get(I18N.getText("user.name")); + final String loginUser = user.length() == 3 ? "hsh00-" + user : user; + final String password = credentials.get(I18N.getText("password")); + final String grantingTicket = ticketService.getGrantingTicket(loginUser, password); + if (grantingTicket != null && !grantingTicket.isEmpty()) { + feedback.setValue("successful login"); + feedback.setVisible(true); + parent.setGrantingTicket(grantingTicket, loginUser); + final HasComponents window = formLayout.getParent(); + if (window != null) { + ((Window) window).close(); + } + } else { + feedback.setValue("login failed, please retry"); + feedback.setVisible(true); + ((Window)subContent.getParent()).markAsDirty(); + } + } catch (RpcException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + }); + subContent.addComponent(okButton); + final Link linkToOld = new Link(I18N.getText("main.panel.link_to_old"), new ExternalResource("https://admin.hostsharing.net/")); + subContent.addComponent(linkToOld); + + setContent(subContent); + } + +} diff --git a/web/src/main/java/de/hsadmin/web/MainPanel.java b/web/src/main/java/de/hsadmin/web/MainPanel.java new file mode 100644 index 0000000..51a16e6 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/MainPanel.java @@ -0,0 +1,18 @@ +package de.hsadmin.web; + +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.Label; +import com.vaadin.ui.Panel; + +public class MainPanel extends CustomComponent{ + + private static final long serialVersionUID = -1085100738394404620L; + + public MainPanel() { + final Label dialog = new Label(); + final Panel panel = new Panel(I18N.getText("main.panel.title")); + dialog.setValue(I18N.getText("main.panel.text")); + panel.setContent(dialog); + setCompositionRoot(panel); + } +} diff --git a/web/src/main/java/de/hsadmin/web/MainToolbar.java b/web/src/main/java/de/hsadmin/web/MainToolbar.java new file mode 100644 index 0000000..dedcd81 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/MainToolbar.java @@ -0,0 +1,56 @@ +package de.hsadmin.web; + +import com.vaadin.server.ThemeResource; +import com.vaadin.server.VaadinRequest; +import com.vaadin.server.VaadinService; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.Component; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Panel; +import com.vaadin.ui.UI; + +public class MainToolbar extends CustomComponent implements ClickListener { + + private static final long serialVersionUID = 1L; + + public MainToolbar() { + final Panel toolbar = new Panel(); + toolbar.setSizeFull(); + final HorizontalLayout layout = new HorizontalLayout(); + layout.setSizeFull(); + final Component whitespace = new Panel(); + whitespace.setStyleName("borderless"); + layout.addComponent(whitespace); + layout.setExpandRatio(whitespace, 1.0f); + final Button logoutBtn = createButton("logout", "x"); + layout.addComponent(logoutBtn); + layout.setExpandRatio(logoutBtn, 0.0f); + toolbar.setContent(layout); + setCompositionRoot(toolbar); + } + + private Button createButton(final String name, final String icon) { + final Button btn = new Button(); + btn.setId(name + "-btn"); + btn.setIcon(new ThemeResource("../icons/" + icon + "-icon.png")); + btn.setDescription(I18N.getText(name + ".tooltip")); + btn.setStyleName("borderless"); + btn.addClickListener(this); + return btn; + } + + @Override + public void buttonClick(final ClickEvent event) { + final String btnId = event.getComponent().getId(); + if ("logout-btn".equals(btnId)) { + final VaadinRequest currentRequest = VaadinService.getCurrentRequest(); + final UI vaadinUI = getUI(); + vaadinUI.getSession().close(); + vaadinUI.getPage().setLocation(currentRequest.getContextPath()); + } + } + +} diff --git a/web/src/main/java/de/hsadmin/web/MainWindow.java b/web/src/main/java/de/hsadmin/web/MainWindow.java new file mode 100644 index 0000000..2adefe1 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/MainWindow.java @@ -0,0 +1,130 @@ +package de.hsadmin.web; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.apache.xmlrpc.XmlRpcException; + +import com.vaadin.ui.AbstractSplitPanel; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.HorizontalSplitPanel; +import com.vaadin.ui.Panel; +import com.vaadin.ui.VerticalLayout; + +import de.hsadmin.model.TicketService; +import de.hsadmin.rpc.HSAdminSession; +import de.hsadmin.rpc.ModulesManager; +import de.hsadmin.rpc.ModulesManagerFactory; +import de.hsadmin.rpc.RpcException; + +public class MainWindow extends CustomComponent implements HSAdminSession { + + private static final long serialVersionUID = 1L; + + private static final Logger LOG = Logger.getLogger(MainWindow.class); + + public static final String[] SERVICE_URLS = new String[] { + "https://config2.hostsharing.net:443/hsar/xmlrpc/hsadmin", + "https://config.hostsharing.net:443/hsar/xmlrpc/hsadmin" + }; + + final private TicketService ticketService; + final private String grantingTicket; + final private String username; + + private ModulesManager modulesManager; + private AbstractSplitPanel content; + + public MainWindow(final TicketService ticketService, final String grantingTicket, final String username) { + this.ticketService = ticketService; + this.grantingTicket = grantingTicket; + this.username = username; + + setSizeFull(); + final Panel mainPanel = new Panel(); + mainPanel.setSizeFull(); + final VerticalLayout vl = new VerticalLayout(); + vl.setSizeFull(); + setCompositionRoot(mainPanel); + mainPanel.setContent(vl); + + try { + final MainToolbar mainToolbar = new MainToolbar(); + vl.addComponent(mainToolbar); + vl.setExpandRatio(mainToolbar, 0.0f); + final ModulesManagerFactory modulesManagerFactory = new ModulesManagerFactory(grantingTicket, username); + modulesManager = modulesManagerFactory.newModulesManager(SERVICE_URLS); + content = new HorizontalSplitPanel(); + content.setSizeFull(); + vl.addComponent(content); + vl.setExpandRatio(content, 1.0f); + final EntryPointsSelector entryPoints = new EntryPointsSelector(this); + entryPoints.setSizeFull(); + content.setFirstComponent(entryPoints); + content.setSecondComponent(new MainPanel()); + content.setSplitPosition(26.6f); + } catch (RpcException e) { + LOG.fatal(e.getLocalizedMessage(), e); + } + } + + /** + * Update center panel. + * @param source module name + * @param itemId + */ + public void setCenterPanel(final String source, final Object itemId) { + final AbstractPanelFactory panelFactory = FactoryProducer.getPanelFactory("panel"); + try { + IHSPanel panel = panelFactory.getPanel(source, this, itemId); + panel.setSizeFull(); + content.setSecondComponent(panel); + } catch (RpcException e) { + LOG.fatal(e.getLocalizedMessage(), e); + } + } + + public List list(final String moduleName, final String... columnNames) { + final List resultList = new ArrayList(); + try { + final List> searchResult = modulesManager.proxy(moduleName).search(username, ticketService.getServiceTicket(grantingTicket), new HashMap()); + for (Map valueMap : searchResult) { + final Object[] valueArr = new Object[columnNames.length]; + for (int idx = 0; idx < columnNames.length; idx++) { + valueArr[idx] = valueMap.get(columnNames[idx]); + } + resultList.add(valueArr); + } + } catch (XmlRpcException | RpcException e) { + LOG.fatal(e.getLocalizedMessage(), e); + } + return resultList; + } + + public String[] entryPointColumns(final String moduleName) { + return modulesManager.entryPointColumns(moduleName); + } + + @Override + public String getGrantingTicket() { + return grantingTicket; + } + + @Override + public TicketService getTicketService() { + return ticketService; + } + + @Override + public ModulesManager getModulesManager() { + return modulesManager; + } + + @Override + public String getUser() { + return username; + } +} diff --git a/web/src/main/java/de/hsadmin/web/NullEditor.java b/web/src/main/java/de/hsadmin/web/NullEditor.java new file mode 100644 index 0000000..165402f --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/NullEditor.java @@ -0,0 +1,32 @@ +package de.hsadmin.web; + +import java.util.Map; + +import com.vaadin.data.Validator; +import com.vaadin.ui.HorizontalLayout; + +public class NullEditor extends HorizontalLayout implements IHSEditor { + + private static final long serialVersionUID = 1L; + + @Override + public void setValues(Map valuesMap) { + + } + + @Override + public Object getValue() { + return null; + } + + @Override + public void addValidator(Validator validator) { + + } + + @Override + public boolean isValid() { + return true; + } + +} diff --git a/web/src/main/java/de/hsadmin/web/PacNamePrefixValidator.java b/web/src/main/java/de/hsadmin/web/PacNamePrefixValidator.java new file mode 100644 index 0000000..53ed830 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/PacNamePrefixValidator.java @@ -0,0 +1,23 @@ +package de.hsadmin.web; + +import com.vaadin.data.Validator; + +public class PacNamePrefixValidator implements Validator { + + private static final long serialVersionUID = 1L; + + private final PacNamePrefixed pacNameProvider; + + public PacNamePrefixValidator(final PacNamePrefixed pacPrefixed) { + this.pacNameProvider = pacPrefixed; + } + + @Override + public void validate(final Object value) throws InvalidValueException { + final String pacName = pacNameProvider.getPacName(); + if (value == null || !(value instanceof String) || !(((String )value).startsWith(pacName))) { + throw new InvalidValueException("name must start with package name \"" + pacName + "\""); + } + } + +} diff --git a/web/src/main/java/de/hsadmin/web/PacNamePrefixed.java b/web/src/main/java/de/hsadmin/web/PacNamePrefixed.java new file mode 100644 index 0000000..39d93fd --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/PacNamePrefixed.java @@ -0,0 +1,7 @@ +package de.hsadmin.web; + +public interface PacNamePrefixed { + + public String getPacName(); + +} diff --git a/web/src/main/java/de/hsadmin/web/PackagePanel.java b/web/src/main/java/de/hsadmin/web/PackagePanel.java new file mode 100644 index 0000000..5f92a76 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/PackagePanel.java @@ -0,0 +1,62 @@ +package de.hsadmin.web; + +import com.vaadin.ui.Component; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.Panel; +import com.vaadin.ui.TabSheet; +import com.vaadin.ui.TabSheet.SelectedTabChangeEvent; +import com.vaadin.ui.TabSheet.SelectedTabChangeListener; + +import de.hsadmin.rpc.HSAdminSession; +import de.hsadmin.rpc.RpcException; + +public class PackagePanel extends CustomComponent implements IHSPanel, SelectedTabChangeListener { + + private static final long serialVersionUID = 5397852733862398775L; + + private final HSAdminSession session; + + public PackagePanel(HSAdminSession session, Object itemId) throws RpcException { + this.session = session; + final Panel panel = new Panel(); + panel.setSizeFull(); + final TabSheet tabsheet = createTabs(itemId); + tabsheet.setSizeFull(); + panel.setContent(tabsheet); + setCompositionRoot(panel); + } + + @Override + public TabSheet createTabs(Object itemId) throws RpcException + { + final TabSheet tabsheet = new TabSheet(); + tabsheet.addSelectedTabChangeListener(this); + tabsheet.addTab(new GenericForm("pac", session, itemId, "name"), I18N.getText("pac")); + final HSTab usersTab = new HSTab("user", session, "pac", itemId, "name"); + usersTab.fillTable(); + tabsheet.addTab(usersTab, I18N.getText("user")); + final HSTab aliasTab = new HSTab("emailalias", session, "pac", itemId, "name"); + tabsheet.addTab(aliasTab, I18N.getText("emailalias")); + final HSTab domainTab = new HSTab("domain", session, "pac", itemId, "name"); + tabsheet.addTab(domainTab, I18N.getText("domain")); + + final HSTab mysqluserTab = new HSTab("mysqluser", session, "pac", itemId, "name"); + tabsheet.addTab(mysqluserTab, I18N.getText("mysqluser")); + final HSTab mysqldbTab = new HSTab("mysqldb", session, "pac", itemId, "name"); + tabsheet.addTab(mysqldbTab, I18N.getText("mysqldb")); + final HSTab postgresqluserTab = new HSTab("postgresqluser", session, "pac", itemId, "name"); + tabsheet.addTab(postgresqluserTab, I18N.getText("postgresqluser")); + final HSTab postgresqldbTab = new HSTab("postgresqldb", session, "pac", itemId, "name"); + tabsheet.addTab(postgresqldbTab, I18N.getText("postgresqldb")); + return tabsheet; + } + + @Override + public void selectedTabChange(SelectedTabChangeEvent event) { + final Component tab = event.getTabSheet().getSelectedTab(); + if (tab instanceof HSTab) { + ((HSTab) tab).fillTable(); + } + } + +} diff --git a/web/src/main/java/de/hsadmin/web/PanelFactory.java b/web/src/main/java/de/hsadmin/web/PanelFactory.java new file mode 100644 index 0000000..1a21c8f --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/PanelFactory.java @@ -0,0 +1,27 @@ +package de.hsadmin.web; + +import de.hsadmin.rpc.HSAdminSession; +import de.hsadmin.rpc.RpcException; + +public class PanelFactory extends AbstractPanelFactory { + + @Override + public IHSPanel getPanel(String panelType, HSAdminSession session, Object itemId) throws RpcException + { + IHSPanel instance = null; + if (panelType.equals("hive")) { + instance = new ServerPanel(session, itemId); + } + if (panelType.equals("domain")) { + instance = new DomainPanel(session, itemId); + } + if (panelType.equals("pac")) { + instance = new PackagePanel(session, itemId); + } + if (panelType.equals("customer")) { + instance = new CustomerPanel(session, itemId); + } + return instance; + } + +} diff --git a/web/src/main/java/de/hsadmin/web/PanelToolbar.java b/web/src/main/java/de/hsadmin/web/PanelToolbar.java new file mode 100644 index 0000000..1fdc5eb --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/PanelToolbar.java @@ -0,0 +1,129 @@ +package de.hsadmin.web; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.xmlrpc.XmlRpcException; + +import com.vaadin.server.ThemeResource; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.UI; +import com.vaadin.ui.Window; + +import de.hsadmin.model.IRemote; +import de.hsadmin.model.TicketService; +import de.hsadmin.rpc.HSAdminSession; +import de.hsadmin.rpc.RpcException; + +public class PanelToolbar extends HorizontalLayout implements ClickListener { + + private static final long serialVersionUID = 1L; + + public static final String ACTION_NEW = "new"; + public static final String ACTION_EDIT = "edit"; + public static final String ACTION_DELETE = "delete"; + public static final String ACTION_VIEW = "view"; + public static final String ACTION_REFRESH = "refresh"; + public static final String ACTION_HELP = "help"; + + private final HSAdminSession session; + private final HSTab parent; + private final String module; + + private final Button newBtn, editBtn, deleteBtn, refreshBtn, helpBtn; + + public PanelToolbar(final String source, final HSAdminSession session, final HSTab parent) + { + super(); + this.module = source; + this.session = session; + this.parent = parent; + newBtn = createButton("New_" + source, "new", "new.tooltip"); + addComponent(newBtn); + editBtn = createButton("Edit_" + source, "edit", "edit.tooltip"); + addComponent(editBtn); + deleteBtn = createButton("Delete_" + source, "trash", "delete.tooltip"); + addComponent(deleteBtn); + refreshBtn = createButton("Refresh_" + source, "reload", "refresh.tooltip"); + addComponent(refreshBtn); + helpBtn = createButton("Help", "question", "help.tooltip"); + addComponent(helpBtn); + } + + private Button createButton(String name, String image, String tooltip) { + Button btn = new Button(); + btn.setId(name + "-btn"); + if (image != null) { + btn.setIcon(new ThemeResource("../icons/" + image + "-icon.png")); + } + btn.setDescription(I18N.getText(tooltip)); + btn.setStyleName("borderless"); + btn.addClickListener(this); + return btn; + } + + @Override + public void buttonClick(ClickEvent event) + { + String action = null; + if (event.getButton().equals(newBtn)) { + action = ACTION_NEW; + } else if (event.getButton().equals(editBtn)) { + action = ACTION_EDIT; + } else if (event.getButton().equals(deleteBtn)) { + action = ACTION_DELETE; + } else if (event.getButton().equals(refreshBtn)) { + action = ACTION_REFRESH; + } else if (event.getButton().equals(helpBtn)) { + action = ACTION_HELP; + } + if (ACTION_REFRESH.equals(action)) { + parent.fillTable(); + return; + } + final Object value = parent.getSelection(); + if (value == null) { + if (ACTION_EDIT.equals(action) || ACTION_DELETE.equals(action)) { + UI.getCurrent().addWindow(new InfoWindow(I18N.getText("emptySelectionMessage") + " " + action)); + return; + } + } + final AbstractWindowFactory windowFactory = FactoryProducer.getWindowFactory("subwindow"); + String type = null; + final String buttonId = event.getButton().getId(); + if (buttonId == null) { + return; + } + type = buttonId.substring(buttonId.indexOf("_") + 1, buttonId.indexOf("-")); + final Window window = windowFactory.getSubWindow(parent, type, action, session); + if (ACTION_EDIT.equals(action) || ACTION_DELETE.equals(action)) { + final IRemote remote = session.getModulesManager().proxy(module); + final HashMap whereParams = new HashMap(); + whereParams.put(parent.getRowIdName(), value.toString()); + try { + final TicketService ticketService = session.getTicketService(); + final String grantingTicket = session.getGrantingTicket(); + final String serviceTicket = ticketService.getServiceTicket(grantingTicket); + final String user = session.getUser(); + final List> list = remote.search(user, serviceTicket, whereParams); + ((IHSWindow) window).setFormData(list.get(0), whereParams); + } catch (XmlRpcException | RpcException e) { + e.printStackTrace(); + } + } + if (ACTION_NEW.equals(action)) { + final Map whereParams = new HashMap(); + final Map parentParams = new HashMap(); + parentParams.put(parent.getSelectPropertyName(), parent.getSelectPropertyValue()); + ((IHSWindow) window).setFormData(parentParams, whereParams); + } + if (window != null) { + UI.getCurrent().addWindow(window); + } + } + +} diff --git a/web/src/main/java/de/hsadmin/web/PasswordValidator.java b/web/src/main/java/de/hsadmin/web/PasswordValidator.java new file mode 100644 index 0000000..bf0398c --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/PasswordValidator.java @@ -0,0 +1,62 @@ +package de.hsadmin.web; + +import com.vaadin.data.Validator; + +public class PasswordValidator implements Validator { + + private static final int MIN_PASSWORD_LEN = 6; + + private static final long serialVersionUID = 1L; + + private final boolean required; + + public PasswordValidator(final boolean passwordRequired) { + this.required = passwordRequired; + } + + @Override + public void validate(final Object value) throws InvalidValueException { + if (value == null) { + if (required) { + throw new InvalidValueException("password required"); + } else { + return; + } + } + final String password = (String) value; + if (password.isEmpty()) { + if (required) { + throw new InvalidValueException("password required"); + } else { + return; + } + } + if (password.length() < MIN_PASSWORD_LEN) { + throw new InvalidValueException("minimal password length is " + MIN_PASSWORD_LEN + " characters"); + } + int hasLowerCaseChar = 0; + int hasUpperCaseChar = 0; + int hasDigits = 0; + int hasSpecialChar = 0; + for (int idx = 0; idx < password.length(); idx++) { + final char test = password.charAt(idx); + final int type = Character.getType(test); + if (type == Character.DECIMAL_DIGIT_NUMBER) { + hasDigits = 1; + } else { + if (type == Character.LOWERCASE_LETTER) { + hasLowerCaseChar = 1; + } else + if (type == Character.UPPERCASE_LETTER) { + hasUpperCaseChar = 1; + } else + hasSpecialChar = 1; + } + } + if (hasDigits + hasLowerCaseChar + hasUpperCaseChar + hasSpecialChar < 3) { + throw new InvalidValueException("a password requires 3 out of 4 " + + "different character types: lowercase, uppercase, digits and special characters"); + } + } + +} diff --git a/web/src/main/java/de/hsadmin/web/ServerPanel.java b/web/src/main/java/de/hsadmin/web/ServerPanel.java new file mode 100644 index 0000000..87ffdd1 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/ServerPanel.java @@ -0,0 +1,48 @@ +package de.hsadmin.web; + +import com.vaadin.ui.Component; +import com.vaadin.ui.CustomComponent; +import com.vaadin.ui.Panel; +import com.vaadin.ui.TabSheet; +import com.vaadin.ui.TabSheet.SelectedTabChangeEvent; +import com.vaadin.ui.TabSheet.SelectedTabChangeListener; + +import de.hsadmin.rpc.HSAdminSession; + +public class ServerPanel extends CustomComponent implements IHSPanel, SelectedTabChangeListener { + + private static final long serialVersionUID = 5720017114380927259L; + + private final HSAdminSession session; + + public ServerPanel(HSAdminSession session, Object itemId) { + this.session = session; + final Panel panel = new Panel(); + + TabSheet tabsheet = createTabs(itemId); + tabsheet.setSizeFull(); + panel.setContent(tabsheet); + + setCompositionRoot(panel); + setSizeFull(); + } + + @Override + public TabSheet createTabs(Object itemId) { + + TabSheet tabsheet = new TabSheet(); + tabsheet.addTab(new HSTab("package", session, "hive", itemId, "name"), "Packages"); + tabsheet.addTab(new HSTab("network", session, "hive", itemId, "name"), "Network"); + + return tabsheet; + } + + @Override + public void selectedTabChange(SelectedTabChangeEvent event) { + Component tab = event.getTabSheet().getSelectedTab(); + if (tab instanceof HSTab) { + ((HSTab) tab).fillTable(); + } + } + +} diff --git a/web/src/main/java/de/hsadmin/web/SubWindowFactory.java b/web/src/main/java/de/hsadmin/web/SubWindowFactory.java new file mode 100644 index 0000000..cd03f37 --- /dev/null +++ b/web/src/main/java/de/hsadmin/web/SubWindowFactory.java @@ -0,0 +1,26 @@ +package de.hsadmin.web; + +import java.util.HashMap; +import java.util.Map; + +import com.vaadin.ui.Window; + +import de.hsadmin.rpc.HSAdminSession; + +public class SubWindowFactory extends AbstractWindowFactory { + + @Override + public Window getSubWindow(HSTab parent, String type, String action, HSAdminSession session) + { + if (type == null) { + return null; + } + if (action.equalsIgnoreCase("help")) { + return new HelpWindow(); + } + final Map whereContext = new HashMap<>(); + whereContext.put(parent.getSelectPropertyName(), parent.getSelectPropertyValue().toString()); + return new GenericFormWindow(parent, type, action, session, whereContext); + } + +} diff --git a/web/src/main/resources/de/hsadmin/web/main.properties b/web/src/main/resources/de/hsadmin/web/main.properties new file mode 100644 index 0000000..4b9fa6a --- /dev/null +++ b/web/src/main/resources/de/hsadmin/web/main.properties @@ -0,0 +1,167 @@ +main.panel.title=Welcome +main.panel.text=to the hostsharing admin application +main.panel.link_to_old=Link to the old HSAdmin-UI +user=User +domain=Domain +emailaddress=Email Address +pac=Package +emailalias=Email Alias +mysqluser=MySql User +mysqldb=MySql Database +postgresqluser=Postgresql User +postgresqldb=Postgresql Database +name=Name +basepac=Base package +hive=Server +unixuser=User/Mailbox +curinetaddr=Network Address +user.name=Username +user.pac=Package +user.comment=Comment +user.shell=Shell +user.homedir=Home +user.locked=Locked +user.quota_softlimit=Quota soft limit +user.quota_hardlimit=Quota hard limit +emailalias.name=Email alias name +emailalias.pac=Package +emailalias.target=Target +domain.name=Domain name +domain.user=Domain User +domain.since=Domain since +domain.dnsMaster=DNS master +domain.domainoptions=Domain options +domainoption.greylisting=greylisting +domainoption.multiviews=multiviews +domainoption.indexes=indexes +domainoption.htdocsfallback=htdocsfallback +domainoption.includes=includes +domainoption.backupmxforexternalmx=backupmxforexternalmx +mysqluser.name=MySql username +mysqluser.instance=MySql instance +mysqluser.pac=MySql package +mysqldb.name=MySql DB name +mysqldb.instance=MySql DB instance +mysqldb.owner=MySql owner +mysqldb.pac=MySql package +mysqldb.encoding=MySql encoding +postgresqluser.name=Postgres username +postgresqluser.instance=Postgres instance +postgresqluser.pac=Postgres package +postgresqldb.name=Postgres DB name +postgresqldb.instance=Postgres DB instance +postgresqldb.owner=Postgres owner +postgresqldb.pac=Postgres package +postgresqldb.encoding=Postgres encoding +since=Since +dnsMaster=DNS master +domainoptions=Domain options +emailaddress.localpart=Local part +emailaddress.subdomain=Subdomain +emailaddress.domain=Domain +emailaddress.target=Target +emailaddress.target=Target +emailtarget.alias=Alias +emailtarget.email=EMail +emailtarget.postbox=Postbox +new.tooltip=New +edit.tooltip=Edit +delete.tooltip=Delete +refresh.tooltip=Refresh +help.tooltip=Help +new=New +edit=Edit +delete=Delete +refresh=Refresh +customer=Customer +contact=Contact +cancel=Cancel +ok=Ok +mandat=Mandat +password=Password +login.title=Sign in +login.button=Sign in +logout.tooltip=Sign out +comment=Comment +shell=Shell +quota_softlimit=Quota soft limit +quota_hardlimit=Quota hard limit +target=Target +owner=Owner +encoding=Encoding +localpart=Local part +subdomain=Subdomain +domain=Domain +target=Target +homedir=Home +locked=Locked +instance=Instance +emptySelectionMessage=Please select a record to +memberNo=Member No +memberRole=Role +memberSince=Member since +memberUntil=Member Until +authorContract=Author Contract +nonDiscContract=Non Disclosure Contract +sharesUpdated=Shares Update Date +sharesSigned=Shared Signed +free=free +exemptVAT=Exempt VAT +indicatorVAT=Indicator VAT +uidVAT=UID VAT +contact.customer=Member uid +contact.salut=Salutation +contact.firstName=First name +contact.lastName=Last name +contact.title=Title +contact.firma=Organization +contact.co=c/o +contact.street=Street +contact.zipCode=ZIP +contact.city=City +contact.country=Country +contact.phonePrivate=Phone private +contact.phoneOffice=Phone office +contact.phoneMobile=Phone mobile +contact.fax=Fax +contact.email=Email +contact.roles=Roles +salut=Salutation +firstName=First name +lastName=Last name +title=Title +firma=Organization +co=c/o +street=Street +zipCode=ZIP +city=City +country=Country +phonePrivate=Phone private +phoneOffice=Phone office +phoneMobile=Phone mobile +fax=Fax +email=Email +roles=Roles +mandat.customer=Member uid +mandat.bankCustomer=Bank customer +mandat.bankName=Bank name +mandat.bankIBAN=IBAN +mandat.bankBIC=BIC +mandat.mandatRef=Mandat ref +mandat.mandatSigned=Date signed +mandat.mandatSince=Date since +mandat.mandatUntil=Date until +mandat.mandatUsed=Date used +bankCustomer=Bank customer +bankName=Bank name +bankIBAN=IBAN +bankBIC=BIC +mandatRef=Mandat ref +mandatSigned=Date signed +mandatSince=Date since +mandatUntil=Date until +mandatUsed=Date used +pac.name=Packet name +pac.basepac=Packet type +pac.hive=Packet server +pac.curinetaddr=IPv4 address diff --git a/web/src/main/resources/de/hsadmin/web/main_de.properties b/web/src/main/resources/de/hsadmin/web/main_de.properties new file mode 100644 index 0000000..566979b --- /dev/null +++ b/web/src/main/resources/de/hsadmin/web/main_de.properties @@ -0,0 +1,164 @@ +main.panel.title=Willkommen +main.panel.text=in der Hostsharing Administration +main.panel.link_to_old=Schnell zum alten HSAdmin-UI +user=User/Postfach +domain=Domain +emailaddress=EMail-Adresse +pac=Web-Paket +emailalias=EMail-Alias +mysqluser=MySql User +mysqldb=MySql Datenbank +postgresqluser=Postgresql User +postgresqldb=Postgresql Datenbank +name=Name +basepac=Paket-Typ +hive=Server +unixuser=User/Postfach +curinetaddr=Netzwerk-Adresse (IPv4) +user.name=User/Postfach +user.pac=Web-Paket +user.comment=Kurzbeschreibung +user.shell=Shell/Kommando-Interpreter +user.homedir=Heimat-Verzeichnis +user.locked=Gesperrt +user.quota_softlimit=Quota (Soft-Limit) +user.quota_hardlimit=Quota (Hard-Limit) +emailalias.name=EMail-Alias +emailalias.pac=Web-Paket +emailalias.target=Postfach/Weiterleitung +domain.name=Domain-Name +domain.user=Domain-Administrator +domain.since=eingerichtet am +domain.dnsMaster=DNS Server +domain.domainoptions=Domain-Optionen +domainoption.greylisting=Greylisting +domainoption.multiviews=Multiviews +domainoption.indexes=Indexes +domainoption.htdocsfallback=htdocsfallback +domainoption.includes=Includes +domainoption.backupmxforexternalmx=Backupmx for external MX +mysqluser.name=MySql User +mysqluser.instance=Datenbank-System +mysqluser.pac=Web-Paket +mysqldb.name=MySql Datenbank +mysqldb.instance=Datenbank-System +mysqldb.owner=MySql User +mysqldb.pac=Web-Paket +mysqldb.encoding=Zeichen-Kodierung +postgresqluser.name=PostgreSQL User +postgresqluser.instance=Datenbank-System +postgresqluser.pac=Web-Paket +postgresqldb.name=PostgreQL Datenbank +postgresqldb.instance=Datenbank-System +postgresqldb.owner=Postgres User +postgresqldb.pac=Web-Paket +postgresqldb.encoding=Zeichen-Kodierung +since=eingerichtet am +dnsMaster=DNS Server +domainoptions=Domain-Optionen +emailaddress.localpart=lokaler Teil +emailaddress.subdomain=Subdomain +emailaddress.domain=Domain +emailaddress.target=Ziel/Weiterleitung +emailtarget.alias=Alias +emailtarget.email=E-Mail +emailtarget.postbox=Postfach +new.tooltip=Neuen Eintrag anlegen +edit.tooltip=Ausgewählten Eintrag bearbeiten +delete.tooltip=Ausgewählten Eintrag löschen +refresh.tooltip=Tabelle neu laden +help.tooltip=Hilfetext anzeigen +new=neu +edit=ändern +delete=löschen +refresh=neu laden +customer=Kunde/Mitglied +contact=Ansprechpartner +cancel=abbrechen +ok=Ok +mandat=SEPA-Mandat +password=Passwort +login.title=Anmeldung +login.button=anmelden +logout.tooltip=abmelden +comment=Kurzbeschreibung +shell=Shell/Kommando-Interpreter +quota_softlimit=Quota (Soft-Limit) +quota_hardlimit=Quota (Hard-Limit) +target=Postfach/Weiterleitung +owner=Domain-Administrator +encoding=Zeichen-Kodierung +localpart=lokaler Teil +subdomain=Subdomain +homedir=Heimat-Verzeichnis +locked=gesperrt +instance=Datenbank-System +emptySelectionMessage=Bitte wählen Sie einen Tabellen-Eintrag zur Bearbeitung +memberNo=Mitglieds-Nr. +memberRole=Rolle / Aufgaben +memberSince=Eintrittsdatum +memberUntil=Austrittsdatum +authorContract=Autorenvereinbarung +nonDiscContract=Datenschutzvereinbarung +sharesUpdated=Anteile (letzte Änd.) +sharesSigned=Anteile +free=frei +exemptVAT=Umsatzsteuerbefreit +indicatorVAT=USt. Indikator +uidVAT=Umsatzsteuer-ID +contact.customer=Mitglieds-Kennung +contact.salut=Anrede +contact.firstName=Vorname +contact.lastName=Nachname +contact.title=Titel +contact.firma=Organisation +contact.co=c/o +contact.street=Straße +contact.zipCode=PLZ +contact.city=Ort +contact.country=Land +contact.phonePrivate=Tel. privat +contact.phoneOffice=Tel. dienstl. +contact.phoneMobile=Tel. mobil +contact.fax=Fax +contact.email=E-Mail +contact.roles=Rollen +salut=Anrede +firstName=Vorname +lastName=Nachname +title=Titel +firma=Organisation +co=c/o +street=Straße +zipCode=PLZ +city=Ort +country=Land +phonePrivate=Tel. privat +phoneOffice=Tel. dienstl. +phoneMobile=Tel. mobil +fax=Fax +email=E-Mail +roles=Rollen +mandat.customer=Mitglieds-Kennung +mandat.bankCustomer=Konto-Inhaber +mandat.bankName=Bank +mandat.bankIBAN=IBAN +mandat.bankBIC=BIC +mandat.mandatRef=Mandatsreferenz +mandat.mandatSigned=gezeichnet am +mandat.mandatSince=gültig ab +mandat.mandatUntil=gültig bis +mandat.mandatUsed=genutzt am +bankCustomer=Konto-Inhaber +bankName=Bank +bankIBAN=IBAN +bankBIC=BIC +mandatRef=Mandatsreferenz +mandatSigned=gezeichnet am +mandatSince=gültig ab +mandatUntil=gültig bis +mandatUsed=genutzt am +pac.name=Paket-Name +pac.basepac=Paket-Typ +pac.hive=Server/Hive +pac.curinetaddr=Netzwerk-Adresse (IPv4) diff --git a/web/src/main/resources/de/hsadmin/web/main_es.properties b/web/src/main/resources/de/hsadmin/web/main_es.properties new file mode 100644 index 0000000..008f2fd --- /dev/null +++ b/web/src/main/resources/de/hsadmin/web/main_es.properties @@ -0,0 +1,164 @@ +user=Usuario +domain=Dominio +emailaddress=Dirección de correo +pac=Paquete +emailalias=Email Alias +mysqluser=Usuario MySql +mysqldb=Base de datos MySql +postgresqluser=Usuario Postgresql +postgresqldb=Base de datos Postgresql +name=Nombre +basepac=Paquete base +hive=Hive +unixuser=Usuario Unix +curinetaddr=Dirección de red +user.name=Nombre de usuario +user.pac=Paquete +user.comment=Comentario +user.shell=Shell +user.homedir=Inicio +user.locked=Bloqueado +user.quota_softlimit=Quota soft limit +user.quota_hardlimit=Quota hard limit +emailalias.name=Nombre de alias +emailalias.pac=Paquete +emailalias.target=Destino +domain.name=Nombre de dominio +domain.user=Usuario de dominio +domain.since=Dominio desde +domain.dnsMaster=Maestro DNS +domain.domainoptions=Opciones de dominio +domainoption.greylisting=greylisting +domainoption.multiviews=multiviews +domainoption.indexes=indexes +domainoption.htdocsfallback=htdocsfallback +domainoption.includes=includes +domainoption.backupmxforexternalmx=backupmxforexternalmx +mysqluser.name=Nombre de usuario MySql +mysqluser.instance=Instancia de MySql +mysqluser.pac=Paquete de usuario MySql +mysqldb.name=Nombre de base de datos MySql +mysqldb.instance=Instancia de base de datos MySql +mysqldb.owner=Propietario base de datos MySql +mysqldb.pac=Paquete base de datos MySql +mysqldb.encoding=Codificación base de datos MySql +postgresqluser.name=Nombre de base de datos Postgres +postgresqluser.instance=Instancia de base de datos Postgres +postgresqluser.pac=Paquete base de datos Postgres +postgresqldb.name=Nombre de base de datos Postgres +postgresqldb.instance=Instancia de base de datos Postgres +postgresqldb.owner=Propietario base de datos Postgres +postgresqldb.pac=Paquete base de datos Postgres +postgresqldb.encoding=Codificación base de datos Postgres +since=Desde +dnsMaster=Maestro DNS +domainoptions=Opciones de dominio +emailaddress.localpart=Parte local +emailaddress.subdomain=Sub-dominio +emailaddress.domain=Dominio +emailaddress.target=Destino +emailtarget.alias=Alias +emailtarget.email=EMail +emailtarget.postbox=Postbox +new.tooltip=Nuevo +edit.tooltip=Editar +delete.tooltip=Eliminar +refresh.tooltip=Refrescar +help.tooltip=Ayuda +new=Nuevo +edit=Editar +delete=Eliminar +refresh=Refrescar +help=Ayuda +customer=Cliente +contact=Contacto +cancel=Cancelar +ok=Ok +mandat=Mandato electrónico +password=Contraseña +login.title=Iniciar sesión +login.button=Iniciar sesión +logout.tooltip=Finalizar Sesión +comment=Comentario +shell=Shell +quota_softlimit=Quota soft limit +quota_hardlimit=Quota hard limit +target=Destino +owner=Propietario +encoding=Codificación +localpart=Parte local +subdomain=Sub-dominio +domain=Dominio +target=Destino +homedir=Inicio +locked=Bloqueado +instance=Instancia +emptySelectionMessage=Por favor seleccione un registro para +memberNo=Member No +memberRole=Role +memberSince=Member since +memberUntil=Member Until +authorContract=Author Contract +nonDiscContract=Non Disclosure Contract +sharesUpdated=Shares Update Date +sharesSigned=Shared Signed +free=free +exemptVAT=Exempt VAT +indicatorVAT=Indicator VAT +uidVAT=UID VAT +contact.customer=Member uid +contact.salut=Salutation +contact.firstName=First name +contact.lastName=Last name +contact.title=Title +contact.firma=Organization +contact.co=c/o +contact.street=Street +contact.zipCode=ZIP +contact.city=City +contact.country=Country +contact.phonePrivate=Phone private +contact.phoneOffice=Phone office +contact.phoneMobile=Phone mobile +contact.fax=Fax +contact.email=Email +contact.roles=Roles +salut=Salutation +firstName=First name +lastName=Last name +title=Title +firma=Organization +co=c/o +street=Street +zipCode=ZIP +city=City +country=Country +phonePrivate=Phone private +phoneOffice=Phone office +phoneMobile=Phone mobile +fax=Fax +email=Email +roles=Roles +mandat.customer=Member uid +mandat.bankCustomer=Bank customer +mandat.bankName=Bank name +mandat.bankIBAN=IBAN +mandat.bankBIC=BIC +mandat.mandatRef=Mandat ref +mandat.mandatSigned=Date signed +mandat.mandatSince=Date since +mandat.mandatUntil=Date until +mandat.mandatUsed=Date used +bankCustomer=Bank customer +bankName=Bank name +bankIBAN=IBAN +bankBIC=BIC +mandatRef=Mandat ref +mandatSigned=Date signed +mandatSince=Date since +mandatUntil=Date until +mandatUsed=Date used +pac.name=Packet name +pac.basepac=Packet type +pac.hive=Packet server +pac.curinetaddr=IPv4 address diff --git a/web/src/main/resources/log4j.properties b/web/src/main/resources/log4j.properties new file mode 100644 index 0000000..76c0b41 --- /dev/null +++ b/web/src/main/resources/log4j.properties @@ -0,0 +1,5 @@ +log4j.rootLogger=INFO, console +log4j.appender.console = org.apache.log4j.ConsoleAppender +;log4j.appender.console.target=System.out +log4j.appender.console.layout = org.apache.log4j.PatternLayout +log4j.appender.console.layout.ConversionPattern = %d{[dd.MM.yyyy] [HH:mm:ss]} %p [%t] %c (%F:%L) - %m%n diff --git a/web/src/main/webapp/META-INF/MANIFEST.MF b/web/src/main/webapp/META-INF/MANIFEST.MF new file mode 100644 index 0000000..5e94951 --- /dev/null +++ b/web/src/main/webapp/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/web/src/main/webapp/VAADIN/themes/hs_admin_peter/addons.scss b/web/src/main/webapp/VAADIN/themes/hs_admin_peter/addons.scss new file mode 100644 index 0000000..a5670b7 --- /dev/null +++ b/web/src/main/webapp/VAADIN/themes/hs_admin_peter/addons.scss @@ -0,0 +1,7 @@ +/* This file is automatically managed and will be overwritten from time to time. */ +/* Do not manually edit this file. */ + +/* Import and include this mixin into your project theme to include the addon themes */ +@mixin addons { +} + diff --git a/web/src/main/webapp/VAADIN/themes/hs_admin_peter/hs_admin_peter.scss b/web/src/main/webapp/VAADIN/themes/hs_admin_peter/hs_admin_peter.scss new file mode 100644 index 0000000..efa0e82 --- /dev/null +++ b/web/src/main/webapp/VAADIN/themes/hs_admin_peter/hs_admin_peter.scss @@ -0,0 +1,36 @@ +// Global variable overrides. Must be declared before importing Valo. + +// Defines the plaintext font size, weight and family. Font size affects general component sizing. +//$v-font-size: 16px; +//$v-font-weight: 300; +//$v-font-family: "Open Sans", sans-serif; + +// Defines the border used by all components. +//$v-border: 1px solid (v-shade 0.7); +//$v-border-radius: 4px; + +// Affects the color of some component elements, e.g Button, Panel title, etc +//$v-background-color: hsl(210, 0%, 98%); +// Affects the color of content areas, e.g Panel and Window content, TextField input etc +//$v-app-background-color: $v-background-color; + +// Affects the visual appearance of all components +//$v-gradient: v-linear 8%; +//$v-bevel-depth: 30%; +//$v-shadow-opacity: 5%; + +// Defines colors for indicating status (focus, success, failure) +//$v-focus-color: valo-focus-color(); // Calculates a suitable color automatically +//$v-friendly-color: #2c9720; +//$v-error-indicator-color: #ed473b; + +// For more information, see: https://vaadin.com/book/-/page/themes.valo.html +// Example variants can be copy/pasted from https://vaadin.com/wiki/-/wiki/Main/Valo+Examples + +@import "../valo/valo.scss"; + +@mixin hs_admin_peter { + @include valo; + + // Insert your own theme rules here +} diff --git a/web/src/main/webapp/VAADIN/themes/hs_admin_peter/styles.scss b/web/src/main/webapp/VAADIN/themes/hs_admin_peter/styles.scss new file mode 100644 index 0000000..a8f1271 --- /dev/null +++ b/web/src/main/webapp/VAADIN/themes/hs_admin_peter/styles.scss @@ -0,0 +1,9 @@ +@import "addons.scss"; +@import "hs_admin_peter.scss"; + +/* This file prefixes all rules with the theme name to avoid causing conflicts with other themes. */ +/* The actual styles should be defined in hs_admin_peter.scss */ +.hs_admin_peter { + @include addons; + @include hs_admin_peter; +} diff --git a/web/src/main/webapp/VAADIN/themes/icons/addons.scss b/web/src/main/webapp/VAADIN/themes/icons/addons.scss new file mode 100644 index 0000000..a5670b7 --- /dev/null +++ b/web/src/main/webapp/VAADIN/themes/icons/addons.scss @@ -0,0 +1,7 @@ +/* This file is automatically managed and will be overwritten from time to time. */ +/* Do not manually edit this file. */ + +/* Import and include this mixin into your project theme to include the addon themes */ +@mixin addons { +} + diff --git a/web/src/main/webapp/VAADIN/themes/icons/bars-icon.png b/web/src/main/webapp/VAADIN/themes/icons/bars-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..666bef3daae8d7d4369262a851f5b706fef7d1a9 GIT binary patch literal 302 zcmV+}0nz@6P)Ob_4%42(R7U?dobr}P+VU?iF-2nue{ z&B$)p%))k3HNiZp=7aZrgSk-#Spe`N*|u$6SHXUzR1gG+NK2%$d7dxJB1=?NRaury zClRv%V4mkEEQxK~Vw~%`+H={y@26=Ju#{3sk~og@fipF~c_@a6c}hI-@6Xx-FN>Mboroks6K0X0yq!8HBLeY$nxix9j_US^{}p6h($% ywA*dRabhAMgq==D*YzL>^7*F^{CDv`etZu@d^7o|=C)q|0000P000;W0ssI2fY-s100003b3#c}2nYz< z;ZNWI00MJKL_t(IjjdI^Yx+ zJkJ9FL{WTsc?kppy1fkREplX637K_El#|HqwYPDuE z8JEjt;5C^{LZOf-imQiThyDHix3@Qg9(Q+lFD@>AZv+5{L?URY>2W@v$K!EyMjJqq zWICNj8O`jsx3?FI1d3)hu)zzvy}bnh;5fdsvx8xnAP8~-LMTbn$;k<-et3B3 z_xnodbUHmAPcRrfJUj%tcLG9qb#*lwjT9ypizO0?y}do2=NX1U2k-TIbGaN^Npnvu zmrLD@3WY+UP%!QY!ytrPTk4cF^Ll)IX0ssI2RYD?%00003b3#c}2nYz< z;ZNWI00L=AL_t(Ijm=dtYw}POy-_km*|)WM|%#YqaCs@P63vkykh(|l6s@}244a}Vd;d&7Gn5JK>0 zDE@8%0IGi#DwRsR-4^1@%gab4^4nhU>3Y51t^?EQE0KnnlVX0Iy zo6S2e^Z7g+4s#s0XL1RSkB?ie*3Lv)tu_z{{N4fp;_6;^G3|#U8lb?%Ug2 zoY`*o;NW1rUgL#CBGGI%`~7~cR`dCMcV7lvUblZnVu6qQP)a9ui` z?smIkYPDKTCX>tMibkUVKsX!@iLpwh>U269jRq%anocH@5~aalXf~T5djoVjox}nF zj7H;6r3e|9*=)94E+ypq`}-ajWj>!jIyzD+l`P8&6wmVrq0`e-Tz7SKH6D+}^yK8k zX0x52pIa;z5Wh6f^RZZLI-QETWHL#Tq+YLQ7^Yk<7GJ^X}qhkH@oEEW{aQHQ(fa^e6cQ X!-*oI{+?m@00000NkvXXu0mjfivmL? literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/VAADIN/themes/icons/copy-icon.png b/web/src/main/webapp/VAADIN/themes/icons/copy-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f4ef8121e9a0cc59366ed81e77e270ef4a75b3eb GIT binary patch literal 576 zcmV-G0>AxxqNbZewR8fmkU@))3j=}x>zhMqk%x6 z+wEG0u0k!nhr@xU>E&_>06w3u*Xx<1p-|{_I=z4b0P^TkRkc#7ESF0h$6pu!f-6Z< zxm;ea*Eo*1TCI<{H**jKfugA0Zg+(uh{e}jbv~bm!y(6U=7Asx5{X1Yq0kLik|dHO zWm&d`0sznR^?Lo$-|zQFqtOkw)9J{v3;?s)ESt@myD(R3nr7I=Vlftr8OvI&CW_+K z{^5?tW1|k~YkRJ$svO4wfUfJC&BpM1Jf3hk{5kh{JOThg5DdfECL4Np z-+rraaqr)UbUJ;PVf!T7aB&C00003b3#c}2nYz< z;ZNWI00Ub|L_t(YiM3WSPwG$@y;O{Cqft`_6`>_=h9Zh2WiW9eK_PJp z1FkIo0tVbzG|`yAz(nhyDTx9@Ed@fN3D}03w6<@!iI0cXsxO|Y_q*Rcr|r4l{jS3_ zP4JsQew7^n;Iz#!4CCS9q0wkalB6h#s;Zi%VHk#C7(oyokB6eD>FMcj3+TFDC=@O( zE;x=;6y@`m@Or)Ba5#}jkR&-Y<*@XC=lP?fqh_=DIq!SKoP1*;%*SwM-a-VHnkF_2lFv5{Voi z9}iA_SZEx_aU2H#peTx>D3T=S=H@UA!*P6cbW~N-zQeHOsO*&r6cj>2!vYF${CLT+n2OVcc%FX_}HGx!rCXfp9n+i^aCLw|zdJ!{LBI zUDx~l{@^acar|wGqA0~;F_+8HG<|Sz@D{iBK-08*KA+F$r>3TSKA+d?B}sC2b{5BR z9LJqbr!32ZCf91UySuyB*H-|5-|ru!vKH|B{kONb0Dx|{TPl@GrIKZuC6ySp2Y#|eUf5lz$D?e_blVrFIrCYYvqb90l+J(N_ij2fu!G`~$aA0VXW7J0t)A002ovPDHLk FV1kZvzvKV_ literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/VAADIN/themes/icons/delete-user-icon.png b/web/src/main/webapp/VAADIN/themes/icons/delete-user-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..eeb28991ae49693f65a6d6ce5da9e6a5fafd8609 GIT binary patch literal 765 zcmV&?THGYcAgm~8JS+r3P-)L3 zoRpRmk+h?RhFU_>Nu6AD5G-maY$#D^vFL;&(B%CM7ni6%IgY;D^YDE>FYoibeyhKGkmav6r% z+S+0mrqgOP8iT>0K(4ecj>TeKp#YH0W{bt5NbbYKLl5`;{k=$Ty+2GUq^lLj@r8v2k=*I&X@|qn>66RlKA*3@zh4ZuUaxeHX4ltK^z?& z)oQix@9(Flr+hwNE|(EPx3{;Oo0}IG7sX<6X=#Zd2(#Jz^76u!vn;!}w?`1f;^Ja5 znM4Tv+>7Jm?(U9Dj*pLDUtdcQLZwn^dwW|**Or%;4-XIBZg-(j;L$ja^XD4FuxK=@)oP^x zkVqtiKmj0~PM@EjQxv7w>$yy|TIHb{jV2O_Xti44=EiS9h|bQ=;_)~|QSNF7hC(5O!N8;4ZZ~lK-Pzd@$bEc#BuR2)WCQ>- z8qMkH>DbtqQmLdUibMDH^*NnR;Qotdvw3-W8H>d#l}hin$Ye5_rWFc>-|s&-IN+xb v0AF8U9*<{jZOvpdLD&E7Pt^XN{gwU!$o4?YWMU{c00000NkvXXu0mjfjd^a7 literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/VAADIN/themes/icons/download-icon.png b/web/src/main/webapp/VAADIN/themes/icons/download-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..988dfed018450bd1b5551cd692b90b04dbc9b962 GIT binary patch literal 490 zcmVrih@p7p@GSyKZ|vU+|yKIEUZ<_ndPtvMdYUD(1boe<6Ok zr#G8Tr_;GyE&zZK%IEXxbox)k#bPm^&+X4ZAmB;#IQ0v2`-I7S0uecTKNt*#!y$p_6vcMC z?Ux7unx?rxMN#Z_yBx>;g6INu$GH)yP){5HfaRrDt0hU2BuS-GX}{ll*577btJTKi z@xvzZJm2f}G)==8uh;8Fqk%E5R4TLC?7>zpm#f$7B);vVEX&kKK@bF8*Q3!W0G!X~ zYPC9@PMu{4q2+SP!y%# z@81(&x!0*wN>x>2zg#W{gTec(M<1zT7>46G(=-XxG|l@y-aKY98UG%y*DJvR012|$ g?4!pw>JwhvZ)1JvXj)HgbN~PV07*qoM6N<$f))SUHvj+t literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/VAADIN/themes/icons/edit-icon.png b/web/src/main/webapp/VAADIN/themes/icons/edit-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..51eac7e853df459e486665b29ea8db156d77f74a GIT binary patch literal 735 zcmV<50wDc~P)kd%00003b3#c}2nYz< z;ZNWI00NguL_t(YiPe?OODa(q#?R}4p5S}Yc~+YJDCe0+?>Vq05VcDtPqZM9l1 zm#f)q3T#KK)dB#XpPvbWczSxuWHP;8@9600A1Fmp&1TbTwVs}yE-x?7CieS%6h#Mv zfmkd?QIs>|@wiANIy^iC@LguJ*<>=YEDMFHUa#-$?A+bmb-Uezg9DvTr_2Z4bvPW~fmSLNkH@pOx7TPi?(gq8GZu@jt*zlW&Xx21r{!{)AP622 z0D$AT$z&Rrb97oNl}=7hFbv}n-EKEQ5R*xv&_bc$^?EfL4Ub5Yq|@o-g#|$$9v=LD zzgn%%X0wz2+1VL}Vbl5lpJ}_@_W67mhFx7<1p)!iL=fcs{QOg*ASg}K48v?}Y`na@ z;5cqD7{p?6C=}Y=-7ORf`}_OffpQ{AvREvpQmI@n7l}l+x3>WR7Z(@xdVM-P$Mi{( zluD%(MHvhR&KVAepC&(`5{abS?Lr6<1er`I6pEXh8}3^!myhq7(P-4^bYwEwH1uQp zTCMi=^);DH@?Nclg$32S#zY8VB9WkJTCdknLy<9}TrRs@E|z5%7Z;b7mcBd%0001; zPKTyxxm~6A;V?E&N(le}fQVh!Ez1Jtlx2Cc3jp56rD-}%(|L8@_lP)-BV$Zk z@YzO}mdZTORaFTgE;y^yb*&X|awhRUrxhP@N^F{DoBCFVrIc|TbIy;8zP}@OT-&yJ zo+n9SD%kHGrPPW(rYH(^!=Lu;*$qRAR5FC`J%eIw;_>eV=~I%CA;3gPv<9ccmrneTVpDLHfrz6u71$_Tr9mJBN+XkKqf#%CTGh#FwE1e`j6J*tS7<|vCaGT(oBz$+ z>rJr(GKy+J3Y6}YUjJj*K(6xVGl|xSFrs3(_wJva$A?i{szvX}HA$7;Q`Ik)!e_aV zV63<3D7Ek-G5PS&S&PLmXaHy9RHYODHP{&1x&RS@*fsVIv+P?(snw!!~?`4vE^E9 zE5MPg)L5FkoM}SnyNwBm)o2B(Qy4189vZz5q&X5S<$iAp#n7kt)4Wg{z;T*aSKM64)@V z(m>^S@0pXm&zBcPjR;gNQX&cNU(LNMz*vVXG-M?!;c@3dbQ2=nVG`7k$y1l6F^%ma zemNP|#@6jgD!3a{tZGo2rY!Yo8Z+o$b`)u}MnT>om8UsNYo4r)`VZLsCv%lQwjxoz z^dV=;N^sK%g~EnX||5T>tW!wa=ds zibrtNMjpYw?9l}Oey|sXpfz{WK_jzoo;UxglY8_mBeU@=BTA7foHBmLhL_Gd{g|C; z&HrMWfKq6InOBFsX&6Z zW#WJJMYmFGbTy?w(2zcV!cOYV^G_N(f~HImuG>F#Fm?l7O5}f&dUjD$Tw1oDxmFK*=@c0S$4O zBYOt{+C`LIW$km5{mN1U?G-Hv#k{m)rC@@3=W0%+gUBnQB};RTcnD7;G>Iq?6F@1H zra6P7F?^~NNXlcyA_S>CSsPg#JW3I@NJPlmG-b~_U<9zDF+*J%%OD=XfOLVp4H8*w z@oma_Qx?xd2!zJbNI(!ah=mCm ztOcb>6)4ysF~QXUrBNa#8a##8wGSTWbKsKN)(LmLzOo@xnFyb-&tOC7mie`GFa0qr z@{^|(0b;cGNeZ+?>JA@5@UiH>=C{t=VjOh5c%`SJVcnc0c|kvqgj$vs<-SVR98^7=kEK;zrP-H#uG#gt1>a| zkB99wv|0$X=Djaho;UgZ4?bSjMo&|wFra7h>01xks=87LuKUNQ7v4ObWE@kHwQKrS z-f--$2k+e9FR`vU_nWJp|McUfl*LHfRlSporkvWEwW|;Q>rEH!ch=}(^{IT(bC)-aocIKehgIxfDe*L|Ijc)z+9ikXHMF;1yUQN` z;OhI{0ZquFE_L3iyZh1K`C{d6;~zjk#9FBJhwm&PVp3JIW_*4xHb7g4E%eIlI@(A` zQGf-a2Y5x1n?uA-3Y}O+Fviw`02@Z?1?$yR8YiDnQ&r->Uw-JwBgPD)IR}Eq%uag@ zeD^P72lOcOzxF7LzjW#E#*W*T)hVoW z1Cy~(*fd7;?@G1+e0j%_dk?E_OS0>rp1&Wt89BR+ZcB=}laAQBccuUH`~!whICLb9 zY0%{C9k=X$&`$l^l6Of)XWev2*UhSE&Ea`Mh(yHdRT-al{kXG#Hw=&h6u4gho=GXh zz+Pn(6iVZ&KHW-yH?KMHne+B-YpOS{`h8{JN>T+{a}|BN%$;;ZpDu}&jhWBCZY+<7 zdRLT0EYndM*Xz)TN|DKvjO3m=aqo5wa@7$#K6>Q=G^TMq1mkzx(huMBvgas`P!>f> zOo=IRi#o=SSf6f?Wg)5a9cf2H1m+8Ck?0PEVpC{z^E+~%8?BMm3PY`}VEO&ko5uCZ z&aCZ}jlci!o2L6e&pBW?K*1qwKL5x4{J@1>TU)uo^(NJ?HUv=yQ2VDE2pToHajKKDA6^Y1`uYGaFlOOdx zX|mkv(vjys?MFCe-yswn1g;8r^S9gft#8dg_U?jPr+r4)0P+O~$QHad#VeP0fz7)o zpPsQ$j+u1NzvlXB4;wXrfm8W~MZ`Tr_A)R*?)e^FL)N~m%y!Yl?_v$~m z*YNFYtaupP`!V8bL%2$3MTewt^29SAFIv?CR9D8)kh8ZO)UzTU0j`r$i( zWD84cTY+B9>#EHKd0=zV9*`j}ZN_pb?Yp40&4jZ)vE!j}mjD`$g!K!9L z7ODJ`=lo{wt%onTYy5&c$IrU)(0xbL(3<^DD%;^FbCm!wUvv-CLGWma1+&Cv5JtOx z<;srFzm{HQ2$3o{fME#G*j|tFm>=Q&FIQ0- zBN_ejn?^rmNS{g!Lw(cy=G+xP|L)1U2akJu>S?`yHGq~J0zzgy5->_MY>|i%v51Fj z=dYgn;bNe=vZU_8<7T~dR<~WYAm^?nT$j|PsEAV<`MNGcFlYo?)0(f^tm>JE|4)B* zg_?7ve)XL4L^!Bm$3@w_|C&o{mi|?AO(NH~Mkyklw{cu5dl+ zZx{Mh4DM3_%v;`w1|d4ACK^l`G9~ca5jAS%P5R%Lt9e)ZA8V>g@U-J9$5TKu8b)Zq z(;d3Qc0JU0^L{&QkY4qn98ks@A=6fiw~axN1_Kg^3Pc5>98nGt=)Pt6wq`+Zg;88H z0wH)y4ubUzg}m)y2&6P+&^tcNVk^6zLTU`z_AO)?ph-q{Kl91!rq1#MM-A$^?A~Lx z*l!V4!IOW=BgCxWHR(|`p2_tssOKX;P4m(_6OYDnb^j#qHJyyF6`*#eP}Zq7BOZD3G!IR%e+ z=&&1KsW|F^LvDOINcf{I{y%}Mik1)5OLCY7vz^i0x0t^ow?h{Y$rAnTjrL6o^W$~y z$d>&0r|gS%@?O+p%YNZImI}J5U~i|J;zilb5!L7)ZLl_FLn>g7zFkXkHMS~C1j_!B z+Ex%42DWq2RWFF&-g@7wU-+LUpSdUL0!oP@Qx-gLjgegnl)C6I)8t+^{_XW3$%7O3 z#8Lk6T|fMsT5~6j8R`cdeB<;3e?RG*o2I97>$gV>!S^%MT2a?2O%SoDZ8>(*Yd}-F z(428*E?nLJf2d_di@Tgso4P)cFAy zkJ}EC&I5_CiDe*!>jfjPXL+1eEo5y9 zPO?1Se{eMjRyP0Nv45YlyaDJ^8byll(R%{2T-BvC;{W(`aUF_nx8JNZ7FuuYjbJ>_ z6}k?oe*LNgfXcCVb{TQS4tw0N_}v9)aJ_YSQK0x>el2kD&YLIq*_w=vr%>Lo-3Jo0 zkb?5qC69gN$DV%Km>u@phNd*GR}%S;%}+no3W`D(kli0Kce~bor9lE{MY-SsVwJJYJEAXw6Hrmg9JoN9QaE#^o)??Rw4l9UD{m-uvBFxmlM5cOF@Ay(iyU(5osj zq)#RA%zF#*G>A64T%br5)o8ay8hs)2W@-Y9)kj#wm*1EYvFoVCo;di03CLLh&AJ!Mf!B6Hte@b}lhJa+eiz>L3)6W5OOt!{oT z!q$)FmJL_~3ZVWb;~+;6QUHb|0xyVdA^%tRz7%9cI}aDoV8as0Y2KU>YC7a@u_kO2 zzITQkiK<(xmCK9f>~Ki>jovjG0V)y^ghUFum0o|>oAVeB{7n)dYMCXm5a3T(5z9Dw_knv2sRlk< zT0ilQHz)}sDT@Z8C>Aym0z-C9#(-|gD5j(&^8Q;3K3iH3R3yR^b{};8KW1I=H2AuvQ$G75A}#*h+3q}ZwD@vy%s(Xy!S`I$=r z%P@LY#1dhvS9#(u<99s$=$&XxcMw-vlZ-Byvtq9+ruqTZR6)-@_1c`TYv-<_ zEJ`%wPgpc&`VQ^A=Qh=it%a!{Ez;=%T4S1f?$EbadBX9$x96=|G5c$hF=8QXx4cWd zrYh-p-rQvkI0{$w+pMA_5>Dsr#mgHp1hz+}u=A(^LuxACn6qO3j73zIj2u?IY;}5d zT{FVK5(9fzMlExBeQQH~8p}dxl*aY?R#zqyp>)n!w4@$WqLd$!$vF#`)FTBUV_@%! zsAVpzZ*8n?#a4w^&aw>S#ZQ(^e(OsqMMWa~=kYt0MndzxX&ijuUGz*M<(m68v_N^( zrwN-oY~O!yO?f)+&0JKwc+Lt+!k9)d%iAsuSxUn@Y}@@f8TkYw~jDUyM<*GiOc+}kdSnE1i zu};p#XTil)Kw!=R@-|8%1kn&$V@N!O6y%-20VozGYJzXhP-ubYktqcE#KJ_(V6GA1 z>s2|2yn_%V!k7jET#sCVg2E7lE#g+uM^)gs*d9_4GBG6zYzNm1Opc}z>?@}VxDMeE z@eq!}bukRWX0Vl;cR^zsgiTai59y$GQV=PsVrzx8r8Nu+_HT9{^zvoD(;C_PTr3k) z@@?y+Cr&(VzagJ3uOB}4ZhDn<;3}UFv_LD;Hje9W$Pf($G*GmCw2z}9B(W@_CR!jg zLaxc}JGg4Y+)Fg*JhF6`@Kr19b1OU^4UIy_2B?(<5bHP$D-a4{V8A`bKG52ZpVmRx zBIHXi70m6CaFLsJUtE@*xvT77vUFq#zbQSCewe9L!U?{$EUXN?~j6lyR_-l_q{Ujktb(TktlNcdTa5$ZSo`Id^djb4A|}&%!e^_2$4Y>;J#G2 zY+t>4l@@tJqlFYY?ujl!Hy|#s#ynsgj%Y;{ik-Sno}JI{dg`K_%Q>X-yX`*cm_4`b zSr%{2*|Qec-~IBO*7>zmC9up*-nN@SuUg+z2lEv&hSC$&)5kln4aW7f$O}D7Bp8iYu|tIZ+G9JAF2G0be{Y^I4(JRjemOH9komUUcDGjpQ{-$M53Pfpi-5H>d7He0SF}L*{`s!L^T<2FZs>aV$u+)RluUtw zgQwPPcW8~P$rg$wcFb9+K%BI_`(GUwrN}u!D!+(;LL1iuvF4P4cGQiUE=c2 zaeHnxsCPx+HLun=nBZ!1>rm(unf2Sm1A*4qUN|1!VOSrUvnY*%bndOI#!lRSNN{va zgX`gWI377WAhN9>ttq%k;e%Y=_2-NJK!;lnrv$g1kdxig<)< zftD;@F=tny0xNcKjKbAug$~?#Y06?s8MgdG0eFgrG#X-I(gnPtr%@_TI!`=8QySY_ z&zz${>84a+Wn-FbftW=@ro(v4J2a$-N60xe7byf>kNPxGi;zJ>2G2ujRy1EcZrgJX z7*0b5Pa_4TQMuQR7u@j%B@uM-NJvwboE?LL*`p_T&z_=R zI`dBx_aK!=2yzY)bJ;&nSI?fJ-#CBgoi?X24gP&JR_)^_l$1s(xHzi$nUgE4;$$7N zPGv>>`Ku2cJ9?;kVdABSZbwTFV0G%c^Y&FQpQWEY^})->kS!ntt@%FvyV-A?r>30p z-UAcRIuH-*AXTt;AJTKl8|SNkoHq65Lvg*}1a{uRkY7$YRZTfXzkcp-_83G%8Uz|r z`DwQwsivN$pPTs9jfaqRNEZ$`V*5)E8F}zd{oUDDR8^JWxU}Y8z4@^5qlX40Wed+- zI{NJ6M>W52hI;n2hyOB;oD&Gw#>^oH3|B9nvFh&=nqQb$_sl8PJ(K_4T;)S4V%F^2 z4mX+_a1fh zEw9S0FYQqtf9#K=Nw5E$aZ_vl^!LTwJO8Dw zA%&C_+#LsXukMn-@j#Pv_8wMq!!f&*jl0Vjch~sc2JE_1e_C_oY_n_fiF5YZ>h#BY z>~&Kz7CQR2SH79M665E%v-78x;hS;%!LPypfv~J zX~1baaSyJ4(h`w(6tMr*FE%V|)UJmiXvtlA$o99tIA_I&i_=ZHxnI>{nPdw)466bD z`O%WZus*lF@Y!LzZjLn8>&@4_B6il_-eW~GwJl$)Xxh4_3rbUP;{Cb|=ux)krT?TN zHuL$}U#w`p;?V7B$zd3Czit9{-+xGY_KLS({Q}cK2s}?COcNXxDE>k;XY8EqPpJU$ zuzB=tuTq!N%NrU~g)MrN;VE3zqaqG``Q}$NX21BRdE3pZiW|e592;g?u+^45%j(m4 zY!}n;k9zhfkA2}O5SD-PGh|^(e}8xLZe^d=rf^hcX=LXuyD$9fQPHsJAwHbHI`Drr z1pe%58JGfCyU%>}wlsF%`{i@ zUMVi>g3zXE3!#Df+7yWhQs9AQRwlv=R<)3f5;742t?*Q3A_UBtbXYWGDfIhauELUN zv97cVnPy`;hbhrggY+GfEUqIKCfJh`2o3FO(GF6GmP`TD06erI1zHd>zh1ohlSQi^xc%_==6yS;x@_{B zUl9p?=Qhqp#fEW}B^TAU`ffm^^W> z!??StsX%Ee<5b4|J_k%Ge!!k31kuoS*S&b%q}Qh3f6Su49@Xdfld!Bt-{&|aY0cqy zRmter4H-u!(rZn=7N8Smpx?Hz3fob^GNFgQKKQ(U|G-mIfKKJ5-Mtt>kQ`wRCwk&I; zBL4H(v^GFn7lK6OiRqtPQjR%fJ95sMr|kjEp0mQ|A*B>B;e_3=-HVUh9%x#$nvmgp zvYxQ_R+R@1r(5Y(dkm`DtO`d#;14PNt<5#>?co2+JHv+eDI4C0y#4&gOL|qr5rU|- zdco@2mh3$j?N81bK4xfjMf`@TvnY*W2vP-LzwP>>xMkwrfFT3Bun@t_f*_b9NwR8W#Gp7TEAcQFmDU6_}4IzB7 z9kWu48y0-qGUbxd6r9cX9XzPI;?Gk)rZk4_4j9D9KDUt+e6QK z5=&wlM6E4Oeq`m}CYZ419;FNpc{`&J3RF;s=@3wW% z`%eC~U!!r?y^I0`<*_sFduPeLN2wVXZ+6l{OP4lc$y~uzO5=|T)5!VeP*b8s#&(p_ z7~ptBLQUzyO~>wX`61hv#;kc?H*J07J(R`QD_b`%Hf$fzzht5{2ZGWtEjeH5K?)ku zBX`{F!|M;0LocJI3+X&skcj+nAD&iGqTSkim^3LXghmxRl1p z7bv)t#eMNcrhpVg!=$pfnzCpRKb1#9ER5@6nt?gPkc7;jUhT_jdv8cj{_|Lg9DmY7 zL@dgp>h<$0kG{XD(N_sJ#$Ms3+6VMSO}n0?XZCY{Fx{myst&OfOr_8@ib)}b8gG6B#ep#{(S~o$M#r*(cMv3_p>E}IN@GZl9k(se^ldAV4u`Ne z5jJ>t+4p8_&-*@ONh9xgshoppVE7$Yzl$8M)+28gos2!`Ak0W2mcv-GdiFC zQ-G(j9h!4=FGWLb3$ZXIku_%-{(EP@?}0Q>D&LwTVymgX literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/VAADIN/themes/icons/inbox-icon.png b/web/src/main/webapp/VAADIN/themes/icons/inbox-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..dec029cfb272fbcdcf36e9e04e06eec477ab532a GIT binary patch literal 465 zcmV;?0WSWDP)P000#T0ssI2JW0||00003b3#c}2nYz< z;ZNWI00D_fL_t(Ijm?z5%EB-d#ZNxEx%dFOSOh0=5SNN{tPdclo6q3j=;T-mzC&rT zL!scJpdtt^f;dR=3F>5Zkct)^3bFo+AL8JdZcc7~xk-GAc<$0cIngDp7&*gG#7Jy2n0>Jlu!!Yhy-EMcc+tH-A%4W04 zWD2ylXPN!3=)#&haIiZItnN z{0O3Y!*X4>R4TD^sGjuW$NGI%B9Zu*!t*=;^2LAkSMTcrC}^3T8G+}200000NkvXX Hu0mjf%xBYb literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/VAADIN/themes/icons/mini-edit-icon.png b/web/src/main/webapp/VAADIN/themes/icons/mini-edit-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..bf0bc3639c5f2b27eadcf7f189026ab788cb0071 GIT binary patch literal 317 zcmV-D0mA-?P)?00003b3#c}2nYz< z;ZNWI008w#L_t(2k&Tie&V(=!g$J?(G#5csK)3^Uzz_sD9I0$l)dO$`91?|s8a$^U zI7$dz(PXnr`qTf(>H9KoUTR4x!6YFBAw)`vG4?!94PQnK0P4CPh5-Q9b!Chx*fwr! znkGpS$8i9Fb500RPfw%}qN=LC@7uPelq%S=EJIp_9mnDO{xnShKq>9I4r8ngmbRe} z1_1Lst6`R9d7ghfnzULhilQ`4zioF?VM2%-#u#&5_uF|-TbAW@UCXj;+xCC~0LWh< zgwFFE$1#p$giuiw`@Tz^G~I?_$T<&!z_xAuw!a!u@H3{l^ZzpZz6ZSl|Ba?7F*NFG P00000NkvXXu0mjfO*VbL literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/VAADIN/themes/icons/new-icon.png b/web/src/main/webapp/VAADIN/themes/icons/new-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..584eb89eb43ab724a6fd3e9e75709cb768630655 GIT binary patch literal 277 zcmV+w0qXvVP)0ym3{a{Ss{eJ`clOmvn70KE6pG(nNo9y@(UY|i-y6iw5> zPHg9#wKk4eYn4)QnK34IDW!}tM5McDRaN=^bzLXp*E`5x5g}q3BF0#J6J6IGwk-8$ bUr+2ipz=oNv|bJk00000NkvXXu0mjfCBSgJ literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/VAADIN/themes/icons/new-square-icon.png b/web/src/main/webapp/VAADIN/themes/icons/new-square-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..81aef3e755501b98dce3b4577fa5667173b5cc7e GIT binary patch literal 402 zcmV;D0d4+?P)ITP%d3T0;F5AbXV+A|78Ae&Oez8dOn}```xzfFbp4$2h6DDa;YeauIng@ zqV0BD6vZ5DT${~?27ow@KP3U+cDvCm%hq-MeU9h(-EKz+!5B}i&P)Yfuh+V+0{|i9 zbUMBDP*bTWih2vakM_%0Wx(`mQc9S(=f5mzRwu@zl46jzuj(4(**p*Y<oCyFA*7&d`1wpc72$C=OP zh$~i|wMN!HV?RLA;DS(Kab3(`;EtFCr#CpB1M35v&CD(#twOR=wD5X&TU(z%U zfl T_33=s00000NkvXXu0mjf>EXO; literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/VAADIN/themes/icons/new-user-icon.png b/web/src/main/webapp/VAADIN/themes/icons/new-user-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..35ed80b4e6c479c0b953b83ab0a533bf16ba5d73 GIT binary patch literal 694 zcmV;n0!jUeP)Wr!OCAH!ZrwVCI_QV7ftr$v9X39EzkS!Vti$&?Jb!&-U;c zHXIJ&*KF$d&;Wpcw$bTyPEJm)udf@822In;%gdrDIvkEK(J|A`RIAlgDpjx7|6F7k zCY#O9&dyFm?{>Qz8yg?c=mE#a$0SLPNjK^H`T4mi8UPeUIXyic6KzhfR4Nt)<#Kr< zdaKp4C}_9a6VYd8W-JOAhM9=Iwzg(bu)e;I{O9NA#l=OA<2a7Hy1E*RzOb+mi^WXQ zf*^#$VH9?|-N9g>`=lqz;DBM6d_M1TxyDhgn=z}UQYo2CTBl|*8Br8B zH#c8jU-gxKzyI*?p!;sOo1!R`9F0b|wzdrI#bR-!5P~28;O_3ubXU_fP18_#e}50? zn?XJKSu?aNiZU`)RaF2;Bob&`Tdh{1P|$sjO#uLo<9@$?r1o!^@mAC6 zG>(6I3x3-S;?mO6(b3V_*;%bt>-BopH6%#}0s&DJ34(}3BK>|J!!Xm+o8PNHWxxB! c@juhw0q_~?){rU2zW@LL07*qoM6N<$g5+6QfdBvi literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/VAADIN/themes/icons/new2-icon.png b/web/src/main/webapp/VAADIN/themes/icons/new2-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1893e3e2e7803526fdd49163815c4a9dd0ab11d6 GIT binary patch literal 639 zcmV-_0)YLAP)P000&U0ssI2y4|4R00003b3#c}2nYz< z;ZNWI00K8jL_t(IjjdG6>oH*z9$#`@xMZWon&p%YAr@|7N&FjA%0@0jN?Bm-4-iW! zw}m2+jk0koLWyi$M)dv`Z_SM1H{as>p4D^C={$3u_nr6f0078;0{^!H0AMf}wA=0J zbb34*aERJeSMaY&MQrNRl*}OjKAZl`ssWJ>G6NiVFk+ZeK#7kQu@oqqUgN;_-NJ zYmp?$3?&i?!aOe&Md$N5nI2?An-CnQ9e0mfjkqCT1$Up80kH2!L%UUIoyr_)(17Ps3il}bNb ZegH2U@3}cq8WaEk002ovPDHLkV1gZBCN%&6 literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/VAADIN/themes/icons/ok-icon.png b/web/src/main/webapp/VAADIN/themes/icons/ok-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e352a64e8a2970e7bfe622cb27816a9559fd1efc GIT binary patch literal 878 zcmV-!1CjiRP)PxM-*6J^&ry~_$>nk7cKYx09`UYxGktE49&15nO@gaBDbyZab=qHFVCP`AYT7?q+s}a0A zJ39{#51xwF-8c9P7D5n0 zD5a4|WO{nKqod;!gfV`8em*=rEEEboJw1bigOih!UjBrT%gf87qa)5aP%y@|TFvkG zFD@?j_xF1tv2EK22M5Js(dY9iijqpDN~IEX4I%XU`ntEbSFhI*LV$K0N7J;Gl@-6= z&pH2+|MvFw;^Kl3^6~M(IkzlpYir9e3?YQ$INRIXZ*Ol%H?u0nXK3A`}_OX*VkTHS(Yu!ip65FSPaT+)`aZt?pCYSVzJoO)dd9;LLMI< zP18I(JA-CJvnZwGMnl*2 z&CShVFzC_0O{^qIx~?Y@2~|~LWMCCFP4gPe80+rtURqiT27@4fi_wQiAQ0Ht*k}&r zO(r44b=}$7*@=mXHambJ1&nbd5}BW$r7;CeV*jsMSd0$`O+S=OC&`_h%V2s(eJuon^ zyu3UzG6I{_ZmoZw!9t-B3WdhT#sYyrHk$*76{LV@6+9YhKbUW!iP zphJ|3w~Dg`leHPkO%_wq9A5 zH#awFn!dTYu`FO&HWUhFG8xO(LCb8j*^EY`cXxLHfMhaxa&lrSsMqT(%K`vIQEWDw z8yg$F$NTp7w!Xd&r2qhz%hg>oHa0dm_;*aFr>7jp_4cwXdwY8e8N;xxt*!1Fx7*Dy zjIKU9I=a8V|H}LD@Nj;94%y@J93LN#kB@hI0RR+5?d(#@bD{dp-^~#e}}xi zy*)ZQYAJ;g3g!JS4aa(IN2Q#ncXg+HS1dVPk&VI&}EeJMEkIeV_Mcc6fsf z!+>8K^LxafQJgk^JRaZP-dnT^>kflS(fMdwY9ZqH0pA>s1#&9m&eCPjPdjH zGgUf2KcC5D!r|~w6iJeDxtykHKXi@|N+y$nARvS&6iJdW#@4{%;^NB6%G}&sx7)qG zzV7vUBqRtzDwVQRTCLX3&d&S$ySe0YxsH#IZn_-DiJ~|)HD$U?qtUP;qR}WpbUK~;`+KuThGF*i z_lfM~<)u=o5SO{UytLMQcz9401pu1O=GN9$I-TC#-8Dlz&s&w&L}#GywjF_{X~kj@0NieODwW#a-Zs~*TL6IJ zaM(Ws9LQy8VvyG_xsc`!C;VFOJ-wZ zgDQ&005~~0@pwGcf>c8Y zVT{T32LK1g*zfmq9CvebW0mTW z4-XFx4(Rj6G(}M`#;sP1n$K}uCX-oRU8U^N_LAtjPUdd6+cgYhW@d)x`A8(PzP|2u jyQu~2l>f88c}YG2@r5Z1mZXyU00000NkvXXu0mjfSOjsJ literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/VAADIN/themes/icons/reload-icon.png b/web/src/main/webapp/VAADIN/themes/icons/reload-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..38d4b9bcf1795ffbfd55592cdcfa223a262147b9 GIT binary patch literal 713 zcmV;)0yh1LP)X0ssI2puDL!00003b3#c}2nYz< z;ZNWI00MzYL_t(IjpdX*XzEZD$8$>rrA0~{tQ9dsS}L^EL2U#P(WN4R(#b&_ijys7 zks=boU8NMV*VWa@McYBBgNWFvR62zweozI2f(pJNkN9=9OW_UgO#ge%J-?iD?>zyt z*$nwTL$|~@j(d4|sn_f6c6&4$VHjpG7#t1yX5}E>_)pa_ZOeRw-7NJoL!-Bz} z-|t6J^y};E?(WXzaz!E$IPUfJH6D)-27~Q=ot>T0G|e!KAP6K$vMdW}wp=bpqtWSf zDtitO4+(<6Fs$G2HyVxa?{CTf_VyMEg;vs+a2&@m3?s8nPEKf=wpc6x0Le3(&7Pm1 zA08ffo`;sagiEK>q9{t*=kqZPqfjUoHvj=j`t8k|c>B2tg18K|omuf;gSd zX0y4%qA2RG{@tnA`FYDf#Ldqxl}deld@RNQ09RL6UauFLDT-n&78{Sp0Dy2fe13ku zgv;e}>p4e9N1Jf@e7;htNP2&NUlQAzwcG79O+!Q7ZujZwNz%v1$3~;^2b@l)OQljP zQz4lsiud>Ty(-%ge{d$H`=}sc^|~9A{bf;NW1< zIlozrMx)c|SeD(}+cTTZ>2$hYuR}p7ie6t|MKVmYPC|SRIOIq v?e=guRIAlEj@xWDilVeyE%ZzO)y)0@wxazW4!g0j00000NkvXXu0mjfkS3JR^S4%1Th4$3}PuM zQifn>ZEGQd7NXz+oFeehsUFOmW^VU=a8L0#_fhM*0=c0iNg@KOstN!O0Kl@WEXz1M zWmyixfTCd-nx@@uxA*(~X$}A&2tpW!IJooqyu}4Uz%Y#CI6K_3ELoP};QGGb#-b=r zr_xyqnf56f)hm%0I2^fifNjPq9jT3dc8i)uSD@Yk6{?wws*LBo}(zj!L@C> zjraRqRn^z^(uIo^AT~}4r>-CDx_5c7p z&-=cQgRAR$i?b|?rfI`4cDQjIFP94r?#F@0aeO=;(=P000*V0ssI2ae;G000003b3#c}2nYz< z;ZNWI00JUOL_t(Ijh)m#YwA!G0Py28(hANZbg(F*&iV<&O%$aaEQlIi6a}S4u!&Hs z;@YWe7FQjlkOol{2SLaOh#+K9T>Jq3iQW!*q&Znw>5 z^ZWao=Xngn%x1IK>kWs)7=}r6G-|Bna+%BJCXH{Xe<`Hy}gys#17Ufqt$B3A+Oh)&*$asNb%>aMbor=n8{?0LaHpD=g-bjYbj#4 z+eyy|p|7v6WHPDNy1&1d4^ydByWQUJ_Z-LJIR5_rzFMus(wTdlPN(DX_~YY4k-xjU zTPzm){T={HrBW~$Jku9V(~(HT<#O33Gqj9u5DU^Hc^?HX801yOm8d6&QexD$SLx?2FKp=1$`o|g!2CuKL zhfuLt4242xpLZR^Z_^1W~@$5&V(ev}OAP6{)Ycv{)qQu(E%gfW# zlS&B0e@?Yp6+5!q?NTA1&tC-n?JF1z&So=tHk-}H27}?6jsO7Q2gP_U4oo$OWdHyG07*qoM6N<$ Ef@k0-qW}N^ literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/VAADIN/themes/icons/task-icon.png b/web/src/main/webapp/VAADIN/themes/icons/task-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a5169a96e31f31adef07ce0133b5a19f320bae3a GIT binary patch literal 323 zcmV-J0lfZ+P)P?1xJeZdl$8o@YW#oB2&$A|l5K@*U0HChx^i8enDg^rBa@)49 z>&li=s)ft4%rs5eGRCAvgphF@zrtt? zw(U5M3X3r|O_R`HA*Moz#~>;hb~MRd4_hhM^FD9+V_WmSxeT zyn>?0vMkHdl@B(N)pWC*bGkxE$R;&GfpByQ@Q<5Z|PDfSM)9I9%Q54CttZCYPKh`CY z<2Z-I0oVKeK91u?qmc_G2!iK%)9JKQsbGiWxNf(LYYLx2yWJ)S{!%>8Tb6YLLI`a( zo7rskJVn=aQ52iaCSG1flO*YQJiZi1k|dtzv*ib|$uJDVFaV&}>#f)8R;vX7uIrA+ z<40Wb^%sjpTrdnnQ53^40Kl?r=HH8)=m+`-{b>;SL7JwCi`{OwTrPtk0D#3}5r*L- z5S9Ib2%*7X@O*^TYL)#ba6MYRUT0bMNs1r{*OVJjsZ`Q+y<9GTOR3drqtPg5evbA_ bz3tY{eG{ny+0Do)00000NkvXXu0mjf(Llk~ literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/VAADIN/themes/icons/upload-icon.png b/web/src/main/webapp/VAADIN/themes/icons/upload-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6efc7057927c66a76e0ccfbde7e619d19fde66ff GIT binary patch literal 414 zcmV;P0b%}$P)L_t(IjqTMfu7f}j0N`0z!4VJ@#gdAK6*Qy=K%;RLHPsabQBMNZJpd`L zNCY0i9l*7zu4($SPtcG)einGCe500~$(LD}u!vF$-w2MK4#Uv%yvO6wEz$Nk91esK zLdbf(zTfYRN=j*KM?nxcj#I4TIJPW{-B&a8sr0lOpt{n>szPl_r}Ya8!;qnr)^@w? zfbu+ND~vMKHjuvWyRKV4&gb*pZpY9&2C{$rL*0R&&*%Ake!X6wyQ9%)GMS9W<8t<9 zvl#$fE|=TwR+b@zL{Y>T0{~hsmuZ?-_|0Zx7)E6?%QDk6KOq266lK5P0{|j~)cZsT z>AEh2$hUtpEUHY}+=^^JQunBuSE{X#gMy zf~IMLAe1Sjs%o!aa!X*0lOzEEyjU!vDEix7Qhby5`dio053oGXkCcaV^#A|>07*qo IM6N<$f;3yVj{pDw literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/VAADIN/themes/icons/x-icon.png b/web/src/main/webapp/VAADIN/themes/icons/x-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8f452ebf25423c66568394d5c7f82ee82108d06a GIT binary patch literal 458 zcmV;*0X6=KP)g_(d>V-b+aWU}sx3;S0y^Pha2;h&Qn#u$7;Umv0TCFp*?kH_Oqr?cDb z($zr_n5OACP83D7hY8(ox8ZQ8D2k#ex~^}xThjG?zu9cYZm-uv2$620BiD63&x_Y# z820=9XJ0`OSeA7@pW`ira5NfaUhQx=klQDVqA-hdWc=&(+O}IC7$OelZmEjnO6e<$g(`2&m~Fv6@>x%o|Q#mg8%@MByk*obh%v87D8w+7;HA1*C1xnKVc<6Oo|`~g+k#aD-pk882kO6qReJ9Q54f}qEe|W z77KPq<#IVqsaC7Z9I4{O&|a@s(=_9;tkr7E<&tzEg!OtocH8at@pvTN1PEgshM{Fy zjYea&TH%x+gsoPq+wGoCC(5EnBzy<^Z)<=07*qoM6N<$f{Jp^ AKmY&$ literal 0 HcmV?d00001 diff --git a/web/src/main/webapp/WEB-INF/web.xml b/web/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..8b7b635 --- /dev/null +++ b/web/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,10 @@ + + + + + COOKIE + + + diff --git a/xmlrpc/pom.xml b/xmlrpc/pom.xml new file mode 100644 index 0000000..3e614cc --- /dev/null +++ b/xmlrpc/pom.xml @@ -0,0 +1,102 @@ + + 4.0.0 + + de.hsadmin + hsadmin-parent + 1.0-SNAPSHOT + + + xmlrpc-webapp + war + HSAdmin XML-RPC Webapp + + + de.hsadmin + authorization + 1.0-SNAPSHOT + + + de.hsadmin + common + 1.0-SNAPSHOT + + + de.hsadmin + framework + 1.0-SNAPSHOT + + + de.hsadmin + persistence + 1.0-SNAPSHOT + + + de.hsadmin + services + 1.0-SNAPSHOT + + + org.apache.xmlrpc + xmlrpc-server + 3.1.3 + + + javax.servlet + servlet-api + + + + + org.apache.tomcat.embed + tomcat-embed-core + 7.0.69 + test + + + org.apache.tomcat.embed + tomcat-embed-logging-juli + 7.0.69 + test + + + org.eclipse.jdt.core.compiler + ecj + 4.5.1 + test + + + org.apache.tomcat.embed + tomcat-embed-jasper + 7.0.69 + test + + + + xmlrpc-webapp + + + org.apache.tomcat.maven + tomcat7-maven-plugin + 2.2 + + / + + + + org.apache.maven.plugins + maven-failsafe-plugin + 2.19.1 + + + + integration-test + verify + + + + + + + diff --git a/xmlrpc/src/main/webapp/WEB-INF/web.xml b/xmlrpc/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..e681660 --- /dev/null +++ b/xmlrpc/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,22 @@ + + + + + XmlRpcServlet + de.hsadmin.xmlrpc.HSXmlRpcServlet + + enabledForExtensions + true + + + + + XmlRpcServlet + /xmlrpc/* + + + + diff --git a/xmlrpc/target/failsafe-reports/failsafe-summary.xml b/xmlrpc/target/failsafe-reports/failsafe-summary.xml new file mode 100644 index 0000000..ac2b7cb --- /dev/null +++ b/xmlrpc/target/failsafe-reports/failsafe-summary.xml @@ -0,0 +1,8 @@ + + + 0 + 0 + 0 + 0 + + \ No newline at end of file diff --git a/xmlrpc/target/maven-archiver/pom.properties b/xmlrpc/target/maven-archiver/pom.properties new file mode 100644 index 0000000..dd6c6b3 --- /dev/null +++ b/xmlrpc/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Fri Jun 10 19:31:19 CEST 2016 +version=1.0-SNAPSHOT +groupId=de.hsadmin +artifactId=xmlrpc-webapp diff --git a/xmlrpc/target/xmlrpc-webapp/WEB-INF/web.xml b/xmlrpc/target/xmlrpc-webapp/WEB-INF/web.xml new file mode 100644 index 0000000..e681660 --- /dev/null +++ b/xmlrpc/target/xmlrpc-webapp/WEB-INF/web.xml @@ -0,0 +1,22 @@ + + + + + XmlRpcServlet + de.hsadmin.xmlrpc.HSXmlRpcServlet + + enabledForExtensions + true + + + + + XmlRpcServlet + /xmlrpc/* + + + +