From 83883319abe1cbff31181877a110594d03906013 Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Tue, 30 Apr 2024 12:20:08 -0400 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=E7=BC=96=E8=AF=91=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web-modules/README.md | 3 + web-modules/apache-tapestry/README.md | 3 + web-modules/apache-tapestry/pom.xml | 152 + .../baeldung/tapestry/components/Layout.java | 16 + .../com/baeldung/tapestry/pages/Error404.java | 5 + .../com/baeldung/tapestry/pages/Home.java | 36 + .../com/baeldung/tapestry/pages/Index.java | 59 + .../com/baeldung/tapestry/pages/Login.java | 42 + .../baeldung/tapestry/services/AppModule.java | 128 + .../tapestry/services/DevelopmentModule.java | 24 + .../baeldung/tapestry/services/QaModule.java | 34 + .../baeldung/tapestry/components/Layout.tml | 21 + .../com/baeldung/tapestry/logback.xml | 13 + .../com/baeldung/tapestry/pages/Error404.tml | 11 + .../baeldung/tapestry/pages/Home.properties | 1 + .../com/baeldung/tapestry/pages/Home.tml | 14 + .../baeldung/tapestry/pages/Index.properties | 1 + .../com/baeldung/tapestry/pages/Index.tml | 46 + .../com/baeldung/tapestry/pages/Login.tml | 16 + .../src/main/resources/log4j.properties | 44 + .../src/main/webapp/WEB-INF/app.properties | 4 + .../src/main/webapp/WEB-INF/web.xml | 54 + .../src/main/webapp/favicon.ico | Bin 0 -> 1150 bytes .../src/main/webapp/images/tapestry.png | Bin 0 -> 34547 bytes .../main/webapp/mybootstrap/css/bootstrap.css | 6588 +++++++++++++++++ .../fonts/glyphicons-halflings-regular.eot | Bin 0 -> 35366 bytes .../fonts/glyphicons-halflings-regular.ttf | Bin 0 -> 57865 bytes .../fonts/glyphicons-halflings-regular.woff | Bin 0 -> 42775 bytes .../fonts/glyphicons-halflings-regular.woff2 | Bin 0 -> 840 bytes .../src/main/webapp/mybootstrap/js/button.js | 116 + .../apache-tapestry/src/site/apt/index.apt | 9 + web-modules/apache-tapestry/src/site/site.xml | 17 + .../apache-tapestry/src/test/conf/testng.xml | 8 + .../src/test/conf/webdefault.xml | 278 + web-modules/blade/pom.xml | 119 + .../blade/src/main/resources/static/app.js | 0 web-modules/bootique/pom.xml | 74 + .../bootique/src/main/resources/logback.xml | 13 + web-modules/dropwizard/README.md | 5 + web-modules/dropwizard/pom.xml | 69 + .../introduction/IntroductionApplication.java | 51 + .../configuration/ApplicationHealthCheck.java | 10 + .../configuration/BasicConfiguration.java | 20 + .../dropwizard/introduction/domain/Brand.java | 19 + .../repository/BrandRepository.java | 32 + .../introduction/resource/BrandResource.java | 35 + .../main/resources/introduction-config.yml | 1 + .../repository/BrandRepositoryUnitTest.java | 47 + web-modules/google-web-toolkit/pom.xml | 109 + .../src/main/resources/logback.xml | 13 + web-modules/jakarta-ee/README.md | 3 + web-modules/jakarta-ee/pom.xml | 109 + .../java/com/baeldung/eclipse/krazo/User.java | 84 + .../eclipse/krazo/UserApplication.java | 11 + .../eclipse/krazo/UserController.java | 85 + .../src/main/webapp/WEB-INF/beans.xml | 6 + .../src/main/webapp/WEB-INF/views/success.jsp | 47 + .../src/main/webapp/WEB-INF/views/user.jsp | 89 + .../jakarta-ee/src/main/webapp/styles.css | 28 + .../baeldung/eclipse/krazo/AppUnitTest.java | 16 + .../eclipse/krazo/UserControllerUnitTest.java | 116 + web-modules/java-lite/pom.xml | 96 + .../java-lite/src/main/resources/logback.xml | 13 + web-modules/javax-servlets-2/README.md | 8 + web-modules/javax-servlets-2/pom.xml | 106 + .../com/baeldung/servlets/UserServlet.java | 24 + .../baeldung/setparam/LanguageServlet.java | 21 + .../setparam/SanitizeParametersFilter.java | 17 + .../SanitizeParametersRequestWrapper.java | 46 + .../setparam/SetParameterRequestWrapper.java | 40 + .../java/com/baeldung/user/check/User.java | 80 + .../baeldung/user/check/UserCheckFilter.java | 50 + .../user/check/UserCheckLoginServlet.java | 56 + .../user/check/UserCheckLogoutServlet.java | 26 + .../baeldung/user/check/UserCheckServlet.java | 28 + .../src/main/resources/logback.xml | 13 + .../main/webapp/WEB-INF/user.check/home.jsp | 31 + .../main/webapp/WEB-INF/user.check/login.jsp | 33 + .../main/webapp/setparam/3rd_party_module.jsp | 13 + .../main/webapp/setparam/with-sanitize.jsp | 10 + .../main/webapp/setparam/without-sanitize.jsp | 10 + .../java/com/baeldung/servlets/TestUtil.java | 678 ++ .../servlets/UserServletUnitTest.java | 93 + .../setparam/LanguageServletLiveTest.java | 34 + .../SanitizeParametersRequestLiveTest.java | 40 + ...itizeParametersRequestWrapperUnitTest.java | 60 + .../SetParameterRequestWrapperUnitTest.java | 61 + .../UnsanitizedParametersRequestLiveTest.java | 42 + .../user/check/UserCheckServletLiveTest.java | 98 + web-modules/javax-servlets/README.md | 15 + web-modules/javax-servlets/pom.xml | 55 + .../com/baeldung/servlets/FormServlet.java | 39 + .../com/baeldung/servlets/MainServlet.java | 21 + .../com/baeldung/servlets/UpdateServlet.java | 31 + .../baeldung/servlets/UserLoginServlet.java | 28 + .../com/baeldung/servlets/UserServlet.java | 49 + .../src/main/resources/logback.xml | 13 + .../src/main/webapp/WEB-INF/jsp/main.jsp | 15 + .../src/main/webapp/WEB-INF/jsp/result.jsp | 15 + .../src/main/webapp/WEB-INF/jsp/update.jsp | 17 + .../src/main/webapp/WEB-INF/jsp/userlogin.jsp | 18 + .../javax-servlets/src/main/webapp/user.jsp | 18 + .../baeldung/test/UserServletUnitTest.java | 52 + web-modules/jee-7/README.md | 14 + web-modules/jee-7/pom.xml | 542 ++ .../soap/ws/client/generated/Country.java | 129 + .../ws/client/generated/CountryService.java | 34 + .../generated/CountryServiceImplService.java | 91 + .../soap/ws/client/generated/Currency.java | 37 + .../ws/client/generated/ObjectFactory.java | 38 + .../ws/client/generated/package-info.java | 2 + .../com/baeldung/soap/ws/server/Country.java | 41 + .../soap/ws/server/CountryRepository.java | 43 + .../soap/ws/server/CountryService.java | 15 + .../soap/ws/server/CountryServiceImpl.java | 15 + .../ws/server/CountryServicePublisher.java | 19 + .../com/baeldung/soap/ws/server/Currency.java | 15 + .../jee-7/src/main/resources/country.xsd | 21 + .../jee-7/src/main/resources/logback.xml | 15 + .../jee-7/src/main/webapp/WEB-INF/beans.xml | 0 .../CustomCheckPointIntegrationTest.java | 33 + .../JobSequenceIntegrationTest.java | 76 + .../SimpleBatchLetIntegrationTest.java | 64 + .../SimpleChunkIntegrationTest.java | 68 + .../SimpleErrorChunkIntegrationTest.java | 45 + .../singleton/CarServiceLiveTest.java | 109 + .../soap/ws/client/CountryClientLiveTest.java | 39 + .../jee-7/src/test/resources/arquillian.xml | 23 + .../src/test/resources/jberet.properties | 1 + web-modules/jooby/conf/application.conf | 4 + web-modules/jooby/pom.xml | 83 + web-modules/jooby/public/form.html | 18 + .../src/main/java/com/baeldung/jooby/App.java | 123 + .../com/baeldung/jooby/mvc/GetController.java | 23 + .../baeldung/jooby/mvc/PostController.java | 13 + .../jooby/src/main/resources/logback.xml | 13 + .../java/com/baeldung/jooby/AppLiveTest.java | 32 + .../java/com/baeldung/jooby/AppUnitTest.java | 17 + web-modules/linkrest/pom.xml | 70 + .../linkrest/src/main/resources/logback.xml | 13 + web-modules/ninja/README.md | 3 + web-modules/ninja/pom.xml | 226 + .../src/main/java/META-INF/persistence.xml | 29 + .../ninja/src/main/java/assets/css/custom.css | 3 + .../ninja/src/main/java/conf/Filters.java | 13 + .../ninja/src/main/java/conf/Module.java | 18 + .../ninja/src/main/java/conf/Routes.java | 32 + .../ninja/src/main/java/conf/application.conf | 21 + .../src/main/java/conf/messages.properties | 2 + .../src/main/java/conf/messages_fr.properties | 2 + .../controllers/ApplicationController.java | 102 + web-modules/ninja/src/main/java/ehcache.xml | 15 + web-modules/ninja/src/main/java/logback.xml | 33 + .../ninja/src/main/java/models/User.java | 25 + .../src/main/java/services/UserService.java | 9 + .../main/java/services/UserServiceImpl.java | 15 + .../ApplicationController/createUser.ftl.html | 12 + .../views/ApplicationController/home.ftl.html | 9 + .../ApplicationController/index.ftl.html | 9 + .../java/views/layout/defaultLayout.ftl.html | 58 + .../main/java/views/layout/footer.ftl.html | 5 + .../main/java/views/layout/header.ftl.html | 20 + .../java/views/system/403forbidden.ftl.html | 18 + .../java/views/system/404notFound.ftl.html | 18 + .../ninja/src/main/webapp/WEB-INF/web.xml | 41 + .../ApiControllerDocTesterUnitTest.java | 27 + .../ApiControllerMockUnitTest.java | 32 + web-modules/play-modules/README.md | 8 + .../controllers/$model__Camel$Controller.java | 43 + .../app/controllers/$model__Camel$Data.java | 37 + .../app/views/$model__camel$/form.scala.html | 12 + .../async-http/.g8/form/default.properties | 2 + .../.g8/form/generated-test/README.md | 1 + .../$model__Camel$ControllerTest.java | 50 + .../play-modules/async-http/.gitignore | 8 + web-modules/play-modules/async-http/README.md | 3 + .../app/controllers/HomeController.java | 38 + web-modules/play-modules/async-http/build.sbt | 12 + .../async-http/conf/application.conf | 11 + .../play-modules/async-http/conf/logback.xml | 36 + .../play-modules/async-http/conf/routes | 10 + .../async-http/project/build.properties | 1 + .../async-http/public/javascripts/main.js | 0 .../async-http/public/stylesheets/main.css | 0 .../test/controllers/HomeControllerTest.java | 232 + .../introduction/public/javascripts/main.js | 0 .../introduction/public/stylesheets/main.css | 0 .../app/views/index.scala.html | 5 + .../routing-in-play/app/views/main.scala.html | 24 + .../routing-in-play/public/images/favicon.png | Bin 0 -> 687 bytes .../public/javascripts/main.js | 0 .../public/stylesheets/main.css | 0 .../student-api/project/plugins.sbt | 7 + web-modules/play-modules/websockets/README.md | 3 + .../websockets/app/actors/Messenger.java | 111 + .../app/controllers/HomeController.java | 79 + .../websockets/app/dto/MessageDTO.java | 60 + .../websockets/app/dto/RequestDTO.java | 27 + .../app/utils/MessageConverter.java | 24 + .../websockets/app/views/index.scala.html | 97 + .../websockets/app/views/main.scala.html | 14 + web-modules/play-modules/websockets/build.sbt | 22 + .../websockets/conf/application.conf | 7 + .../play-modules/websockets/conf/logback.xml | 37 + .../play-modules/websockets/conf/routes | 11 + .../websockets/project/build.properties | 1 + .../websockets/project/plugins.sbt | 7 + .../websockets/public/images/favicon.png | Bin 0 -> 687 bytes .../websockets/public/javascripts/main.js | 0 .../websockets/public/stylesheets/main.css | 0 .../test/controllers/HomeControllerTest.java | 32 + web-modules/pom.xml | 52 + .../raml-modules/annotations/README.md | 7 + .../raml-modules/modularization/README.md | 6 + .../resource-types-and-traits/README.md | 2 + web-modules/ratpack/README.md | 14 + web-modules/ratpack/build.gradle | 37 + web-modules/ratpack/pom.xml | 111 + .../main/java/com/baeldung/Application.java | 82 + .../main/java/com/baeldung/model/Quote.java | 107 + .../repository/EmployeeRepository.java | 10 + .../rxjava/service/QuotesService.java | 44 + .../spring/EmbedRatpackStreamsApp.java | 206 + .../ratpack/src/main/resources/logback.xml | 13 + .../baeldung/ratpack/CompliantPublisher.java | 63 + .../baeldung/ratpack/LoggingSubscriber.java | 67 + .../ratpack/NonCompliantPublisher.java | 46 + .../ratpack/RatpackStreamsUnitTest.java | 140 + web-modules/resteasy/pom.xml | 135 + .../resteasy/src/main/resources/logback.xml | 13 + .../main/webapp/WEB-INF/classes/logback.xml | 19 + web-modules/restx/pom.xml | 144 + .../resources/restx/demo/settings.properties | 2 + .../HelloResourceSpecIntegrationTest.java | 23 + web-modules/spark-java/pom.xml | 36 + .../spark-java/src/main/resources/logback.xml | 13 + web-modules/struts-2/WebContent/result.jsp | 11 + web-modules/struts-2/pom.xml | 75 + .../struts-2/src/main/resources/logback.xml | 13 + web-modules/vraptor/pom.xml | 127 + .../main/java/com/baeldung/daos/UserDao.java | 47 + web-modules/wicket/pom.xml | 89 + .../wicket/src/main/resources/logback.xml | 13 + 243 files changed, 16741 insertions(+) create mode 100644 web-modules/README.md create mode 100644 web-modules/apache-tapestry/README.md create mode 100644 web-modules/apache-tapestry/pom.xml create mode 100644 web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/components/Layout.java create mode 100644 web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Error404.java create mode 100644 web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Home.java create mode 100644 web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Index.java create mode 100644 web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Login.java create mode 100644 web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/services/AppModule.java create mode 100644 web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/services/DevelopmentModule.java create mode 100644 web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/services/QaModule.java create mode 100644 web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/components/Layout.tml create mode 100644 web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/logback.xml create mode 100644 web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Error404.tml create mode 100644 web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Home.properties create mode 100644 web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Home.tml create mode 100644 web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Index.properties create mode 100644 web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Index.tml create mode 100644 web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Login.tml create mode 100644 web-modules/apache-tapestry/src/main/resources/log4j.properties create mode 100644 web-modules/apache-tapestry/src/main/webapp/WEB-INF/app.properties create mode 100644 web-modules/apache-tapestry/src/main/webapp/WEB-INF/web.xml create mode 100644 web-modules/apache-tapestry/src/main/webapp/favicon.ico create mode 100644 web-modules/apache-tapestry/src/main/webapp/images/tapestry.png create mode 100644 web-modules/apache-tapestry/src/main/webapp/mybootstrap/css/bootstrap.css create mode 100644 web-modules/apache-tapestry/src/main/webapp/mybootstrap/fonts/glyphicons-halflings-regular.eot create mode 100644 web-modules/apache-tapestry/src/main/webapp/mybootstrap/fonts/glyphicons-halflings-regular.ttf create mode 100644 web-modules/apache-tapestry/src/main/webapp/mybootstrap/fonts/glyphicons-halflings-regular.woff create mode 100644 web-modules/apache-tapestry/src/main/webapp/mybootstrap/fonts/glyphicons-halflings-regular.woff2 create mode 100644 web-modules/apache-tapestry/src/main/webapp/mybootstrap/js/button.js create mode 100644 web-modules/apache-tapestry/src/site/apt/index.apt create mode 100644 web-modules/apache-tapestry/src/site/site.xml create mode 100644 web-modules/apache-tapestry/src/test/conf/testng.xml create mode 100644 web-modules/apache-tapestry/src/test/conf/webdefault.xml create mode 100644 web-modules/blade/pom.xml create mode 100644 web-modules/blade/src/main/resources/static/app.js create mode 100644 web-modules/bootique/pom.xml create mode 100644 web-modules/bootique/src/main/resources/logback.xml create mode 100644 web-modules/dropwizard/README.md create mode 100644 web-modules/dropwizard/pom.xml create mode 100644 web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/IntroductionApplication.java create mode 100644 web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/configuration/ApplicationHealthCheck.java create mode 100644 web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/configuration/BasicConfiguration.java create mode 100644 web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/domain/Brand.java create mode 100644 web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/repository/BrandRepository.java create mode 100644 web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/resource/BrandResource.java create mode 100644 web-modules/dropwizard/src/main/resources/introduction-config.yml create mode 100644 web-modules/dropwizard/src/test/java/com/baeldung/dropwizard/introduction/repository/BrandRepositoryUnitTest.java create mode 100644 web-modules/google-web-toolkit/pom.xml create mode 100644 web-modules/google-web-toolkit/src/main/resources/logback.xml create mode 100644 web-modules/jakarta-ee/README.md create mode 100644 web-modules/jakarta-ee/pom.xml create mode 100644 web-modules/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/User.java create mode 100644 web-modules/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/UserApplication.java create mode 100644 web-modules/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/UserController.java create mode 100644 web-modules/jakarta-ee/src/main/webapp/WEB-INF/beans.xml create mode 100644 web-modules/jakarta-ee/src/main/webapp/WEB-INF/views/success.jsp create mode 100644 web-modules/jakarta-ee/src/main/webapp/WEB-INF/views/user.jsp create mode 100644 web-modules/jakarta-ee/src/main/webapp/styles.css create mode 100644 web-modules/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/AppUnitTest.java create mode 100644 web-modules/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/UserControllerUnitTest.java create mode 100644 web-modules/java-lite/pom.xml create mode 100644 web-modules/java-lite/src/main/resources/logback.xml create mode 100644 web-modules/javax-servlets-2/README.md create mode 100644 web-modules/javax-servlets-2/pom.xml create mode 100644 web-modules/javax-servlets-2/src/main/java/com/baeldung/servlets/UserServlet.java create mode 100644 web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/LanguageServlet.java create mode 100644 web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/SanitizeParametersFilter.java create mode 100644 web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/SanitizeParametersRequestWrapper.java create mode 100644 web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/SetParameterRequestWrapper.java create mode 100644 web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/User.java create mode 100644 web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckFilter.java create mode 100644 web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckLoginServlet.java create mode 100644 web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckLogoutServlet.java create mode 100644 web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckServlet.java create mode 100644 web-modules/javax-servlets-2/src/main/resources/logback.xml create mode 100644 web-modules/javax-servlets-2/src/main/webapp/WEB-INF/user.check/home.jsp create mode 100644 web-modules/javax-servlets-2/src/main/webapp/WEB-INF/user.check/login.jsp create mode 100644 web-modules/javax-servlets-2/src/main/webapp/setparam/3rd_party_module.jsp create mode 100644 web-modules/javax-servlets-2/src/main/webapp/setparam/with-sanitize.jsp create mode 100644 web-modules/javax-servlets-2/src/main/webapp/setparam/without-sanitize.jsp create mode 100644 web-modules/javax-servlets-2/src/test/java/com/baeldung/servlets/TestUtil.java create mode 100644 web-modules/javax-servlets-2/src/test/java/com/baeldung/servlets/UserServletUnitTest.java create mode 100644 web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/LanguageServletLiveTest.java create mode 100644 web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/SanitizeParametersRequestLiveTest.java create mode 100644 web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/SanitizeParametersRequestWrapperUnitTest.java create mode 100644 web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/SetParameterRequestWrapperUnitTest.java create mode 100644 web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/UnsanitizedParametersRequestLiveTest.java create mode 100644 web-modules/javax-servlets-2/src/test/java/com/baeldung/user/check/UserCheckServletLiveTest.java create mode 100644 web-modules/javax-servlets/README.md create mode 100644 web-modules/javax-servlets/pom.xml create mode 100644 web-modules/javax-servlets/src/main/java/com/baeldung/servlets/FormServlet.java create mode 100644 web-modules/javax-servlets/src/main/java/com/baeldung/servlets/MainServlet.java create mode 100644 web-modules/javax-servlets/src/main/java/com/baeldung/servlets/UpdateServlet.java create mode 100644 web-modules/javax-servlets/src/main/java/com/baeldung/servlets/UserLoginServlet.java create mode 100644 web-modules/javax-servlets/src/main/java/com/baeldung/servlets/UserServlet.java create mode 100644 web-modules/javax-servlets/src/main/resources/logback.xml create mode 100644 web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/main.jsp create mode 100644 web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/result.jsp create mode 100644 web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/update.jsp create mode 100644 web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/userlogin.jsp create mode 100644 web-modules/javax-servlets/src/main/webapp/user.jsp create mode 100644 web-modules/javax-servlets/src/test/java/com/baeldung/test/UserServletUnitTest.java create mode 100644 web-modules/jee-7/README.md create mode 100644 web-modules/jee-7/pom.xml create mode 100644 web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Country.java create mode 100644 web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryService.java create mode 100644 web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryServiceImplService.java create mode 100644 web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Currency.java create mode 100644 web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/ObjectFactory.java create mode 100644 web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/package-info.java create mode 100644 web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/Country.java create mode 100644 web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryRepository.java create mode 100644 web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryService.java create mode 100644 web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServiceImpl.java create mode 100644 web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServicePublisher.java create mode 100644 web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/Currency.java create mode 100644 web-modules/jee-7/src/main/resources/country.xsd create mode 100644 web-modules/jee-7/src/main/resources/logback.xml create mode 100644 web-modules/jee-7/src/main/webapp/WEB-INF/beans.xml create mode 100644 web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/CustomCheckPointIntegrationTest.java create mode 100644 web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/JobSequenceIntegrationTest.java create mode 100644 web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleBatchLetIntegrationTest.java create mode 100644 web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleChunkIntegrationTest.java create mode 100644 web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleErrorChunkIntegrationTest.java create mode 100644 web-modules/jee-7/src/test/java/com/baeldung/singleton/CarServiceLiveTest.java create mode 100644 web-modules/jee-7/src/test/java/com/baeldung/soap/ws/client/CountryClientLiveTest.java create mode 100644 web-modules/jee-7/src/test/resources/arquillian.xml create mode 100644 web-modules/jee-7/src/test/resources/jberet.properties create mode 100644 web-modules/jooby/conf/application.conf create mode 100644 web-modules/jooby/pom.xml create mode 100644 web-modules/jooby/public/form.html create mode 100644 web-modules/jooby/src/main/java/com/baeldung/jooby/App.java create mode 100644 web-modules/jooby/src/main/java/com/baeldung/jooby/mvc/GetController.java create mode 100644 web-modules/jooby/src/main/java/com/baeldung/jooby/mvc/PostController.java create mode 100644 web-modules/jooby/src/main/resources/logback.xml create mode 100644 web-modules/jooby/src/test/java/com/baeldung/jooby/AppLiveTest.java create mode 100644 web-modules/jooby/src/test/java/com/baeldung/jooby/AppUnitTest.java create mode 100644 web-modules/linkrest/pom.xml create mode 100644 web-modules/linkrest/src/main/resources/logback.xml create mode 100644 web-modules/ninja/README.md create mode 100644 web-modules/ninja/pom.xml create mode 100644 web-modules/ninja/src/main/java/META-INF/persistence.xml create mode 100644 web-modules/ninja/src/main/java/assets/css/custom.css create mode 100644 web-modules/ninja/src/main/java/conf/Filters.java create mode 100644 web-modules/ninja/src/main/java/conf/Module.java create mode 100644 web-modules/ninja/src/main/java/conf/Routes.java create mode 100644 web-modules/ninja/src/main/java/conf/application.conf create mode 100644 web-modules/ninja/src/main/java/conf/messages.properties create mode 100644 web-modules/ninja/src/main/java/conf/messages_fr.properties create mode 100644 web-modules/ninja/src/main/java/controllers/ApplicationController.java create mode 100644 web-modules/ninja/src/main/java/ehcache.xml create mode 100644 web-modules/ninja/src/main/java/logback.xml create mode 100644 web-modules/ninja/src/main/java/models/User.java create mode 100644 web-modules/ninja/src/main/java/services/UserService.java create mode 100644 web-modules/ninja/src/main/java/services/UserServiceImpl.java create mode 100644 web-modules/ninja/src/main/java/views/ApplicationController/createUser.ftl.html create mode 100644 web-modules/ninja/src/main/java/views/ApplicationController/home.ftl.html create mode 100644 web-modules/ninja/src/main/java/views/ApplicationController/index.ftl.html create mode 100644 web-modules/ninja/src/main/java/views/layout/defaultLayout.ftl.html create mode 100644 web-modules/ninja/src/main/java/views/layout/footer.ftl.html create mode 100644 web-modules/ninja/src/main/java/views/layout/header.ftl.html create mode 100644 web-modules/ninja/src/main/java/views/system/403forbidden.ftl.html create mode 100644 web-modules/ninja/src/main/java/views/system/404notFound.ftl.html create mode 100644 web-modules/ninja/src/main/webapp/WEB-INF/web.xml create mode 100644 web-modules/ninja/src/test/java/controllers/ApiControllerDocTesterUnitTest.java create mode 100644 web-modules/ninja/src/test/java/controllers/ApiControllerMockUnitTest.java create mode 100644 web-modules/play-modules/README.md create mode 100644 web-modules/play-modules/async-http/.g8/form/app/controllers/$model__Camel$Controller.java create mode 100644 web-modules/play-modules/async-http/.g8/form/app/controllers/$model__Camel$Data.java create mode 100644 web-modules/play-modules/async-http/.g8/form/app/views/$model__camel$/form.scala.html create mode 100644 web-modules/play-modules/async-http/.g8/form/default.properties create mode 100644 web-modules/play-modules/async-http/.g8/form/generated-test/README.md create mode 100644 web-modules/play-modules/async-http/.g8/form/generated-test/controllers/$model__Camel$ControllerTest.java create mode 100644 web-modules/play-modules/async-http/.gitignore create mode 100644 web-modules/play-modules/async-http/README.md create mode 100644 web-modules/play-modules/async-http/app/controllers/HomeController.java create mode 100644 web-modules/play-modules/async-http/build.sbt create mode 100644 web-modules/play-modules/async-http/conf/application.conf create mode 100644 web-modules/play-modules/async-http/conf/logback.xml create mode 100644 web-modules/play-modules/async-http/conf/routes create mode 100644 web-modules/play-modules/async-http/project/build.properties create mode 100644 web-modules/play-modules/async-http/public/javascripts/main.js create mode 100644 web-modules/play-modules/async-http/public/stylesheets/main.css create mode 100644 web-modules/play-modules/async-http/test/controllers/HomeControllerTest.java create mode 100644 web-modules/play-modules/introduction/public/javascripts/main.js create mode 100644 web-modules/play-modules/introduction/public/stylesheets/main.css create mode 100644 web-modules/play-modules/routing-in-play/app/views/index.scala.html create mode 100644 web-modules/play-modules/routing-in-play/app/views/main.scala.html create mode 100644 web-modules/play-modules/routing-in-play/public/images/favicon.png create mode 100644 web-modules/play-modules/routing-in-play/public/javascripts/main.js create mode 100644 web-modules/play-modules/routing-in-play/public/stylesheets/main.css create mode 100644 web-modules/play-modules/student-api/project/plugins.sbt create mode 100644 web-modules/play-modules/websockets/README.md create mode 100644 web-modules/play-modules/websockets/app/actors/Messenger.java create mode 100644 web-modules/play-modules/websockets/app/controllers/HomeController.java create mode 100644 web-modules/play-modules/websockets/app/dto/MessageDTO.java create mode 100644 web-modules/play-modules/websockets/app/dto/RequestDTO.java create mode 100644 web-modules/play-modules/websockets/app/utils/MessageConverter.java create mode 100644 web-modules/play-modules/websockets/app/views/index.scala.html create mode 100644 web-modules/play-modules/websockets/app/views/main.scala.html create mode 100644 web-modules/play-modules/websockets/build.sbt create mode 100644 web-modules/play-modules/websockets/conf/application.conf create mode 100644 web-modules/play-modules/websockets/conf/logback.xml create mode 100644 web-modules/play-modules/websockets/conf/routes create mode 100644 web-modules/play-modules/websockets/project/build.properties create mode 100644 web-modules/play-modules/websockets/project/plugins.sbt create mode 100644 web-modules/play-modules/websockets/public/images/favicon.png create mode 100644 web-modules/play-modules/websockets/public/javascripts/main.js create mode 100644 web-modules/play-modules/websockets/public/stylesheets/main.css create mode 100644 web-modules/play-modules/websockets/test/controllers/HomeControllerTest.java create mode 100644 web-modules/pom.xml create mode 100644 web-modules/raml-modules/annotations/README.md create mode 100644 web-modules/raml-modules/modularization/README.md create mode 100644 web-modules/raml-modules/resource-types-and-traits/README.md create mode 100644 web-modules/ratpack/README.md create mode 100644 web-modules/ratpack/build.gradle create mode 100644 web-modules/ratpack/pom.xml create mode 100644 web-modules/ratpack/src/main/java/com/baeldung/Application.java create mode 100644 web-modules/ratpack/src/main/java/com/baeldung/model/Quote.java create mode 100644 web-modules/ratpack/src/main/java/com/baeldung/repository/EmployeeRepository.java create mode 100644 web-modules/ratpack/src/main/java/com/baeldung/rxjava/service/QuotesService.java create mode 100644 web-modules/ratpack/src/main/java/com/baeldung/spring/EmbedRatpackStreamsApp.java create mode 100644 web-modules/ratpack/src/main/resources/logback.xml create mode 100644 web-modules/ratpack/src/test/java/com/baeldung/ratpack/CompliantPublisher.java create mode 100644 web-modules/ratpack/src/test/java/com/baeldung/ratpack/LoggingSubscriber.java create mode 100644 web-modules/ratpack/src/test/java/com/baeldung/ratpack/NonCompliantPublisher.java create mode 100644 web-modules/ratpack/src/test/java/com/baeldung/ratpack/RatpackStreamsUnitTest.java create mode 100644 web-modules/resteasy/pom.xml create mode 100644 web-modules/resteasy/src/main/resources/logback.xml create mode 100644 web-modules/resteasy/src/main/webapp/WEB-INF/classes/logback.xml create mode 100644 web-modules/restx/pom.xml create mode 100644 web-modules/restx/src/main/resources/restx/demo/settings.properties create mode 100644 web-modules/restx/src/test/java/restx/demo/rest/HelloResourceSpecIntegrationTest.java create mode 100644 web-modules/spark-java/pom.xml create mode 100644 web-modules/spark-java/src/main/resources/logback.xml create mode 100644 web-modules/struts-2/WebContent/result.jsp create mode 100644 web-modules/struts-2/pom.xml create mode 100644 web-modules/struts-2/src/main/resources/logback.xml create mode 100644 web-modules/vraptor/pom.xml create mode 100644 web-modules/vraptor/src/main/java/com/baeldung/daos/UserDao.java create mode 100644 web-modules/wicket/pom.xml create mode 100644 web-modules/wicket/src/main/resources/logback.xml diff --git a/web-modules/README.md b/web-modules/README.md new file mode 100644 index 0000000000..1329ce18db --- /dev/null +++ b/web-modules/README.md @@ -0,0 +1,3 @@ +## Web + +This module contains web modules. diff --git a/web-modules/apache-tapestry/README.md b/web-modules/apache-tapestry/README.md new file mode 100644 index 0000000000..e41345bada --- /dev/null +++ b/web-modules/apache-tapestry/README.md @@ -0,0 +1,3 @@ +### Relevant Articles + +- [Intro to Apache Tapestry](https://www.baeldung.com/apache-tapestry) diff --git a/web-modules/apache-tapestry/pom.xml b/web-modules/apache-tapestry/pom.xml new file mode 100644 index 0000000000..562cdff00c --- /dev/null +++ b/web-modules/apache-tapestry/pom.xml @@ -0,0 +1,152 @@ + + + 4.0.0 + apache-tapestry + 0.0.1-SNAPSHOT + apache-tapestry + war + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + + + + org.apache.tapestry + tapestry-core + ${tapestry.version} + + + + org.slf4j + slf4j-log4j12 + ${slf4j-release-version} + + + org.apache.tapestry + tapestry-webresources + ${tapestry.version} + + + + + + + + + + + + + org.testng + testng + ${testng-release-version} + test + + + org.apache.tapestry + tapestry-test + ${tapestry.version} + test + + + + javax.servlet + servlet-api + ${servlet-api-release-version} + provided + + + + org.apache.tapestry + tapestry-javadoc + ${tapestry.version} + provided + + + + + apache-tapestry + + + org.apache.maven.plugins + maven-compiler-plugin + ${compiler.plugin.version} + + ${source.version} + ${target.version} + true + + + + org.apache.maven.plugins + maven-surefire-plugin + ${compiler.surefire.version} + + + Qa + + + + + + org.mortbay.jetty + maven-jetty-plugin + ${compiler.jetty.version} + + + + + + true + + + + tapestry.execution-mode + development + + + + + + org.apache.maven.plugins + maven-war-plugin + 3.3.1 + + + + true + + + + + + + + + + jboss + http://repository.jboss.org/nexus/content/groups/public/ + + + + + 6.1.16 + 3.0.0-M5 + 3.8.1 + 11 + 11 + 5.8.2 + 2.5 + 6.8.21 + 1.7.19 + + + \ No newline at end of file diff --git a/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/components/Layout.java b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/components/Layout.java new file mode 100644 index 0000000000..5316bd9722 --- /dev/null +++ b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/components/Layout.java @@ -0,0 +1,16 @@ +package com.baeldung.tapestry.components; + +import org.apache.tapestry5.BindingConstants; +import org.apache.tapestry5.annotations.Parameter; +import org.apache.tapestry5.annotations.Property; + +/** + * Layout component for pages of application. + */ +public class Layout { + + @Property + @Parameter(required = true, defaultPrefix = BindingConstants.LITERAL) + private String title; + +} diff --git a/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Error404.java b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Error404.java new file mode 100644 index 0000000000..c629b82d01 --- /dev/null +++ b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Error404.java @@ -0,0 +1,5 @@ +package com.baeldung.tapestry.pages; + +public class Error404 { + +} diff --git a/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Home.java b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Home.java new file mode 100644 index 0000000000..34e99a9cce --- /dev/null +++ b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Home.java @@ -0,0 +1,36 @@ +package com.baeldung.tapestry.pages; + +import java.util.Date; + +import org.apache.tapestry5.Block; +import org.apache.tapestry5.annotations.Log; +import org.apache.tapestry5.annotations.Property; +import org.apache.tapestry5.ioc.annotations.Inject; +import org.apache.tapestry5.services.ajax.AjaxResponseRenderer; +import org.slf4j.Logger; + +public class Home { + + @Property + private String appName = "apache-tapestry"; + + public Date getCurrentTime() { + return new Date(); + } + + @Inject + private Logger logger; + + @Inject + private AjaxResponseRenderer ajaxResponseRenderer; + + @Inject + private Block ajaxBlock; + + @Log + void onCallAjax() { + logger.info("Ajax call"); + ajaxResponseRenderer.addRender("ajaxZone", ajaxBlock); + } + +} diff --git a/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Index.java b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Index.java new file mode 100644 index 0000000000..7d9e9a1aaa --- /dev/null +++ b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Index.java @@ -0,0 +1,59 @@ +package com.baeldung.tapestry.pages; + + +import org.apache.tapestry5.Block; +import org.apache.tapestry5.EventContext; +import org.apache.tapestry5.SymbolConstants; +import org.apache.tapestry5.annotations.InjectPage; +import org.apache.tapestry5.annotations.Log; +import org.apache.tapestry5.annotations.Property; +import org.apache.tapestry5.ioc.annotations.Inject; +import org.apache.tapestry5.ioc.annotations.Symbol; +import org.apache.tapestry5.services.HttpError; +import org.apache.tapestry5.services.ajax.AjaxResponseRenderer; +import org.slf4j.Logger; + +import java.util.Date; + +/** + * Start page of application apache-tapestry. + */ +public class Index { + @Inject + private Logger logger; + + @Inject + private AjaxResponseRenderer ajaxResponseRenderer; + + @Property + @Inject + @Symbol(SymbolConstants.TAPESTRY_VERSION) + private String tapestryVersion; + + @Inject + private Block block; + + // Handle call with an unwanted context + Object onActivate(EventContext eventContext) { + return eventContext.getCount() > 0 ? + new HttpError(404, "Resource not found") : + null; + } + + @Log + void onComplete() { + logger.info("Complete call on Index page"); + } + + @Log + void onAjax() { + logger.info("Ajax call on Index page"); + + ajaxResponseRenderer.addRender("middlezone", block); + } + + public Date getCurrentTime() { + return new Date(); + } + +} diff --git a/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Login.java b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Login.java new file mode 100644 index 0000000000..c5005f11f5 --- /dev/null +++ b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/pages/Login.java @@ -0,0 +1,42 @@ +package com.baeldung.tapestry.pages; + +import org.apache.tapestry5.alerts.AlertManager; +import org.apache.tapestry5.annotations.InjectComponent; +import org.apache.tapestry5.annotations.Property; +import org.apache.tapestry5.corelib.components.Form; +import org.apache.tapestry5.ioc.annotations.Inject; +import org.slf4j.Logger; + +public class Login { + @Inject + private Logger logger; + + @Inject + private AlertManager alertManager; + + @InjectComponent + private Form login; + + @Property + private String email; + + @Property + private String password; + + void onValidateFromLogin() { + if(email == null || password == null) { + alertManager.error("Email/Password is null"); + login.recordError("Validation failed"); + } + } + + Object onSuccessFromLogin() { + alertManager.success("Welcome! Login Successful"); + return Home.class; + } + + void onFailureFromLogin() { + alertManager.error("Please try again with correct credentials"); + } + +} diff --git a/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/services/AppModule.java b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/services/AppModule.java new file mode 100644 index 0000000000..2798e4a75b --- /dev/null +++ b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/services/AppModule.java @@ -0,0 +1,128 @@ +package com.baeldung.tapestry.services; + +import java.io.IOException; + +import org.apache.tapestry5.SymbolConstants; +import org.apache.tapestry5.commons.MappedConfiguration; +import org.apache.tapestry5.commons.OrderedConfiguration; +import org.apache.tapestry5.http.services.Request; +import org.apache.tapestry5.http.services.RequestFilter; +import org.apache.tapestry5.http.services.RequestHandler; +import org.apache.tapestry5.http.services.Response; +import org.apache.tapestry5.ioc.ServiceBinder; +import org.apache.tapestry5.ioc.annotations.Contribute; +import org.apache.tapestry5.ioc.annotations.Local; +import org.apache.tapestry5.ioc.services.ApplicationDefaults; +import org.apache.tapestry5.ioc.services.SymbolProvider; +import org.slf4j.Logger; + +/** + * This module is automatically included as part of the Tapestry IoC Registry, it's a good place to + * configure and extend Tapestry, or to place your own service definitions. + */ +public class AppModule { + public static void bind(ServiceBinder binder) { + // binder.bind(MyServiceInterface.class, MyServiceImpl.class); + + // Make bind() calls on the binder object to define most IoC services. + // Use service builder methods (example below) when the implementation + // is provided inline, or requires more initialization than simply + // invoking the constructor. + } + + public static void contributeFactoryDefaults( + MappedConfiguration configuration) { + // The values defined here (as factory default overrides) are themselves + // overridden with application defaults by DevelopmentModule and QaModule. + + // The application version is primarily useful as it appears in + // any exception reports (HTML or textual). + configuration.override(SymbolConstants.APPLICATION_VERSION, "0.0.1-SNAPSHOT"); + + // This is something that should be removed when going to production, but is useful + // in the early stages of development. + configuration.override(SymbolConstants.PRODUCTION_MODE, false); + } + + public static void contributeApplicationDefaults( + MappedConfiguration configuration) { + // Contributions to ApplicationDefaults will override any contributions to + // FactoryDefaults (with the same key). Here we're restricting the supported + // locales to just "en" (English). As you add localised message catalogs and other assets, + // you can extend this list of locales (it's a comma separated series of locale names; + // the first locale name is the default when there's no reasonable match). + configuration.add(SymbolConstants.SUPPORTED_LOCALES, "en"); + + // You should change the passphrase immediately; the HMAC passphrase is used to secure + // the hidden field data stored in forms to encrypt and digitally sign client-side data. + configuration.add(SymbolConstants.HMAC_PASSPHRASE, "change this immediately"); + } + + /** + * Use annotation or method naming convention: contributeApplicationDefaults + */ + @Contribute(SymbolProvider.class) + @ApplicationDefaults + public static void setupEnvironment(MappedConfiguration configuration) { + // Support for jQuery is new in Tapestry 5.4 and will become the only supported + // option in 5.5. + configuration.add(SymbolConstants.JAVASCRIPT_INFRASTRUCTURE_PROVIDER, "jquery"); + configuration.add(SymbolConstants.BOOTSTRAP_ROOT, "context:mybootstrap"); + } + + + /** + * This is a service definition, the service will be named "TimingFilter". The interface, + * RequestFilter, is used within the RequestHandler service pipeline, which is built from the + * RequestHandler service configuration. Tapestry IoC is responsible for passing in an + * appropriate Logger instance. Requests for static resources are handled at a higher level, so + * this filter will only be invoked for Tapestry related requests. + * + * + * Service builder methods are useful when the implementation is inline as an inner class + * (as here) or require some other kind of special initialization. In most cases, + * use the static bind() method instead. + * + * + * If this method was named "build", then the service id would be taken from the + * service interface and would be "RequestFilter". Since Tapestry already defines + * a service named "RequestFilter" we use an explicit service id that we can reference + * inside the contribution method. + */ + public RequestFilter buildTimingFilter(final Logger log) { + return new RequestFilter() { + public boolean service(Request request, Response response, RequestHandler handler) + throws IOException { + long startTime = System.currentTimeMillis(); + + try { + // The responsibility of a filter is to invoke the corresponding method + // in the handler. When you chain multiple filters together, each filter + // received a handler that is a bridge to the next filter. + + return handler.service(request, response); + } finally { + long elapsed = System.currentTimeMillis() - startTime; + + log.info("Request time: {} ms", elapsed); + } + } + }; + } + + /** + * This is a contribution to the RequestHandler service configuration. This is how we extend + * Tapestry using the timing filter. A common use for this kind of filter is transaction + * management or security. The @Local annotation selects the desired service by type, but only + * from the same module. Without @Local, there would be an error due to the other service(s) + * that implement RequestFilter (defined in other modules). + */ + @Contribute(RequestHandler.class) + public void addTimingFilter(OrderedConfiguration configuration, @Local RequestFilter filter) { + // Each contribution to an ordered configuration has a name, When necessary, you may + // set constraints to precisely control the invocation order of the contributed filter + // within the pipeline. + + configuration.add("Timing", filter); + } +} diff --git a/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/services/DevelopmentModule.java b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/services/DevelopmentModule.java new file mode 100644 index 0000000000..1c89587c53 --- /dev/null +++ b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/services/DevelopmentModule.java @@ -0,0 +1,24 @@ +package com.baeldung.tapestry.services; + +import org.apache.tapestry5.SymbolConstants; +import org.apache.tapestry5.commons.MappedConfiguration; + +/** + * This module is automatically included as part of the Tapestry IoC Registry if tapestry.execution-mode + * includes development. + */ +public class DevelopmentModule { + public static void contributeApplicationDefaults( + MappedConfiguration configuration) { + // The factory default is true but during the early stages of an application + // overriding to false is a good idea. In addition, this is often overridden + // on the command line as -Dtapestry.production-mode=false + configuration.add(SymbolConstants.PRODUCTION_MODE, false); + + // The application version number is incorprated into URLs for some + // assets. Web browsers will cache assets because of the far future expires + // header. If existing assets are changed, the version number should also + // change, to force the browser to download new versions. + configuration.add(SymbolConstants.APPLICATION_VERSION, "0.0.1-SNAPSHOT-DEV"); + } +} diff --git a/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/services/QaModule.java b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/services/QaModule.java new file mode 100644 index 0000000000..d16e498a4b --- /dev/null +++ b/web-modules/apache-tapestry/src/main/java/com/baeldung/tapestry/services/QaModule.java @@ -0,0 +1,34 @@ +package com.baeldung.tapestry.services; + +import org.apache.tapestry5.SymbolConstants; +import org.apache.tapestry5.commons.MappedConfiguration; +import org.apache.tapestry5.ioc.ServiceBinder; + +/** + * This module is automatically included as part of the Tapestry IoC Registry if tapestry.execution-mode + * includes qa ("quality assurance"). + */ +public class QaModule +{ + public static void bind(ServiceBinder binder) + { + // Bind any services needed by the QA team to produce their reports + // binder.bind(MyServiceMonitorInterface.class, MyServiceMonitorImpl.class); + } + + + public static void contributeApplicationDefaults( + MappedConfiguration configuration) + { + // The factory default is true but during the early stages of an application + // overriding to false is a good idea. In addition, this is often overridden + // on the command line as -Dtapestry.production-mode=false + configuration.add(SymbolConstants.PRODUCTION_MODE, false); + + // The application version number is incorprated into URLs for some + // assets. Web browsers will cache assets because of the far future expires + // header. If existing assets are changed, the version number should also + // change, to force the browser to download new versions. + configuration.add(SymbolConstants.APPLICATION_VERSION, "0.0.1-SNAPSHOT-QA"); + } +} diff --git a/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/components/Layout.tml b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/components/Layout.tml new file mode 100644 index 0000000000..baa17aef8e --- /dev/null +++ b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/components/Layout.tml @@ -0,0 +1,21 @@ + + + ${title} + + +
+
+
+ +
+
+
+
+ +
+
+

© Your Company

+
+
+ + diff --git a/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/logback.xml b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/logback.xml new file mode 100644 index 0000000000..2997ecb099 --- /dev/null +++ b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/logback.xml @@ -0,0 +1,13 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + diff --git a/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Error404.tml b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Error404.tml new file mode 100644 index 0000000000..b18492221e --- /dev/null +++ b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Error404.tml @@ -0,0 +1,11 @@ + + +
+
+

Requested page not found!

+
+
+ + diff --git a/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Home.properties b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Home.properties new file mode 100644 index 0000000000..4647845163 --- /dev/null +++ b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Home.properties @@ -0,0 +1 @@ +introMsg=Welcome to the Apache Tapestry Tutorial diff --git a/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Home.tml b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Home.tml new file mode 100644 index 0000000000..3dafb63f0a --- /dev/null +++ b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Home.tml @@ -0,0 +1,14 @@ + + +

Home! ${appName}

+

${message:introMsg}

+

${currentTime}

+

Call Ajax

+ + +
+

Rendered through Ajax

+

The current time is: ${currentTime}

+
+ + diff --git a/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Index.properties b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Index.properties new file mode 100644 index 0000000000..bc49edd53f --- /dev/null +++ b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Index.properties @@ -0,0 +1 @@ +greeting=Welcome to Tapestry 5! We hope that this project template will get you going in style. diff --git a/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Index.tml b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Index.tml new file mode 100644 index 0000000000..625a3c2fcc --- /dev/null +++ b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Index.tml @@ -0,0 +1,46 @@ + + + + + +
+

+ ${message:greeting} +

+

${message:greeting}

+

The current time is: ${currentTime}

+

+ This is a template for a simple marketing or informational website. It includes a large callout called + the hero unit and three supporting pieces of content. Use it as a starting point to create something + more unique. +

+

Learn more »

+
+ + +
+
+

Normal link

+

Clink the bottom link and the page refresh with event complete

+

Complete»

+
+ + + +
+

Ajax link

+

Click the bottom link to update just the middle column with Ajax call with event ajax

+

Ajax»

+
+
+ + +

Ajax updated

+

I'v been updated through AJAX call

+

The current time is: ${currentTime}

+
+ + diff --git a/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Login.tml b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Login.tml new file mode 100644 index 0000000000..ac78a55341 --- /dev/null +++ b/web-modules/apache-tapestry/src/main/resources/com/baeldung/tapestry/pages/Login.tml @@ -0,0 +1,16 @@ + + +
+
+ +

Please sign in

+ + + +
+
+
+ + diff --git a/web-modules/apache-tapestry/src/main/resources/log4j.properties b/web-modules/apache-tapestry/src/main/resources/log4j.properties new file mode 100644 index 0000000000..bd90a762ca --- /dev/null +++ b/web-modules/apache-tapestry/src/main/resources/log4j.properties @@ -0,0 +1,44 @@ +# Default to info level output; this is very handy if you eventually use Hibernate as well. +log4j.rootCategory=info, A1 + +# A1 is set to be a ConsoleAppender. +log4j.appender.A1=org.apache.log4j.ConsoleAppender + +# A1 uses PatternLayout. +log4j.appender.A1.layout=org.apache.log4j.PatternLayout +log4j.appender.A1.layout.ConversionPattern=[%p] %c{2} %m%n + +# Service category names are the name of the defining module class +# and then the service id. +log4j.category.com.baeldung.tapestry.services.AppModule.TimingFilter=info + +# Outputs a list of pages, components and mixins at startup. +log4j.category.org.apache.tapestry5.modules.TapestryModule.ComponentClassResolver=info + +# Outputs startup statistics; elapsed time to setup and initialize the registry, a list of +# available services, and a launch banner that includes the Tapestry version number. +log4j.category.org.apache.tapestry5.TapestryFilter=info + + +# Turning on debug mode for a page's or component's transformer logger +# will show all of the code changes that occur when the +# class is loaded. + +# log4j.category.tapestry.transformer.com.baeldung.tapestry.pages.Index=debug + +# Turning on debug mode for a component's events logger will show all the events triggered on the +# component, and which component methods are invoked as a result. + +# log4j.category.tapestry.events.com.baeldung.tapestry.pages.Index=debug + +# Turning on trace mode for a page's render logger provides extended information about every step +# in rendering (this is not generally helpful). Turning on debug mode will add a one-line +# summary that includes the elapsed render time, which can be useful in tracking down +# performance issues. + +# log4j.category.tapestry.render.com.baeldung.tapestry.pages.Index=debug + +# Turn on some verbose debugging about everything in the application. This is nice initially, +# while getting everything set up. You'll probably want to remove this once you are +# up and running, replacing it with more selective debugging output. +log4j.category.com.baeldung.tapestry=debug diff --git a/web-modules/apache-tapestry/src/main/webapp/WEB-INF/app.properties b/web-modules/apache-tapestry/src/main/webapp/WEB-INF/app.properties new file mode 100644 index 0000000000..1c299311bb --- /dev/null +++ b/web-modules/apache-tapestry/src/main/webapp/WEB-INF/app.properties @@ -0,0 +1,4 @@ +# This is where global application properties go. +# You can also have individual message catalogs for each page and each +# component that override these defaults. +# The name of this file is based on the element in web. \ No newline at end of file diff --git a/web-modules/apache-tapestry/src/main/webapp/WEB-INF/web.xml b/web-modules/apache-tapestry/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..c5bdfd415c --- /dev/null +++ b/web-modules/apache-tapestry/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,54 @@ + + + + + apache-tapestry Tapestry 5 Application + + + tapestry.app-package + com.baeldung.tapestry + + + + + tapestry.development-modules + + com.baeldung.tapestry.services.DevelopmentModule + + + + tapestry.qa-modules + + com.baeldung.tapestry.services.QaModule + + + + + + + app + org.apache.tapestry5.TapestryFilter + + + + app + /* + REQUEST + ERROR + + + + 404 + /error404 + + + \ No newline at end of file diff --git a/web-modules/apache-tapestry/src/main/webapp/favicon.ico b/web-modules/apache-tapestry/src/main/webapp/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b9715a2aed5813613f6523136ca7adecce80ff66 GIT binary patch literal 1150 zcma)5eJs>*82|mw8L~zlwziT@v(%IfrEup^x>(-2NGUR_ElEeaN{+nL4$Dj0oj+K~ zS#`+U8Lm@ArSw9jA}*#{N!FW4zo+N-<4jw%p5H#-m*;stpWmME_xTb8iJz${fuj|% zk4+F31VJoEpbI_Iew+vbV;tjYF#CTGH_ zx8A+PG5{Wacm-S4XTYuYB*m*v2A(3}xxm(iJ_K@3og`b73*wK*lHMS)ClC)Uv_1%a}9iJ9qJ7z_RJZjUv z@f)O+utf#~Uq)c)>nQALF9v?26!@wP;MYiiUw#A}QbU4}Gq<0ZyLVR}@8#B|ffs6= z>aL^GyKBJ{xm-Md_bSQQh6{0;Wl>(<$eoAK-2q`a(?9m7!VmGVU)*a_V0Wt=!dv9v zT7KfK%Z2zVTTy^Na_Byp<>7j+(S9?x(zt$Zg&2e?>6gf=oK|~rNGST}BS@0XBCPjr zn#-A88!cKuui17-1H7GbBP8~*0sKVO`N){uboxpEx3P^4^cSqMG(rL^s=3HwfBQxH mp8sf5_$sGN2;w_dr9~t&Fa7t_WZYh#ffnOh%pc<-2k{FrL~ptP literal 0 HcmV?d00001 diff --git a/web-modules/apache-tapestry/src/main/webapp/images/tapestry.png b/web-modules/apache-tapestry/src/main/webapp/images/tapestry.png new file mode 100644 index 0000000000000000000000000000000000000000..eba58883c668d2847b60d10213e10db466a2e7e9 GIT binary patch literal 34547 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 literal 0 HcmV?d00001 diff --git a/web-modules/apache-tapestry/src/main/webapp/mybootstrap/css/bootstrap.css b/web-modules/apache-tapestry/src/main/webapp/mybootstrap/css/bootstrap.css new file mode 100644 index 0000000000..057ff46dae --- /dev/null +++ b/web-modules/apache-tapestry/src/main/webapp/mybootstrap/css/bootstrap.css @@ -0,0 +1,6588 @@ +/*! + * Bootstrap v3.3.4 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ +html { + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; +} +body { + margin: 0; +} +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} +audio, +canvas, +progress, +video { + display: inline-block; + vertical-align: baseline; +} +audio:not([controls]) { + display: none; + height: 0; +} +[hidden], +template { + display: none; +} +a { + background-color: transparent; +} +a:active, +a:hover { + outline: 0; +} +abbr[title] { + border-bottom: 1px dotted; +} +b, +strong { + font-weight: bold; +} +dfn { + font-style: italic; +} +h1 { + margin: .67em 0; + font-size: 2em; +} +mark { + color: #000; + background: #ff0; +} +small { + font-size: 80%; +} +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} +sup { + top: -.5em; +} +sub { + bottom: -.25em; +} +img { + border: 0; +} +svg:not(:root) { + overflow: hidden; +} +figure { + margin: 1em 40px; +} +hr { + height: 0; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; +} +pre { + overflow: auto; +} +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} +button, +input, +optgroup, +select, +textarea { + margin: 0; + font: inherit; + color: inherit; +} +button { + overflow: visible; +} +button, +select { + text-transform: none; +} +button, +html input[type="button"], +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; + cursor: pointer; +} +button[disabled], +html input[disabled] { + cursor: default; +} +button::-moz-focus-inner, +input::-moz-focus-inner { + padding: 0; + border: 0; +} +input { + line-height: normal; +} +input[type="checkbox"], +input[type="radio"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + padding: 0; +} +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} +input[type="search"] { + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; +} +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} +fieldset { + padding: .35em .625em .75em; + margin: 0 2px; + border: 1px solid #c0c0c0; +} +legend { + padding: 0; + border: 0; +} +textarea { + overflow: auto; +} +optgroup { + font-weight: bold; +} +table { + border-spacing: 0; + border-collapse: collapse; +} +td, +th { + padding: 0; +} +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + -webkit-box-shadow: none !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #fff !important; + } + .navbar { + display: none; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } +} +@font-face { + font-family: 'Glyphicons Halflings'; + + src: url('../fonts/glyphicons-halflings-regular.eot'); + src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} +.glyphicon-asterisk:before { + content: "\2a"; +} +.glyphicon-plus:before { + content: "\2b"; +} +.glyphicon-euro:before, +.glyphicon-eur:before { + content: "\20ac"; +} +.glyphicon-minus:before { + content: "\2212"; +} +.glyphicon-cloud:before { + content: "\2601"; +} +.glyphicon-envelope:before { + content: "\2709"; +} +.glyphicon-pencil:before { + content: "\270f"; +} +.glyphicon-glass:before { + content: "\e001"; +} +.glyphicon-music:before { + content: "\e002"; +} +.glyphicon-search:before { + content: "\e003"; +} +.glyphicon-heart:before { + content: "\e005"; +} +.glyphicon-star:before { + content: "\e006"; +} +.glyphicon-star-empty:before { + content: "\e007"; +} +.glyphicon-user:before { + content: "\e008"; +} +.glyphicon-film:before { + content: "\e009"; +} +.glyphicon-th-large:before { + content: "\e010"; +} +.glyphicon-th:before { + content: "\e011"; +} +.glyphicon-th-list:before { + content: "\e012"; +} +.glyphicon-ok:before { + content: "\e013"; +} +.glyphicon-remove:before { + content: "\e014"; +} +.glyphicon-zoom-in:before { + content: "\e015"; +} +.glyphicon-zoom-out:before { + content: "\e016"; +} +.glyphicon-off:before { + content: "\e017"; +} +.glyphicon-signal:before { + content: "\e018"; +} +.glyphicon-cog:before { + content: "\e019"; +} +.glyphicon-trash:before { + content: "\e020"; +} +.glyphicon-home:before { + content: "\e021"; +} +.glyphicon-file:before { + content: "\e022"; +} +.glyphicon-time:before { + content: "\e023"; +} +.glyphicon-road:before { + content: "\e024"; +} +.glyphicon-download-alt:before { + content: "\e025"; +} +.glyphicon-download:before { + content: "\e026"; +} +.glyphicon-upload:before { + content: "\e027"; +} +.glyphicon-inbox:before { + content: "\e028"; +} +.glyphicon-play-circle:before { + content: "\e029"; +} +.glyphicon-repeat:before { + content: "\e030"; +} +.glyphicon-refresh:before { + content: "\e031"; +} +.glyphicon-list-alt:before { + content: "\e032"; +} +.glyphicon-lock:before { + content: "\e033"; +} +.glyphicon-flag:before { + content: "\e034"; +} +.glyphicon-headphones:before { + content: "\e035"; +} +.glyphicon-volume-off:before { + content: "\e036"; +} +.glyphicon-volume-down:before { + content: "\e037"; +} +.glyphicon-volume-up:before { + content: "\e038"; +} +.glyphicon-qrcode:before { + content: "\e039"; +} +.glyphicon-barcode:before { + content: "\e040"; +} +.glyphicon-tag:before { + content: "\e041"; +} +.glyphicon-tags:before { + content: "\e042"; +} +.glyphicon-book:before { + content: "\e043"; +} +.glyphicon-bookmark:before { + content: "\e044"; +} +.glyphicon-print:before { + content: "\e045"; +} +.glyphicon-camera:before { + content: "\e046"; +} +.glyphicon-font:before { + content: "\e047"; +} +.glyphicon-bold:before { + content: "\e048"; +} +.glyphicon-italic:before { + content: "\e049"; +} +.glyphicon-text-height:before { + content: "\e050"; +} +.glyphicon-text-width:before { + content: "\e051"; +} +.glyphicon-align-left:before { + content: "\e052"; +} +.glyphicon-align-center:before { + content: "\e053"; +} +.glyphicon-align-right:before { + content: "\e054"; +} +.glyphicon-align-justify:before { + content: "\e055"; +} +.glyphicon-list:before { + content: "\e056"; +} +.glyphicon-indent-left:before { + content: "\e057"; +} +.glyphicon-indent-right:before { + content: "\e058"; +} +.glyphicon-facetime-video:before { + content: "\e059"; +} +.glyphicon-picture:before { + content: "\e060"; +} +.glyphicon-map-marker:before { + content: "\e062"; +} +.glyphicon-adjust:before { + content: "\e063"; +} +.glyphicon-tint:before { + content: "\e064"; +} +.glyphicon-edit:before { + content: "\e065"; +} +.glyphicon-share:before { + content: "\e066"; +} +.glyphicon-check:before { + content: "\e067"; +} +.glyphicon-move:before { + content: "\e068"; +} +.glyphicon-step-backward:before { + content: "\e069"; +} +.glyphicon-fast-backward:before { + content: "\e070"; +} +.glyphicon-backward:before { + content: "\e071"; +} +.glyphicon-play:before { + content: "\e072"; +} +.glyphicon-pause:before { + content: "\e073"; +} +.glyphicon-stop:before { + content: "\e074"; +} +.glyphicon-forward:before { + content: "\e075"; +} +.glyphicon-fast-forward:before { + content: "\e076"; +} +.glyphicon-step-forward:before { + content: "\e077"; +} +.glyphicon-eject:before { + content: "\e078"; +} +.glyphicon-chevron-left:before { + content: "\e079"; +} +.glyphicon-chevron-right:before { + content: "\e080"; +} +.glyphicon-plus-sign:before { + content: "\e081"; +} +.glyphicon-minus-sign:before { + content: "\e082"; +} +.glyphicon-remove-sign:before { + content: "\e083"; +} +.glyphicon-ok-sign:before { + content: "\e084"; +} +.glyphicon-question-sign:before { + content: "\e085"; +} +.glyphicon-info-sign:before { + content: "\e086"; +} +.glyphicon-screenshot:before { + content: "\e087"; +} +.glyphicon-remove-circle:before { + content: "\e088"; +} +.glyphicon-ok-circle:before { + content: "\e089"; +} +.glyphicon-ban-circle:before { + content: "\e090"; +} +.glyphicon-arrow-left:before { + content: "\e091"; +} +.glyphicon-arrow-right:before { + content: "\e092"; +} +.glyphicon-arrow-up:before { + content: "\e093"; +} +.glyphicon-arrow-down:before { + content: "\e094"; +} +.glyphicon-share-alt:before { + content: "\e095"; +} +.glyphicon-resize-full:before { + content: "\e096"; +} +.glyphicon-resize-small:before { + content: "\e097"; +} +.glyphicon-exclamation-sign:before { + content: "\e101"; +} +.glyphicon-gift:before { + content: "\e102"; +} +.glyphicon-leaf:before { + content: "\e103"; +} +.glyphicon-fire:before { + content: "\e104"; +} +.glyphicon-eye-open:before { + content: "\e105"; +} +.glyphicon-eye-close:before { + content: "\e106"; +} +.glyphicon-warning-sign:before { + content: "\e107"; +} +.glyphicon-plane:before { + content: "\e108"; +} +.glyphicon-calendar:before { + content: "\e109"; +} +.glyphicon-random:before { + content: "\e110"; +} +.glyphicon-comment:before { + content: "\e111"; +} +.glyphicon-magnet:before { + content: "\e112"; +} +.glyphicon-chevron-up:before { + content: "\e113"; +} +.glyphicon-chevron-down:before { + content: "\e114"; +} +.glyphicon-retweet:before { + content: "\e115"; +} +.glyphicon-shopping-cart:before { + content: "\e116"; +} +.glyphicon-folder-close:before { + content: "\e117"; +} +.glyphicon-folder-open:before { + content: "\e118"; +} +.glyphicon-resize-vertical:before { + content: "\e119"; +} +.glyphicon-resize-horizontal:before { + content: "\e120"; +} +.glyphicon-hdd:before { + content: "\e121"; +} +.glyphicon-bullhorn:before { + content: "\e122"; +} +.glyphicon-bell:before { + content: "\e123"; +} +.glyphicon-certificate:before { + content: "\e124"; +} +.glyphicon-thumbs-up:before { + content: "\e125"; +} +.glyphicon-thumbs-down:before { + content: "\e126"; +} +.glyphicon-hand-right:before { + content: "\e127"; +} +.glyphicon-hand-left:before { + content: "\e128"; +} +.glyphicon-hand-up:before { + content: "\e129"; +} +.glyphicon-hand-down:before { + content: "\e130"; +} +.glyphicon-circle-arrow-right:before { + content: "\e131"; +} +.glyphicon-circle-arrow-left:before { + content: "\e132"; +} +.glyphicon-circle-arrow-up:before { + content: "\e133"; +} +.glyphicon-circle-arrow-down:before { + content: "\e134"; +} +.glyphicon-globe:before { + content: "\e135"; +} +.glyphicon-wrench:before { + content: "\e136"; +} +.glyphicon-tasks:before { + content: "\e137"; +} +.glyphicon-filter:before { + content: "\e138"; +} +.glyphicon-briefcase:before { + content: "\e139"; +} +.glyphicon-fullscreen:before { + content: "\e140"; +} +.glyphicon-dashboard:before { + content: "\e141"; +} +.glyphicon-paperclip:before { + content: "\e142"; +} +.glyphicon-heart-empty:before { + content: "\e143"; +} +.glyphicon-link:before { + content: "\e144"; +} +.glyphicon-phone:before { + content: "\e145"; +} +.glyphicon-pushpin:before { + content: "\e146"; +} +.glyphicon-usd:before { + content: "\e148"; +} +.glyphicon-gbp:before { + content: "\e149"; +} +.glyphicon-sort:before { + content: "\e150"; +} +.glyphicon-sort-by-alphabet:before { + content: "\e151"; +} +.glyphicon-sort-by-alphabet-alt:before { + content: "\e152"; +} +.glyphicon-sort-by-order:before { + content: "\e153"; +} +.glyphicon-sort-by-order-alt:before { + content: "\e154"; +} +.glyphicon-sort-by-attributes:before { + content: "\e155"; +} +.glyphicon-sort-by-attributes-alt:before { + content: "\e156"; +} +.glyphicon-unchecked:before { + content: "\e157"; +} +.glyphicon-expand:before { + content: "\e158"; +} +.glyphicon-collapse-down:before { + content: "\e159"; +} +.glyphicon-collapse-up:before { + content: "\e160"; +} +.glyphicon-log-in:before { + content: "\e161"; +} +.glyphicon-flash:before { + content: "\e162"; +} +.glyphicon-log-out:before { + content: "\e163"; +} +.glyphicon-new-window:before { + content: "\e164"; +} +.glyphicon-record:before { + content: "\e165"; +} +.glyphicon-save:before { + content: "\e166"; +} +.glyphicon-open:before { + content: "\e167"; +} +.glyphicon-saved:before { + content: "\e168"; +} +.glyphicon-import:before { + content: "\e169"; +} +.glyphicon-export:before { + content: "\e170"; +} +.glyphicon-send:before { + content: "\e171"; +} +.glyphicon-floppy-disk:before { + content: "\e172"; +} +.glyphicon-floppy-saved:before { + content: "\e173"; +} +.glyphicon-floppy-remove:before { + content: "\e174"; +} +.glyphicon-floppy-save:before { + content: "\e175"; +} +.glyphicon-floppy-open:before { + content: "\e176"; +} +.glyphicon-credit-card:before { + content: "\e177"; +} +.glyphicon-transfer:before { + content: "\e178"; +} +.glyphicon-cutlery:before { + content: "\e179"; +} +.glyphicon-header:before { + content: "\e180"; +} +.glyphicon-compressed:before { + content: "\e181"; +} +.glyphicon-earphone:before { + content: "\e182"; +} +.glyphicon-phone-alt:before { + content: "\e183"; +} +.glyphicon-tower:before { + content: "\e184"; +} +.glyphicon-stats:before { + content: "\e185"; +} +.glyphicon-sd-video:before { + content: "\e186"; +} +.glyphicon-hd-video:before { + content: "\e187"; +} +.glyphicon-subtitles:before { + content: "\e188"; +} +.glyphicon-sound-stereo:before { + content: "\e189"; +} +.glyphicon-sound-dolby:before { + content: "\e190"; +} +.glyphicon-sound-5-1:before { + content: "\e191"; +} +.glyphicon-sound-6-1:before { + content: "\e192"; +} +.glyphicon-sound-7-1:before { + content: "\e193"; +} +.glyphicon-copyright-mark:before { + content: "\e194"; +} +.glyphicon-registration-mark:before { + content: "\e195"; +} +.glyphicon-cloud-download:before { + content: "\e197"; +} +.glyphicon-cloud-upload:before { + content: "\e198"; +} +.glyphicon-tree-conifer:before { + content: "\e199"; +} +.glyphicon-tree-deciduous:before { + content: "\e200"; +} +.glyphicon-cd:before { + content: "\e201"; +} +.glyphicon-save-file:before { + content: "\e202"; +} +.glyphicon-open-file:before { + content: "\e203"; +} +.glyphicon-level-up:before { + content: "\e204"; +} +.glyphicon-copy:before { + content: "\e205"; +} +.glyphicon-paste:before { + content: "\e206"; +} +.glyphicon-alert:before { + content: "\e209"; +} +.glyphicon-equalizer:before { + content: "\e210"; +} +.glyphicon-king:before { + content: "\e211"; +} +.glyphicon-queen:before { + content: "\e212"; +} +.glyphicon-pawn:before { + content: "\e213"; +} +.glyphicon-bishop:before { + content: "\e214"; +} +.glyphicon-knight:before { + content: "\e215"; +} +.glyphicon-baby-formula:before { + content: "\e216"; +} +.glyphicon-tent:before { + content: "\26fa"; +} +.glyphicon-blackboard:before { + content: "\e218"; +} +.glyphicon-bed:before { + content: "\e219"; +} +.glyphicon-apple:before { + content: "\f8ff"; +} +.glyphicon-erase:before { + content: "\e221"; +} +.glyphicon-hourglass:before { + content: "\231b"; +} +.glyphicon-lamp:before { + content: "\e223"; +} +.glyphicon-duplicate:before { + content: "\e224"; +} +.glyphicon-piggy-bank:before { + content: "\e225"; +} +.glyphicon-scissors:before { + content: "\e226"; +} +.glyphicon-bitcoin:before { + content: "\e227"; +} +.glyphicon-btc:before { + content: "\e227"; +} +.glyphicon-xbt:before { + content: "\e227"; +} +.glyphicon-yen:before { + content: "\00a5"; +} +.glyphicon-jpy:before { + content: "\00a5"; +} +.glyphicon-ruble:before { + content: "\20bd"; +} +.glyphicon-rub:before { + content: "\20bd"; +} +.glyphicon-scale:before { + content: "\e230"; +} +.glyphicon-ice-lolly:before { + content: "\e231"; +} +.glyphicon-ice-lolly-tasted:before { + content: "\e232"; +} +.glyphicon-education:before { + content: "\e233"; +} +.glyphicon-option-horizontal:before { + content: "\e234"; +} +.glyphicon-option-vertical:before { + content: "\e235"; +} +.glyphicon-menu-hamburger:before { + content: "\e236"; +} +.glyphicon-modal-window:before { + content: "\e237"; +} +.glyphicon-oil:before { + content: "\e238"; +} +.glyphicon-grain:before { + content: "\e239"; +} +.glyphicon-sunglasses:before { + content: "\e240"; +} +.glyphicon-text-size:before { + content: "\e241"; +} +.glyphicon-text-color:before { + content: "\e242"; +} +.glyphicon-text-background:before { + content: "\e243"; +} +.glyphicon-object-align-top:before { + content: "\e244"; +} +.glyphicon-object-align-bottom:before { + content: "\e245"; +} +.glyphicon-object-align-horizontal:before { + content: "\e246"; +} +.glyphicon-object-align-left:before { + content: "\e247"; +} +.glyphicon-object-align-vertical:before { + content: "\e248"; +} +.glyphicon-object-align-right:before { + content: "\e249"; +} +.glyphicon-triangle-right:before { + content: "\e250"; +} +.glyphicon-triangle-left:before { + content: "\e251"; +} +.glyphicon-triangle-bottom:before { + content: "\e252"; +} +.glyphicon-triangle-top:before { + content: "\e253"; +} +.glyphicon-console:before { + content: "\e254"; +} +.glyphicon-superscript:before { + content: "\e255"; +} +.glyphicon-subscript:before { + content: "\e256"; +} +.glyphicon-menu-left:before { + content: "\e257"; +} +.glyphicon-menu-right:before { + content: "\e258"; +} +.glyphicon-menu-down:before { + content: "\e259"; +} +.glyphicon-menu-up:before { + content: "\e260"; +} +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +*:before, +*:after { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +html { + font-size: 10px; + + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333; + background-color: #fff; +} +input, +button, +select, +textarea { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} +a { + color: #337ab7; + text-decoration: none; +} +a:hover, +a:focus { + color: #23527c; + text-decoration: underline; +} +a:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +figure { + margin: 0; +} +img { + vertical-align: middle; +} +.img-responsive, +.thumbnail > img, +.thumbnail a > img, +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + display: block; + max-width: 100%; + height: auto; +} +.img-rounded { + border-radius: 6px; +} +.img-thumbnail { + display: inline-block; + max-width: 100%; + height: auto; + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + -o-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; +} +.img-circle { + border-radius: 50%; +} +hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} +[role="button"] { + cursor: pointer; +} +h1, +h2, +h3, +h4, +h5, +h6, +.h1, +.h2, +.h3, +.h4, +.h5, +.h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} +h1 small, +h2 small, +h3 small, +h4 small, +h5 small, +h6 small, +.h1 small, +.h2 small, +.h3 small, +.h4 small, +.h5 small, +.h6 small, +h1 .small, +h2 .small, +h3 .small, +h4 .small, +h5 .small, +h6 .small, +.h1 .small, +.h2 .small, +.h3 .small, +.h4 .small, +.h5 .small, +.h6 .small { + font-weight: normal; + line-height: 1; + color: #777; +} +h1, +.h1, +h2, +.h2, +h3, +.h3 { + margin-top: 20px; + margin-bottom: 10px; +} +h1 small, +.h1 small, +h2 small, +.h2 small, +h3 small, +.h3 small, +h1 .small, +.h1 .small, +h2 .small, +.h2 .small, +h3 .small, +.h3 .small { + font-size: 65%; +} +h4, +.h4, +h5, +.h5, +h6, +.h6 { + margin-top: 10px; + margin-bottom: 10px; +} +h4 small, +.h4 small, +h5 small, +.h5 small, +h6 small, +.h6 small, +h4 .small, +.h4 .small, +h5 .small, +.h5 .small, +h6 .small, +.h6 .small { + font-size: 75%; +} +h1, +.h1 { + font-size: 36px; +} +h2, +.h2 { + font-size: 30px; +} +h3, +.h3 { + font-size: 24px; +} +h4, +.h4 { + font-size: 18px; +} +h5, +.h5 { + font-size: 14px; +} +h6, +.h6 { + font-size: 12px; +} +p { + margin: 0 0 10px; +} +.lead { + margin-bottom: 20px; + font-size: 16px; + font-weight: 300; + line-height: 1.4; +} +@media (min-width: 768px) { + .lead { + font-size: 21px; + } +} +small, +.small { + font-size: 85%; +} +mark, +.mark { + padding: .2em; + background-color: #fcf8e3; +} +.text-left { + text-align: left; +} +.text-right { + text-align: right; +} +.text-center { + text-align: center; +} +.text-justify { + text-align: justify; +} +.text-nowrap { + white-space: nowrap; +} +.text-lowercase { + text-transform: lowercase; +} +.text-uppercase { + text-transform: uppercase; +} +.text-capitalize { + text-transform: capitalize; +} +.text-muted { + color: #777; +} +.text-primary { + color: #337ab7; +} +a.text-primary:hover { + color: #286090; +} +.text-success { + color: #3c763d; +} +a.text-success:hover { + color: #2b542c; +} +.text-info { + color: #31708f; +} +a.text-info:hover { + color: #245269; +} +.text-warning { + color: #8a6d3b; +} +a.text-warning:hover { + color: #66512c; +} +.text-danger { + color: #a94442; +} +a.text-danger:hover { + color: #843534; +} +.bg-primary { + color: #fff; + background-color: #337ab7; +} +a.bg-primary:hover { + background-color: #286090; +} +.bg-success { + background-color: #dff0d8; +} +a.bg-success:hover { + background-color: #c1e2b3; +} +.bg-info { + background-color: #d9edf7; +} +a.bg-info:hover { + background-color: #afd9ee; +} +.bg-warning { + background-color: #fcf8e3; +} +a.bg-warning:hover { + background-color: #f7ecb5; +} +.bg-danger { + background-color: #f2dede; +} +a.bg-danger:hover { + background-color: #e4b9b9; +} +.page-header { + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; +} +ul, +ol { + margin-top: 0; + margin-bottom: 10px; +} +ul ul, +ol ul, +ul ol, +ol ol { + margin-bottom: 0; +} +.list-unstyled { + padding-left: 0; + list-style: none; +} +.list-inline { + padding-left: 0; + margin-left: -5px; + list-style: none; +} +.list-inline > li { + display: inline-block; + padding-right: 5px; + padding-left: 5px; +} +dl { + margin-top: 0; + margin-bottom: 20px; +} +dt, +dd { + line-height: 1.42857143; +} +dt { + font-weight: bold; +} +dd { + margin-left: 0; +} +@media (min-width: 768px) { + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + .dl-horizontal dd { + margin-left: 180px; + } +} +abbr[title], +abbr[data-original-title] { + cursor: help; + border-bottom: 1px dotted #777; +} +.initialism { + font-size: 90%; + text-transform: uppercase; +} +blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; +} +blockquote p:last-child, +blockquote ul:last-child, +blockquote ol:last-child { + margin-bottom: 0; +} +blockquote footer, +blockquote small, +blockquote .small { + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #777; +} +blockquote footer:before, +blockquote small:before, +blockquote .small:before { + content: '\2014 \00A0'; +} +.blockquote-reverse, +blockquote.pull-right { + padding-right: 15px; + padding-left: 0; + text-align: right; + border-right: 5px solid #eee; + border-left: 0; +} +.blockquote-reverse footer:before, +blockquote.pull-right footer:before, +.blockquote-reverse small:before, +blockquote.pull-right small:before, +.blockquote-reverse .small:before, +blockquote.pull-right .small:before { + content: ''; +} +.blockquote-reverse footer:after, +blockquote.pull-right footer:after, +.blockquote-reverse small:after, +blockquote.pull-right small:after, +.blockquote-reverse .small:after, +blockquote.pull-right .small:after { + content: '\00A0 \2014'; +} +address { + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; +} +code, +kbd, +pre, +samp { + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; +} +code { + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + background-color: #f9f2f4; + border-radius: 4px; +} +kbd { + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); +} +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: bold; + -webkit-box-shadow: none; + box-shadow: none; +} +pre { + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; +} +pre code { + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; +} +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} +.container { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +@media (min-width: 768px) { + .container { + width: 750px; + } +} +@media (min-width: 992px) { + .container { + width: 970px; + } +} +@media (min-width: 1200px) { + .container { + width: 1170px; + } +} +.container-fluid { + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} +.row { + margin-right: -15px; + margin-left: -15px; +} +.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 { + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} +.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { + float: left; +} +.col-xs-12 { + width: 100%; +} +.col-xs-11 { + width: 91.66666667%; +} +.col-xs-10 { + width: 83.33333333%; +} +.col-xs-9 { + width: 75%; +} +.col-xs-8 { + width: 66.66666667%; +} +.col-xs-7 { + width: 58.33333333%; +} +.col-xs-6 { + width: 50%; +} +.col-xs-5 { + width: 41.66666667%; +} +.col-xs-4 { + width: 33.33333333%; +} +.col-xs-3 { + width: 25%; +} +.col-xs-2 { + width: 16.66666667%; +} +.col-xs-1 { + width: 8.33333333%; +} +.col-xs-pull-12 { + right: 100%; +} +.col-xs-pull-11 { + right: 91.66666667%; +} +.col-xs-pull-10 { + right: 83.33333333%; +} +.col-xs-pull-9 { + right: 75%; +} +.col-xs-pull-8 { + right: 66.66666667%; +} +.col-xs-pull-7 { + right: 58.33333333%; +} +.col-xs-pull-6 { + right: 50%; +} +.col-xs-pull-5 { + right: 41.66666667%; +} +.col-xs-pull-4 { + right: 33.33333333%; +} +.col-xs-pull-3 { + right: 25%; +} +.col-xs-pull-2 { + right: 16.66666667%; +} +.col-xs-pull-1 { + right: 8.33333333%; +} +.col-xs-pull-0 { + right: auto; +} +.col-xs-push-12 { + left: 100%; +} +.col-xs-push-11 { + left: 91.66666667%; +} +.col-xs-push-10 { + left: 83.33333333%; +} +.col-xs-push-9 { + left: 75%; +} +.col-xs-push-8 { + left: 66.66666667%; +} +.col-xs-push-7 { + left: 58.33333333%; +} +.col-xs-push-6 { + left: 50%; +} +.col-xs-push-5 { + left: 41.66666667%; +} +.col-xs-push-4 { + left: 33.33333333%; +} +.col-xs-push-3 { + left: 25%; +} +.col-xs-push-2 { + left: 16.66666667%; +} +.col-xs-push-1 { + left: 8.33333333%; +} +.col-xs-push-0 { + left: auto; +} +.col-xs-offset-12 { + margin-left: 100%; +} +.col-xs-offset-11 { + margin-left: 91.66666667%; +} +.col-xs-offset-10 { + margin-left: 83.33333333%; +} +.col-xs-offset-9 { + margin-left: 75%; +} +.col-xs-offset-8 { + margin-left: 66.66666667%; +} +.col-xs-offset-7 { + margin-left: 58.33333333%; +} +.col-xs-offset-6 { + margin-left: 50%; +} +.col-xs-offset-5 { + margin-left: 41.66666667%; +} +.col-xs-offset-4 { + margin-left: 33.33333333%; +} +.col-xs-offset-3 { + margin-left: 25%; +} +.col-xs-offset-2 { + margin-left: 16.66666667%; +} +.col-xs-offset-1 { + margin-left: 8.33333333%; +} +.col-xs-offset-0 { + margin-left: 0; +} +@media (min-width: 768px) { + .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { + float: left; + } + .col-sm-12 { + width: 100%; + } + .col-sm-11 { + width: 91.66666667%; + } + .col-sm-10 { + width: 83.33333333%; + } + .col-sm-9 { + width: 75%; + } + .col-sm-8 { + width: 66.66666667%; + } + .col-sm-7 { + width: 58.33333333%; + } + .col-sm-6 { + width: 50%; + } + .col-sm-5 { + width: 41.66666667%; + } + .col-sm-4 { + width: 33.33333333%; + } + .col-sm-3 { + width: 25%; + } + .col-sm-2 { + width: 16.66666667%; + } + .col-sm-1 { + width: 8.33333333%; + } + .col-sm-pull-12 { + right: 100%; + } + .col-sm-pull-11 { + right: 91.66666667%; + } + .col-sm-pull-10 { + right: 83.33333333%; + } + .col-sm-pull-9 { + right: 75%; + } + .col-sm-pull-8 { + right: 66.66666667%; + } + .col-sm-pull-7 { + right: 58.33333333%; + } + .col-sm-pull-6 { + right: 50%; + } + .col-sm-pull-5 { + right: 41.66666667%; + } + .col-sm-pull-4 { + right: 33.33333333%; + } + .col-sm-pull-3 { + right: 25%; + } + .col-sm-pull-2 { + right: 16.66666667%; + } + .col-sm-pull-1 { + right: 8.33333333%; + } + .col-sm-pull-0 { + right: auto; + } + .col-sm-push-12 { + left: 100%; + } + .col-sm-push-11 { + left: 91.66666667%; + } + .col-sm-push-10 { + left: 83.33333333%; + } + .col-sm-push-9 { + left: 75%; + } + .col-sm-push-8 { + left: 66.66666667%; + } + .col-sm-push-7 { + left: 58.33333333%; + } + .col-sm-push-6 { + left: 50%; + } + .col-sm-push-5 { + left: 41.66666667%; + } + .col-sm-push-4 { + left: 33.33333333%; + } + .col-sm-push-3 { + left: 25%; + } + .col-sm-push-2 { + left: 16.66666667%; + } + .col-sm-push-1 { + left: 8.33333333%; + } + .col-sm-push-0 { + left: auto; + } + .col-sm-offset-12 { + margin-left: 100%; + } + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + .col-sm-offset-9 { + margin-left: 75%; + } + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + .col-sm-offset-6 { + margin-left: 50%; + } + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + .col-sm-offset-3 { + margin-left: 25%; + } + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + .col-sm-offset-0 { + margin-left: 0; + } +} +@media (min-width: 992px) { + .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 { + float: left; + } + .col-md-12 { + width: 100%; + } + .col-md-11 { + width: 91.66666667%; + } + .col-md-10 { + width: 83.33333333%; + } + .col-md-9 { + width: 75%; + } + .col-md-8 { + width: 66.66666667%; + } + .col-md-7 { + width: 58.33333333%; + } + .col-md-6 { + width: 50%; + } + .col-md-5 { + width: 41.66666667%; + } + .col-md-4 { + width: 33.33333333%; + } + .col-md-3 { + width: 25%; + } + .col-md-2 { + width: 16.66666667%; + } + .col-md-1 { + width: 8.33333333%; + } + .col-md-pull-12 { + right: 100%; + } + .col-md-pull-11 { + right: 91.66666667%; + } + .col-md-pull-10 { + right: 83.33333333%; + } + .col-md-pull-9 { + right: 75%; + } + .col-md-pull-8 { + right: 66.66666667%; + } + .col-md-pull-7 { + right: 58.33333333%; + } + .col-md-pull-6 { + right: 50%; + } + .col-md-pull-5 { + right: 41.66666667%; + } + .col-md-pull-4 { + right: 33.33333333%; + } + .col-md-pull-3 { + right: 25%; + } + .col-md-pull-2 { + right: 16.66666667%; + } + .col-md-pull-1 { + right: 8.33333333%; + } + .col-md-pull-0 { + right: auto; + } + .col-md-push-12 { + left: 100%; + } + .col-md-push-11 { + left: 91.66666667%; + } + .col-md-push-10 { + left: 83.33333333%; + } + .col-md-push-9 { + left: 75%; + } + .col-md-push-8 { + left: 66.66666667%; + } + .col-md-push-7 { + left: 58.33333333%; + } + .col-md-push-6 { + left: 50%; + } + .col-md-push-5 { + left: 41.66666667%; + } + .col-md-push-4 { + left: 33.33333333%; + } + .col-md-push-3 { + left: 25%; + } + .col-md-push-2 { + left: 16.66666667%; + } + .col-md-push-1 { + left: 8.33333333%; + } + .col-md-push-0 { + left: auto; + } + .col-md-offset-12 { + margin-left: 100%; + } + .col-md-offset-11 { + margin-left: 91.66666667%; + } + .col-md-offset-10 { + margin-left: 83.33333333%; + } + .col-md-offset-9 { + margin-left: 75%; + } + .col-md-offset-8 { + margin-left: 66.66666667%; + } + .col-md-offset-7 { + margin-left: 58.33333333%; + } + .col-md-offset-6 { + margin-left: 50%; + } + .col-md-offset-5 { + margin-left: 41.66666667%; + } + .col-md-offset-4 { + margin-left: 33.33333333%; + } + .col-md-offset-3 { + margin-left: 25%; + } + .col-md-offset-2 { + margin-left: 16.66666667%; + } + .col-md-offset-1 { + margin-left: 8.33333333%; + } + .col-md-offset-0 { + margin-left: 0; + } +} +@media (min-width: 1200px) { + .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 { + float: left; + } + .col-lg-12 { + width: 100%; + } + .col-lg-11 { + width: 91.66666667%; + } + .col-lg-10 { + width: 83.33333333%; + } + .col-lg-9 { + width: 75%; + } + .col-lg-8 { + width: 66.66666667%; + } + .col-lg-7 { + width: 58.33333333%; + } + .col-lg-6 { + width: 50%; + } + .col-lg-5 { + width: 41.66666667%; + } + .col-lg-4 { + width: 33.33333333%; + } + .col-lg-3 { + width: 25%; + } + .col-lg-2 { + width: 16.66666667%; + } + .col-lg-1 { + width: 8.33333333%; + } + .col-lg-pull-12 { + right: 100%; + } + .col-lg-pull-11 { + right: 91.66666667%; + } + .col-lg-pull-10 { + right: 83.33333333%; + } + .col-lg-pull-9 { + right: 75%; + } + .col-lg-pull-8 { + right: 66.66666667%; + } + .col-lg-pull-7 { + right: 58.33333333%; + } + .col-lg-pull-6 { + right: 50%; + } + .col-lg-pull-5 { + right: 41.66666667%; + } + .col-lg-pull-4 { + right: 33.33333333%; + } + .col-lg-pull-3 { + right: 25%; + } + .col-lg-pull-2 { + right: 16.66666667%; + } + .col-lg-pull-1 { + right: 8.33333333%; + } + .col-lg-pull-0 { + right: auto; + } + .col-lg-push-12 { + left: 100%; + } + .col-lg-push-11 { + left: 91.66666667%; + } + .col-lg-push-10 { + left: 83.33333333%; + } + .col-lg-push-9 { + left: 75%; + } + .col-lg-push-8 { + left: 66.66666667%; + } + .col-lg-push-7 { + left: 58.33333333%; + } + .col-lg-push-6 { + left: 50%; + } + .col-lg-push-5 { + left: 41.66666667%; + } + .col-lg-push-4 { + left: 33.33333333%; + } + .col-lg-push-3 { + left: 25%; + } + .col-lg-push-2 { + left: 16.66666667%; + } + .col-lg-push-1 { + left: 8.33333333%; + } + .col-lg-push-0 { + left: auto; + } + .col-lg-offset-12 { + margin-left: 100%; + } + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + .col-lg-offset-9 { + margin-left: 75%; + } + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + .col-lg-offset-6 { + margin-left: 50%; + } + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + .col-lg-offset-3 { + margin-left: 25%; + } + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + .col-lg-offset-0 { + margin-left: 0; + } +} +table { + background-color: transparent; +} +caption { + padding-top: 8px; + padding-bottom: 8px; + color: #777; + text-align: left; +} +th { + text-align: left; +} +.table { + width: 100%; + max-width: 100%; + margin-bottom: 20px; +} +.table > thead > tr > th, +.table > tbody > tr > th, +.table > tfoot > tr > th, +.table > thead > tr > td, +.table > tbody > tr > td, +.table > tfoot > tr > td { + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd; +} +.table > thead > tr > th { + vertical-align: bottom; + border-bottom: 2px solid #ddd; +} +.table > caption + thead > tr:first-child > th, +.table > colgroup + thead > tr:first-child > th, +.table > thead:first-child > tr:first-child > th, +.table > caption + thead > tr:first-child > td, +.table > colgroup + thead > tr:first-child > td, +.table > thead:first-child > tr:first-child > td { + border-top: 0; +} +.table > tbody + tbody { + border-top: 2px solid #ddd; +} +.table .table { + background-color: #fff; +} +.table-condensed > thead > tr > th, +.table-condensed > tbody > tr > th, +.table-condensed > tfoot > tr > th, +.table-condensed > thead > tr > td, +.table-condensed > tbody > tr > td, +.table-condensed > tfoot > tr > td { + padding: 5px; +} +.table-bordered { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > tbody > tr > th, +.table-bordered > tfoot > tr > th, +.table-bordered > thead > tr > td, +.table-bordered > tbody > tr > td, +.table-bordered > tfoot > tr > td { + border: 1px solid #ddd; +} +.table-bordered > thead > tr > th, +.table-bordered > thead > tr > td { + border-bottom-width: 2px; +} +.table-striped > tbody > tr:nth-of-type(odd) { + background-color: #f9f9f9; +} +.table-hover > tbody > tr:hover { + background-color: #f5f5f5; +} +table col[class*="col-"] { + position: static; + display: table-column; + float: none; +} +table td[class*="col-"], +table th[class*="col-"] { + position: static; + display: table-cell; + float: none; +} +.table > thead > tr > td.active, +.table > tbody > tr > td.active, +.table > tfoot > tr > td.active, +.table > thead > tr > th.active, +.table > tbody > tr > th.active, +.table > tfoot > tr > th.active, +.table > thead > tr.active > td, +.table > tbody > tr.active > td, +.table > tfoot > tr.active > td, +.table > thead > tr.active > th, +.table > tbody > tr.active > th, +.table > tfoot > tr.active > th { + background-color: #f5f5f5; +} +.table-hover > tbody > tr > td.active:hover, +.table-hover > tbody > tr > th.active:hover, +.table-hover > tbody > tr.active:hover > td, +.table-hover > tbody > tr:hover > .active, +.table-hover > tbody > tr.active:hover > th { + background-color: #e8e8e8; +} +.table > thead > tr > td.success, +.table > tbody > tr > td.success, +.table > tfoot > tr > td.success, +.table > thead > tr > th.success, +.table > tbody > tr > th.success, +.table > tfoot > tr > th.success, +.table > thead > tr.success > td, +.table > tbody > tr.success > td, +.table > tfoot > tr.success > td, +.table > thead > tr.success > th, +.table > tbody > tr.success > th, +.table > tfoot > tr.success > th { + background-color: #dff0d8; +} +.table-hover > tbody > tr > td.success:hover, +.table-hover > tbody > tr > th.success:hover, +.table-hover > tbody > tr.success:hover > td, +.table-hover > tbody > tr:hover > .success, +.table-hover > tbody > tr.success:hover > th { + background-color: #d0e9c6; +} +.table > thead > tr > td.info, +.table > tbody > tr > td.info, +.table > tfoot > tr > td.info, +.table > thead > tr > th.info, +.table > tbody > tr > th.info, +.table > tfoot > tr > th.info, +.table > thead > tr.info > td, +.table > tbody > tr.info > td, +.table > tfoot > tr.info > td, +.table > thead > tr.info > th, +.table > tbody > tr.info > th, +.table > tfoot > tr.info > th { + background-color: #d9edf7; +} +.table-hover > tbody > tr > td.info:hover, +.table-hover > tbody > tr > th.info:hover, +.table-hover > tbody > tr.info:hover > td, +.table-hover > tbody > tr:hover > .info, +.table-hover > tbody > tr.info:hover > th { + background-color: #c4e3f3; +} +.table > thead > tr > td.warning, +.table > tbody > tr > td.warning, +.table > tfoot > tr > td.warning, +.table > thead > tr > th.warning, +.table > tbody > tr > th.warning, +.table > tfoot > tr > th.warning, +.table > thead > tr.warning > td, +.table > tbody > tr.warning > td, +.table > tfoot > tr.warning > td, +.table > thead > tr.warning > th, +.table > tbody > tr.warning > th, +.table > tfoot > tr.warning > th { + background-color: #fcf8e3; +} +.table-hover > tbody > tr > td.warning:hover, +.table-hover > tbody > tr > th.warning:hover, +.table-hover > tbody > tr.warning:hover > td, +.table-hover > tbody > tr:hover > .warning, +.table-hover > tbody > tr.warning:hover > th { + background-color: #faf2cc; +} +.table > thead > tr > td.danger, +.table > tbody > tr > td.danger, +.table > tfoot > tr > td.danger, +.table > thead > tr > th.danger, +.table > tbody > tr > th.danger, +.table > tfoot > tr > th.danger, +.table > thead > tr.danger > td, +.table > tbody > tr.danger > td, +.table > tfoot > tr.danger > td, +.table > thead > tr.danger > th, +.table > tbody > tr.danger > th, +.table > tfoot > tr.danger > th { + background-color: #f2dede; +} +.table-hover > tbody > tr > td.danger:hover, +.table-hover > tbody > tr > th.danger:hover, +.table-hover > tbody > tr.danger:hover > td, +.table-hover > tbody > tr:hover > .danger, +.table-hover > tbody > tr.danger:hover > th { + background-color: #ebcccc; +} +.table-responsive { + min-height: .01%; + overflow-x: auto; +} +@media screen and (max-width: 767px) { + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-y: hidden; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + .table-responsive > .table { + margin-bottom: 0; + } + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + .table-responsive > .table-bordered { + border: 0; + } + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } +} +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} +legend { + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5; +} +label { + display: inline-block; + max-width: 100%; + margin-bottom: 5px; + font-weight: bold; +} +input[type="search"] { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} +input[type="radio"], +input[type="checkbox"] { + margin: 4px 0 0; + margin-top: 1px \9; + line-height: normal; +} +input[type="file"] { + display: block; +} +input[type="range"] { + display: block; + width: 100%; +} +select[multiple], +select[size] { + height: auto; +} +input[type="file"]:focus, +input[type="radio"]:focus, +input[type="checkbox"]:focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +output { + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555; +} +.form-control { + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +} +.form-control:focus { + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); +} +.form-control::-moz-placeholder { + color: #999; + opacity: 1; +} +.form-control:-ms-input-placeholder { + color: #999; +} +.form-control::-webkit-input-placeholder { + color: #999; +} +.form-control[disabled], +.form-control[readonly], +fieldset[disabled] .form-control { + background-color: #eee; + opacity: 1; +} +.form-control[disabled], +fieldset[disabled] .form-control { + cursor: not-allowed; +} +textarea.form-control { + height: auto; +} +input[type="search"] { + -webkit-appearance: none; +} +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"], + input[type="time"], + input[type="datetime-local"], + input[type="month"] { + line-height: 34px; + } + input[type="date"].input-sm, + input[type="time"].input-sm, + input[type="datetime-local"].input-sm, + input[type="month"].input-sm, + .input-group-sm input[type="date"], + .input-group-sm input[type="time"], + .input-group-sm input[type="datetime-local"], + .input-group-sm input[type="month"] { + line-height: 30px; + } + input[type="date"].input-lg, + input[type="time"].input-lg, + input[type="datetime-local"].input-lg, + input[type="month"].input-lg, + .input-group-lg input[type="date"], + .input-group-lg input[type="time"], + .input-group-lg input[type="datetime-local"], + .input-group-lg input[type="month"] { + line-height: 46px; + } +} +.form-group { + margin-bottom: 15px; +} +.radio, +.checkbox { + position: relative; + display: block; + margin-top: 10px; + margin-bottom: 10px; +} +.radio label, +.checkbox label { + min-height: 20px; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + cursor: pointer; +} +.radio input[type="radio"], +.radio-inline input[type="radio"], +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"] { + position: absolute; + margin-top: 4px \9; + margin-left: -20px; +} +.radio + .radio, +.checkbox + .checkbox { + margin-top: -5px; +} +.radio-inline, +.checkbox-inline { + position: relative; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; +} +.radio-inline + .radio-inline, +.checkbox-inline + .checkbox-inline { + margin-top: 0; + margin-left: 10px; +} +input[type="radio"][disabled], +input[type="checkbox"][disabled], +input[type="radio"].disabled, +input[type="checkbox"].disabled, +fieldset[disabled] input[type="radio"], +fieldset[disabled] input[type="checkbox"] { + cursor: not-allowed; +} +.radio-inline.disabled, +.checkbox-inline.disabled, +fieldset[disabled] .radio-inline, +fieldset[disabled] .checkbox-inline { + cursor: not-allowed; +} +.radio.disabled label, +.checkbox.disabled label, +fieldset[disabled] .radio label, +fieldset[disabled] .checkbox label { + cursor: not-allowed; +} +.form-control-static { + min-height: 34px; + padding-top: 7px; + padding-bottom: 7px; + margin-bottom: 0; +} +.form-control-static.input-lg, +.form-control-static.input-sm { + padding-right: 0; + padding-left: 0; +} +.input-sm { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-sm { + height: 30px; + line-height: 30px; +} +textarea.input-sm, +select[multiple].input-sm { + height: auto; +} +.form-group-sm .form-control { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.form-group-sm .form-control { + height: 30px; + line-height: 30px; +} +textarea.form-group-sm .form-control, +select[multiple].form-group-sm .form-control { + height: auto; +} +.form-group-sm .form-control-static { + height: 30px; + min-height: 32px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; +} +.input-lg { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-lg { + height: 46px; + line-height: 46px; +} +textarea.input-lg, +select[multiple].input-lg { + height: auto; +} +.form-group-lg .form-control { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.form-group-lg .form-control { + height: 46px; + line-height: 46px; +} +textarea.form-group-lg .form-control, +select[multiple].form-group-lg .form-control { + height: auto; +} +.form-group-lg .form-control-static { + height: 46px; + min-height: 38px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; +} +.has-feedback { + position: relative; +} +.has-feedback .form-control { + padding-right: 42.5px; +} +.form-control-feedback { + position: absolute; + top: 0; + right: 0; + z-index: 2; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; + pointer-events: none; +} +.input-lg + .form-control-feedback { + width: 46px; + height: 46px; + line-height: 46px; +} +.input-sm + .form-control-feedback { + width: 30px; + height: 30px; + line-height: 30px; +} +.has-success .help-block, +.has-success .control-label, +.has-success .radio, +.has-success .checkbox, +.has-success .radio-inline, +.has-success .checkbox-inline, +.has-success.radio label, +.has-success.checkbox label, +.has-success.radio-inline label, +.has-success.checkbox-inline label { + color: #3c763d; +} +.has-success .form-control { + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-success .form-control:focus { + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; +} +.has-success .input-group-addon { + color: #3c763d; + background-color: #dff0d8; + border-color: #3c763d; +} +.has-success .form-control-feedback { + color: #3c763d; +} +.has-warning .help-block, +.has-warning .control-label, +.has-warning .radio, +.has-warning .checkbox, +.has-warning .radio-inline, +.has-warning .checkbox-inline, +.has-warning.radio label, +.has-warning.checkbox label, +.has-warning.radio-inline label, +.has-warning.checkbox-inline label { + color: #8a6d3b; +} +.has-warning .form-control { + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-warning .form-control:focus { + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; +} +.has-warning .input-group-addon { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #8a6d3b; +} +.has-warning .form-control-feedback { + color: #8a6d3b; +} +.has-error .help-block, +.has-error .control-label, +.has-error .radio, +.has-error .checkbox, +.has-error .radio-inline, +.has-error .checkbox-inline, +.has-error.radio label, +.has-error.checkbox label, +.has-error.radio-inline label, +.has-error.checkbox-inline label { + color: #a94442; +} +.has-error .form-control { + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); +} +.has-error .form-control:focus { + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; +} +.has-error .input-group-addon { + color: #a94442; + background-color: #f2dede; + border-color: #a94442; +} +.has-error .form-control-feedback { + color: #a94442; +} +.has-feedback label ~ .form-control-feedback { + top: 25px; +} +.has-feedback label.sr-only ~ .form-control-feedback { + top: 0; +} +.help-block { + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; +} +@media (min-width: 768px) { + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-static { + display: inline-block; + } + .form-inline .input-group { + display: inline-table; + vertical-align: middle; + } + .form-inline .input-group .input-group-addon, + .form-inline .input-group .input-group-btn, + .form-inline .input-group .form-control { + width: auto; + } + .form-inline .input-group > .form-control { + width: 100%; + } + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .form-inline .radio label, + .form-inline .checkbox label { + padding-left: 0; + } + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .form-inline .has-feedback .form-control-feedback { + top: 0; + } +} +.form-horizontal .radio, +.form-horizontal .checkbox, +.form-horizontal .radio-inline, +.form-horizontal .checkbox-inline { + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; +} +.form-horizontal .radio, +.form-horizontal .checkbox { + min-height: 27px; +} +.form-horizontal .form-group { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .form-horizontal .control-label { + padding-top: 7px; + margin-bottom: 0; + text-align: right; + } +} +.form-horizontal .has-feedback .form-control-feedback { + right: 15px; +} +@media (min-width: 768px) { + .form-horizontal .form-group-lg .control-label { + padding-top: 14.333333px; + } +} +@media (min-width: 768px) { + .form-horizontal .form-group-sm .control-label { + padding-top: 6px; + } +} +.btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.btn:focus, +.btn:active:focus, +.btn.active:focus, +.btn.focus, +.btn:active.focus, +.btn.active.focus { + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; +} +.btn:hover, +.btn:focus, +.btn.focus { + color: #333; + text-decoration: none; +} +.btn:active, +.btn.active { + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + pointer-events: none; + cursor: not-allowed; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + opacity: .65; +} +.btn-default { + color: #333; + background-color: #fff; + border-color: #ccc; +} +.btn-default:hover, +.btn-default:focus, +.btn-default.focus, +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + color: #333; + background-color: #e6e6e6; + border-color: #adadad; +} +.btn-default:active, +.btn-default.active, +.open > .dropdown-toggle.btn-default { + background-image: none; +} +.btn-default.disabled, +.btn-default[disabled], +fieldset[disabled] .btn-default, +.btn-default.disabled:hover, +.btn-default[disabled]:hover, +fieldset[disabled] .btn-default:hover, +.btn-default.disabled:focus, +.btn-default[disabled]:focus, +fieldset[disabled] .btn-default:focus, +.btn-default.disabled.focus, +.btn-default[disabled].focus, +fieldset[disabled] .btn-default.focus, +.btn-default.disabled:active, +.btn-default[disabled]:active, +fieldset[disabled] .btn-default:active, +.btn-default.disabled.active, +.btn-default[disabled].active, +fieldset[disabled] .btn-default.active { + background-color: #fff; + border-color: #ccc; +} +.btn-default .badge { + color: #fff; + background-color: #333; +} +.btn-primary { + color: #fff; + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary:hover, +.btn-primary:focus, +.btn-primary.focus, +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + color: #fff; + background-color: #286090; + border-color: #204d74; +} +.btn-primary:active, +.btn-primary.active, +.open > .dropdown-toggle.btn-primary { + background-image: none; +} +.btn-primary.disabled, +.btn-primary[disabled], +fieldset[disabled] .btn-primary, +.btn-primary.disabled:hover, +.btn-primary[disabled]:hover, +fieldset[disabled] .btn-primary:hover, +.btn-primary.disabled:focus, +.btn-primary[disabled]:focus, +fieldset[disabled] .btn-primary:focus, +.btn-primary.disabled.focus, +.btn-primary[disabled].focus, +fieldset[disabled] .btn-primary.focus, +.btn-primary.disabled:active, +.btn-primary[disabled]:active, +fieldset[disabled] .btn-primary:active, +.btn-primary.disabled.active, +.btn-primary[disabled].active, +fieldset[disabled] .btn-primary.active { + background-color: #337ab7; + border-color: #2e6da4; +} +.btn-primary .badge { + color: #337ab7; + background-color: #fff; +} +.btn-success { + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success:hover, +.btn-success:focus, +.btn-success.focus, +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + color: #fff; + background-color: #449d44; + border-color: #398439; +} +.btn-success:active, +.btn-success.active, +.open > .dropdown-toggle.btn-success { + background-image: none; +} +.btn-success.disabled, +.btn-success[disabled], +fieldset[disabled] .btn-success, +.btn-success.disabled:hover, +.btn-success[disabled]:hover, +fieldset[disabled] .btn-success:hover, +.btn-success.disabled:focus, +.btn-success[disabled]:focus, +fieldset[disabled] .btn-success:focus, +.btn-success.disabled.focus, +.btn-success[disabled].focus, +fieldset[disabled] .btn-success.focus, +.btn-success.disabled:active, +.btn-success[disabled]:active, +fieldset[disabled] .btn-success:active, +.btn-success.disabled.active, +.btn-success[disabled].active, +fieldset[disabled] .btn-success.active { + background-color: #5cb85c; + border-color: #4cae4c; +} +.btn-success .badge { + color: #5cb85c; + background-color: #fff; +} +.btn-info { + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info:hover, +.btn-info:focus, +.btn-info.focus, +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + color: #fff; + background-color: #31b0d5; + border-color: #269abc; +} +.btn-info:active, +.btn-info.active, +.open > .dropdown-toggle.btn-info { + background-image: none; +} +.btn-info.disabled, +.btn-info[disabled], +fieldset[disabled] .btn-info, +.btn-info.disabled:hover, +.btn-info[disabled]:hover, +fieldset[disabled] .btn-info:hover, +.btn-info.disabled:focus, +.btn-info[disabled]:focus, +fieldset[disabled] .btn-info:focus, +.btn-info.disabled.focus, +.btn-info[disabled].focus, +fieldset[disabled] .btn-info.focus, +.btn-info.disabled:active, +.btn-info[disabled]:active, +fieldset[disabled] .btn-info:active, +.btn-info.disabled.active, +.btn-info[disabled].active, +fieldset[disabled] .btn-info.active { + background-color: #5bc0de; + border-color: #46b8da; +} +.btn-info .badge { + color: #5bc0de; + background-color: #fff; +} +.btn-warning { + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning:hover, +.btn-warning:focus, +.btn-warning.focus, +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + color: #fff; + background-color: #ec971f; + border-color: #d58512; +} +.btn-warning:active, +.btn-warning.active, +.open > .dropdown-toggle.btn-warning { + background-image: none; +} +.btn-warning.disabled, +.btn-warning[disabled], +fieldset[disabled] .btn-warning, +.btn-warning.disabled:hover, +.btn-warning[disabled]:hover, +fieldset[disabled] .btn-warning:hover, +.btn-warning.disabled:focus, +.btn-warning[disabled]:focus, +fieldset[disabled] .btn-warning:focus, +.btn-warning.disabled.focus, +.btn-warning[disabled].focus, +fieldset[disabled] .btn-warning.focus, +.btn-warning.disabled:active, +.btn-warning[disabled]:active, +fieldset[disabled] .btn-warning:active, +.btn-warning.disabled.active, +.btn-warning[disabled].active, +fieldset[disabled] .btn-warning.active { + background-color: #f0ad4e; + border-color: #eea236; +} +.btn-warning .badge { + color: #f0ad4e; + background-color: #fff; +} +.btn-danger { + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger:hover, +.btn-danger:focus, +.btn-danger.focus, +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + color: #fff; + background-color: #c9302c; + border-color: #ac2925; +} +.btn-danger:active, +.btn-danger.active, +.open > .dropdown-toggle.btn-danger { + background-image: none; +} +.btn-danger.disabled, +.btn-danger[disabled], +fieldset[disabled] .btn-danger, +.btn-danger.disabled:hover, +.btn-danger[disabled]:hover, +fieldset[disabled] .btn-danger:hover, +.btn-danger.disabled:focus, +.btn-danger[disabled]:focus, +fieldset[disabled] .btn-danger:focus, +.btn-danger.disabled.focus, +.btn-danger[disabled].focus, +fieldset[disabled] .btn-danger.focus, +.btn-danger.disabled:active, +.btn-danger[disabled]:active, +fieldset[disabled] .btn-danger:active, +.btn-danger.disabled.active, +.btn-danger[disabled].active, +fieldset[disabled] .btn-danger.active { + background-color: #d9534f; + border-color: #d43f3a; +} +.btn-danger .badge { + color: #d9534f; + background-color: #fff; +} +.btn-link { + font-weight: normal; + color: #337ab7; + border-radius: 0; +} +.btn-link, +.btn-link:active, +.btn-link.active, +.btn-link[disabled], +fieldset[disabled] .btn-link { + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; +} +.btn-link, +.btn-link:hover, +.btn-link:focus, +.btn-link:active { + border-color: transparent; +} +.btn-link:hover, +.btn-link:focus { + color: #23527c; + text-decoration: underline; + background-color: transparent; +} +.btn-link[disabled]:hover, +fieldset[disabled] .btn-link:hover, +.btn-link[disabled]:focus, +fieldset[disabled] .btn-link:focus { + color: #777; + text-decoration: none; +} +.btn-lg, +.btn-group-lg > .btn { + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +.btn-sm, +.btn-group-sm > .btn { + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-xs, +.btn-group-xs > .btn { + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +.btn-block { + display: block; + width: 100%; +} +.btn-block + .btn-block { + margin-top: 5px; +} +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} +.fade { + opacity: 0; + -webkit-transition: opacity .15s linear; + -o-transition: opacity .15s linear; + transition: opacity .15s linear; +} +.fade.in { + opacity: 1; +} +.collapse { + display: none; +} +.collapse.in { + display: block; +} +tr.collapse.in { + display: table-row; +} +tbody.collapse.in { + display: table-row-group; +} +.collapsing { + position: relative; + height: 0; + overflow: hidden; + -webkit-transition-timing-function: ease; + -o-transition-timing-function: ease; + transition-timing-function: ease; + -webkit-transition-duration: .35s; + -o-transition-duration: .35s; + transition-duration: .35s; + -webkit-transition-property: height, visibility; + -o-transition-property: height, visibility; + transition-property: height, visibility; +} +.caret { + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px dashed; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} +.dropup, +.dropdown { + position: relative; +} +.dropdown-toggle:focus { + outline: 0; +} +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} +.dropdown-menu.pull-right { + right: 0; + left: auto; +} +.dropdown-menu .divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.dropdown-menu > li > a { + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333; + white-space: nowrap; +} +.dropdown-menu > li > a:hover, +.dropdown-menu > li > a:focus { + color: #262626; + text-decoration: none; + background-color: #f5f5f5; +} +.dropdown-menu > .active > a, +.dropdown-menu > .active > a:hover, +.dropdown-menu > .active > a:focus { + color: #fff; + text-decoration: none; + background-color: #337ab7; + outline: 0; +} +.dropdown-menu > .disabled > a, +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + color: #777; +} +.dropdown-menu > .disabled > a:hover, +.dropdown-menu > .disabled > a:focus { + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); +} +.open > .dropdown-menu { + display: block; +} +.open > a { + outline: 0; +} +.dropdown-menu-right { + right: 0; + left: auto; +} +.dropdown-menu-left { + right: auto; + left: 0; +} +.dropdown-header { + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #777; + white-space: nowrap; +} +.dropdown-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; +} +.pull-right > .dropdown-menu { + right: 0; + left: auto; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + content: ""; + border-top: 0; + border-bottom: 4px solid; +} +.dropup .dropdown-menu, +.navbar-fixed-bottom .dropdown .dropdown-menu { + top: auto; + bottom: 100%; + margin-bottom: 2px; +} +@media (min-width: 768px) { + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } + .navbar-right .dropdown-menu-left { + right: auto; + left: 0; + } +} +.btn-group, +.btn-group-vertical { + position: relative; + display: inline-block; + vertical-align: middle; +} +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + float: left; +} +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover, +.btn-group > .btn:focus, +.btn-group-vertical > .btn:focus, +.btn-group > .btn:active, +.btn-group-vertical > .btn:active, +.btn-group > .btn.active, +.btn-group-vertical > .btn.active { + z-index: 2; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group { + margin-left: -1px; +} +.btn-toolbar { + margin-left: -5px; +} +.btn-toolbar .btn-group, +.btn-toolbar .input-group { + float: left; +} +.btn-toolbar > .btn, +.btn-toolbar > .btn-group, +.btn-toolbar > .input-group { + margin-left: 5px; +} +.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { + border-radius: 0; +} +.btn-group > .btn:first-child { + margin-left: 0; +} +.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn:last-child:not(:first-child), +.btn-group > .dropdown-toggle:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group > .btn-group { + float: left; +} +.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group .dropdown-toggle:active, +.btn-group.open .dropdown-toggle { + outline: 0; +} +.btn-group > .btn + .dropdown-toggle { + padding-right: 8px; + padding-left: 8px; +} +.btn-group > .btn-lg + .dropdown-toggle { + padding-right: 12px; + padding-left: 12px; +} +.btn-group.open .dropdown-toggle { + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); +} +.btn-group.open .dropdown-toggle.btn-link { + -webkit-box-shadow: none; + box-shadow: none; +} +.btn .caret { + margin-left: 0; +} +.btn-lg .caret { + border-width: 5px 5px 0; + border-bottom-width: 0; +} +.dropup .btn-lg .caret { + border-width: 0 5px 5px; +} +.btn-group-vertical > .btn, +.btn-group-vertical > .btn-group, +.btn-group-vertical > .btn-group > .btn { + display: block; + float: none; + width: 100%; + max-width: 100%; +} +.btn-group-vertical > .btn-group > .btn { + float: none; +} +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} +.btn-group-vertical > .btn:not(:first-child):not(:last-child) { + border-radius: 0; +} +.btn-group-vertical > .btn:first-child:not(:last-child) { + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn:last-child:not(:first-child) { + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 4px; +} +.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { + border-radius: 0; +} +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, +.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.btn-group-justified { + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; +} +.btn-group-justified > .btn, +.btn-group-justified > .btn-group { + display: table-cell; + float: none; + width: 1%; +} +.btn-group-justified > .btn-group .btn { + width: 100%; +} +.btn-group-justified > .btn-group .dropdown-menu { + left: auto; +} +[data-toggle="buttons"] > .btn input[type="radio"], +[data-toggle="buttons"] > .btn-group > .btn input[type="radio"], +[data-toggle="buttons"] > .btn input[type="checkbox"], +[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} +.input-group { + position: relative; + display: table; + border-collapse: separate; +} +.input-group[class*="col-"] { + float: none; + padding-right: 0; + padding-left: 0; +} +.input-group .form-control { + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; +} +.input-group-lg > .form-control, +.input-group-lg > .input-group-addon, +.input-group-lg > .input-group-btn > .btn { + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.3333333; + border-radius: 6px; +} +select.input-group-lg > .form-control, +select.input-group-lg > .input-group-addon, +select.input-group-lg > .input-group-btn > .btn { + height: 46px; + line-height: 46px; +} +textarea.input-group-lg > .form-control, +textarea.input-group-lg > .input-group-addon, +textarea.input-group-lg > .input-group-btn > .btn, +select[multiple].input-group-lg > .form-control, +select[multiple].input-group-lg > .input-group-addon, +select[multiple].input-group-lg > .input-group-btn > .btn { + height: auto; +} +.input-group-sm > .form-control, +.input-group-sm > .input-group-addon, +.input-group-sm > .input-group-btn > .btn { + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; +} +select.input-group-sm > .form-control, +select.input-group-sm > .input-group-addon, +select.input-group-sm > .input-group-btn > .btn { + height: 30px; + line-height: 30px; +} +textarea.input-group-sm > .form-control, +textarea.input-group-sm > .input-group-addon, +textarea.input-group-sm > .input-group-btn > .btn, +select[multiple].input-group-sm > .form-control, +select[multiple].input-group-sm > .input-group-addon, +select[multiple].input-group-sm > .input-group-btn > .btn { + height: auto; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon:not(:first-child):not(:last-child), +.input-group-btn:not(:first-child):not(:last-child), +.input-group .form-control:not(:first-child):not(:last-child) { + border-radius: 0; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.input-group-addon { + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px; +} +.input-group-addon.input-sm { + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; +} +.input-group-addon.input-lg { + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; +} +.input-group-addon input[type="radio"], +.input-group-addon input[type="checkbox"] { + margin-top: 0; +} +.input-group .form-control:first-child, +.input-group-addon:first-child, +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group > .btn, +.input-group-btn:first-child > .dropdown-toggle, +.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group-btn:last-child > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.input-group-addon:first-child { + border-right: 0; +} +.input-group .form-control:last-child, +.input-group-addon:last-child, +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group > .btn, +.input-group-btn:last-child > .dropdown-toggle, +.input-group-btn:first-child > .btn:not(:first-child), +.input-group-btn:first-child > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +.input-group-addon:last-child { + border-left: 0; +} +.input-group-btn { + position: relative; + font-size: 0; + white-space: nowrap; +} +.input-group-btn > .btn { + position: relative; +} +.input-group-btn > .btn + .btn { + margin-left: -1px; +} +.input-group-btn > .btn:hover, +.input-group-btn > .btn:focus, +.input-group-btn > .btn:active { + z-index: 2; +} +.input-group-btn:first-child > .btn, +.input-group-btn:first-child > .btn-group { + margin-right: -1px; +} +.input-group-btn:last-child > .btn, +.input-group-btn:last-child > .btn-group { + margin-left: -1px; +} +.nav { + padding-left: 0; + margin-bottom: 0; + list-style: none; +} +.nav > li { + position: relative; + display: block; +} +.nav > li > a { + position: relative; + display: block; + padding: 10px 15px; +} +.nav > li > a:hover, +.nav > li > a:focus { + text-decoration: none; + background-color: #eee; +} +.nav > li.disabled > a { + color: #777; +} +.nav > li.disabled > a:hover, +.nav > li.disabled > a:focus { + color: #777; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; +} +.nav .open > a, +.nav .open > a:hover, +.nav .open > a:focus { + background-color: #eee; + border-color: #337ab7; +} +.nav .nav-divider { + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; +} +.nav > li > a > img { + max-width: none; +} +.nav-tabs { + border-bottom: 1px solid #ddd; +} +.nav-tabs > li { + float: left; + margin-bottom: -1px; +} +.nav-tabs > li > a { + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; +} +.nav-tabs > li > a:hover { + border-color: #eee #eee #ddd; +} +.nav-tabs > li.active > a, +.nav-tabs > li.active > a:hover, +.nav-tabs > li.active > a:focus { + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; +} +.nav-tabs.nav-justified { + width: 100%; + border-bottom: 0; +} +.nav-tabs.nav-justified > li { + float: none; +} +.nav-tabs.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-tabs.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs.nav-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs.nav-justified > .active > a, +.nav-tabs.nav-justified > .active > a:hover, +.nav-tabs.nav-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.nav-pills > li { + float: left; +} +.nav-pills > li > a { + border-radius: 4px; +} +.nav-pills > li + li { + margin-left: 2px; +} +.nav-pills > li.active > a, +.nav-pills > li.active > a:hover, +.nav-pills > li.active > a:focus { + color: #fff; + background-color: #337ab7; +} +.nav-stacked > li { + float: none; +} +.nav-stacked > li + li { + margin-top: 2px; + margin-left: 0; +} +.nav-justified { + width: 100%; +} +.nav-justified > li { + float: none; +} +.nav-justified > li > a { + margin-bottom: 5px; + text-align: center; +} +.nav-justified > .dropdown .dropdown-menu { + top: auto; + left: auto; +} +@media (min-width: 768px) { + .nav-justified > li { + display: table-cell; + width: 1%; + } + .nav-justified > li > a { + margin-bottom: 0; + } +} +.nav-tabs-justified { + border-bottom: 0; +} +.nav-tabs-justified > li > a { + margin-right: 0; + border-radius: 4px; +} +.nav-tabs-justified > .active > a, +.nav-tabs-justified > .active > a:hover, +.nav-tabs-justified > .active > a:focus { + border: 1px solid #ddd; +} +@media (min-width: 768px) { + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } +} +.tab-content > .tab-pane { + display: none; +} +.tab-content > .active { + display: block; +} +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar { + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; +} +@media (min-width: 768px) { + .navbar { + border-radius: 4px; + } +} +@media (min-width: 768px) { + .navbar-header { + float: left; + } +} +.navbar-collapse { + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + -webkit-overflow-scrolling: touch; + border-top: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); +} +.navbar-collapse.in { + overflow-y: auto; +} +@media (min-width: 768px) { + .navbar-collapse { + width: auto; + border-top: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + .navbar-collapse.in { + overflow-y: visible; + } + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-right: 0; + padding-left: 0; + } +} +.navbar-fixed-top .navbar-collapse, +.navbar-fixed-bottom .navbar-collapse { + max-height: 340px; +} +@media (max-device-width: 480px) and (orientation: landscape) { + .navbar-fixed-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + max-height: 200px; + } +} +.container > .navbar-header, +.container-fluid > .navbar-header, +.container > .navbar-collapse, +.container-fluid > .navbar-collapse { + margin-right: -15px; + margin-left: -15px; +} +@media (min-width: 768px) { + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } +} +.navbar-static-top { + z-index: 1000; + border-width: 0 0 1px; +} +@media (min-width: 768px) { + .navbar-static-top { + border-radius: 0; + } +} +.navbar-fixed-top, +.navbar-fixed-bottom { + position: fixed; + right: 0; + left: 0; + z-index: 1030; +} +@media (min-width: 768px) { + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } +} +.navbar-fixed-top { + top: 0; + border-width: 0 0 1px; +} +.navbar-fixed-bottom { + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; +} +.navbar-brand { + float: left; + height: 50px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; +} +.navbar-brand:hover, +.navbar-brand:focus { + text-decoration: none; +} +.navbar-brand > img { + display: block; +} +@media (min-width: 768px) { + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } +} +.navbar-toggle { + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} +.navbar-toggle:focus { + outline: 0; +} +.navbar-toggle .icon-bar { + display: block; + width: 22px; + height: 2px; + border-radius: 1px; +} +.navbar-toggle .icon-bar + .icon-bar { + margin-top: 4px; +} +@media (min-width: 768px) { + .navbar-toggle { + display: none; + } +} +.navbar-nav { + margin: 7.5px -15px; +} +.navbar-nav > li > a { + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; +} +@media (max-width: 767px) { + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } +} +@media (min-width: 768px) { + .navbar-nav { + float: left; + margin: 0; + } + .navbar-nav > li { + float: left; + } + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } +} +.navbar-form { + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); +} +@media (min-width: 768px) { + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .navbar-form .form-control-static { + display: inline-block; + } + .navbar-form .input-group { + display: inline-table; + vertical-align: middle; + } + .navbar-form .input-group .input-group-addon, + .navbar-form .input-group .input-group-btn, + .navbar-form .input-group .form-control { + width: auto; + } + .navbar-form .input-group > .form-control { + width: 100%; + } + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + .navbar-form .radio label, + .navbar-form .checkbox label { + padding-left: 0; + } + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + position: relative; + margin-left: 0; + } + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } +} +@media (max-width: 767px) { + .navbar-form .form-group { + margin-bottom: 5px; + } + .navbar-form .form-group:last-child { + margin-bottom: 0; + } +} +@media (min-width: 768px) { + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } +} +.navbar-nav > li > .dropdown-menu { + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; +} +.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.navbar-btn { + margin-top: 8px; + margin-bottom: 8px; +} +.navbar-btn.btn-sm { + margin-top: 10px; + margin-bottom: 10px; +} +.navbar-btn.btn-xs { + margin-top: 14px; + margin-bottom: 14px; +} +.navbar-text { + margin-top: 15px; + margin-bottom: 15px; +} +@media (min-width: 768px) { + .navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px; + } +} +@media (min-width: 768px) { + .navbar-left { + float: left !important; + } + .navbar-right { + float: right !important; + margin-right: -15px; + } + .navbar-right ~ .navbar-right { + margin-right: 0; + } +} +.navbar-default { + background-color: #f8f8f8; + border-color: #e7e7e7; +} +.navbar-default .navbar-brand { + color: #777; +} +.navbar-default .navbar-brand:hover, +.navbar-default .navbar-brand:focus { + color: #5e5e5e; + background-color: transparent; +} +.navbar-default .navbar-text { + color: #777; +} +.navbar-default .navbar-nav > li > a { + color: #777; +} +.navbar-default .navbar-nav > li > a:hover, +.navbar-default .navbar-nav > li > a:focus { + color: #333; + background-color: transparent; +} +.navbar-default .navbar-nav > .active > a, +.navbar-default .navbar-nav > .active > a:hover, +.navbar-default .navbar-nav > .active > a:focus { + color: #555; + background-color: #e7e7e7; +} +.navbar-default .navbar-nav > .disabled > a, +.navbar-default .navbar-nav > .disabled > a:hover, +.navbar-default .navbar-nav > .disabled > a:focus { + color: #ccc; + background-color: transparent; +} +.navbar-default .navbar-toggle { + border-color: #ddd; +} +.navbar-default .navbar-toggle:hover, +.navbar-default .navbar-toggle:focus { + background-color: #ddd; +} +.navbar-default .navbar-toggle .icon-bar { + background-color: #888; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #e7e7e7; +} +.navbar-default .navbar-nav > .open > a, +.navbar-default .navbar-nav > .open > a:hover, +.navbar-default .navbar-nav > .open > a:focus { + color: #555; + background-color: #e7e7e7; +} +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + .navbar-default .navbar-nav .open .dropdown-menu > .active > a, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #555; + background-color: #e7e7e7; + } + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #ccc; + background-color: transparent; + } +} +.navbar-default .navbar-link { + color: #777; +} +.navbar-default .navbar-link:hover { + color: #333; +} +.navbar-default .btn-link { + color: #777; +} +.navbar-default .btn-link:hover, +.navbar-default .btn-link:focus { + color: #333; +} +.navbar-default .btn-link[disabled]:hover, +fieldset[disabled] .navbar-default .btn-link:hover, +.navbar-default .btn-link[disabled]:focus, +fieldset[disabled] .navbar-default .btn-link:focus { + color: #ccc; +} +.navbar-inverse { + background-color: #222; + border-color: #080808; +} +.navbar-inverse .navbar-brand { + color: #9d9d9d; +} +.navbar-inverse .navbar-brand:hover, +.navbar-inverse .navbar-brand:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-text { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a { + color: #9d9d9d; +} +.navbar-inverse .navbar-nav > li > a:hover, +.navbar-inverse .navbar-nav > li > a:focus { + color: #fff; + background-color: transparent; +} +.navbar-inverse .navbar-nav > .active > a, +.navbar-inverse .navbar-nav > .active > a:hover, +.navbar-inverse .navbar-nav > .active > a:focus { + color: #fff; + background-color: #080808; +} +.navbar-inverse .navbar-nav > .disabled > a, +.navbar-inverse .navbar-nav > .disabled > a:hover, +.navbar-inverse .navbar-nav > .disabled > a:focus { + color: #444; + background-color: transparent; +} +.navbar-inverse .navbar-toggle { + border-color: #333; +} +.navbar-inverse .navbar-toggle:hover, +.navbar-inverse .navbar-toggle:focus { + background-color: #333; +} +.navbar-inverse .navbar-toggle .icon-bar { + background-color: #fff; +} +.navbar-inverse .navbar-collapse, +.navbar-inverse .navbar-form { + border-color: #101010; +} +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { + color: #fff; + background-color: #080808; +} +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #9d9d9d; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus { + color: #fff; + background-color: #080808; + } + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus { + color: #444; + background-color: transparent; + } +} +.navbar-inverse .navbar-link { + color: #9d9d9d; +} +.navbar-inverse .navbar-link:hover { + color: #fff; +} +.navbar-inverse .btn-link { + color: #9d9d9d; +} +.navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link:focus { + color: #fff; +} +.navbar-inverse .btn-link[disabled]:hover, +fieldset[disabled] .navbar-inverse .btn-link:hover, +.navbar-inverse .btn-link[disabled]:focus, +fieldset[disabled] .navbar-inverse .btn-link:focus { + color: #444; +} +.breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; +} +.breadcrumb > li { + display: inline-block; +} +.breadcrumb > li + li:before { + padding: 0 5px; + color: #ccc; + content: "/\00a0"; +} +.breadcrumb > .active { + color: #777; +} +.pagination { + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; +} +.pagination > li { + display: inline; +} +.pagination > li > a, +.pagination > li > span { + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.42857143; + color: #337ab7; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; +} +.pagination > li:first-child > a, +.pagination > li:first-child > span { + margin-left: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; +} +.pagination > li:last-child > a, +.pagination > li:last-child > span { + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; +} +.pagination > li > a:hover, +.pagination > li > span:hover, +.pagination > li > a:focus, +.pagination > li > span:focus { + color: #23527c; + background-color: #eee; + border-color: #ddd; +} +.pagination > .active > a, +.pagination > .active > span, +.pagination > .active > a:hover, +.pagination > .active > span:hover, +.pagination > .active > a:focus, +.pagination > .active > span:focus { + z-index: 2; + color: #fff; + cursor: default; + background-color: #337ab7; + border-color: #337ab7; +} +.pagination > .disabled > span, +.pagination > .disabled > span:hover, +.pagination > .disabled > span:focus, +.pagination > .disabled > a, +.pagination > .disabled > a:hover, +.pagination > .disabled > a:focus { + color: #777; + cursor: not-allowed; + background-color: #fff; + border-color: #ddd; +} +.pagination-lg > li > a, +.pagination-lg > li > span { + padding: 10px 16px; + font-size: 18px; +} +.pagination-lg > li:first-child > a, +.pagination-lg > li:first-child > span { + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; +} +.pagination-lg > li:last-child > a, +.pagination-lg > li:last-child > span { + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; +} +.pagination-sm > li > a, +.pagination-sm > li > span { + padding: 5px 10px; + font-size: 12px; +} +.pagination-sm > li:first-child > a, +.pagination-sm > li:first-child > span { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} +.pagination-sm > li:last-child > a, +.pagination-sm > li:last-child > span { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} +.pager { + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; +} +.pager li { + display: inline; +} +.pager li > a, +.pager li > span { + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; +} +.pager li > a:hover, +.pager li > a:focus { + text-decoration: none; + background-color: #eee; +} +.pager .next > a, +.pager .next > span { + float: right; +} +.pager .previous > a, +.pager .previous > span { + float: left; +} +.pager .disabled > a, +.pager .disabled > a:hover, +.pager .disabled > a:focus, +.pager .disabled > span { + color: #777; + cursor: not-allowed; + background-color: #fff; +} +.label { + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; +} +a.label:hover, +a.label:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.label:empty { + display: none; +} +.btn .label { + position: relative; + top: -1px; +} +.label-default { + background-color: #777; +} +.label-default[href]:hover, +.label-default[href]:focus { + background-color: #5e5e5e; +} +.label-primary { + background-color: #337ab7; +} +.label-primary[href]:hover, +.label-primary[href]:focus { + background-color: #286090; +} +.label-success { + background-color: #5cb85c; +} +.label-success[href]:hover, +.label-success[href]:focus { + background-color: #449d44; +} +.label-info { + background-color: #5bc0de; +} +.label-info[href]:hover, +.label-info[href]:focus { + background-color: #31b0d5; +} +.label-warning { + background-color: #f0ad4e; +} +.label-warning[href]:hover, +.label-warning[href]:focus { + background-color: #ec971f; +} +.label-danger { + background-color: #d9534f; +} +.label-danger[href]:hover, +.label-danger[href]:focus { + background-color: #c9302c; +} +.badge { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + background-color: #777; + border-radius: 10px; +} +.badge:empty { + display: none; +} +.btn .badge { + position: relative; + top: -1px; +} +.btn-xs .badge, +.btn-group-xs > .btn .badge { + top: 0; + padding: 1px 5px; +} +a.badge:hover, +a.badge:focus { + color: #fff; + text-decoration: none; + cursor: pointer; +} +.list-group-item.active > .badge, +.nav-pills > .active > a > .badge { + color: #337ab7; + background-color: #fff; +} +.list-group-item > .badge { + float: right; +} +.list-group-item > .badge + .badge { + margin-right: 5px; +} +.nav-pills > li > a > .badge { + margin-left: 3px; +} +.jumbotron { + padding: 30px 15px; + margin-bottom: 30px; + color: inherit; + background-color: #eee; +} +.jumbotron h1, +.jumbotron .h1 { + color: inherit; +} +.jumbotron p { + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; +} +.jumbotron > hr { + border-top-color: #d5d5d5; +} +.container .jumbotron, +.container-fluid .jumbotron { + border-radius: 6px; +} +.jumbotron .container { + max-width: 100%; +} +@media screen and (min-width: 768px) { + .jumbotron { + padding: 48px 0; + } + .container .jumbotron, + .container-fluid .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } +} +.thumbnail { + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: border .2s ease-in-out; + -o-transition: border .2s ease-in-out; + transition: border .2s ease-in-out; +} +.thumbnail > img, +.thumbnail a > img { + margin-right: auto; + margin-left: auto; +} +a.thumbnail:hover, +a.thumbnail:focus, +a.thumbnail.active { + border-color: #337ab7; +} +.thumbnail .caption { + padding: 9px; + color: #333; +} +.alert { + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; +} +.alert h4 { + margin-top: 0; + color: inherit; +} +.alert .alert-link { + font-weight: bold; +} +.alert > p, +.alert > ul { + margin-bottom: 0; +} +.alert > p + p { + margin-top: 5px; +} +.alert-dismissable, +.alert-dismissible { + padding-right: 35px; +} +.alert-dismissable .close, +.alert-dismissible .close { + position: relative; + top: -2px; + right: -21px; + color: inherit; +} +.alert-success { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.alert-success hr { + border-top-color: #c9e2b3; +} +.alert-success .alert-link { + color: #2b542c; +} +.alert-info { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.alert-info hr { + border-top-color: #a6e1ec; +} +.alert-info .alert-link { + color: #245269; +} +.alert-warning { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.alert-warning hr { + border-top-color: #f7e1b5; +} +.alert-warning .alert-link { + color: #66512c; +} +.alert-danger { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.alert-danger hr { + border-top-color: #e4b9c0; +} +.alert-danger .alert-link { + color: #843534; +} +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@-o-keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +@keyframes progress-bar-stripes { + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } +} +.progress { + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); +} +.progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #337ab7; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + -webkit-transition: width .6s ease; + -o-transition: width .6s ease; + transition: width .6s ease; +} +.progress-striped .progress-bar, +.progress-bar-striped { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + -webkit-background-size: 40px 40px; + background-size: 40px 40px; +} +.progress.active .progress-bar, +.progress-bar.active { + -webkit-animation: progress-bar-stripes 2s linear infinite; + -o-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; +} +.progress-bar-success { + background-color: #5cb85c; +} +.progress-striped .progress-bar-success { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-info { + background-color: #5bc0de; +} +.progress-striped .progress-bar-info { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-warning { + background-color: #f0ad4e; +} +.progress-striped .progress-bar-warning { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.progress-bar-danger { + background-color: #d9534f; +} +.progress-striped .progress-bar-danger { + background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); + background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); +} +.media { + margin-top: 15px; +} +.media:first-child { + margin-top: 0; +} +.media, +.media-body { + overflow: hidden; + zoom: 1; +} +.media-body { + width: 10000px; +} +.media-object { + display: block; +} +.media-right, +.media > .pull-right { + padding-left: 10px; +} +.media-left, +.media > .pull-left { + padding-right: 10px; +} +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} +.media-middle { + vertical-align: middle; +} +.media-bottom { + vertical-align: bottom; +} +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +.media-list { + padding-left: 0; + list-style: none; +} +.list-group { + padding-left: 0; + margin-bottom: 20px; +} +.list-group-item { + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; +} +.list-group-item:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} +a.list-group-item { + color: #555; +} +a.list-group-item .list-group-item-heading { + color: #333; +} +a.list-group-item:hover, +a.list-group-item:focus { + color: #555; + text-decoration: none; + background-color: #f5f5f5; +} +.list-group-item.disabled, +.list-group-item.disabled:hover, +.list-group-item.disabled:focus { + color: #777; + cursor: not-allowed; + background-color: #eee; +} +.list-group-item.disabled .list-group-item-heading, +.list-group-item.disabled:hover .list-group-item-heading, +.list-group-item.disabled:focus .list-group-item-heading { + color: inherit; +} +.list-group-item.disabled .list-group-item-text, +.list-group-item.disabled:hover .list-group-item-text, +.list-group-item.disabled:focus .list-group-item-text { + color: #777; +} +.list-group-item.active, +.list-group-item.active:hover, +.list-group-item.active:focus { + z-index: 2; + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.list-group-item.active .list-group-item-heading, +.list-group-item.active:hover .list-group-item-heading, +.list-group-item.active:focus .list-group-item-heading, +.list-group-item.active .list-group-item-heading > small, +.list-group-item.active:hover .list-group-item-heading > small, +.list-group-item.active:focus .list-group-item-heading > small, +.list-group-item.active .list-group-item-heading > .small, +.list-group-item.active:hover .list-group-item-heading > .small, +.list-group-item.active:focus .list-group-item-heading > .small { + color: inherit; +} +.list-group-item.active .list-group-item-text, +.list-group-item.active:hover .list-group-item-text, +.list-group-item.active:focus .list-group-item-text { + color: #c7ddef; +} +.list-group-item-success { + color: #3c763d; + background-color: #dff0d8; +} +a.list-group-item-success { + color: #3c763d; +} +a.list-group-item-success .list-group-item-heading { + color: inherit; +} +a.list-group-item-success:hover, +a.list-group-item-success:focus { + color: #3c763d; + background-color: #d0e9c6; +} +a.list-group-item-success.active, +a.list-group-item-success.active:hover, +a.list-group-item-success.active:focus { + color: #fff; + background-color: #3c763d; + border-color: #3c763d; +} +.list-group-item-info { + color: #31708f; + background-color: #d9edf7; +} +a.list-group-item-info { + color: #31708f; +} +a.list-group-item-info .list-group-item-heading { + color: inherit; +} +a.list-group-item-info:hover, +a.list-group-item-info:focus { + color: #31708f; + background-color: #c4e3f3; +} +a.list-group-item-info.active, +a.list-group-item-info.active:hover, +a.list-group-item-info.active:focus { + color: #fff; + background-color: #31708f; + border-color: #31708f; +} +.list-group-item-warning { + color: #8a6d3b; + background-color: #fcf8e3; +} +a.list-group-item-warning { + color: #8a6d3b; +} +a.list-group-item-warning .list-group-item-heading { + color: inherit; +} +a.list-group-item-warning:hover, +a.list-group-item-warning:focus { + color: #8a6d3b; + background-color: #faf2cc; +} +a.list-group-item-warning.active, +a.list-group-item-warning.active:hover, +a.list-group-item-warning.active:focus { + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; +} +.list-group-item-danger { + color: #a94442; + background-color: #f2dede; +} +a.list-group-item-danger { + color: #a94442; +} +a.list-group-item-danger .list-group-item-heading { + color: inherit; +} +a.list-group-item-danger:hover, +a.list-group-item-danger:focus { + color: #a94442; + background-color: #ebcccc; +} +a.list-group-item-danger.active, +a.list-group-item-danger.active:hover, +a.list-group-item-danger.active:focus { + color: #fff; + background-color: #a94442; + border-color: #a94442; +} +.list-group-item-heading { + margin-top: 0; + margin-bottom: 5px; +} +.list-group-item-text { + margin-bottom: 0; + line-height: 1.3; +} +.panel { + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); +} +.panel-body { + padding: 15px; +} +.panel-heading { + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel-heading > .dropdown .dropdown-toggle { + color: inherit; +} +.panel-title { + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; +} +.panel-title > a, +.panel-title > small, +.panel-title > .small, +.panel-title > small > a, +.panel-title > .small > a { + color: inherit; +} +.panel-footer { + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .list-group, +.panel > .panel-collapse > .list-group { + margin-bottom: 0; +} +.panel > .list-group .list-group-item, +.panel > .panel-collapse > .list-group .list-group-item { + border-width: 1px 0; + border-radius: 0; +} +.panel > .list-group:first-child .list-group-item:first-child, +.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child { + border-top: 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .list-group:last-child .list-group-item:last-child, +.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child { + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel-heading + .list-group .list-group-item:first-child { + border-top-width: 0; +} +.list-group + .panel-footer { + border-top-width: 0; +} +.panel > .table, +.panel > .table-responsive > .table, +.panel > .panel-collapse > .table { + margin-bottom: 0; +} +.panel > .table caption, +.panel > .table-responsive > .table caption, +.panel > .panel-collapse > .table caption { + padding-right: 15px; + padding-left: 15px; +} +.panel > .table:first-child, +.panel > .table-responsive:first-child > .table:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child { + border-top-left-radius: 3px; + border-top-right-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { + border-top-left-radius: 3px; +} +.panel > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child, +.panel > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, +.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, +.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { + border-top-right-radius: 3px; +} +.panel > .table:last-child, +.panel > .table-responsive:last-child > .table:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child { + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { + border-bottom-left-radius: 3px; +} +.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child, +.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, +.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, +.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { + border-bottom-right-radius: 3px; +} +.panel > .panel-body + .table, +.panel > .panel-body + .table-responsive, +.panel > .table + .panel-body, +.panel > .table-responsive + .panel-body { + border-top: 1px solid #ddd; +} +.panel > .table > tbody:first-child > tr:first-child th, +.panel > .table > tbody:first-child > tr:first-child td { + border-top: 0; +} +.panel > .table-bordered, +.panel > .table-responsive > .table-bordered { + border: 0; +} +.panel > .table-bordered > thead > tr > th:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:first-child, +.panel > .table-bordered > tbody > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child, +.panel > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child, +.panel > .table-bordered > thead > tr > td:first-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:first-child, +.panel > .table-bordered > tbody > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, +.panel > .table-bordered > tfoot > tr > td:first-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; +} +.panel > .table-bordered > thead > tr > th:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > th:last-child, +.panel > .table-bordered > tbody > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child, +.panel > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child, +.panel > .table-bordered > thead > tr > td:last-child, +.panel > .table-responsive > .table-bordered > thead > tr > td:last-child, +.panel > .table-bordered > tbody > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, +.panel > .table-bordered > tfoot > tr > td:last-child, +.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; +} +.panel > .table-bordered > thead > tr:first-child > td, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > td, +.panel > .table-bordered > tbody > tr:first-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td, +.panel > .table-bordered > thead > tr:first-child > th, +.panel > .table-responsive > .table-bordered > thead > tr:first-child > th, +.panel > .table-bordered > tbody > tr:first-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { + border-bottom: 0; +} +.panel > .table-bordered > tbody > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, +.panel > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td, +.panel > .table-bordered > tbody > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, +.panel > .table-bordered > tfoot > tr:last-child > th, +.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { + border-bottom: 0; +} +.panel > .table-responsive { + margin-bottom: 0; + border: 0; +} +.panel-group { + margin-bottom: 20px; +} +.panel-group .panel { + margin-bottom: 0; + border-radius: 4px; +} +.panel-group .panel + .panel { + margin-top: 5px; +} +.panel-group .panel-heading { + border-bottom: 0; +} +.panel-group .panel-heading + .panel-collapse > .panel-body, +.panel-group .panel-heading + .panel-collapse > .list-group { + border-top: 1px solid #ddd; +} +.panel-group .panel-footer { + border-top: 0; +} +.panel-group .panel-footer + .panel-collapse .panel-body { + border-bottom: 1px solid #ddd; +} +.panel-default { + border-color: #ddd; +} +.panel-default > .panel-heading { + color: #333; + background-color: #f5f5f5; + border-color: #ddd; +} +.panel-default > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ddd; +} +.panel-default > .panel-heading .badge { + color: #f5f5f5; + background-color: #333; +} +.panel-default > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ddd; +} +.panel-primary { + border-color: #337ab7; +} +.panel-primary > .panel-heading { + color: #fff; + background-color: #337ab7; + border-color: #337ab7; +} +.panel-primary > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #337ab7; +} +.panel-primary > .panel-heading .badge { + color: #337ab7; + background-color: #fff; +} +.panel-primary > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #337ab7; +} +.panel-success { + border-color: #d6e9c6; +} +.panel-success > .panel-heading { + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; +} +.panel-success > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #d6e9c6; +} +.panel-success > .panel-heading .badge { + color: #dff0d8; + background-color: #3c763d; +} +.panel-success > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #d6e9c6; +} +.panel-info { + border-color: #bce8f1; +} +.panel-info > .panel-heading { + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; +} +.panel-info > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #bce8f1; +} +.panel-info > .panel-heading .badge { + color: #d9edf7; + background-color: #31708f; +} +.panel-info > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #bce8f1; +} +.panel-warning { + border-color: #faebcc; +} +.panel-warning > .panel-heading { + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; +} +.panel-warning > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #faebcc; +} +.panel-warning > .panel-heading .badge { + color: #fcf8e3; + background-color: #8a6d3b; +} +.panel-warning > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #faebcc; +} +.panel-danger { + border-color: #ebccd1; +} +.panel-danger > .panel-heading { + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; +} +.panel-danger > .panel-heading + .panel-collapse > .panel-body { + border-top-color: #ebccd1; +} +.panel-danger > .panel-heading .badge { + color: #f2dede; + background-color: #a94442; +} +.panel-danger > .panel-footer + .panel-collapse > .panel-body { + border-bottom-color: #ebccd1; +} +.embed-responsive { + position: relative; + display: block; + height: 0; + padding: 0; + overflow: hidden; +} +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; +} +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} +.embed-responsive-4by3 { + padding-bottom: 75%; +} +.well { + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); +} +.well blockquote { + border-color: #ddd; + border-color: rgba(0, 0, 0, .15); +} +.well-lg { + padding: 24px; + border-radius: 6px; +} +.well-sm { + padding: 9px; + border-radius: 3px; +} +.close { + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: .2; +} +.close:hover, +.close:focus { + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: .5; +} +button.close { + -webkit-appearance: none; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; +} +.modal-open { + overflow: hidden; +} +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: hidden; + -webkit-overflow-scrolling: touch; + outline: 0; +} +.modal.fade .modal-dialog { + -webkit-transition: -webkit-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + -o-transform: translate(0, -25%); + transform: translate(0, -25%); +} +.modal.in .modal-dialog { + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + -o-transform: translate(0, 0); + transform: translate(0, 0); +} +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} +.modal-dialog { + position: relative; + width: auto; + margin: 10px; +} +.modal-content { + position: relative; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + outline: 0; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + box-shadow: 0 3px 9px rgba(0, 0, 0, .5); +} +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} +.modal-backdrop.fade { + filter: alpha(opacity=0); + opacity: 0; +} +.modal-backdrop.in { + filter: alpha(opacity=50); + opacity: .5; +} +.modal-header { + min-height: 16.42857143px; + padding: 15px; + border-bottom: 1px solid #e5e5e5; +} +.modal-header .close { + margin-top: -2px; +} +.modal-title { + margin: 0; + line-height: 1.42857143; +} +.modal-body { + position: relative; + padding: 15px; +} +.modal-footer { + padding: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; +} +.modal-footer .btn + .btn { + margin-bottom: 0; + margin-left: 5px; +} +.modal-footer .btn-group .btn + .btn { + margin-left: -1px; +} +.modal-footer .btn-block + .btn-block { + margin-left: 0; +} +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} +@media (min-width: 768px) { + .modal-dialog { + width: 600px; + margin: 30px auto; + } + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + } + .modal-sm { + width: 300px; + } +} +@media (min-width: 992px) { + .modal-lg { + width: 900px; + } +} +.tooltip { + position: absolute; + z-index: 1070; + display: block; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 12px; + font-weight: normal; + line-height: 1.4; + filter: alpha(opacity=0); + opacity: 0; +} +.tooltip.in { + filter: alpha(opacity=90); + opacity: .9; +} +.tooltip.top { + padding: 5px 0; + margin-top: -3px; +} +.tooltip.right { + padding: 0 5px; + margin-left: 3px; +} +.tooltip.bottom { + padding: 5px 0; + margin-top: 3px; +} +.tooltip.left { + padding: 0 5px; + margin-left: -3px; +} +.tooltip-inner { + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + text-decoration: none; + background-color: #000; + border-radius: 4px; +} +.tooltip-arrow { + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.tooltip.top .tooltip-arrow { + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-left .tooltip-arrow { + right: 5px; + bottom: 0; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.top-right .tooltip-arrow { + bottom: 0; + left: 5px; + margin-bottom: -5px; + border-width: 5px 5px 0; + border-top-color: #000; +} +.tooltip.right .tooltip-arrow { + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; +} +.tooltip.left .tooltip-arrow { + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; +} +.tooltip.bottom .tooltip-arrow { + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-left .tooltip-arrow { + top: 0; + right: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.tooltip.bottom-right .tooltip-arrow { + top: 0; + left: 5px; + margin-top: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; +} +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: none; + max-width: 276px; + padding: 1px; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: left; + white-space: normal; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + box-shadow: 0 5px 10px rgba(0, 0, 0, .2); +} +.popover.top { + margin-top: -10px; +} +.popover.right { + margin-left: 10px; +} +.popover.bottom { + margin-top: 10px; +} +.popover.left { + margin-left: -10px; +} +.popover-title { + padding: 8px 14px; + margin: 0; + font-size: 14px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; +} +.popover-content { + padding: 9px 14px; +} +.popover > .arrow, +.popover > .arrow:after { + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; +} +.popover > .arrow { + border-width: 11px; +} +.popover > .arrow:after { + content: ""; + border-width: 10px; +} +.popover.top > .arrow { + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, .25); + border-bottom-width: 0; +} +.popover.top > .arrow:after { + bottom: 1px; + margin-left: -10px; + content: " "; + border-top-color: #fff; + border-bottom-width: 0; +} +.popover.right > .arrow { + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, .25); + border-left-width: 0; +} +.popover.right > .arrow:after { + bottom: -10px; + left: 1px; + content: " "; + border-right-color: #fff; + border-left-width: 0; +} +.popover.bottom > .arrow { + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, .25); +} +.popover.bottom > .arrow:after { + top: 1px; + margin-left: -10px; + content: " "; + border-top-width: 0; + border-bottom-color: #fff; +} +.popover.left > .arrow { + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, .25); +} +.popover.left > .arrow:after { + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff; +} +.carousel { + position: relative; +} +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} +.carousel-inner > .item { + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + -o-transition: .6s ease-in-out left; + transition: .6s ease-in-out left; +} +.carousel-inner > .item > img, +.carousel-inner > .item > a > img { + line-height: 1; +} +@media all and (transform-3d), (-webkit-transform-3d) { + .carousel-inner > .item { + -webkit-transition: -webkit-transform .6s ease-in-out; + -o-transition: -o-transform .6s ease-in-out; + transition: transform .6s ease-in-out; + + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000; + perspective: 1000; + } + .carousel-inner > .item.next, + .carousel-inner > .item.active.right { + left: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + .carousel-inner > .item.prev, + .carousel-inner > .item.active.left { + left: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + .carousel-inner > .item.next.left, + .carousel-inner > .item.prev.right, + .carousel-inner > .item.active { + left: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} +.carousel-inner > .active, +.carousel-inner > .next, +.carousel-inner > .prev { + display: block; +} +.carousel-inner > .active { + left: 0; +} +.carousel-inner > .next, +.carousel-inner > .prev { + position: absolute; + top: 0; + width: 100%; +} +.carousel-inner > .next { + left: 100%; +} +.carousel-inner > .prev { + left: -100%; +} +.carousel-inner > .next.left, +.carousel-inner > .prev.right { + left: 0; +} +.carousel-inner > .active.left { + left: -100%; +} +.carousel-inner > .active.right { + left: 100%; +} +.carousel-control { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + filter: alpha(opacity=50); + opacity: .5; +} +.carousel-control.left { + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .5)), to(rgba(0, 0, 0, .0001))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control.right { + right: 0; + left: auto; + background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -o-linear-gradient(left, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, .0001)), to(rgba(0, 0, 0, .5))); + background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x; +} +.carousel-control:hover, +.carousel-control:focus { + color: #fff; + text-decoration: none; + filter: alpha(opacity=90); + outline: 0; + opacity: .9; +} +.carousel-control .icon-prev, +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-left, +.carousel-control .glyphicon-chevron-right { + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; +} +.carousel-control .icon-prev, +.carousel-control .glyphicon-chevron-left { + left: 50%; + margin-left: -10px; +} +.carousel-control .icon-next, +.carousel-control .glyphicon-chevron-right { + right: 50%; + margin-right: -10px; +} +.carousel-control .icon-prev, +.carousel-control .icon-next { + width: 20px; + height: 20px; + margin-top: -10px; + font-family: serif; + line-height: 1; +} +.carousel-control .icon-prev:before { + content: '\2039'; +} +.carousel-control .icon-next:before { + content: '\203a'; +} +.carousel-indicators { + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; +} +.carousel-indicators li { + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + border: 1px solid #fff; + border-radius: 10px; +} +.carousel-indicators .active { + width: 12px; + height: 12px; + margin: 0; + background-color: #fff; +} +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); +} +.carousel-caption .btn { + text-shadow: none; +} +@media screen and (min-width: 768px) { + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + font-size: 30px; + } + .carousel-control .glyphicon-chevron-left, + .carousel-control .icon-prev { + margin-left: -15px; + } + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-next { + margin-right: -15px; + } + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + .carousel-indicators { + bottom: 20px; + } +} +.clearfix:before, +.clearfix:after, +.dl-horizontal dd:before, +.dl-horizontal dd:after, +.container:before, +.container:after, +.container-fluid:before, +.container-fluid:after, +.row:before, +.row:after, +.form-horizontal .form-group:before, +.form-horizontal .form-group:after, +.btn-toolbar:before, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:before, +.btn-group-vertical > .btn-group:after, +.nav:before, +.nav:after, +.navbar:before, +.navbar:after, +.navbar-header:before, +.navbar-header:after, +.navbar-collapse:before, +.navbar-collapse:after, +.pager:before, +.pager:after, +.panel-body:before, +.panel-body:after, +.modal-footer:before, +.modal-footer:after { + display: table; + content: " "; +} +.clearfix:after, +.dl-horizontal dd:after, +.container:after, +.container-fluid:after, +.row:after, +.form-horizontal .form-group:after, +.btn-toolbar:after, +.btn-group-vertical > .btn-group:after, +.nav:after, +.navbar:after, +.navbar-header:after, +.navbar-collapse:after, +.pager:after, +.panel-body:after, +.modal-footer:after { + clear: both; +} +.center-block { + display: block; + margin-right: auto; + margin-left: auto; +} +.pull-right { + float: right !important; +} +.pull-left { + float: left !important; +} +.hide { + display: none !important; +} +.show { + display: block !important; +} +.invisible { + visibility: hidden; +} +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} +.hidden { + display: none !important; +} +.affix { + position: fixed; +} +@-ms-viewport { + width: device-width; +} +.visible-xs, +.visible-sm, +.visible-md, +.visible-lg { + display: none !important; +} +.visible-xs-block, +.visible-xs-inline, +.visible-xs-inline-block, +.visible-sm-block, +.visible-sm-inline, +.visible-sm-inline-block, +.visible-md-block, +.visible-md-inline, +.visible-md-inline-block, +.visible-lg-block, +.visible-lg-inline, +.visible-lg-inline-block { + display: none !important; +} +@media (max-width: 767px) { + .visible-xs { + display: block !important; + } + table.visible-xs { + display: table; + } + tr.visible-xs { + display: table-row !important; + } + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } +} +@media (max-width: 767px) { + .visible-xs-block { + display: block !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline { + display: inline !important; + } +} +@media (max-width: 767px) { + .visible-xs-inline-block { + display: inline-block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm { + display: block !important; + } + table.visible-sm { + display: table; + } + tr.visible-sm { + display: table-row !important; + } + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-block { + display: block !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline { + display: inline !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .visible-sm-inline-block { + display: inline-block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md { + display: block !important; + } + table.visible-md { + display: table; + } + tr.visible-md { + display: table-row !important; + } + th.visible-md, + td.visible-md { + display: table-cell !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-block { + display: block !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline { + display: inline !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .visible-md-inline-block { + display: inline-block !important; + } +} +@media (min-width: 1200px) { + .visible-lg { + display: block !important; + } + table.visible-lg { + display: table; + } + tr.visible-lg { + display: table-row !important; + } + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } +} +@media (min-width: 1200px) { + .visible-lg-block { + display: block !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline { + display: inline !important; + } +} +@media (min-width: 1200px) { + .visible-lg-inline-block { + display: inline-block !important; + } +} +@media (max-width: 767px) { + .hidden-xs { + display: none !important; + } +} +@media (min-width: 768px) and (max-width: 991px) { + .hidden-sm { + display: none !important; + } +} +@media (min-width: 992px) and (max-width: 1199px) { + .hidden-md { + display: none !important; + } +} +@media (min-width: 1200px) { + .hidden-lg { + display: none !important; + } +} +.visible-print { + display: none !important; +} +@media print { + .visible-print { + display: block !important; + } + table.visible-print { + display: table; + } + tr.visible-print { + display: table-row !important; + } + th.visible-print, + td.visible-print { + display: table-cell !important; + } +} +.visible-print-block { + display: none !important; +} +@media print { + .visible-print-block { + display: block !important; + } +} +.visible-print-inline { + display: none !important; +} +@media print { + .visible-print-inline { + display: inline !important; + } +} +.visible-print-inline-block { + display: none !important; +} +@media print { + .visible-print-inline-block { + display: inline-block !important; + } +} +@media print { + .hidden-print { + display: none !important; + } +} + +/* tapestry-quickstart customizations start here: */ + +body { padding-top: 70px; } + diff --git a/web-modules/apache-tapestry/src/main/webapp/mybootstrap/fonts/glyphicons-halflings-regular.eot b/web-modules/apache-tapestry/src/main/webapp/mybootstrap/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000000000000000000000000000000000000..9879fec538743e4da2d8928ceef3e6c4305f8359 GIT binary patch literal 35366 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 WZ(xwT4i*jKX_HKRs&O97_J07Q@0tPt literal 0 HcmV?d00001 diff --git a/web-modules/apache-tapestry/src/main/webapp/mybootstrap/fonts/glyphicons-halflings-regular.ttf b/web-modules/apache-tapestry/src/main/webapp/mybootstrap/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..c0e841e44b7ea5c470b8ec42b85b7a23c8d70a7a GIT binary patch literal 57865 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 literal 0 HcmV?d00001 diff --git a/web-modules/apache-tapestry/src/main/webapp/mybootstrap/fonts/glyphicons-halflings-regular.woff b/web-modules/apache-tapestry/src/main/webapp/mybootstrap/fonts/glyphicons-halflings-regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..59d837ee613eab6b8d8bbf451355a847706ad554 GIT binary patch literal 42775 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 Gi~k$SvEqLK literal 0 HcmV?d00001 diff --git a/web-modules/apache-tapestry/src/main/webapp/mybootstrap/fonts/glyphicons-halflings-regular.woff2 b/web-modules/apache-tapestry/src/main/webapp/mybootstrap/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..006d10650b00643a558cc7e61dbaa99f3fe9ef21 GIT binary patch literal 840 zcmaJq zvJnfhw~!zfVrjub;x9PYozB9-NH9?{}xE0of(!1U&MJP(b>9cRPj3Ea>!p zs{cNcEGzzsa?vRL*Y;8h( z=134?dD+clvySEUVmn=p)Ij%QG(ptP1MJYP06K@U!P36~ZO8{j*#Jvh(&xe1GBTPX zFoUp#tGEDHKAzIp7&IF7F4KJ?3Oc#jy70Ew!W)Vpu0GDwEDpQ+YeG&v9CuGD4C&4; zpqgryZIFO(;R$)g?HZq*DTj^!l%xX_0pPqIhI%Ekc*ou;h=@ zh@X#r;8D#+ViFTBh&Qavj(B)sh?>=)Hbb+HwS(+5N}!tsY(%tj^>72-<{bQfcLG+- zfw{@SV5d73?{H{q38k0*Cmo2Q3Xs#=1Ew)IQu1+l4z57}9y_bX!{$6oj2gMW2F)Nm FwjV{&02BZK literal 0 HcmV?d00001 diff --git a/web-modules/apache-tapestry/src/main/webapp/mybootstrap/js/button.js b/web-modules/apache-tapestry/src/main/webapp/mybootstrap/js/button.js new file mode 100644 index 0000000000..7c7c021f95 --- /dev/null +++ b/web-modules/apache-tapestry/src/main/webapp/mybootstrap/js/button.js @@ -0,0 +1,116 @@ +/* ======================================================================== + * Bootstrap: button.js v3.3.4 + * http://getbootstrap.com/javascript/#buttons + * ======================================================================== + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // BUTTON PUBLIC CLASS DEFINITION + // ============================== + + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Button.DEFAULTS, options) + this.isLoading = false + } + + Button.VERSION = '3.3.4' + + Button.DEFAULTS = { + loadingText: 'loading...' + } + + Button.prototype.setState = function (state) { + var d = 'disabled' + var $el = this.$element + var val = $el.is('input') ? 'val' : 'html' + var data = $el.data() + + state = state + 'Text' + + if (data.resetText == null) $el.data('resetText', $el[val]()) + + // push to event loop to allow forms to submit + setTimeout($.proxy(function () { + $el[val](data[state] == null ? this.options[state] : data[state]) + + if (state == 'loadingText') { + this.isLoading = true + $el.addClass(d).attr(d, d) + } else if (this.isLoading) { + this.isLoading = false + $el.removeClass(d).removeAttr(d) + } + }, this), 0) + } + + Button.prototype.toggle = function () { + var changed = true + var $parent = this.$element.closest('[data-toggle="buttons"]') + + if ($parent.length) { + var $input = this.$element.find('input') + if ($input.prop('type') == 'radio') { + if ($input.prop('checked') && this.$element.hasClass('active')) changed = false + else $parent.find('.active').removeClass('active') + } + if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change') + } else { + this.$element.attr('aria-pressed', !this.$element.hasClass('active')) + } + + if (changed) this.$element.toggleClass('active') + } + + + // BUTTON PLUGIN DEFINITION + // ======================== + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.button') + var options = typeof option == 'object' && option + + if (!data) $this.data('bs.button', (data = new Button(this, options))) + + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } + + var old = $.fn.button + + $.fn.button = Plugin + $.fn.button.Constructor = Button + + + // BUTTON NO CONFLICT + // ================== + + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } + + + // BUTTON DATA-API + // =============== + + $(document) + .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + Plugin.call($btn, 'toggle') + e.preventDefault() + }) + .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { + $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) + }) + +}(jQuery); diff --git a/web-modules/apache-tapestry/src/site/apt/index.apt b/web-modules/apache-tapestry/src/site/apt/index.apt new file mode 100644 index 0000000000..0e22d10c32 --- /dev/null +++ b/web-modules/apache-tapestry/src/site/apt/index.apt @@ -0,0 +1,9 @@ + ---- + Module com.baeldung:apache-tapestry + ---- + +com.baeldung:apache-tapestry Documentation + + This is where you can start to document your module. + + Create new files in the Maven APT format, and update the site.xml file to point to them. diff --git a/web-modules/apache-tapestry/src/site/site.xml b/web-modules/apache-tapestry/src/site/site.xml new file mode 100644 index 0000000000..774861b479 --- /dev/null +++ b/web-modules/apache-tapestry/src/site/site.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/web-modules/apache-tapestry/src/test/conf/testng.xml b/web-modules/apache-tapestry/src/test/conf/testng.xml new file mode 100644 index 0000000000..c1c01e64aa --- /dev/null +++ b/web-modules/apache-tapestry/src/test/conf/testng.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/web-modules/apache-tapestry/src/test/conf/webdefault.xml b/web-modules/apache-tapestry/src/test/conf/webdefault.xml new file mode 100644 index 0000000000..c587ac7a5d --- /dev/null +++ b/web-modules/apache-tapestry/src/test/conf/webdefault.xml @@ -0,0 +1,278 @@ + + + + + Default web.xml file. + This file is applied to a Web application before it's own WEB_INF/web.xml file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + default + org.mortbay.jetty.servlet.Default + + acceptRanges + true + + + dirAllowed + true + + + putAllowed + false + + + delAllowed + false + + + redirectWelcome + false + + + minGzipLength + 8192 + + 0 + + + + + default + / + + + + + 30 + + + + + + index.html + index.htm + + + + + + ar + ISO-8859-6 + + + be + ISO-8859-5 + + + bg + ISO-8859-5 + + + ca + ISO-8859-1 + + + cs + ISO-8859-2 + + + da + ISO-8859-1 + + + de + ISO-8859-1 + + + el + ISO-8859-7 + + + en + ISO-8859-1 + + + es + ISO-8859-1 + + + et + ISO-8859-1 + + + fi + ISO-8859-1 + + + fr + ISO-8859-1 + + + hr + ISO-8859-2 + + + hu + ISO-8859-2 + + + is + ISO-8859-1 + + + it + ISO-8859-1 + + + iw + ISO-8859-8 + + + ja + Shift_JIS + + + ko + EUC-KR + + + lt + ISO-8859-2 + + + lv + ISO-8859-2 + + + mk + ISO-8859-5 + + + nl + ISO-8859-1 + + + no + ISO-8859-1 + + + pl + ISO-8859-2 + + + pt + ISO-8859-1 + + + ro + ISO-8859-2 + + + ru + ISO-8859-5 + + + sh + ISO-8859-5 + + + sk + ISO-8859-2 + + + sl + ISO-8859-2 + + + sq + ISO-8859-2 + + + sr + ISO-8859-5 + + + sv + ISO-8859-1 + + + tr + ISO-8859-9 + + + uk + ISO-8859-5 + + + zh + GB2312 + + + zh_TW + Big5 + + + + + + diff --git a/web-modules/blade/pom.xml b/web-modules/blade/pom.xml new file mode 100644 index 0000000000..2748c05663 --- /dev/null +++ b/web-modules/blade/pom.xml @@ -0,0 +1,119 @@ + + + 4.0.0 + blade + blade + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + com.bladejava + blade-mvc + ${blade-mvc.version} + + + org.webjars + bootstrap + ${bootstrap.version} + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + org.projectlombok + lombok + ${lombok.version} + provided + + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + test + + + org.apache.httpcomponents + httpmime + ${httpmime.version} + test + + + org.apache.httpcomponents + httpcore + ${httpcore.version} + test + + + + + blade + + + org.apache.maven.plugins + maven-failsafe-plugin + ${maven-failsafe-plugin.version} + + true + + **/*LiveTest.java + + + + + + integration-test + verify + + + + + + maven-assembly-plugin + ${assembly.plugin.version} + + ${project.build.finalName} + false + + + com.baeldung.blade.sample.App + + + + jar-with-dependencies + + + + + make-assembly + package + + single + + + + + + + + + 2.0.14.RELEASE + 4.2.1 + 4.5.6 + 4.5.6 + 4.4.10 + 0.7 + 3.1.0 + + + \ No newline at end of file diff --git a/web-modules/blade/src/main/resources/static/app.js b/web-modules/blade/src/main/resources/static/app.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web-modules/bootique/pom.xml b/web-modules/bootique/pom.xml new file mode 100644 index 0000000000..8da24ebf0a --- /dev/null +++ b/web-modules/bootique/pom.xml @@ -0,0 +1,74 @@ + + + 4.0.0 + com.baeldung.bootique + bootique + 1.0-SNAPSHOT + bootique + jar + http://maven.apache.org + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + + io.bootique.bom + bootique-bom + ${bootique-bom.version} + pom + import + + + + + + + io.bootique.jersey + bootique-jersey + compile + + + io.bootique.logback + bootique-logback + compile + + + io.bootique + bootique-test + test + + + + + + + org.apache.maven.plugins + maven-shade-plugin + ${maven-shade-plugin.version} + + + org.apache.maven.plugins + maven-surefire-plugin + + + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + com.baeldung.bootique.App + 0.23 + 2.4.3 + + + \ No newline at end of file diff --git a/web-modules/bootique/src/main/resources/logback.xml b/web-modules/bootique/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/web-modules/bootique/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/web-modules/dropwizard/README.md b/web-modules/dropwizard/README.md new file mode 100644 index 0000000000..76311ebbb3 --- /dev/null +++ b/web-modules/dropwizard/README.md @@ -0,0 +1,5 @@ +# Dropwizard + +### Relevant Articles: + +- [Introduction to Dropwizard](https://www.baeldung.com/java-dropwizard) diff --git a/web-modules/dropwizard/pom.xml b/web-modules/dropwizard/pom.xml new file mode 100644 index 0000000000..03562acded --- /dev/null +++ b/web-modules/dropwizard/pom.xml @@ -0,0 +1,69 @@ + + + 4.0.0 + dropwizard + 0.0.1-SNAPSHOT + dropwizard + jar + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + io.dropwizard + dropwizard-core + ${dropwizard.version} + + + + + + + org.apache.maven.plugins + maven-shade-plugin + + true + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + package + + shade + + + + + + com.baeldung.dropwizard.introduction.IntroductionApplication + + + + + + + + + + + 2.0.0 + + + \ No newline at end of file diff --git a/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/IntroductionApplication.java b/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/IntroductionApplication.java new file mode 100644 index 0000000000..d9af590017 --- /dev/null +++ b/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/IntroductionApplication.java @@ -0,0 +1,51 @@ +package com.baeldung.dropwizard.introduction; + +import com.baeldung.dropwizard.introduction.configuration.ApplicationHealthCheck; +import com.baeldung.dropwizard.introduction.configuration.BasicConfiguration; +import com.baeldung.dropwizard.introduction.domain.Brand; +import com.baeldung.dropwizard.introduction.repository.BrandRepository; +import com.baeldung.dropwizard.introduction.resource.BrandResource; +import io.dropwizard.Application; +import io.dropwizard.configuration.ResourceConfigurationSourceProvider; +import io.dropwizard.setup.Bootstrap; +import io.dropwizard.setup.Environment; + +import java.util.ArrayList; +import java.util.List; + +public class IntroductionApplication extends Application { + + public static void main(final String[] args) throws Exception { + new IntroductionApplication().run("server", "introduction-config.yml"); + } + + @Override + public void run(final BasicConfiguration basicConfiguration, final Environment environment) { + final int defaultSize = basicConfiguration.getDefaultSize(); + final BrandRepository brandRepository = new BrandRepository(initBrands()); + final BrandResource brandResource = new BrandResource(defaultSize, brandRepository); + environment + .jersey() + .register(brandResource); + + final ApplicationHealthCheck healthCheck = new ApplicationHealthCheck(); + environment + .healthChecks() + .register("application", healthCheck); + } + + @Override + public void initialize(final Bootstrap bootstrap) { + bootstrap.setConfigurationSourceProvider(new ResourceConfigurationSourceProvider()); + super.initialize(bootstrap); + } + + private List initBrands() { + final List brands = new ArrayList<>(); + brands.add(new Brand(1L, "Brand1")); + brands.add(new Brand(2L, "Brand2")); + brands.add(new Brand(3L, "Brand3")); + + return brands; + } +} diff --git a/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/configuration/ApplicationHealthCheck.java b/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/configuration/ApplicationHealthCheck.java new file mode 100644 index 0000000000..bf4b710937 --- /dev/null +++ b/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/configuration/ApplicationHealthCheck.java @@ -0,0 +1,10 @@ +package com.baeldung.dropwizard.introduction.configuration; + +import com.codahale.metrics.health.HealthCheck; + +public class ApplicationHealthCheck extends HealthCheck { + @Override + protected Result check() throws Exception { + return Result.healthy(); + } +} diff --git a/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/configuration/BasicConfiguration.java b/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/configuration/BasicConfiguration.java new file mode 100644 index 0000000000..5098f89d62 --- /dev/null +++ b/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/configuration/BasicConfiguration.java @@ -0,0 +1,20 @@ +package com.baeldung.dropwizard.introduction.configuration; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.dropwizard.Configuration; + +import javax.validation.constraints.NotNull; + +public class BasicConfiguration extends Configuration { + @NotNull private final int defaultSize; + + @JsonCreator + public BasicConfiguration(@JsonProperty("defaultSize") final int defaultSize) { + this.defaultSize = defaultSize; + } + + public int getDefaultSize() { + return defaultSize; + } +} diff --git a/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/domain/Brand.java b/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/domain/Brand.java new file mode 100644 index 0000000000..c83f67bb6e --- /dev/null +++ b/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/domain/Brand.java @@ -0,0 +1,19 @@ +package com.baeldung.dropwizard.introduction.domain; + +public class Brand { + private final Long id; + private final String name; + + public Brand(final Long id, final String name) { + this.id = id; + this.name = name; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } +} diff --git a/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/repository/BrandRepository.java b/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/repository/BrandRepository.java new file mode 100644 index 0000000000..3f187df3de --- /dev/null +++ b/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/repository/BrandRepository.java @@ -0,0 +1,32 @@ +package com.baeldung.dropwizard.introduction.repository; + +import com.baeldung.dropwizard.introduction.domain.Brand; +import com.google.common.collect.ImmutableList; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +public class BrandRepository { + private final List brands; + + public BrandRepository(final List brands) { + this.brands = ImmutableList.copyOf(brands); + } + + public List findAll(final int size) { + return brands + .stream() + .limit(size) + .collect(Collectors.toList()); + } + + public Optional findById(final Long id) { + return brands + .stream() + .filter(brand -> brand + .getId() + .equals(id)) + .findFirst(); + } +} diff --git a/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/resource/BrandResource.java b/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/resource/BrandResource.java new file mode 100644 index 0000000000..5f97e26faf --- /dev/null +++ b/web-modules/dropwizard/src/main/java/com/baeldung/dropwizard/introduction/resource/BrandResource.java @@ -0,0 +1,35 @@ +package com.baeldung.dropwizard.introduction.resource; + +import com.baeldung.dropwizard.introduction.domain.Brand; +import com.baeldung.dropwizard.introduction.repository.BrandRepository; + +import javax.ws.rs.*; +import javax.ws.rs.core.MediaType; +import java.util.List; +import java.util.Optional; + +@Path("/brands") +@Produces(MediaType.APPLICATION_JSON) +public class BrandResource { + private final int defaultSize; + private final BrandRepository brandRepository; + + public BrandResource(final int defaultSize, final BrandRepository brandRepository) { + this.defaultSize = defaultSize; + this.brandRepository = brandRepository; + + } + + @GET + public List getBrands(@QueryParam("size") final Optional size) { + return brandRepository.findAll(size.orElse(defaultSize)); + } + + @GET + @Path("/{id}") + public Brand getById(@PathParam("id") final Long id) { + return brandRepository + .findById(id) + .orElseThrow(RuntimeException::new); + } +} diff --git a/web-modules/dropwizard/src/main/resources/introduction-config.yml b/web-modules/dropwizard/src/main/resources/introduction-config.yml new file mode 100644 index 0000000000..02ff36de05 --- /dev/null +++ b/web-modules/dropwizard/src/main/resources/introduction-config.yml @@ -0,0 +1 @@ +defaultSize: 5 \ No newline at end of file diff --git a/web-modules/dropwizard/src/test/java/com/baeldung/dropwizard/introduction/repository/BrandRepositoryUnitTest.java b/web-modules/dropwizard/src/test/java/com/baeldung/dropwizard/introduction/repository/BrandRepositoryUnitTest.java new file mode 100644 index 0000000000..b996883ee5 --- /dev/null +++ b/web-modules/dropwizard/src/test/java/com/baeldung/dropwizard/introduction/repository/BrandRepositoryUnitTest.java @@ -0,0 +1,47 @@ +package com.baeldung.dropwizard.introduction.repository; + +import com.baeldung.dropwizard.introduction.domain.Brand; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class BrandRepositoryUnitTest { + + private static final Brand BRAND_1 = new Brand(1L, "Brand1"); + + private final BrandRepository brandRepository = new BrandRepository(getBrands()); + + @Test + void givenSize_whenFindingAll_thenReturnList() { + final int size = 2; + + final List result = brandRepository.findAll(size); + + assertEquals(size, result.size()); + } + + @Test + void givenId_whenFindingById_thenReturnFoundBrand() { + final Long id = BRAND_1.getId(); + + final Optional result = brandRepository.findById(id); + + Assertions.assertTrue(result.isPresent()); + assertEquals(BRAND_1, result.get()); + } + + + private List getBrands() { + final List brands = new ArrayList<>(); + brands.add(BRAND_1); + brands.add(new Brand(2L, "Brand2")); + brands.add(new Brand(3L, "Brand3")); + + return brands; + } +} \ No newline at end of file diff --git a/web-modules/google-web-toolkit/pom.xml b/web-modules/google-web-toolkit/pom.xml new file mode 100644 index 0000000000..1fdb38f0a1 --- /dev/null +++ b/web-modules/google-web-toolkit/pom.xml @@ -0,0 +1,109 @@ + + + + 4.0.0 + google-web-toolkit + 1.0-SNAPSHOT + google-web-toolkit + war + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + + + com.google.gwt + gwt + ${gwt.version} + pom + import + + + + + + + com.google.gwt + gwt-servlet + runtime + + + com.google.gwt + gwt-user + provided + + + com.google.gwt + gwt-dev + provided + + + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + + net.ltgt.gwt.maven + gwt-maven-plugin + ${gwt.plugin.version} + + + + compile + test + + + + + com.baeldung.Google_web_toolkit + Google_web_toolkit + true + + + ${maven.compiler.source} + + + + -compileReport + -XcompilerMetrics + + + ${project.build.directory}/${project.build.finalName} + compile+runtime + + + Google_web_toolkit.html + + + + + + maven-surefire-plugin + + true + + + + + + + + + + 1.8 + 1.8 + 2.8.2 + 1.0-rc-8 + + + \ No newline at end of file diff --git a/web-modules/google-web-toolkit/src/main/resources/logback.xml b/web-modules/google-web-toolkit/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/web-modules/google-web-toolkit/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/web-modules/jakarta-ee/README.md b/web-modules/jakarta-ee/README.md new file mode 100644 index 0000000000..54f372f736 --- /dev/null +++ b/web-modules/jakarta-ee/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Introduction to Jakarta EE MVC / Eclipse Krazo](https://www.baeldung.com/java-ee-mvc-eclipse-krazo) diff --git a/web-modules/jakarta-ee/pom.xml b/web-modules/jakarta-ee/pom.xml new file mode 100644 index 0000000000..066bc14766 --- /dev/null +++ b/web-modules/jakarta-ee/pom.xml @@ -0,0 +1,109 @@ + + 4.0.0 + com.baeldung + jakarta-ee + 1.0-SNAPSHOT + jakarta-ee + war + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + jakarta.platform + jakarta.jakartaee-web-api + ${jakartaee-api.version} + provided + + + jakarta.mvc + jakarta.mvc-api + ${jakarta.mvc-api.version} + + + org.eclipse.krazo + krazo-jersey + ${krazo.version} + + + org.junit.jupiter + junit-jupiter-api + ${junit.jupiter.version} + test + + + org.mockito + mockito-all + ${mockito.version} + test + + + + + mvc-2.0 + + + org.glassfish.maven.plugin + maven-glassfish-plugin + 2.1 + + ${local.glassfish.home} + admin + + password + + ${local.glassfish.domain} + 8080 + 4848 + + + + ${project.artifactId} + target/${project.build.finalName}.war + + + true + false + true + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 11 + 11 + + + + org.apache.maven.plugins + maven-war-plugin + + false + + + + + + + 9.0.0 + 2.0.0 + 2.0.0 + 5.8.2 + C:/glassfish6 + admin + mvn-domain + 1.10.19 + + ${local.glassfish.home}\\domains\\${local.glassfish.domain}\\config\\domain-passwords + + + + \ No newline at end of file diff --git a/web-modules/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/User.java b/web-modules/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/User.java new file mode 100644 index 0000000000..a2253b6aa6 --- /dev/null +++ b/web-modules/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/User.java @@ -0,0 +1,84 @@ +package com.baeldung.eclipse.krazo; + +import jakarta.enterprise.context.RequestScoped; +import jakarta.inject.Named; +import jakarta.mvc.RedirectScoped; +import jakarta.mvc.binding.MvcBinding; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Null; +import jakarta.validation.constraints.Size; +import jakarta.ws.rs.FormParam; + +import java.io.Serializable; + +@Named("user") +@RedirectScoped +public class User implements Serializable { + @MvcBinding + @Null + private String id; + + @MvcBinding + @NotNull + @Size(min = 1, message = "Name cannot be blank") + @FormParam("name") + private String name; + + @MvcBinding + @Min(value = 18, message = "The minimum age of the user should be 18 years") + @FormParam("age") + private int age; + + @MvcBinding + @Email(message = "The email cannot be blank and should be in a valid format") + @Size(min=3, message = "Email cannot be empty") + @FormParam("email") + private String email; + + @MvcBinding + @Null + @FormParam("phone") + private String phone; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } +} diff --git a/web-modules/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/UserApplication.java b/web-modules/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/UserApplication.java new file mode 100644 index 0000000000..5a272806cb --- /dev/null +++ b/web-modules/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/UserApplication.java @@ -0,0 +1,11 @@ +package com.baeldung.eclipse.krazo; + +import jakarta.ws.rs.ApplicationPath; +import jakarta.ws.rs.core.Application; + +/** + * Default JAX-RS application listening on /app + */ +@ApplicationPath("/app") +public class UserApplication extends Application { +} diff --git a/web-modules/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/UserController.java b/web-modules/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/UserController.java new file mode 100644 index 0000000000..92ddf73571 --- /dev/null +++ b/web-modules/jakarta-ee/src/main/java/com/baeldung/eclipse/krazo/UserController.java @@ -0,0 +1,85 @@ +package com.baeldung.eclipse.krazo; + +import jakarta.inject.Inject; +import jakarta.mvc.Controller; +import jakarta.mvc.Models; +import jakarta.mvc.binding.BindingResult; +import jakarta.mvc.security.CsrfProtected; +import jakarta.validation.Valid; +import jakarta.ws.rs.BeanParam; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * The class contains two controllers and a REST API + */ +@Path("users") +public class UserController { + @Inject + private BindingResult bindingResult; + + private static final List users = new ArrayList<>(); + + @Inject + private Models models; + + /** + * This is a controller. It displays a initial form to the user. + * @return The view name + */ + @GET + @Controller + public String showForm() { + return "user.jsp"; + } + + /** + * The method handles the form submits + * Handles HTTP POST and is CSRF protected. The client invoking this controller should provide a CSRF token. + * @param user The user details that has to be stored + * @return Returns a view name + */ + @POST + @Controller + @CsrfProtected + public String saveUser(@Valid @BeanParam User user) { + if (bindingResult.isFailed()) { + models.put("errors", bindingResult.getAllErrors()); + return "user.jsp"; + } + String id = UUID.randomUUID().toString(); + user.setId(id); + users.add(user); + return "redirect:users/success"; + } + + /** + * Handles a redirect view + * @return The view name + */ + @GET + @Controller + @Path("success") + public String saveUserSuccess() { + return "success.jsp"; + } + + /** + * The REST API that returns all the user details in the JSON format + * @return The list of users that are saved. The List is converted into Json Array. + * If no user is present a empty array is returned + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + public List getUsers() { + return users; + } + +} diff --git a/web-modules/jakarta-ee/src/main/webapp/WEB-INF/beans.xml b/web-modules/jakarta-ee/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 0000000000..d068fbd3e4 --- /dev/null +++ b/web-modules/jakarta-ee/src/main/webapp/WEB-INF/beans.xml @@ -0,0 +1,6 @@ + + + diff --git a/web-modules/jakarta-ee/src/main/webapp/WEB-INF/views/success.jsp b/web-modules/jakarta-ee/src/main/webapp/WEB-INF/views/success.jsp new file mode 100644 index 0000000000..19d45e46ba --- /dev/null +++ b/web-modules/jakarta-ee/src/main/webapp/WEB-INF/views/success.jsp @@ -0,0 +1,47 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + + + MVC 2.0 + + + + + + + + + + +
+
+
+
+ +
+

User created successfully!

+
+
+ +
+ +
+
+ + + + + + \ No newline at end of file diff --git a/web-modules/jakarta-ee/src/main/webapp/WEB-INF/views/user.jsp b/web-modules/jakarta-ee/src/main/webapp/WEB-INF/views/user.jsp new file mode 100644 index 0000000000..a36655950d --- /dev/null +++ b/web-modules/jakarta-ee/src/main/webapp/WEB-INF/views/user.jsp @@ -0,0 +1,89 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + + + MVC 2.0 + + + + + + + + + + +
+
+
+

+ User Details +

+
+ + + +
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+
+ +
+
+ + +
+ +
+ +
+
+ + + + + + \ No newline at end of file diff --git a/web-modules/jakarta-ee/src/main/webapp/styles.css b/web-modules/jakarta-ee/src/main/webapp/styles.css new file mode 100644 index 0000000000..9cc9e62f12 --- /dev/null +++ b/web-modules/jakarta-ee/src/main/webapp/styles.css @@ -0,0 +1,28 @@ +body, html { + font-family: Raleway, serif; + font-weight: 300; +} + +.bg-dark { + background-color: #63b175 !important; + font-weight: 600 !important; +} + +body { + padding-top: 80px; +} + +@media (max-width: 979px) { + body { + padding-top: 0; + } +} + +label { + font-weight: bold; +} + +.hr-dark { + border-top: 2px solid #000; + margin-bottom: 20px; +} \ No newline at end of file diff --git a/web-modules/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/AppUnitTest.java b/web-modules/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/AppUnitTest.java new file mode 100644 index 0000000000..8c77a75318 --- /dev/null +++ b/web-modules/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/AppUnitTest.java @@ -0,0 +1,16 @@ +package com.baeldung.eclipse.krazo; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Dummy Test + */ +public class AppUnitTest { + + @Test + public void test() { + assertTrue(true); + } +} diff --git a/web-modules/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/UserControllerUnitTest.java b/web-modules/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/UserControllerUnitTest.java new file mode 100644 index 0000000000..5e79924ed7 --- /dev/null +++ b/web-modules/jakarta-ee/src/test/java/com/baeldung/eclipse/krazo/UserControllerUnitTest.java @@ -0,0 +1,116 @@ +package com.baeldung.eclipse.krazo; + +import com.baeldung.eclipse.krazo.User; +import com.baeldung.eclipse.krazo.UserController; +import jakarta.mvc.Models; +import jakarta.mvc.binding.BindingResult; +import org.eclipse.krazo.core.ModelsImpl; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.when; + +/** + * The class contains unit tests. We do only unit tests. Most of the classes are mocked + */ +@DisplayName("Eclipse Krazo MVC 2.0 Test Suite") +class UserControllerUnitTest { + + @InjectMocks + UserController userController = new UserController(); + + @Mock + Models models; + + @Mock + BindingResult bindingResult; + + @BeforeEach + public void setUpClass() { + MockitoAnnotations.initMocks(this); + } + + @Test + @DisplayName("Test Show Form") + void whenShowForm_thenReturnViewName() { + assertNotNull(userController.showForm()); + assertEquals("user.jsp", userController.showForm()); + } + + @Test + @DisplayName("Test Save User Success") + void whenSaveUser_thenReturnSuccess() { + when(bindingResult.isFailed()).thenReturn(false); + + User user = new User(); + + assertNotNull(userController.saveUser(user)); + assertDoesNotThrow(() -> userController.saveUser(user)); + assertEquals("redirect:users/success", userController.saveUser(user)); + } + + @Test + @DisplayName("Test Save User Binding Errors") + void whenSaveUser_thenReturnError() { + when(bindingResult.isFailed()).thenReturn(true); + Models testModels = new ModelsImpl(); + when(models.put(anyString(), any())).thenReturn(testModels); + User user = getUser(); + assertNotNull(userController.saveUser(user)); + assertDoesNotThrow(() -> userController.saveUser(user)); + assertEquals("user.jsp", userController.saveUser(user)); + } + + @Test + @DisplayName("Test Save User Success View") + void whenSaveUserSuccess_thenRedirectSuccess() { + assertNotNull(userController.saveUserSuccess()); + assertDoesNotThrow(() -> userController.saveUserSuccess()); + assertEquals("success.jsp", userController.saveUserSuccess()); + } + + @Test + @DisplayName("Test Get Users API") + void whenGetUser_thenReturnUsers() { + when(bindingResult.isFailed()).thenReturn(false); + + User user= getUser(); + + assertNotNull(user); + assertEquals(30, user.getAge()); + assertEquals("john doe", user.getName()); + assertEquals("anymail", user.getEmail()); + assertEquals("99887766554433", user.getPhone()); + assertEquals("1", user.getId()); + + userController.saveUser(user); + userController.saveUser(user); + userController.saveUser(user); + + assertNotNull(userController.getUsers()); + assertDoesNotThrow(() -> userController.getUsers()); + assertEquals(3, userController.getUsers().size()); + + } + + private User getUser() { + User user = new User(); + user.setId("1"); + user.setName("john doe"); + user.setAge(30); + user.setEmail("anymail"); + user.setPhone("99887766554433"); + return user; + } + +} diff --git a/web-modules/java-lite/pom.xml b/web-modules/java-lite/pom.xml new file mode 100644 index 0000000000..7f1c9182f7 --- /dev/null +++ b/web-modules/java-lite/pom.xml @@ -0,0 +1,96 @@ + + + 4.0.0 + org.baeldung + java-lite + 1.0-SNAPSHOT + java-lite + war + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + org.javalite + activeweb + ${activeweb.version} + + + mysql + mysql-connector-java + ${mysql.connector.java.version} + + + com.sun + tools + ${sun.tools.version} + system + ${java.home}/../lib/tools.jar + + + org.javalite + activeweb-testing + ${activeweb-testing.version} + test + + + + + + + src/main/webapp/WEB-INF + + + + + org.eclipse.jetty + jetty-maven-plugin + ${jetty.maven.plugin.version} + + + + activejdbc.log + + + active_reload + true + + + activeweb.log.request + true + + + + + + org.javalite + activejdbc-instrumentation + ${activejdbc.version} + + + process-classes + + instrument + + + + + + + + + 9.4.8.v20171121 + 1.4.13 + 1.15 + 5.1.45 + 1.7.0 + 1.15 + + + \ No newline at end of file diff --git a/web-modules/java-lite/src/main/resources/logback.xml b/web-modules/java-lite/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/web-modules/java-lite/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/web-modules/javax-servlets-2/README.md b/web-modules/javax-servlets-2/README.md new file mode 100644 index 0000000000..179264f90a --- /dev/null +++ b/web-modules/javax-servlets-2/README.md @@ -0,0 +1,8 @@ +## Servlets + +This module contains articles about Servlets. + +### Relevant Articles: +- [Check if a User Is Logged-in With Servlets and JSP](https://www.baeldung.com/servlets-jsp-check-user-login) +- [How to Mock HttpServletRequest](https://www.baeldung.com/java-httpservletrequest-mock) +- [Set a Parameter in an HttpServletRequest in Java](https://www.baeldung.com/java-servlet-request-set-parameter) diff --git a/web-modules/javax-servlets-2/pom.xml b/web-modules/javax-servlets-2/pom.xml new file mode 100644 index 0000000000..9ba12352fd --- /dev/null +++ b/web-modules/javax-servlets-2/pom.xml @@ -0,0 +1,106 @@ + + + 4.0.0 + com.baeldung.javax-servlets + javax-servlets-2 + 1.0-SNAPSHOT + javax-servlets-2 + war + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + + commons-fileupload + commons-fileupload + ${commons-fileupload.version} + + + org.apache.commons + commons-text + ${commons-text.version} + + + + javax.servlet + javax.servlet-api + ${javax.servlet-api.version} + + + javax.servlet.jsp + javax.servlet.jsp-api + ${javax.servlet.jsp-api.version} + provided + + + javax.servlet + jstl + ${jstl.version} + + + org.jmockit + jmockit + ${jmockit.version} + test + + + org.springframework + spring-test + ${spring-test.version} + test + + + org.apache.httpcomponents + httpclient + ${org.apache.httpcomponents.version} + test + + + commons-logging + commons-logging + + + + + + + + + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + -javaagent:"${settings.localRepository}"/org/jmockit/jmockit/${jmockit.version}/jmockit-${jmockit.version}.jar + + + + + org.eclipse.jetty + jetty-maven-plugin + ${jetty-maven-plugin.version} + + + / + + + + + + + + 4.5.13 + 1.49 + 5.3.20 + 2.22.2 + 10.0.4 + 1.10.0 + + + \ No newline at end of file diff --git a/web-modules/javax-servlets-2/src/main/java/com/baeldung/servlets/UserServlet.java b/web-modules/javax-servlets-2/src/main/java/com/baeldung/servlets/UserServlet.java new file mode 100644 index 0000000000..a71a4da8e4 --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/java/com/baeldung/servlets/UserServlet.java @@ -0,0 +1,24 @@ +package com.baeldung.servlets; + +import java.io.IOException; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebServlet(name = "UserServlet", urlPatterns = "/user") +public class UserServlet extends HttpServlet { + + private static final long serialVersionUID = 2923732283720972121L; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { + String firstName = request.getParameter("firstName"); + String lastName = request.getParameter("lastName"); + + response.getWriter() + .append("Full Name: " + firstName + " " + lastName); + } + +} diff --git a/web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/LanguageServlet.java b/web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/LanguageServlet.java new file mode 100644 index 0000000000..983066ec51 --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/LanguageServlet.java @@ -0,0 +1,21 @@ +package com.baeldung.setparam; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.*; + +@WebServlet(name = "LanguageServlet", urlPatterns = "/setparam/lang") +public class LanguageServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + + SetParameterRequestWrapper requestWrapper = new SetParameterRequestWrapper(request); + requestWrapper.setParameter("locale", Locale.getDefault().getLanguage()); + request.getRequestDispatcher("/setparam/3rd_party_module.jsp").forward(requestWrapper, response); + } + +} \ No newline at end of file diff --git a/web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/SanitizeParametersFilter.java b/web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/SanitizeParametersFilter.java new file mode 100644 index 0000000000..3f93591bd9 --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/SanitizeParametersFilter.java @@ -0,0 +1,17 @@ +package com.baeldung.setparam; + +import java.io.IOException; +import javax.servlet.*; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; + +@WebFilter(urlPatterns = { "/setparam/with-sanitize.jsp" }) +public class SanitizeParametersFilter implements Filter { + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletRequest httpReq = (HttpServletRequest) request; + chain.doFilter(new SanitizeParametersRequestWrapper(httpReq), response); + } + +} \ No newline at end of file diff --git a/web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/SanitizeParametersRequestWrapper.java b/web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/SanitizeParametersRequestWrapper.java new file mode 100644 index 0000000000..e4c2870ca6 --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/SanitizeParametersRequestWrapper.java @@ -0,0 +1,46 @@ +package com.baeldung.setparam; + +import java.util.*; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +import org.apache.commons.text.StringEscapeUtils; + +public class SanitizeParametersRequestWrapper extends HttpServletRequestWrapper { + + private final Map sanitizedMap; + + public SanitizeParametersRequestWrapper(HttpServletRequest request) { + super(request); + sanitizedMap = Collections.unmodifiableMap( + request.getParameterMap().entrySet().stream() + .collect(Collectors.toMap( + Map.Entry::getKey, + entry -> Arrays.stream(entry.getValue()) + .map(StringEscapeUtils::escapeHtml4) + .toArray(String[]::new) + ))); + } + + @Override + public Map getParameterMap() { + return sanitizedMap; + } + + @Override + public String[] getParameterValues(String name) { + return Optional.ofNullable(getParameterMap().get(name)) + .map(values -> Arrays.copyOf(values, values.length)) + .orElse(null); + } + + @Override + public String getParameter(String name) { + return Optional.ofNullable(getParameterValues(name)) + .map(values -> values[0]) + .orElse(null); + } + +} \ No newline at end of file diff --git a/web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/SetParameterRequestWrapper.java b/web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/SetParameterRequestWrapper.java new file mode 100644 index 0000000000..7b2ab4597c --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/java/com/baeldung/setparam/SetParameterRequestWrapper.java @@ -0,0 +1,40 @@ +package com.baeldung.setparam; + +import java.util.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +public class SetParameterRequestWrapper extends HttpServletRequestWrapper { + + private final Map paramMap; + + public SetParameterRequestWrapper(HttpServletRequest request) { + super(request); + paramMap = new HashMap<>(request.getParameterMap()); + } + + @Override + public Map getParameterMap() { + return Collections.unmodifiableMap(paramMap); + } + + @Override + public String[] getParameterValues(String name) { + return Optional.ofNullable(getParameterMap().get(name)) + .map(values -> Arrays.copyOf(values, values.length)) + .orElse(null); + } + + @Override + public String getParameter(String name) { + return Optional.ofNullable(getParameterValues(name)) + .map(values -> values[0]) + .orElse(null); + } + + public void setParameter(String name, String value) { + paramMap.put(name, new String[] {value}); + } + +} \ No newline at end of file diff --git a/web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/User.java b/web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/User.java new file mode 100644 index 0000000000..f61c0490bc --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/User.java @@ -0,0 +1,80 @@ +package com.baeldung.user.check; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; + +/** + * @since 6 de fev de 2022 + * @author ulisses + */ +public class User implements Serializable { + private static final long serialVersionUID = 1L; + + protected static final HashMap DB = new HashMap<>(); + static { + DB.put("admin", new User("admin", "password")); + DB.put("user", new User("user", "pass")); + } + + private String name; + private String password; + + private List logins = new ArrayList(); + + public User(String name, String password) { + this.name = name; + this.password = password; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getLogins() { + return logins; + } + + public void setLogins(List logins) { + this.logins = logins; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + User other = (User) obj; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + return true; + } +} diff --git a/web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckFilter.java b/web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckFilter.java new file mode 100644 index 0000000000..835275c255 --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckFilter.java @@ -0,0 +1,50 @@ +package com.baeldung.user.check; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebFilter("/user-check/*") +public class UserCheckFilter implements Filter { + public static void forward(HttpServletRequest request, HttpServletResponse response, String page) throws ServletException, IOException { + request.getRequestDispatcher("/WEB-INF/user.check" + page) + .forward(request, response); + } + + @Override + public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { + if (!(req instanceof HttpServletRequest)) { + throw new ServletException("Can only process HttpServletRequest"); + } + + if (!(res instanceof HttpServletResponse)) { + throw new ServletException("Can only process HttpServletResponse"); + } + + HttpServletRequest request = (HttpServletRequest) req; + HttpServletResponse response = (HttpServletResponse) res; + + request.setAttribute("origin", request.getRequestURI()); + + if (!request.getRequestURI() + .contains("login") && request.getSession(false) == null) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + forward(request, response, "/login.jsp"); + // we return here so the original servlet is not processed + return; + } + + chain.doFilter(request, response); + } + + public void init(FilterConfig arg) throws ServletException { + } +} diff --git a/web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckLoginServlet.java b/web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckLoginServlet.java new file mode 100644 index 0000000000..e1a38fc7b8 --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckLoginServlet.java @@ -0,0 +1,56 @@ +package com.baeldung.user.check; + +import java.io.IOException; +import java.util.Date; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +@WebServlet("/user-check/login") +public class UserCheckLoginServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + if (request.getSession(false) != null) { + response.sendRedirect(request.getContextPath() + "/user-check/home"); + return; + } + + String referer = (String) request.getAttribute("origin"); + request.setAttribute("origin", referer); + UserCheckFilter.forward(request, response, "/login.jsp"); + } + + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + String key = request.getParameter("name"); + String pass = request.getParameter("password"); + + User user = User.DB.get(key); + if (user == null || !user.getPassword() + .equals(pass)) { + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + request.setAttribute("origin", request.getParameter("origin")); + request.setAttribute("error", "invalid login"); + UserCheckFilter.forward(request, response, "/login.jsp"); + return; + } + + user.getLogins() + .add(new Date()); + + HttpSession session = request.getSession(); + session.setAttribute("user", user); + + String origin = request.getParameter("origin"); + if (origin == null || origin.contains("login")) + origin = "./"; + + response.sendRedirect(origin); + } +} diff --git a/web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckLogoutServlet.java b/web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckLogoutServlet.java new file mode 100644 index 0000000000..42c0bb87ab --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckLogoutServlet.java @@ -0,0 +1,26 @@ +package com.baeldung.user.check; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +@WebServlet("/user-check/logout") +public class UserCheckLogoutServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + HttpSession session = request.getSession(false); + if (session != null) { + session.invalidate(); + } + + request.setAttribute("loggedOut", true); + response.sendRedirect("./"); + } +} diff --git a/web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckServlet.java b/web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckServlet.java new file mode 100644 index 0000000000..d7d5d1e762 --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/java/com/baeldung/user/check/UserCheckServlet.java @@ -0,0 +1,28 @@ +package com.baeldung.user.check; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +@WebServlet(name = "home", urlPatterns = { "/user-check/", "/user-check", "/user-check/home" }) +public class UserCheckServlet extends HttpServlet { + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + HttpSession session = request.getSession(false); + if (session == null || session.getAttribute("user") == null) { + throw new IllegalStateException("user not logged in"); + } + + User user = (User) session.getAttribute("user"); + request.setAttribute("user", user); + + UserCheckFilter.forward(request, response, "/home.jsp"); + } +} diff --git a/web-modules/javax-servlets-2/src/main/resources/logback.xml b/web-modules/javax-servlets-2/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/web-modules/javax-servlets-2/src/main/webapp/WEB-INF/user.check/home.jsp b/web-modules/javax-servlets-2/src/main/webapp/WEB-INF/user.check/home.jsp new file mode 100644 index 0000000000..4e17763552 --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/webapp/WEB-INF/user.check/home.jsp @@ -0,0 +1,31 @@ +<%@ page contentType="text/html;charset=UTF-8" session="false"%> +<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"%> + + + + login success - current session info + + +
+

user info

+
+ name: ${user.name} +
+ +
+ logins: +
    + +
  • ${login}
  • +
    +
+
+ +
+
+ + diff --git a/web-modules/javax-servlets-2/src/main/webapp/WEB-INF/user.check/login.jsp b/web-modules/javax-servlets-2/src/main/webapp/WEB-INF/user.check/login.jsp new file mode 100644 index 0000000000..19a857585d --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/webapp/WEB-INF/user.check/login.jsp @@ -0,0 +1,33 @@ +<%@ page contentType="text/html;charset=UTF-8" session="false"%> +<%@ taglib uri="http://java.sun.com/jstl/core_rt" prefix="c"%> + + + + login + + +
+ + +
* redirected to login from: ${origin}
+
+ + +
* error: ${error}
+
+ +
+ credentials + + + + + + + + +
+
+ + diff --git a/web-modules/javax-servlets-2/src/main/webapp/setparam/3rd_party_module.jsp b/web-modules/javax-servlets-2/src/main/webapp/setparam/3rd_party_module.jsp new file mode 100644 index 0000000000..9ab4fd2c00 --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/webapp/setparam/3rd_party_module.jsp @@ -0,0 +1,13 @@ +<%@ page import="java.util.*"%> + + + 3rd party Module + + + <% + String localeStr = request.getParameter("locale"); + Locale currentLocale = (localeStr != null ? new Locale(localeStr) : null); + %> + The language you have selected: <%=currentLocale != null ? currentLocale.getDisplayLanguage(currentLocale) : " None"%> + + \ No newline at end of file diff --git a/web-modules/javax-servlets-2/src/main/webapp/setparam/with-sanitize.jsp b/web-modules/javax-servlets-2/src/main/webapp/setparam/with-sanitize.jsp new file mode 100644 index 0000000000..68704d6133 --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/webapp/setparam/with-sanitize.jsp @@ -0,0 +1,10 @@ + + + Sanitized request parameter + + + The text below comes from request parameter "input": +
+ <%=request.getParameter("input")%> + + \ No newline at end of file diff --git a/web-modules/javax-servlets-2/src/main/webapp/setparam/without-sanitize.jsp b/web-modules/javax-servlets-2/src/main/webapp/setparam/without-sanitize.jsp new file mode 100644 index 0000000000..f5437164ef --- /dev/null +++ b/web-modules/javax-servlets-2/src/main/webapp/setparam/without-sanitize.jsp @@ -0,0 +1,10 @@ + + + Non sanitized request parameter + + + The text below comes from request parameter "input": +
+ <%=request.getParameter("input")%> + + \ No newline at end of file diff --git a/web-modules/javax-servlets-2/src/test/java/com/baeldung/servlets/TestUtil.java b/web-modules/javax-servlets-2/src/test/java/com/baeldung/servlets/TestUtil.java new file mode 100644 index 0000000000..e010de3a55 --- /dev/null +++ b/web-modules/javax-servlets-2/src/test/java/com/baeldung/servlets/TestUtil.java @@ -0,0 +1,678 @@ +package com.baeldung.servlets; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.security.Principal; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Map; + +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpUpgradeHandler; +import javax.servlet.http.Part; + +public class TestUtil { + + public static HttpServletRequest getRequest(Map params) { + return new HttpServletRequest() { + + @Override + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException { + // TODO Auto-generated method stub + return null; + } + + @Override + public AsyncContext startAsync() throws IllegalStateException { + // TODO Auto-generated method stub + return null; + } + + @Override + public void setCharacterEncoding(String env) throws UnsupportedEncodingException { + // TODO Auto-generated method stub + + } + + @Override + public void setAttribute(String name, Object o) { + // TODO Auto-generated method stub + + } + + @Override + public void removeAttribute(String name) { + // TODO Auto-generated method stub + + } + + @Override + public boolean isSecure() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isAsyncSupported() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isAsyncStarted() { + // TODO Auto-generated method stub + return false; + } + + @Override + public ServletContext getServletContext() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getServerPort() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getServerName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getScheme() { + // TODO Auto-generated method stub + return null; + } + + @Override + public RequestDispatcher getRequestDispatcher(String path) { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getRemotePort() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getRemoteHost() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRemoteAddr() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRealPath(String path) { + // TODO Auto-generated method stub + return null; + } + + @Override + public BufferedReader getReader() throws IOException { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getProtocol() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String[] getParameterValues(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getParameterNames() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Map getParameterMap() { + return params; + } + + @Override + public String getParameter(String name) { + String[] values = params.get(name); + if (values == null || values.length == 0) + return null; + return values[0]; + } + + @Override + public Enumeration getLocales() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Locale getLocale() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getLocalPort() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getLocalName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getLocalAddr() { + // TODO Auto-generated method stub + return null; + } + + @Override + public ServletInputStream getInputStream() throws IOException { + // TODO Auto-generated method stub + return null; + } + + @Override + public DispatcherType getDispatcherType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getContentType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public long getContentLengthLong() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public int getContentLength() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getCharacterEncoding() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getAttributeNames() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Object getAttribute(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public AsyncContext getAsyncContext() { + // TODO Auto-generated method stub + return null; + } + + @Override + public T upgrade(Class handlerClass) throws IOException, ServletException { + // TODO Auto-generated method stub + return null; + } + + @Override + public void logout() throws ServletException { + // TODO Auto-generated method stub + + } + + @Override + public void login(String username, String password) throws ServletException { + // TODO Auto-generated method stub + + } + + @Override + public boolean isUserInRole(String role) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isRequestedSessionIdValid() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isRequestedSessionIdFromUrl() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isRequestedSessionIdFromURL() { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean isRequestedSessionIdFromCookie() { + // TODO Auto-generated method stub + return false; + } + + @Override + public Principal getUserPrincipal() { + // TODO Auto-generated method stub + return null; + } + + @Override + public HttpSession getSession(boolean create) { + // TODO Auto-generated method stub + return null; + } + + @Override + public HttpSession getSession() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getServletPath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRequestedSessionId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public StringBuffer getRequestURL() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRequestURI() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getRemoteUser() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getQueryString() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getPathTranslated() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getPathInfo() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection getParts() throws IOException, ServletException { + // TODO Auto-generated method stub + return null; + } + + @Override + public Part getPart(String name) throws IOException, ServletException { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getMethod() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getIntHeader(String name) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public Enumeration getHeaders(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Enumeration getHeaderNames() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getHeader(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public long getDateHeader(String name) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public Cookie[] getCookies() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getContextPath() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getAuthType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String changeSessionId() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { + // TODO Auto-generated method stub + return false; + } + }; + } + + public static HttpServletResponse getResponse(StringWriter writer) { + + return new HttpServletResponse() { + + @Override + public void setLocale(Locale loc) { + // TODO Auto-generated method stub + + } + + @Override + public void setContentType(String type) { + // TODO Auto-generated method stub + + } + + @Override + public void setContentLengthLong(long len) { + // TODO Auto-generated method stub + + } + + @Override + public void setContentLength(int len) { + // TODO Auto-generated method stub + + } + + @Override + public void setCharacterEncoding(String charset) { + // TODO Auto-generated method stub + + } + + @Override + public void setBufferSize(int size) { + // TODO Auto-generated method stub + + } + + @Override + public void resetBuffer() { + // TODO Auto-generated method stub + + } + + @Override + public void reset() { + // TODO Auto-generated method stub + + } + + @Override + public boolean isCommitted() { + return true; + } + + @Override + public PrintWriter getWriter() throws IOException { + return new PrintWriter(writer, isCommitted()); + } + + @Override + public ServletOutputStream getOutputStream() throws IOException { + // TODO Auto-generated method stub + return null; + } + + @Override + public Locale getLocale() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getContentType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getCharacterEncoding() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getBufferSize() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public void flushBuffer() throws IOException { + // TODO Auto-generated method stub + + } + + @Override + public void setStatus(int sc, String sm) { + // TODO Auto-generated method stub + + } + + @Override + public void setStatus(int sc) { + // TODO Auto-generated method stub + + } + + @Override + public void setIntHeader(String name, int value) { + // TODO Auto-generated method stub + + } + + @Override + public void setHeader(String name, String value) { + // TODO Auto-generated method stub + + } + + @Override + public void setDateHeader(String name, long date) { + // TODO Auto-generated method stub + + } + + @Override + public void sendRedirect(String location) throws IOException { + // TODO Auto-generated method stub + + } + + @Override + public void sendError(int sc, String msg) throws IOException { + // TODO Auto-generated method stub + + } + + @Override + public void sendError(int sc) throws IOException { + // TODO Auto-generated method stub + + } + + @Override + public int getStatus() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public Collection getHeaders(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection getHeaderNames() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getHeader(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String encodeUrl(String url) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String encodeURL(String url) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String encodeRedirectUrl(String url) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String encodeRedirectURL(String url) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean containsHeader(String name) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void addIntHeader(String name, int value) { + // TODO Auto-generated method stub + + } + + @Override + public void addHeader(String name, String value) { + // TODO Auto-generated method stub + + } + + @Override + public void addDateHeader(String name, long date) { + // TODO Auto-generated method stub + + } + + @Override + public void addCookie(Cookie cookie) { + // TODO Auto-generated method stub + + } + }; + + } +} \ No newline at end of file diff --git a/web-modules/javax-servlets-2/src/test/java/com/baeldung/servlets/UserServletUnitTest.java b/web-modules/javax-servlets-2/src/test/java/com/baeldung/servlets/UserServletUnitTest.java new file mode 100644 index 0000000000..7c207d5be3 --- /dev/null +++ b/web-modules/javax-servlets-2/src/test/java/com/baeldung/servlets/UserServletUnitTest.java @@ -0,0 +1,93 @@ +package com.baeldung.servlets; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; + +import mockit.Expectations; +import mockit.Mocked; + +class UserServletUnitTest { + + private UserServlet servlet; + private StringWriter writer; + + @Mocked + HttpServletRequest mockRequest; + @Mocked + HttpServletResponse mockResponse; + + @BeforeEach + public void setUp() throws IOException { + servlet = new UserServlet(); + writer = new StringWriter(); + } + + @Test + void givenHttpServletRequest_whenUsingAnonymousClass_thenReturnsParameterValues() throws IOException { + final Map params = new HashMap<>(); + params.put("firstName", new String[] { "Anonymous Class" }); + params.put("lastName", new String[] { "Test" }); + + servlet.doGet(TestUtil.getRequest(params), TestUtil.getResponse(writer)); + + assertThat(writer.toString()).isEqualTo("Full Name: Anonymous Class Test"); + } + + @Test + void givenHttpServletRequest_whenMockedWithMockito_thenReturnsParameterValues() throws IOException { + // mock HttpServletRequest & HttpServletResponse + HttpServletRequest request = mock(HttpServletRequest.class); + HttpServletResponse response = mock(HttpServletResponse.class); + + // mock the returned value of request.getParameterMap() + when(request.getParameter("firstName")).thenReturn("Mockito"); + when(request.getParameter("lastName")).thenReturn("Test"); + when(response.getWriter()).thenReturn(new PrintWriter(writer)); + + servlet.doGet(request, response); + + assertThat(writer.toString()).isEqualTo("Full Name: Mockito Test"); + } + + @Test + void givenHttpServletRequest_whenMockedWithJMockit_thenReturnsParameterValues() throws IOException { + + new Expectations() {{ + mockRequest.getParameter("firstName"); result = "JMockit"; + mockRequest.getParameter("lastName"); result = "Test"; + mockResponse.getWriter(); result = new PrintWriter(writer); + }}; + + servlet.doGet(mockRequest, mockResponse); + + assertThat(writer.toString()).isEqualTo("Full Name: JMockit Test"); + } + + @Test + void givenHttpServletRequest_whenUsingMockHttpServletRequest_thenReturnsParameterValues() throws IOException { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setParameter("firstName", "Spring"); + request.setParameter("lastName", "Test"); + MockHttpServletResponse response = new MockHttpServletResponse(); + + servlet.doGet(request, response); + + assertThat(response.getContentAsString()).isEqualTo("Full Name: Spring Test"); + } + +} diff --git a/web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/LanguageServletLiveTest.java b/web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/LanguageServletLiveTest.java new file mode 100644 index 0000000000..c539ce63b9 --- /dev/null +++ b/web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/LanguageServletLiveTest.java @@ -0,0 +1,34 @@ +package com.baeldung.setparam; + +import static org.junit.Assert.assertTrue; + +import java.util.Locale; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.junit.Test; + +public class LanguageServletLiveTest { + + @Test + public void whenGetRequestUsingHttpClient_thenResponseBodyContainsDefaultLanguage() throws Exception { + + // When + HttpClient client = HttpClientBuilder.create().build(); + HttpGet method = new HttpGet("http://localhost:8080/setparam/lang"); + HttpResponse httpResponse = client.execute(method); + + // Then + Locale defaultLocale = Locale.getDefault(); + String expectedLanguage = defaultLocale.getDisplayLanguage(defaultLocale); + + HttpEntity entity = httpResponse.getEntity(); + String responseBody = EntityUtils.toString(entity, "UTF-8"); + assertTrue(responseBody.contains("The language you have selected: " + expectedLanguage)); + } + +} diff --git a/web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/SanitizeParametersRequestLiveTest.java b/web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/SanitizeParametersRequestLiveTest.java new file mode 100644 index 0000000000..5fffea1824 --- /dev/null +++ b/web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/SanitizeParametersRequestLiveTest.java @@ -0,0 +1,40 @@ +package com.baeldung.setparam; + +import static org.junit.Assert.assertTrue; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.junit.BeforeClass; +import org.junit.Test; + +public class SanitizeParametersRequestLiveTest { + + private static String PARAM_INPUT; + + @BeforeClass + public static void init() throws UnsupportedEncodingException { + PARAM_INPUT = URLEncoder.encode("", "UTF-8"); + } + + @Test + public void whenInputParameterContainsXss_thenResponseBodyContainsSanitizedValue() throws Exception { + + // When + HttpClient client = HttpClientBuilder.create().build(); + HttpGet method = new HttpGet(String.format("http://localhost:8080/setparam/with-sanitize.jsp?input=%s", PARAM_INPUT)); + HttpResponse httpResponse = client.execute(method); + + // Then + HttpEntity entity = httpResponse.getEntity(); + String responseBody = EntityUtils.toString(entity, "UTF-8"); + assertTrue(responseBody.contains("<script>alert('Hello');</script>")); + } + +} \ No newline at end of file diff --git a/web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/SanitizeParametersRequestWrapperUnitTest.java b/web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/SanitizeParametersRequestWrapperUnitTest.java new file mode 100644 index 0000000000..029cf41d1c --- /dev/null +++ b/web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/SanitizeParametersRequestWrapperUnitTest.java @@ -0,0 +1,60 @@ +package com.baeldung.setparam; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class SanitizeParametersRequestWrapperUnitTest { + + private static final String NEW_VALUE = "NEW VALUE"; + + private Map parameterMap; + + @Mock + private HttpServletRequest request; + + @Before + public void initBeforeEachTest() { + parameterMap = new HashMap<>(); + parameterMap.put("input", new String[] {""}); + when(request.getParameterMap()).thenReturn(parameterMap); + } + + @Test + public void whenGetParameterViaWrapper_thenParameterReturnedIsSanitized() { + SanitizeParametersRequestWrapper wrapper = new SanitizeParametersRequestWrapper(request); + String actualValue = wrapper.getParameter("input"); + + assertEquals("<script>alert('Hello');</script>", actualValue); + } + + @Test(expected = UnsupportedOperationException.class) + public void whenPutValueToWrapperParameterMap_thenThrowsUnsupportedOperationException() { + SanitizeParametersRequestWrapper wrapper = new SanitizeParametersRequestWrapper(request); + Map wrapperParamMap = wrapper.getParameterMap(); + wrapperParamMap.put("input", new String[] {NEW_VALUE}); + } + + @Test + public void whenSetValueToWrapperParametersStringArray_thenThe2ndCallShouldNotEqualToNewValue() { + SanitizeParametersRequestWrapper wrapper = new SanitizeParametersRequestWrapper(request); + String[] firstCallValues = wrapper.getParameterValues("input"); + + firstCallValues[0] = NEW_VALUE; + String[] secondCallValues = wrapper.getParameterValues("input"); + assertThat(secondCallValues).doesNotContain(NEW_VALUE); + } + +} \ No newline at end of file diff --git a/web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/SetParameterRequestWrapperUnitTest.java b/web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/SetParameterRequestWrapperUnitTest.java new file mode 100644 index 0000000000..8ef5307d44 --- /dev/null +++ b/web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/SetParameterRequestWrapperUnitTest.java @@ -0,0 +1,61 @@ +package com.baeldung.setparam; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class SetParameterRequestWrapperUnitTest { + + private static final String NEW_VALUE = "NEW VALUE"; + + private Map parameterMap; + + @Mock + private HttpServletRequest request; + + @Before + public void initBeforeEachTest() { + parameterMap = new HashMap<>(); + parameterMap.put("input", new String[] {"inputValue"}); + when(request.getParameterMap()).thenReturn(parameterMap); + } + + @Test + public void whenSetParameterViaWrapper_thenGetParameterShouldReturnTheSameValue() { + SetParameterRequestWrapper wrapper = new SetParameterRequestWrapper(request); + wrapper.setParameter("newInput", "newInputValue"); + String actualValue = wrapper.getParameter("newInput"); + + assertEquals("newInputValue", actualValue); + } + + @Test(expected = UnsupportedOperationException.class) + public void whenPutValueToWrapperParameterMap_thenThrowsUnsupportedOperationException() { + SetParameterRequestWrapper wrapper = new SetParameterRequestWrapper(request); + Map wrapperParamMap = wrapper.getParameterMap(); + wrapperParamMap.put("input", new String[] {NEW_VALUE}); + } + + @Test + public void whenSetValueToWrapperParametersStringArray_thenThe2ndCallShouldNotEqualToNewValue() { + SetParameterRequestWrapper wrapper = new SetParameterRequestWrapper(request); + String[] firstCallValues = wrapper.getParameterValues("input"); + + firstCallValues[0] = NEW_VALUE; + String[] secondCallValues = wrapper.getParameterValues("input"); + assertThat(secondCallValues).doesNotContain(NEW_VALUE); + } + +} \ No newline at end of file diff --git a/web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/UnsanitizedParametersRequestLiveTest.java b/web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/UnsanitizedParametersRequestLiveTest.java new file mode 100644 index 0000000000..f6cc566bfc --- /dev/null +++ b/web-modules/javax-servlets-2/src/test/java/com/baeldung/setparam/UnsanitizedParametersRequestLiveTest.java @@ -0,0 +1,42 @@ +package com.baeldung.setparam; + +import static org.junit.Assert.assertTrue; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.util.EntityUtils; +import org.junit.BeforeClass; +import org.junit.Test; + +public class UnsanitizedParametersRequestLiveTest { + + private static final String TAG_SCRIPT = ""; + + private static String PARAM_INPUT; + + @BeforeClass + public static void init() throws UnsupportedEncodingException { + PARAM_INPUT = URLEncoder.encode(TAG_SCRIPT, "UTF-8"); + } + + @Test + public void whenInputParameterContainsXss_thenResponseBodyContainsUnsanitizedValue() throws Exception { + + // When + HttpClient client = HttpClientBuilder.create().build(); + HttpGet method = new HttpGet(String.format("http://localhost:8080/setparam/without-sanitize.jsp?input=%s", PARAM_INPUT)); + HttpResponse httpResponse = client.execute(method); + + // Then + HttpEntity entity = httpResponse.getEntity(); + String responseBody = EntityUtils.toString(entity, "UTF-8"); + assertTrue(responseBody.contains(TAG_SCRIPT)); + } + +} \ No newline at end of file diff --git a/web-modules/javax-servlets-2/src/test/java/com/baeldung/user/check/UserCheckServletLiveTest.java b/web-modules/javax-servlets-2/src/test/java/com/baeldung/user/check/UserCheckServletLiveTest.java new file mode 100644 index 0000000000..42858d61e7 --- /dev/null +++ b/web-modules/javax-servlets-2/src/test/java/com/baeldung/user/check/UserCheckServletLiveTest.java @@ -0,0 +1,98 @@ +package com.baeldung.user.check; + +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.impl.client.LaxRedirectStrategy; +import org.apache.http.message.BasicNameValuePair; +import org.apache.http.util.EntityUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class UserCheckServletLiveTest { + private static final String BASE_URL = "http://localhost:8080/javax-servlets-2/user-check"; + + @Mock + HttpServletRequest request; + + @Mock + HttpServletResponse response; + + private CloseableHttpClient buildClient() { + return HttpClientBuilder.create() + .setRedirectStrategy(new LaxRedirectStrategy()) + .build(); + } + + @Test + public void whenCorrectCredentials_thenLoginSucceeds() throws Exception { + try (CloseableHttpClient client = buildClient()) { + HttpPost post = new HttpPost(BASE_URL + "/login"); + + List form = new ArrayList<>(); + form.add(new BasicNameValuePair("name", "admin")); + form.add(new BasicNameValuePair("password", "password")); + + post.setEntity(new UrlEncodedFormEntity(form)); + try (CloseableHttpResponse response = client.execute(post)) { + String body = EntityUtils.toString(response.getEntity()); + + assertTrue(response.getStatusLine() + .getStatusCode() == 200); + + assertTrue(body.contains("login success")); + } + } + } + + @Test + public void whenIncorrectCredentials_thenLoginFails() throws Exception { + try (CloseableHttpClient client = buildClient()) { + HttpPost post = new HttpPost(BASE_URL + "/login"); + + List form = new ArrayList<>(); + form.add(new BasicNameValuePair("name", "admin")); + form.add(new BasicNameValuePair("password", "invalid")); + + post.setEntity(new UrlEncodedFormEntity(form)); + try (CloseableHttpResponse response = client.execute(post)) { + String body = EntityUtils.toString(response.getEntity()); + + assertTrue(response.getStatusLine() + .getStatusCode() == 401); + + assertTrue(body.contains("invalid login")); + } + } + } + + @Test + public void whenNotLoggedIn_thenRedirectedToLoginPage() throws Exception { + try (CloseableHttpClient client = buildClient()) { + HttpGet get = new HttpGet(BASE_URL + "/home"); + + try (CloseableHttpResponse response = client.execute(get)) { + String body = EntityUtils.toString(response.getEntity()); + + assertTrue(response.getStatusLine() + .getStatusCode() == 401); + + assertTrue(body.contains("redirected to login")); + } + } + } +} diff --git a/web-modules/javax-servlets/README.md b/web-modules/javax-servlets/README.md new file mode 100644 index 0000000000..bda7cd19e3 --- /dev/null +++ b/web-modules/javax-servlets/README.md @@ -0,0 +1,15 @@ +## Servlets + +This module contains articles about Servlets. + +### Relevant Articles: +- [Introduction to Java Servlets](https://www.baeldung.com/intro-to-servlets) +- [An MVC Example with Servlets and JSP](https://www.baeldung.com/mvc-servlet-jsp) +- [Handling Cookies and a Session in a Java Servlet](https://www.baeldung.com/java-servlet-cookies-session) +- [Uploading Files with Servlets and JSP](https://www.baeldung.com/upload-file-servlet) +- [Example of Downloading File in a Servlet](https://www.baeldung.com/servlet-download-file) +- [Returning a JSON Response from a Servlet](https://www.baeldung.com/servlet-json-response) +- [Jakarta EE Servlet Exception Handling](https://www.baeldung.com/servlet-exceptions) +- [Context and Servlet Initialization Parameters](https://www.baeldung.com/context-servlet-initialization-param) +- [The Difference between getRequestURI and getPathInfo in HttpServletRequest](https://www.baeldung.com/http-servlet-request-requesturi-pathinfo) +- [Difference Between request.getSession() and request.getSession(true)](https://www.baeldung.com/java-request-getsession) diff --git a/web-modules/javax-servlets/pom.xml b/web-modules/javax-servlets/pom.xml new file mode 100644 index 0000000000..80a1e3af9f --- /dev/null +++ b/web-modules/javax-servlets/pom.xml @@ -0,0 +1,55 @@ + + + 4.0.0 + com.baeldung.javax-servlets + javax-servlets + 1.0-SNAPSHOT + javax-servlets + war + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + + commons-fileupload + commons-fileupload + ${commons-fileupload.version} + + + + javax.servlet + javax.servlet-api + ${javax.servlet-api.version} + + + org.apache.httpcomponents + httpclient + ${org.apache.httpcomponents.version} + test + + + commons-logging + commons-logging + + + + + com.google.code.gson + gson + ${gson.version} + + + + + 4.5.3 + 2.8.2 + + + \ No newline at end of file diff --git a/web-modules/javax-servlets/src/main/java/com/baeldung/servlets/FormServlet.java b/web-modules/javax-servlets/src/main/java/com/baeldung/servlets/FormServlet.java new file mode 100644 index 0000000000..72a2b39a67 --- /dev/null +++ b/web-modules/javax-servlets/src/main/java/com/baeldung/servlets/FormServlet.java @@ -0,0 +1,39 @@ +package com.baeldung.servlets; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@WebServlet(name = "FormServlet", urlPatterns = "/calculateServlet") +public class FormServlet extends HttpServlet { + + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + + String height = request.getParameter("height"); + String weight = request.getParameter("weight"); + try { + double bmi = calculateBMI(Double.parseDouble(weight), Double.parseDouble(height)); + request.setAttribute("bmi", bmi); + response.setHeader("Test", "Success"); + response.setHeader("BMI", String.valueOf(bmi)); + request.getRequestDispatcher("/WEB-INF/jsp/index.jsp").forward(request, response); + } catch (Exception e) { + request.getRequestDispatcher("/WEB-INF/jsp/index.jsp").forward(request, response); + } + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + RequestDispatcher dispatcher = request.getRequestDispatcher("/WEB-INF/jsp/index.jsp"); + dispatcher.forward(request, response); + } + + private Double calculateBMI(Double weight, Double height) { + return weight / (height * height); + } +} \ No newline at end of file diff --git a/web-modules/javax-servlets/src/main/java/com/baeldung/servlets/MainServlet.java b/web-modules/javax-servlets/src/main/java/com/baeldung/servlets/MainServlet.java new file mode 100644 index 0000000000..198920cb23 --- /dev/null +++ b/web-modules/javax-servlets/src/main/java/com/baeldung/servlets/MainServlet.java @@ -0,0 +1,21 @@ +package com.baeldung.servlets; + +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebServlet("/main") +public class MainServlet extends HttpServlet { + + + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + request.getRequestDispatcher("/WEB-INF/jsp/main.jsp").forward(request, response); + } + + + + +} diff --git a/web-modules/javax-servlets/src/main/java/com/baeldung/servlets/UpdateServlet.java b/web-modules/javax-servlets/src/main/java/com/baeldung/servlets/UpdateServlet.java new file mode 100644 index 0000000000..8582a1ccef --- /dev/null +++ b/web-modules/javax-servlets/src/main/java/com/baeldung/servlets/UpdateServlet.java @@ -0,0 +1,31 @@ +package com.baeldung.servlets; + +import java.io.IOException; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +@WebServlet("/update") +public class UpdateServlet extends HttpServlet { + + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + + HttpSession session = request.getSession(false); + + if (session != null) { + + session.setAttribute("userName", request.getParameter("userName")); + session.setAttribute("age", request.getParameter("age")); + + request.setAttribute("sessionData", session); + } + + request.getRequestDispatcher("/WEB-INF/jsp/update.jsp").forward(request, response); + } + +} diff --git a/web-modules/javax-servlets/src/main/java/com/baeldung/servlets/UserLoginServlet.java b/web-modules/javax-servlets/src/main/java/com/baeldung/servlets/UserLoginServlet.java new file mode 100644 index 0000000000..25ec6a8f59 --- /dev/null +++ b/web-modules/javax-servlets/src/main/java/com/baeldung/servlets/UserLoginServlet.java @@ -0,0 +1,28 @@ +package com.baeldung.servlets; + + +import java.io.IOException; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +@WebServlet("/u_login") +public class UserLoginServlet extends HttpServlet { + + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + HttpSession session = request.getSession(); + + session.setAttribute("userId", request.getParameter("userId")); + + request.setAttribute("id", session.getAttribute("userId")); + + request.getRequestDispatcher("/WEB-INF/jsp/userlogin.jsp").forward(request, response); + + } + +} diff --git a/web-modules/javax-servlets/src/main/java/com/baeldung/servlets/UserServlet.java b/web-modules/javax-servlets/src/main/java/com/baeldung/servlets/UserServlet.java new file mode 100644 index 0000000000..75977b0660 --- /dev/null +++ b/web-modules/javax-servlets/src/main/java/com/baeldung/servlets/UserServlet.java @@ -0,0 +1,49 @@ +package com.baeldung.servlets; + +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebInitParam; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebServlet(name = "UserServlet", urlPatterns = "/userServlet", initParams={ + @WebInitParam(name="name", value="Not provided"), + @WebInitParam(name="email", value="Not provided")}) +public class UserServlet extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + processRequest(request, response); + forwardRequest(request, response, "/WEB-INF/jsp/result.jsp"); + } + + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + } + + protected void processRequest(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + request.setAttribute("name", getRequestParameter(request, "name")); + request.setAttribute("email", getRequestParameter(request, "email")); + request.setAttribute("province", getContextParameter("province")); + request.setAttribute("country", getContextParameter("country")); + } + + protected String getRequestParameter(HttpServletRequest request, String name) { + String param = request.getParameter(name); + return !param.isEmpty() ? param : getInitParameter(name); + } + + protected String getContextParameter(String name) { + return getServletContext().getInitParameter(name); + } + + protected void forwardRequest(HttpServletRequest request, HttpServletResponse response, String path) + throws ServletException, IOException { + request.getRequestDispatcher(path).forward(request, response); + } +} \ No newline at end of file diff --git a/web-modules/javax-servlets/src/main/resources/logback.xml b/web-modules/javax-servlets/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/web-modules/javax-servlets/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/main.jsp b/web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/main.jsp new file mode 100644 index 0000000000..313310a2a9 --- /dev/null +++ b/web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/main.jsp @@ -0,0 +1,15 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + + + +
+

Enter your User Id and Password

+ User ID:
+ Password:
+
+ + \ No newline at end of file diff --git a/web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/result.jsp b/web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/result.jsp new file mode 100644 index 0000000000..7259b96ed0 --- /dev/null +++ b/web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/result.jsp @@ -0,0 +1,15 @@ +<%@ page contentType="text/html" pageEncoding="UTF-8"%> + + + + + User Data + + +

User Information

+

Name: ${name}

+

Email: ${email}

+

Province: ${province}

+

Country: ${country}

+ + diff --git a/web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/update.jsp b/web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/update.jsp new file mode 100644 index 0000000000..fae5ea2ac2 --- /dev/null +++ b/web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/update.jsp @@ -0,0 +1,17 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + + + + + Hi, User : ${sessionData.getAttribute("userId")} + +
Your User Data has been updated as below : +
User Name: ${sessionData.getAttribute("userName")} +
Age : ${sessionData.getAttribute("age")} + + + \ No newline at end of file diff --git a/web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/userlogin.jsp b/web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/userlogin.jsp new file mode 100644 index 0000000000..b2a550b811 --- /dev/null +++ b/web-modules/javax-servlets/src/main/webapp/WEB-INF/jsp/userlogin.jsp @@ -0,0 +1,18 @@ +<%@ page language="java" contentType="text/html; charset=ISO-8859-1" + pageEncoding="ISO-8859-1"%> + + + + + + +

Update your User Details:

+ +
+ User ID:
User Name: + Age:
+
+ + \ No newline at end of file diff --git a/web-modules/javax-servlets/src/main/webapp/user.jsp b/web-modules/javax-servlets/src/main/webapp/user.jsp new file mode 100644 index 0000000000..2139052a3a --- /dev/null +++ b/web-modules/javax-servlets/src/main/webapp/user.jsp @@ -0,0 +1,18 @@ +<%@ page contentType="text/html" pageEncoding="UTF-8"%> + + + + Context and Servlet Initialization Parameters + + + +

Please fill the form below:

+
+ + + + + +
+ + diff --git a/web-modules/javax-servlets/src/test/java/com/baeldung/test/UserServletUnitTest.java b/web-modules/javax-servlets/src/test/java/com/baeldung/test/UserServletUnitTest.java new file mode 100644 index 0000000000..ef3d877dd7 --- /dev/null +++ b/web-modules/javax-servlets/src/test/java/com/baeldung/test/UserServletUnitTest.java @@ -0,0 +1,52 @@ +package com.baeldung.test; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.BeforeClass; +import org.junit.Test; +import static org.mockito.Mockito.atLeast; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class UserServletUnitTest { + + private static HttpServletRequest request; + private static HttpServletResponse response; + + + @BeforeClass + public static void setUpHttpServletRequestMockInstance() { + request = mock(HttpServletRequest.class); + } + + @BeforeClass + public static void setUpHttpServletResponsetMockInstance() { + response = mock(HttpServletResponse.class); + } + + @Test + public void givenHttpServletRequestMockInstance_whenCalledgetParameter_thenCalledAtLeastOnce() { + request.getParameter("name"); + verify(request, atLeast(1)).getParameter("name"); + } + + @Test + public void givenHttpServletRequestMockInstance_whenCalledgetParameter_thenOneAssertion() { + when(request.getParameter("name")).thenReturn("username"); + assertThat(request.getParameter("name")).isEqualTo("username"); + } + + @Test + public void givenHttpServletResponseMockInstance_whenCalledgetContentType_thenCalledAtLeastOnce() { + response.getContentType(); + verify(response, atLeast(1)).getContentType(); + } + + @Test + public void givenHttpServletResponseMockInstance_whenCalledgetContentType_thenOneAssertion() { + when(response.getContentType()).thenReturn("text/html"); + assertThat(response.getContentType()).isEqualTo("text/html"); + } +} \ No newline at end of file diff --git a/web-modules/jee-7/README.md b/web-modules/jee-7/README.md new file mode 100644 index 0000000000..88359a81ec --- /dev/null +++ b/web-modules/jee-7/README.md @@ -0,0 +1,14 @@ +## JEE 7 + +This module contains articles about JEE 7. + +### Relevant Articles: +- [Scheduling in Jakarta EE](https://www.baeldung.com/scheduling-in-java-enterprise-edition) +- [JSON Processing in Java EE 7](https://www.baeldung.com/jee7-json) +- [Converters, Listeners and Validators in Java EE 7](https://www.baeldung.com/java-ee7-converter-listener-validator) +- [Introduction to JAX-WS](https://www.baeldung.com/jax-ws) +- [A Guide to Java EE Web-Related Annotations](https://www.baeldung.com/javaee-web-annotations) +- [Introduction to Testing with Arquillian](https://www.baeldung.com/arquillian) +- [Java EE 7 Batch Processing](https://www.baeldung.com/java-ee-7-batch-processing) +- [The Difference Between CDI and EJB Singleton](https://www.baeldung.com/jee-cdi-vs-ejb-singleton) +- [Invoking a SOAP Web Service in Java](https://www.baeldung.com/java-soap-web-service) diff --git a/web-modules/jee-7/pom.xml b/web-modules/jee-7/pom.xml new file mode 100644 index 0000000000..b26027d9bf --- /dev/null +++ b/web-modules/jee-7/pom.xml @@ -0,0 +1,542 @@ + + + 4.0.0 + com.baeldung.jee-7 + jee-7 + 1.0-SNAPSHOT + jee-7 + war + JavaEE 7 Arquillian Archetype Sample + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + + org.jboss.arquillian + arquillian-bom + ${arquillian_core.version} + import + pom + + + org.jboss.arquillian.extension + arquillian-drone-bom + ${arquillian-drone-bom.version} + pom + import + + + + + + + javax + javaee-api + ${javaee_api.version} + provided + + + org.jboss.arquillian.junit + arquillian-junit-container + test + + + org.jboss.arquillian.graphene + graphene-webdriver + ${graphene-webdriver.version} + pom + test + + + com.jayway.awaitility + awaitility + ${awaitility.version} + test + + + org.jboss.shrinkwrap.resolver + shrinkwrap-resolver-impl-maven + test + jar + + + org.jboss.shrinkwrap.resolver + shrinkwrap-resolver-impl-maven-archive + test + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + commons-io + commons-io + ${commons-io.version} + + + com.sun.faces + jsf-api + ${com.sun.faces.jsf.version} + + + com.sun.faces + jsf-impl + ${com.sun.faces.jsf.version} + + + javax.servlet + jstl + ${jstl.version} + + + javax.servlet + javax.servlet-api + ${javax.servlet-api.version} + + + javax.servlet.jsp + jsp-api + ${jsp-api.version} + provided + + + taglibs + standard + ${taglibs.standard.version} + + + javax.mvc + javax.mvc-api + ${mvc.api.version} + + + org.glassfish.ozark + ozark + ${ozark.version} + + + org.springframework.security + spring-security-web + ${org.springframework.security.version} + + + org.springframework.security + spring-security-config + ${org.springframework.security.version} + + + org.springframework.security + spring-security-taglibs + ${org.springframework.security.version} + + + + org.jboss.spec.javax.batch + jboss-batch-api_1.0_spec + ${jboss-batch-api.version} + + + org.jberet + jberet-core + ${jberet.version} + + + org.jberet + jberet-support + ${jberet.version} + + + org.jboss.spec.javax.transaction + jboss-transaction-api_1.2_spec + ${jboss-transaction-api.version} + + + org.jboss.marshalling + jboss-marshalling + ${jboss-marshalling.version} + + + org.jboss.weld + weld-core + ${weld.version} + + + org.jboss.weld.se + weld-se + ${weld.version} + + + org.jberet + jberet-se + ${jberet.version} + + + com.h2database + h2 + ${h2.version} + + + org.glassfish.jersey.containers + jersey-container-jetty-servlet + ${jersey-container-jetty-servlet.version} + + + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + src/main/webapp + false + + + + + + + + + org.eclipse.m2e + lifecycle-mapping + ${lifecycle.mapping.version} + + + + + + + org.apache.maven.plugins + + + maven-pmd-plugin + + + [3.8,) + + + check + + + + + + + + + + + + + org.codehaus.mojo + jaxws-maven-plugin + 2.6 + + + wsimport-from-jdk + + wsimport + + + + + + http://localhost:8888/ws/country?wsdl + + true + com.baeldung.soap.ws.client.generated + src/main/java + + + + org.apache.maven.plugins + maven-surefire-plugin + + + --add-opens java.base/java.lang=ALL-UNNAMED + --add-opens=java.base/java.lang.reflect=ALL-UNNAMED + --add-opens java.base/java.io=ALL-UNNAMED + + + + + + + + + + wildfly-managed-arquillian + + true + + + + io.undertow + undertow-websockets-jsr + ${undertow-websockets-jsr.version} + test + + + org.jboss.resteasy + resteasy-client + ${resteasy.version} + test + + + org.jboss.resteasy + resteasy-jaxb-provider + ${resteasy.version} + test + + + org.jboss.resteasy + resteasy-json-p-provider + ${resteasy.version} + test + + + org.wildfly + wildfly-arquillian-container-managed + ${wildfly.version} + test + + + sun.jdk + jconsole + + + + + + + + + maven-dependency-plugin + ${maven-dependency-plugin.version} + + ${maven.test.skip} + + + + unpack + process-test-classes + + unpack + + + + + org.wildfly + wildfly-dist + ${wildfly.version} + zip + false + ${project.build.directory} + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + wildfly-remote-arquillian + + + io.undertow + undertow-websockets-jsr + ${undertow-websockets-jsr.version} + test + + + org.jboss.resteasy + resteasy-client + ${resteasy.version} + test + + + org.jboss.resteasy + resteasy-jaxb-provider + ${resteasy.version} + test + + + org.jboss.resteasy + resteasy-json-p-provider + ${resteasy.version} + test + + + org.wildfly + wildfly-arquillian-container-remote + ${wildfly.version} + test + + + sun.jdk + jconsole + + + + + + + glassfish-embedded-arquillian + + + org.glassfish.main.extras + glassfish-embedded-all + ${glassfish-embedded-all.version} + test + + + org.glassfish + javax.json + ${javax.json.version} + test + + + org.glassfish.tyrus + tyrus-client + ${tyrus.version} + test + + + org.glassfish.tyrus + tyrus-container-grizzly-client + ${tyrus.version} + test + + + org.glassfish.jersey.core + jersey-client + ${jersey.version} + test + + + org.jboss.arquillian.container + arquillian-glassfish-embedded-3.1 + ${arquillian-glassfish.version} + test + + + + + glassfish-remote-arquillian + + + org.glassfish + javax.json + ${javax.json.version} + test + + + org.glassfish.tyrus + tyrus-client + ${tyrus.version} + test + + + org.glassfish.tyrus + tyrus-container-grizzly-client + ${tyrus.version} + test + + + org.glassfish.jersey.core + jersey-client + ${jersey.version} + test + + + org.glassfish.jersey.media + jersey-media-json-jackson + ${jersey.version} + test + + + org.glassfish.jersey.media + jersey-media-json-processing + ${jersey.version} + test + + + org.jboss.arquillian.container + arquillian-glassfish-remote-3.1 + ${arquillian-glassfish.version} + test + + + + + webdriver-chrome + + true + + + chrome + + + + webdriver-firefox + + firefox + + + + + + 1.0.0 + 1.0-edr2 + 1.8 + 3.0.0 + 7.0 + 1.1.11.Final + 8.2.1.Final + 1.7.0 + 1.4.6.Final + 3.0.19.Final + 4.1.1 + 1.0.4 + 1.13 + 2.25 + 1.0.0.Final + 4.2.3.RELEASE + 1.1.2 + 2.2.14 + 4.5 + 2.0.1.Final + 2.1.0.Final + 2.8 + 2.2 + 1.0.0-m02 + 1.0.0.Final + 1.0.2.Final + 1.0.0.Final + 2.1.1.Final + 2.1.1.Final + 2.22.1 + + + \ No newline at end of file diff --git a/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Country.java b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Country.java new file mode 100644 index 0000000000..6a810b9afa --- /dev/null +++ b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Country.java @@ -0,0 +1,129 @@ + +package com.baeldung.soap.ws.client.generated; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + +/** + *

Java class for country complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="country">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="capital" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="currency" type="{http://server.ws.soap.baeldung.com/}currency" minOccurs="0"/>
+ *         <element name="name" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         <element name="population" type="{http://www.w3.org/2001/XMLSchema}int"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "country", propOrder = { "capital", "currency", "name", "population" }) +public class Country { + + protected String capital; + @XmlSchemaType(name = "string") + protected Currency currency; + protected String name; + protected int population; + + /** + * Gets the value of the capital property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getCapital() { + return capital; + } + + /** + * Sets the value of the capital property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setCapital(String value) { + this.capital = value; + } + + /** + * Gets the value of the currency property. + * + * @return + * possible object is + * {@link Currency } + * + */ + public Currency getCurrency() { + return currency; + } + + /** + * Sets the value of the currency property. + * + * @param value + * allowed object is + * {@link Currency } + * + */ + public void setCurrency(Currency value) { + this.currency = value; + } + + /** + * Gets the value of the name property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the population property. + * + */ + public int getPopulation() { + return population; + } + + /** + * Sets the value of the population property. + * + */ + public void setPopulation(int value) { + this.population = value; + } + +} diff --git a/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryService.java b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryService.java new file mode 100644 index 0000000000..bda4a305a5 --- /dev/null +++ b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryService.java @@ -0,0 +1,34 @@ + +package com.baeldung.soap.ws.client.generated; + +import javax.jws.WebMethod; +import javax.jws.WebParam; +import javax.jws.WebResult; +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; +import javax.xml.bind.annotation.XmlSeeAlso; +import javax.xml.ws.Action; + +/** + * This class was generated by the JAX-WS RI. + * JAX-WS RI 2.3.2 + * Generated source version: 2.2 + * + */ +@WebService(name = "CountryService", targetNamespace = "http://server.ws.soap.baeldung.com/") +@SOAPBinding(style = SOAPBinding.Style.RPC) +@XmlSeeAlso({ ObjectFactory.class }) +public interface CountryService { + + /** + * + * @param arg0 + * @return + * returns com.baeldung.soap.ws.client.generated.Country + */ + @WebMethod + @WebResult(partName = "return") + @Action(input = "http://server.ws.soap.baeldung.com/CountryService/findByNameRequest", output = "http://server.ws.soap.baeldung.com/CountryService/findByNameResponse") + public Country findByName(@WebParam(name = "arg0", partName = "arg0") String arg0); + +} diff --git a/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryServiceImplService.java b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryServiceImplService.java new file mode 100644 index 0000000000..a6983938f5 --- /dev/null +++ b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/CountryServiceImplService.java @@ -0,0 +1,91 @@ + +package com.baeldung.soap.ws.client.generated; + +import java.net.MalformedURLException; +import java.net.URL; +import javax.xml.namespace.QName; +import javax.xml.ws.Service; +import javax.xml.ws.WebEndpoint; +import javax.xml.ws.WebServiceClient; +import javax.xml.ws.WebServiceException; +import javax.xml.ws.WebServiceFeature; + +/** + * This class was generated by the JAX-WS RI. + * JAX-WS RI 2.2.9-b130926.1035 + * Generated source version: 2.2 + * + */ +@WebServiceClient(name = "CountryServiceImplService", targetNamespace = "http://server.ws.soap.baeldung.com/", wsdlLocation = "http://localhost:8888/ws/country?wsdl") +public class CountryServiceImplService extends Service { + + private final static URL COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION; + private final static WebServiceException COUNTRYSERVICEIMPLSERVICE_EXCEPTION; + private final static QName COUNTRYSERVICEIMPLSERVICE_QNAME = new QName("http://server.ws.soap.baeldung.com/", "CountryServiceImplService"); + + static { + URL url = null; + WebServiceException e = null; + try { + url = new URL("http://localhost:8888/ws/country?wsdl"); + } catch (MalformedURLException ex) { + e = new WebServiceException(ex); + } + COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION = url; + COUNTRYSERVICEIMPLSERVICE_EXCEPTION = e; + } + + public CountryServiceImplService() { + super(__getWsdlLocation(), COUNTRYSERVICEIMPLSERVICE_QNAME); + } + + public CountryServiceImplService(WebServiceFeature... features) { + super(__getWsdlLocation(), COUNTRYSERVICEIMPLSERVICE_QNAME, features); + } + + public CountryServiceImplService(URL wsdlLocation) { + super(wsdlLocation, COUNTRYSERVICEIMPLSERVICE_QNAME); + } + + public CountryServiceImplService(URL wsdlLocation, WebServiceFeature... features) { + super(wsdlLocation, COUNTRYSERVICEIMPLSERVICE_QNAME, features); + } + + public CountryServiceImplService(URL wsdlLocation, QName serviceName) { + super(wsdlLocation, serviceName); + } + + public CountryServiceImplService(URL wsdlLocation, QName serviceName, WebServiceFeature... features) { + super(wsdlLocation, serviceName, features); + } + + /** + * + * @return + * returns CountryService + */ + @WebEndpoint(name = "CountryServiceImplPort") + public CountryService getCountryServiceImplPort() { + return super.getPort(new QName("http://server.ws.soap.baeldung.com/", "CountryServiceImplPort"), CountryService.class); + } + + /** + * + * @param features + * A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the features parameter will have their default values. + * @return + * returns CountryService + */ + @WebEndpoint(name = "CountryServiceImplPort") + public CountryService getCountryServiceImplPort(WebServiceFeature... features) { + return super.getPort(new QName("http://server.ws.soap.baeldung.com/", "CountryServiceImplPort"), CountryService.class, features); + } + + private static URL __getWsdlLocation() { + if (COUNTRYSERVICEIMPLSERVICE_EXCEPTION != null) { + throw COUNTRYSERVICEIMPLSERVICE_EXCEPTION; + } + return COUNTRYSERVICEIMPLSERVICE_WSDL_LOCATION; + } + +} diff --git a/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Currency.java b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Currency.java new file mode 100644 index 0000000000..8b9355edc5 --- /dev/null +++ b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/Currency.java @@ -0,0 +1,37 @@ + +package com.baeldung.soap.ws.client.generated; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlType; + +/** + *

Java class for currency. + * + *

The following schema fragment specifies the expected content contained within this class. + *

+ *

+ * <simpleType name="currency">
+ *   <restriction base="{http://www.w3.org/2001/XMLSchema}string">
+ *     <enumeration value="EUR"/>
+ *     <enumeration value="INR"/>
+ *     <enumeration value="USD"/>
+ *   </restriction>
+ * </simpleType>
+ * 
+ * + */ +@XmlType(name = "currency") +@XmlEnum +public enum Currency { + + EUR, INR, USD; + + public String value() { + return name(); + } + + public static Currency fromValue(String v) { + return valueOf(v); + } + +} diff --git a/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/ObjectFactory.java b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/ObjectFactory.java new file mode 100644 index 0000000000..241debe758 --- /dev/null +++ b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/ObjectFactory.java @@ -0,0 +1,38 @@ + +package com.baeldung.soap.ws.client.generated; + +import javax.xml.bind.annotation.XmlRegistry; + +/** + * This object contains factory methods for each + * Java content interface and Java element interface + * generated in the com.baeldung.soap.ws.client.generated package. + *

An ObjectFactory allows you to programatically + * construct new instances of the Java representation + * for XML content. The Java representation of XML + * content can consist of schema derived interfaces + * and classes representing the binding of schema + * type definitions, element declarations and model + * groups. Factory methods for each of these are + * provided in this class. + * + */ +@XmlRegistry +public class ObjectFactory { + + /** + * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: com.baeldung.soap.ws.client.generated + * + */ + public ObjectFactory() { + } + + /** + * Create an instance of {@link Country } + * + */ + public Country createCountry() { + return new Country(); + } + +} diff --git a/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/package-info.java b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/package-info.java new file mode 100644 index 0000000000..6df70b70f1 --- /dev/null +++ b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/client/generated/package-info.java @@ -0,0 +1,2 @@ +@javax.xml.bind.annotation.XmlSchema(namespace = "http://server.ws.soap.baeldung.com/", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) +package com.baeldung.soap.ws.client.generated; diff --git a/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/Country.java b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/Country.java new file mode 100644 index 0000000000..62ea4a22ed --- /dev/null +++ b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/Country.java @@ -0,0 +1,41 @@ +package com.baeldung.soap.ws.server; + +public class Country { + protected String name; + protected int population; + protected String capital; + protected Currency currency; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getPopulation() { + return population; + } + + public void setPopulation(int population) { + this.population = population; + } + + public String getCapital() { + return capital; + } + + public void setCapital(String capital) { + this.capital = capital; + } + + public Currency getCurrency() { + return currency; + } + + public void setCurrency(Currency currency) { + this.currency = currency; + } + +} \ No newline at end of file diff --git a/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryRepository.java b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryRepository.java new file mode 100644 index 0000000000..558f7c1293 --- /dev/null +++ b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryRepository.java @@ -0,0 +1,43 @@ +package com.baeldung.soap.ws.server; + +import java.util.HashMap; +import java.util.Map; + +public class CountryRepository { + + private static final Map countries = new HashMap<>(); + + { + initData(); + } + + private final static void initData() { + Country usa = new Country(); + usa.setName("USA"); + usa.setCapital("Washington D.C."); + usa.setCurrency(Currency.USD); + usa.setPopulation(323947000); + + countries.put(usa.getName(), usa); + + Country india = new Country(); + india.setName("India"); + india.setCapital("New Delhi"); + india.setCurrency(Currency.INR); + india.setPopulation(1295210000); + + countries.put(india.getName(), india); + + Country france = new Country(); + france.setName("France"); + france.setCapital("Paris"); + france.setCurrency(Currency.EUR); + france.setPopulation(66710000); + + countries.put(france.getName(), france); + } + + public Country findCountry(String name) { + return countries.get(name); + } +} diff --git a/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryService.java b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryService.java new file mode 100644 index 0000000000..e3f68a4e59 --- /dev/null +++ b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryService.java @@ -0,0 +1,15 @@ +package com.baeldung.soap.ws.server; + +import javax.jws.WebMethod; +import javax.jws.WebService; +import javax.jws.soap.SOAPBinding; +import javax.jws.soap.SOAPBinding.Style; + +@WebService +@SOAPBinding(style=Style.RPC) +public interface CountryService { + + @WebMethod + Country findByName(String name); + +} diff --git a/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServiceImpl.java b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServiceImpl.java new file mode 100644 index 0000000000..a8c6250354 --- /dev/null +++ b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServiceImpl.java @@ -0,0 +1,15 @@ +package com.baeldung.soap.ws.server; + +import javax.jws.WebService; + +@WebService(endpointInterface = "com.baeldung.soap.ws.server.CountryService") +public class CountryServiceImpl implements CountryService { + + private CountryRepository countryRepository = new CountryRepository(); + + @Override + public Country findByName(String name) { + return countryRepository.findCountry(name); + } + +} diff --git a/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServicePublisher.java b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServicePublisher.java new file mode 100644 index 0000000000..e7c1c480f4 --- /dev/null +++ b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/CountryServicePublisher.java @@ -0,0 +1,19 @@ +package com.baeldung.soap.ws.server; + +import javax.xml.ws.Endpoint; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class CountryServicePublisher { + + private static final Logger logger = LoggerFactory.getLogger(CountryServicePublisher.class); + + public static void main(String[] args) { + Endpoint endpoint = Endpoint.create(new CountryServiceImpl()); + endpoint.publish("http://localhost:8888/ws/country"); + + logger.info("Country web service ready to consume requests!"); + } +} \ No newline at end of file diff --git a/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/Currency.java b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/Currency.java new file mode 100644 index 0000000000..d1b25a26c6 --- /dev/null +++ b/web-modules/jee-7/src/main/java/com/baeldung/soap/ws/server/Currency.java @@ -0,0 +1,15 @@ +package com.baeldung.soap.ws.server; + +public enum Currency { + + EUR, INR, USD; + + public String value() { + return name(); + } + + public static Currency fromValue(String v) { + return valueOf(v); + } + +} diff --git a/web-modules/jee-7/src/main/resources/country.xsd b/web-modules/jee-7/src/main/resources/country.xsd new file mode 100644 index 0000000000..c94b6047f9 --- /dev/null +++ b/web-modules/jee-7/src/main/resources/country.xsd @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web-modules/jee-7/src/main/resources/logback.xml b/web-modules/jee-7/src/main/resources/logback.xml new file mode 100644 index 0000000000..5c1b7ec771 --- /dev/null +++ b/web-modules/jee-7/src/main/resources/logback.xml @@ -0,0 +1,15 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + \ No newline at end of file diff --git a/web-modules/jee-7/src/main/webapp/WEB-INF/beans.xml b/web-modules/jee-7/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/CustomCheckPointIntegrationTest.java b/web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/CustomCheckPointIntegrationTest.java new file mode 100644 index 0000000000..8190ae5afb --- /dev/null +++ b/web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/CustomCheckPointIntegrationTest.java @@ -0,0 +1,33 @@ +package com.baeldung.batch.understanding; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Properties; + +import javax.batch.operations.JobOperator; +import javax.batch.runtime.BatchRuntime; +import javax.batch.runtime.BatchStatus; +import javax.batch.runtime.JobExecution; +import javax.batch.runtime.StepExecution; + +import org.junit.jupiter.api.Test; + +class CustomCheckPointIntegrationTest { + @Test + public void givenChunk_whenCustomCheckPoint_thenCommitCountIsThree() throws Exception { + JobOperator jobOperator = BatchRuntime.getJobOperator(); + Long executionId = jobOperator.start("customCheckPoint", new Properties()); + JobExecution jobExecution = jobOperator.getJobExecution(executionId); + jobExecution = BatchTestHelper.keepTestAlive(jobExecution); + for (StepExecution stepExecution : jobOperator.getStepExecutions(executionId)) { + if (stepExecution.getStepName() + .equals("firstChunkStep")) { + jobOperator.getStepExecutions(executionId) + .stream() + .map(BatchTestHelper::getCommitCount) + .forEach(count -> assertEquals(3L, count.longValue())); + } + } + assertEquals(jobExecution.getBatchStatus(), BatchStatus.COMPLETED); + } +} diff --git a/web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/JobSequenceIntegrationTest.java b/web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/JobSequenceIntegrationTest.java new file mode 100644 index 0000000000..7dda13a752 --- /dev/null +++ b/web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/JobSequenceIntegrationTest.java @@ -0,0 +1,76 @@ +package com.baeldung.batch.understanding; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import javax.batch.operations.JobOperator; +import javax.batch.runtime.BatchRuntime; +import javax.batch.runtime.BatchStatus; +import javax.batch.runtime.JobExecution; +import javax.batch.runtime.StepExecution; + +import org.junit.jupiter.api.Test; + +class JobSequenceIntegrationTest { + @Test + public void givenTwoSteps_thenBatch_CompleteWithSuccess() throws Exception { + JobOperator jobOperator = BatchRuntime.getJobOperator(); + Long executionId = jobOperator.start("simpleJobSequence", new Properties()); + JobExecution jobExecution = jobOperator.getJobExecution(executionId); + jobExecution = BatchTestHelper.keepTestAlive(jobExecution); + assertEquals(2 , jobOperator.getStepExecutions(executionId).size()); + assertEquals(jobExecution.getBatchStatus(), BatchStatus.COMPLETED); + } + + @Test + public void givenFlow_thenBatch_CompleteWithSuccess() throws Exception { + JobOperator jobOperator = BatchRuntime.getJobOperator(); + Long executionId = jobOperator.start("flowJobSequence", new Properties()); + JobExecution jobExecution = jobOperator.getJobExecution(executionId); + jobExecution = BatchTestHelper.keepTestAlive(jobExecution); + assertEquals(3 , jobOperator.getStepExecutions(executionId).size()); + assertEquals(jobExecution.getBatchStatus(), BatchStatus.COMPLETED); + } + + @Test + public void givenDecider_thenBatch_CompleteWithSuccess() throws Exception { + JobOperator jobOperator = BatchRuntime.getJobOperator(); + Long executionId = jobOperator.start("decideJobSequence", new Properties()); + JobExecution jobExecution = jobOperator.getJobExecution(executionId); + jobExecution = BatchTestHelper.keepTestAlive(jobExecution); + List stepExecutions = jobOperator.getStepExecutions(executionId); + List executedSteps = new ArrayList<>(); + for (StepExecution stepExecution : stepExecutions) { + executedSteps.add(stepExecution.getStepName()); + } + assertEquals(2, jobOperator.getStepExecutions(executionId).size()); + assertArrayEquals(new String[] { "firstBatchStepStep1", "firstBatchStepStep3" }, executedSteps.toArray()); + assertEquals(jobExecution.getBatchStatus(), BatchStatus.COMPLETED); + } + + @Test + public void givenSplit_thenBatch_CompletesWithSuccess() throws Exception { + JobOperator jobOperator = BatchRuntime.getJobOperator(); + Long executionId = jobOperator.start("splitJobSequence", new Properties()); + JobExecution jobExecution = jobOperator.getJobExecution(executionId); + jobExecution = BatchTestHelper.keepTestAlive(jobExecution); + List stepExecutions = jobOperator.getStepExecutions(executionId); + List executedSteps = new ArrayList<>(); + for (StepExecution stepExecution : stepExecutions) { + executedSteps.add(stepExecution.getStepName()); + } + assertEquals(3, stepExecutions.size()); + assertTrue(executedSteps.contains("splitJobSequenceStep1")); + assertTrue(executedSteps.contains("splitJobSequenceStep2")); + assertTrue(executedSteps.contains("splitJobSequenceStep3")); + assertTrue(executedSteps.get(0).equals("splitJobSequenceStep1") || executedSteps.get(0).equals("splitJobSequenceStep2")); + assertTrue(executedSteps.get(1).equals("splitJobSequenceStep1") || executedSteps.get(1).equals("splitJobSequenceStep2")); + assertTrue(executedSteps.get(2).equals("splitJobSequenceStep3")); + assertEquals(jobExecution.getBatchStatus(), BatchStatus.COMPLETED); + } +} diff --git a/web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleBatchLetIntegrationTest.java b/web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleBatchLetIntegrationTest.java new file mode 100644 index 0000000000..dc91f747d3 --- /dev/null +++ b/web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleBatchLetIntegrationTest.java @@ -0,0 +1,64 @@ +package com.baeldung.batch.understanding; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Properties; + +import javax.batch.operations.JobOperator; +import javax.batch.runtime.BatchRuntime; +import javax.batch.runtime.BatchStatus; +import javax.batch.runtime.JobExecution; + +import org.junit.jupiter.api.Test; + +class SimpleBatchLetIntegrationTest { + @Test + public void givenBatchLet_thenBatch_CompleteWithSuccess() throws Exception { + JobOperator jobOperator = BatchRuntime.getJobOperator(); + Long executionId = jobOperator.start("simpleBatchLet", new Properties()); + JobExecution jobExecution = jobOperator.getJobExecution(executionId); + jobExecution = BatchTestHelper.keepTestAlive(jobExecution); + assertEquals(jobExecution.getBatchStatus(), BatchStatus.COMPLETED); + } + + @Test + public void givenBatchLetProperty_thenBatch_CompleteWithSuccess() throws Exception { + JobOperator jobOperator = BatchRuntime.getJobOperator(); + Long executionId = jobOperator.start("injectionSimpleBatchLet", new Properties()); + JobExecution jobExecution = jobOperator.getJobExecution(executionId); + jobExecution = BatchTestHelper.keepTestAlive(jobExecution); + assertEquals(jobExecution.getBatchStatus(), BatchStatus.COMPLETED); + } + + @Test + public void givenBatchLetPartition_thenBatch_CompleteWithSuccess() throws Exception { + JobOperator jobOperator = BatchRuntime.getJobOperator(); + Long executionId = jobOperator.start("partitionSimpleBatchLet", new Properties()); + JobExecution jobExecution = jobOperator.getJobExecution(executionId); + jobExecution = BatchTestHelper.keepTestAlive(jobExecution); + assertEquals(jobExecution.getBatchStatus(), BatchStatus.COMPLETED); + } + + @Test + public void givenBatchLetStarted_whenStopped_thenBatchStopped() throws Exception { + JobOperator jobOperator = BatchRuntime.getJobOperator(); + Long executionId = jobOperator.start("simpleBatchLet", new Properties()); + JobExecution jobExecution = jobOperator.getJobExecution(executionId); + jobOperator.stop(executionId); + jobExecution = BatchTestHelper.keepTestStopped(jobExecution); + assertEquals(jobExecution.getBatchStatus(), BatchStatus.STOPPED); + } + + @Test + public void givenBatchLetStopped_whenRestarted_thenBatchCompletesSuccess() throws Exception { + JobOperator jobOperator = BatchRuntime.getJobOperator(); + Long executionId = jobOperator.start("simpleBatchLet", new Properties()); + JobExecution jobExecution = jobOperator.getJobExecution(executionId); + jobOperator.stop(executionId); + jobExecution = BatchTestHelper.keepTestStopped(jobExecution); + assertEquals(jobExecution.getBatchStatus(), BatchStatus.STOPPED); + executionId = jobOperator.restart(jobExecution.getExecutionId(), new Properties()); + jobExecution = BatchTestHelper.keepTestAlive(jobOperator.getJobExecution(executionId)); + assertEquals(jobExecution.getBatchStatus(), BatchStatus.COMPLETED); + } +} diff --git a/web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleChunkIntegrationTest.java b/web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleChunkIntegrationTest.java new file mode 100644 index 0000000000..a7884dbb32 --- /dev/null +++ b/web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleChunkIntegrationTest.java @@ -0,0 +1,68 @@ +package com.baeldung.batch.understanding; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.batch.operations.JobOperator; +import javax.batch.runtime.BatchRuntime; +import javax.batch.runtime.BatchStatus; +import javax.batch.runtime.JobExecution; +import javax.batch.runtime.Metric; +import javax.batch.runtime.StepExecution; + +import org.junit.jupiter.api.Test; + +class SimpleChunkIntegrationTest { + @Test + public void givenChunk_thenBatch_CompletesWithSucess() throws Exception { + JobOperator jobOperator = BatchRuntime.getJobOperator(); + Long executionId = jobOperator.start("simpleChunk", new Properties()); + JobExecution jobExecution = jobOperator.getJobExecution(executionId); + jobExecution = BatchTestHelper.keepTestAlive(jobExecution); + List stepExecutions = jobOperator.getStepExecutions(executionId); + for (StepExecution stepExecution : stepExecutions) { + if (stepExecution.getStepName() + .equals("firstChunkStep")) { + Map metricsMap = BatchTestHelper.getMetricsMap(stepExecution.getMetrics()); + assertEquals(10L, metricsMap.get(Metric.MetricType.READ_COUNT) + .longValue()); + assertEquals(10L / 2L, metricsMap.get(Metric.MetricType.WRITE_COUNT) + .longValue()); + assertEquals(10L / 3 + (10L % 3 > 0 ? 1 : 0), metricsMap.get(Metric.MetricType.COMMIT_COUNT) + .longValue()); + } + } + assertEquals(jobExecution.getBatchStatus(), BatchStatus.COMPLETED); + } + + @Test + public void givenChunk__thenBatch_fetchInformation() throws Exception { + JobOperator jobOperator = BatchRuntime.getJobOperator(); + Long executionId = jobOperator.start("simpleChunk", new Properties()); + JobExecution jobExecution = jobOperator.getJobExecution(executionId); + jobExecution = BatchTestHelper.keepTestAlive(jobExecution); + // job name contains simpleBatchLet which is the name of the file + assertTrue(jobOperator.getJobNames().contains("simpleChunk")); + // job parameters are empty + assertTrue(jobOperator.getParameters(executionId).isEmpty()); + // step execution information + List stepExecutions = jobOperator.getStepExecutions(executionId); + assertEquals("firstChunkStep", stepExecutions.get(0).getStepName()); + // finding out batch status + assertEquals(BatchStatus.COMPLETED, stepExecutions.get(0).getBatchStatus()); + Map metricTest = BatchTestHelper.getMetricsMap(stepExecutions.get(0).getMetrics()); + assertEquals(10L, metricTest.get(Metric.MetricType.READ_COUNT).longValue()); + assertEquals(5L, metricTest.get(Metric.MetricType.FILTER_COUNT).longValue()); + assertEquals(4L, metricTest.get(Metric.MetricType.COMMIT_COUNT).longValue()); + assertEquals(5L, metricTest.get(Metric.MetricType.WRITE_COUNT).longValue()); + assertEquals(0L, metricTest.get(Metric.MetricType.READ_SKIP_COUNT).longValue()); + assertEquals(0L, metricTest.get(Metric.MetricType.WRITE_SKIP_COUNT).longValue()); + assertEquals(0L, metricTest.get(Metric.MetricType.PROCESS_SKIP_COUNT).longValue()); + assertEquals(0L, metricTest.get(Metric.MetricType.ROLLBACK_COUNT).longValue()); + assertEquals(jobExecution.getBatchStatus(), BatchStatus.COMPLETED); + } +} diff --git a/web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleErrorChunkIntegrationTest.java b/web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleErrorChunkIntegrationTest.java new file mode 100644 index 0000000000..8c3beeb2f3 --- /dev/null +++ b/web-modules/jee-7/src/test/java/com/baeldung/batch/understanding/SimpleErrorChunkIntegrationTest.java @@ -0,0 +1,45 @@ +package com.baeldung.batch.understanding; + +import static org.junit.Assert.assertEquals; + +import java.util.List; +import java.util.Properties; + +import javax.batch.operations.JobOperator; +import javax.batch.runtime.BatchRuntime; +import javax.batch.runtime.BatchStatus; +import javax.batch.runtime.JobExecution; +import javax.batch.runtime.StepExecution; + +import org.junit.jupiter.api.Test; + +class SimpleErrorChunkIntegrationTest { + + @Test + public void givenChunkError_thenBatch_CompletesWithFailed() throws Exception { + JobOperator jobOperator = BatchRuntime.getJobOperator(); + Long executionId = jobOperator.start("simpleErrorChunk", new Properties()); + JobExecution jobExecution = jobOperator.getJobExecution(executionId); + jobExecution = BatchTestHelper.keepTestFailed(jobExecution); + assertEquals(jobExecution.getBatchStatus(), BatchStatus.FAILED); + } + + @Test + public void givenChunkError_thenErrorSkipped_CompletesWithSuccess() throws Exception { + JobOperator jobOperator = BatchRuntime.getJobOperator(); + Long executionId = jobOperator.start("simpleErrorSkipChunk", new Properties()); + JobExecution jobExecution = jobOperator.getJobExecution(executionId); + jobExecution = BatchTestHelper.keepTestAlive(jobExecution); + List stepExecutions = jobOperator.getStepExecutions(executionId); + for (StepExecution stepExecution : stepExecutions) { + if (stepExecution.getStepName() + .equals("errorStep")) { + jobOperator.getStepExecutions(executionId) + .stream() + .map(BatchTestHelper::getProcessSkipCount) + .forEach(skipCount -> assertEquals(1L, skipCount.longValue())); + } + } + assertEquals(jobExecution.getBatchStatus(), BatchStatus.COMPLETED); + } +} diff --git a/web-modules/jee-7/src/test/java/com/baeldung/singleton/CarServiceLiveTest.java b/web-modules/jee-7/src/test/java/com/baeldung/singleton/CarServiceLiveTest.java new file mode 100644 index 0000000000..c054f9c2db --- /dev/null +++ b/web-modules/jee-7/src/test/java/com/baeldung/singleton/CarServiceLiveTest.java @@ -0,0 +1,109 @@ +package com.baeldung.singleton; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import javax.ejb.EJB; +import javax.enterprise.context.spi.CreationalContext; +import javax.enterprise.inject.spi.Bean; +import javax.enterprise.inject.spi.BeanManager; +import javax.enterprise.inject.spi.CDI; +import javax.inject.Inject; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.JavaArchive; +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@RunWith(Arquillian.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class CarServiceLiveTest { + + public static final Logger LOG = LoggerFactory.getLogger(CarServiceLiveTest.class); + + @Deployment + public static JavaArchive createDeployment() { + return ShrinkWrap.create(JavaArchive.class) + .addClasses(CarServiceBean.class, CarServiceSingleton.class, CarServiceEjbSingleton.class, Car.class) + .addAsResource("META-INF/persistence.xml") + .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); + } + + @Inject + private CarServiceBean carServiceBean; + + @Inject + private CarServiceSingleton carServiceSingleton; + + @EJB + private CarServiceEjbSingleton carServiceEjbSingleton; + + @Test + public void givenASingleton_whenGetBeanIsCalledTwice_thenTheSameInstanceIsReturned() { + CarServiceSingleton one = getBean(CarServiceSingleton.class); + CarServiceSingleton two = getBean(CarServiceSingleton.class); + assertTrue(one == two); + } + + @Test + public void givenAPojo_whenGetBeanIsCalledTwice_thenDifferentInstancesAreReturned() { + CarServiceBean one = getBean(CarServiceBean.class); + CarServiceBean two = getBean(CarServiceBean.class); + assertTrue(one != two); + } + + @SuppressWarnings("unchecked") + private T getBean(Class beanClass) { + BeanManager bm = CDI.current().getBeanManager(); + Bean bean = (Bean) bm.getBeans(beanClass).iterator().next(); + CreationalContext ctx = bm.createCreationalContext(bean); + return (T) bm.getReference(bean, beanClass, ctx); + } + + @Test + public void givenCDI_whenConcurrentAccess_thenLockingIsNotProvided() { + for (int i = 0; i < 10; i++) { + new Thread(new Runnable() { + @Override + public void run() { + String model = Double.toString(Math.round(Math.random() * 100)); + Car car = new Car("Speedster", model); + int serviceQueue = carServiceSingleton.service(car); + assertTrue(serviceQueue < 10); + } + }).start(); + } + return; + } + + @Test + public void givenEJB_whenConcurrentAccess_thenLockingIsProvided() { + for (int i = 0; i < 10; i++) { + new Thread(new Runnable() { + @Override + public void run() { + String model = Double.toString(Math.round(Math.random() * 100)); + Car car = new Car("Speedster", model); + int serviceQueue = carServiceEjbSingleton.service(car); + assertEquals(0, serviceQueue); + } + }).start(); + } + return; + } + +} \ No newline at end of file diff --git a/web-modules/jee-7/src/test/java/com/baeldung/soap/ws/client/CountryClientLiveTest.java b/web-modules/jee-7/src/test/java/com/baeldung/soap/ws/client/CountryClientLiveTest.java new file mode 100644 index 0000000000..ae423f9bdd --- /dev/null +++ b/web-modules/jee-7/src/test/java/com/baeldung/soap/ws/client/CountryClientLiveTest.java @@ -0,0 +1,39 @@ +package com.baeldung.soap.ws.client; + +import static org.junit.Assert.assertEquals; + +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baeldung.soap.ws.client.generated.CountryService; +import com.baeldung.soap.ws.client.generated.CountryServiceImplService; +import com.baeldung.soap.ws.client.generated.Currency; + +//Ensure that com.baeldung.soap.ws.server.CountryServicePublisher is running before executing this test +public class CountryClientLiveTest { + + private static CountryService countryService; + + @BeforeClass + public static void setup() { + CountryServiceImplService service = new CountryServiceImplService(); + countryService = service.getCountryServiceImplPort(); + } + + @Test + public void givenCountryService_whenCountryIndia_thenCapitalIsNewDelhi() { + assertEquals("New Delhi", countryService.findByName("India").getCapital()); + } + + @Test + public void givenCountryService_whenCountryFrance_thenPopulationCorrect() { + assertEquals(66710000, countryService.findByName("France").getPopulation()); + } + + @Test + public void givenCountryService_whenCountryUSA_thenCurrencyUSD() { + assertEquals(Currency.USD, countryService.findByName("USA").getCurrency()); + } + + +} diff --git a/web-modules/jee-7/src/test/resources/arquillian.xml b/web-modules/jee-7/src/test/resources/arquillian.xml new file mode 100644 index 0000000000..f4274877fd --- /dev/null +++ b/web-modules/jee-7/src/test/resources/arquillian.xml @@ -0,0 +1,23 @@ + + + + + target/wildfly-8.2.1.Final + standalone.xml + true + 9990 + -Djboss.http.port=8639 + + + + + + 127.0.0.1 + 9990 + admin + pass + true + + + + \ No newline at end of file diff --git a/web-modules/jee-7/src/test/resources/jberet.properties b/web-modules/jee-7/src/test/resources/jberet.properties new file mode 100644 index 0000000000..e8b9907de5 --- /dev/null +++ b/web-modules/jee-7/src/test/resources/jberet.properties @@ -0,0 +1 @@ +db-url=jdbc:h2:mem:jberet-repo;DB_CLOSE_DELAY=-1 \ No newline at end of file diff --git a/web-modules/jooby/conf/application.conf b/web-modules/jooby/conf/application.conf new file mode 100644 index 0000000000..7da56eef6b --- /dev/null +++ b/web-modules/jooby/conf/application.conf @@ -0,0 +1,4 @@ +#application.secret = 2o128940921eo298e21 +#db = /url/to/the/datastore + +#redis = "redis://localhost:6379" \ No newline at end of file diff --git a/web-modules/jooby/pom.xml b/web-modules/jooby/pom.xml new file mode 100644 index 0000000000..238f17571f --- /dev/null +++ b/web-modules/jooby/pom.xml @@ -0,0 +1,83 @@ + + + 4.0.0 + com.baeldung.jooby + jooby + 1.0 + jooby + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + io.jooby + jooby + ${jooby.version} + + + io.jooby + jooby-test + ${jooby.version} + + + io.jooby + jooby-jetty + ${jooby.version} + + + io.jooby + jooby-redis + ${jooby.version} + + + io.rest-assured + rest-assured + test + ${rest-assured.version} + + + com.squareup.okhttp3 + okhttp + ${squareup.okhttp.version} + + + + + + + maven-shade-plugin + ${maven-shade-plugin.version} + + + io.jooby + jooby-maven-plugin + ${jooby.version} + + + maven-compiler-plugin + ${maven-compiler.version} + + + -parameters + + + + + + + + 2.16.1 + 3.1.1 + com.baeldung.jooby.App + 3.2.4 + 3.8.1 + 4.9.1 + + + \ No newline at end of file diff --git a/web-modules/jooby/public/form.html b/web-modules/jooby/public/form.html new file mode 100644 index 0000000000..bb9a705b9a --- /dev/null +++ b/web-modules/jooby/public/form.html @@ -0,0 +1,18 @@ + + + + + Insert title here + + +

+
+
+
+
+
+

+ +
+ + \ No newline at end of file diff --git a/web-modules/jooby/src/main/java/com/baeldung/jooby/App.java b/web-modules/jooby/src/main/java/com/baeldung/jooby/App.java new file mode 100644 index 0000000000..1bfaf6de5d --- /dev/null +++ b/web-modules/jooby/src/main/java/com/baeldung/jooby/App.java @@ -0,0 +1,123 @@ +package com.baeldung.jooby; + +import com.baeldung.jooby.bean.Employee; + +import io.jooby.Jooby; +import io.jooby.ServerOptions; +import io.jooby.Session; +import io.jooby.SessionStore; + +public class App extends Jooby { + { + setServerOptions(new ServerOptions().setPort(8080) + .setSecurePort(8433)); + } + + { + get("/", ctx -> "Hello World!"); + } + + { + get("/user/{id}", ctx -> "Hello user : " + ctx.path("id") + .value()); + get("/user/:id", ctx -> "Hello user: " + ctx.path("id") + .value()); + get("/uid:{id}", ctx -> "Hello User with id : uid = " + ctx.path("id") + .value()); + } + + { + onStarting(() -> System.out.println("starting app")); + + onStop(() -> System.out.println("stopping app")); + + onStarted(() -> System.out.println("app started")); + } + + { + get("/login", ctx -> "Hello from Baeldung"); + } + + { + post("/save", ctx -> { + String userId = ctx.query("id") + .value(); + return userId; + }); + } + + { + { + assets("/employee", "public/form.html"); + } + + post("/submitForm", ctx -> { + Employee employee = ctx.path(Employee.class); + // ... + return "employee data saved successfully"; + }); + + } + + { + decorator(next -> ctx -> { + System.out.println("first"); + // Moves execution to next handler: second + return next.apply(ctx); + }); + decorator(next -> ctx -> { + System.out.println("second"); + // Moves execution to next handler: third + return next.apply(ctx); + }); + + get("/handler", ctx -> "third"); + } + + { + get("/sessionInMemory", ctx -> { + Session session = ctx.session(); + session.put("token", "value"); + return session.get("token") + .value(); + }); + } + + { + String secret = "super secret token"; + + setSessionStore(SessionStore.signed(secret)); + + get("/signedSession", ctx -> { + Session session = ctx.session(); + session.put("token", "value"); + return session.get("token") + .value(); + }); + } + + { + get("/sessionInMemoryRedis", ctx -> { + Session session = ctx.session(); + session.put("token", "value"); + return session.get("token") + .value(); + }); + } + + /* This will work once redis is installed locally + { + install(new RedisModule("redis")); + setSessionStore(new RedisSessionStore(require(RedisClient.class))); + get("/redisSession", ctx -> { + Session session = ctx.session(); + session.put("token", "value"); + return session.get("token"); + }); + }*/ + + public static void main(final String[] args) { + runApp(args, App::new); + } + +} diff --git a/web-modules/jooby/src/main/java/com/baeldung/jooby/mvc/GetController.java b/web-modules/jooby/src/main/java/com/baeldung/jooby/mvc/GetController.java new file mode 100644 index 0000000000..bd43fb1717 --- /dev/null +++ b/web-modules/jooby/src/main/java/com/baeldung/jooby/mvc/GetController.java @@ -0,0 +1,23 @@ +package com.baeldung.jooby.mvc; + +import java.util.HashMap; + +import io.jooby.ModelAndView; +import io.jooby.annotations.GET; +import io.jooby.annotations.Path; + +@Path("/hello") +public class GetController { + + @GET + public String hello() { + return "Hello Baeldung"; + } + + @GET + @Path("/home") + public ModelAndView home() { + return new ModelAndView("welcome.html", new HashMap<>()); + } + +} diff --git a/web-modules/jooby/src/main/java/com/baeldung/jooby/mvc/PostController.java b/web-modules/jooby/src/main/java/com/baeldung/jooby/mvc/PostController.java new file mode 100644 index 0000000000..0f014580f9 --- /dev/null +++ b/web-modules/jooby/src/main/java/com/baeldung/jooby/mvc/PostController.java @@ -0,0 +1,13 @@ +package com.baeldung.jooby.mvc; + +import io.jooby.annotations.POST; +import io.jooby.annotations.Path; + +@Path("/submit") +public class PostController { + + @POST + public String hello() { + return "Submit Baeldung"; + } +} diff --git a/web-modules/jooby/src/main/resources/logback.xml b/web-modules/jooby/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/web-modules/jooby/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/web-modules/jooby/src/test/java/com/baeldung/jooby/AppLiveTest.java b/web-modules/jooby/src/test/java/com/baeldung/jooby/AppLiveTest.java new file mode 100644 index 0000000000..e55e0e04a4 --- /dev/null +++ b/web-modules/jooby/src/test/java/com/baeldung/jooby/AppLiveTest.java @@ -0,0 +1,32 @@ +package com.baeldung.jooby; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; + +import io.jooby.JoobyTest; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +@JoobyTest(value = App.class, port = 8080) +class AppLiveTest { + + static OkHttpClient client = new OkHttpClient(); + + @Test + void given_defaultUrl_expect_fixedString() { + Request request = new Request.Builder().url("http://localhost:8080") + .build(); + try (Response response = client.newCall(request) + .execute()) { + assertEquals("Hello World!", response.body() + .string()); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/web-modules/jooby/src/test/java/com/baeldung/jooby/AppUnitTest.java b/web-modules/jooby/src/test/java/com/baeldung/jooby/AppUnitTest.java new file mode 100644 index 0000000000..98184e11f3 --- /dev/null +++ b/web-modules/jooby/src/test/java/com/baeldung/jooby/AppUnitTest.java @@ -0,0 +1,17 @@ +package com.baeldung.jooby; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import io.jooby.MockRouter; + +public class AppUnitTest { + + @Test + public void given_defaultUrl_with_mockrouter_expect_fixedString() { + MockRouter router = new MockRouter(new App()); + assertEquals("Hello World!", router.get("/") + .value()); + } +} diff --git a/web-modules/linkrest/pom.xml b/web-modules/linkrest/pom.xml new file mode 100644 index 0000000000..f43add6910 --- /dev/null +++ b/web-modules/linkrest/pom.xml @@ -0,0 +1,70 @@ + + + 4.0.0 + linkrest + 0.0.1-SNAPSHOT + linkrest + war + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + com.nhl.link.rest + link-rest + ${linkrest.version} + + + org.glassfish.jersey.containers + jersey-container-servlet + ${jersey.version} + + + + + + + maven-war-plugin + ${maven-war-plugin.version} + + WebContent + false + + + + org.apache.cayenne.plugins + cayenne-maven-plugin + ${cayenne.version} + + + ${project.basedir}/src/main/resources/linkrest.map.xml + + + + + cgen + + + + + + org.apache.cayenne.plugins + cayenne-modeler-maven-plugin + ${cayenne.version} + + + + + + 2.9 + 4.0.B1 + 2.25.1 + + + \ No newline at end of file diff --git a/web-modules/linkrest/src/main/resources/logback.xml b/web-modules/linkrest/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/web-modules/linkrest/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/web-modules/ninja/README.md b/web-modules/ninja/README.md new file mode 100644 index 0000000000..554d088c1b --- /dev/null +++ b/web-modules/ninja/README.md @@ -0,0 +1,3 @@ +### Relevant Articles + +- [Introduction to Ninja Framework](https://www.baeldung.com/ninja-framework-intro) diff --git a/web-modules/ninja/pom.xml b/web-modules/ninja/pom.xml new file mode 100644 index 0000000000..cb3e234172 --- /dev/null +++ b/web-modules/ninja/pom.xml @@ -0,0 +1,226 @@ + + + 4.0.0 + ninja + 1.0.0 + jar + http://www.ninjaframework.org + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + org.webjars + bootstrap + ${bootstrap.version} + + + org.webjars + jquery + ${jquery.version} + + + com.h2database + h2 + ${h2.version} + + + org.ninjaframework + ninja-standalone + ${ninja.version} + + + org.ninjaframework + ninja-test-utilities + ${ninja.version} + test + + + + junit + junit + + + + + org.junit.jupiter + junit-jupiter + ${junit-jupiter.version} + test + + + org.junit.vintage + junit-vintage-engine + ${junit-jupiter.version} + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${compiler.plugin.version} + + ${source.version} + ${target.version} + + + + org.apache.maven.plugins + maven-enforcer-plugin + ${enforcer.plugin.version} + + + enforce-banned-dependencies + + enforce + + + + + + commons-logging + + + + true + + + + + + org.eclipse.jetty + jetty-maven-plugin + ${jetty.version} + + + / + + stop + 8889 + 1 + automatic + + + target/classes + + **/* + + + **/*.ftl.html + assets/** + + + + + + ninja.mode + dev + + + + + + + + + org.ninjaframework + ninja-maven-plugin + ${ninja.version} + + + org.apache.maven.plugins + maven-deploy-plugin + ${deploy.plugin.version} + + true + + + + org.apache.maven.plugins + maven-shade-plugin + ${shade.plugin.version} + + true + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + package + + shade + + + + + + ninja.standalone.NinjaJetty + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + src/main/java + + **/* + + + **/*.java + + + + src/main/resources + + **/* + + + + + + + 6.5.0 + 9.4.18.v20190429 + 3.3.4 + 2.1.3 + 3.2 + 17 + 17 + 1.3.1 + 2.8.2 + 2.2 + 5.8.1 + + + \ No newline at end of file diff --git a/web-modules/ninja/src/main/java/META-INF/persistence.xml b/web-modules/ninja/src/main/java/META-INF/persistence.xml new file mode 100644 index 0000000000..e57cd5ecc0 --- /dev/null +++ b/web-modules/ninja/src/main/java/META-INF/persistence.xml @@ -0,0 +1,29 @@ + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web-modules/ninja/src/main/java/assets/css/custom.css b/web-modules/ninja/src/main/java/assets/css/custom.css new file mode 100644 index 0000000000..41d249d3cb --- /dev/null +++ b/web-modules/ninja/src/main/java/assets/css/custom.css @@ -0,0 +1,3 @@ +/* Add additional stylesheets below +-------------------------------------------------- */ + diff --git a/web-modules/ninja/src/main/java/conf/Filters.java b/web-modules/ninja/src/main/java/conf/Filters.java new file mode 100644 index 0000000000..b201780fa1 --- /dev/null +++ b/web-modules/ninja/src/main/java/conf/Filters.java @@ -0,0 +1,13 @@ +package conf; + +import java.util.List; +import ninja.Filter; + +public class Filters implements ninja.application.ApplicationFilters { + + @Override + public void addFilters(List> filters) { + // Add your application - wide filters here + // filters.add(MyFilter.class); + } +} diff --git a/web-modules/ninja/src/main/java/conf/Module.java b/web-modules/ninja/src/main/java/conf/Module.java new file mode 100644 index 0000000000..f7c03a4b26 --- /dev/null +++ b/web-modules/ninja/src/main/java/conf/Module.java @@ -0,0 +1,18 @@ +package conf; + +import com.google.inject.AbstractModule; +import com.google.inject.Singleton; + +import services.UserService; +import services.UserServiceImpl; + +@Singleton +public class Module extends AbstractModule { + + protected void configure() { + + bind(UserService.class).to(UserServiceImpl.class); + + } + +} diff --git a/web-modules/ninja/src/main/java/conf/Routes.java b/web-modules/ninja/src/main/java/conf/Routes.java new file mode 100644 index 0000000000..a1727d55b0 --- /dev/null +++ b/web-modules/ninja/src/main/java/conf/Routes.java @@ -0,0 +1,32 @@ +package conf; + +import ninja.AssetsController; +import ninja.Router; +import ninja.application.ApplicationRoutes; +import controllers.ApplicationController; + +public class Routes implements ApplicationRoutes { + + @Override + public void init(Router router) { + + router.GET().route("/index").with(ApplicationController::index); + router.GET().route("/home").with(ApplicationController::home); + router.GET().route("/hello").with(ApplicationController::helloWorld); + router.GET().route("/userJson").with(ApplicationController::userJson); + router.GET().route("/createUser").with(ApplicationController::createUser); + router.GET().route("/flash").with(ApplicationController::showFlashMsg); + + router.GET().route("/users").with(ApplicationController::fetchUsers); + router.POST().route("/users").with(ApplicationController::insertUser); + + //Assets + router.GET().route("/assets/webjars/{fileName: .*}").with(AssetsController::serveWebJars); + router.GET().route("/assets/{fileName: .*}").with(AssetsController::serveStatic); + + //Index + router.GET().route("/.*").with(ApplicationController::index); + + } + +} diff --git a/web-modules/ninja/src/main/java/conf/application.conf b/web-modules/ninja/src/main/java/conf/application.conf new file mode 100644 index 0000000000..0ae4c7ec40 --- /dev/null +++ b/web-modules/ninja/src/main/java/conf/application.conf @@ -0,0 +1,21 @@ +application.name=baeldung ninja dev application +%test.application.name=baeldung ninja test application +%prod.application.name=baeldung ninja application + +application.cookie.prefix=NINJA + +application.languages=fr,en + +application.session.expire_time_in_seconds=3600 +application.session.send_only_if_changed=true +application.session.transferred_over_https_only=false + +ninja.port=8000 +ninja.ssl.port=8001 +application.secret = fxSjSL9Q017BSL7gBnkyo2Prln7uXaXIT35gotXRIED8c46OSa8s4QdoIQdTsEtj + +# h2 jpa configuration +ninja.jpa.persistence_unit_name=dev_unit +db.connection.url=jdbc:h2:./devDb +db.connection.username=sa +db.connection.password= diff --git a/web-modules/ninja/src/main/java/conf/messages.properties b/web-modules/ninja/src/main/java/conf/messages.properties new file mode 100644 index 0000000000..3bddfcd8c7 --- /dev/null +++ b/web-modules/ninja/src/main/java/conf/messages.properties @@ -0,0 +1,2 @@ +header.home=Home! +helloMsg=Hello, welcome to Ninja Framework! \ No newline at end of file diff --git a/web-modules/ninja/src/main/java/conf/messages_fr.properties b/web-modules/ninja/src/main/java/conf/messages_fr.properties new file mode 100644 index 0000000000..89264e0cb9 --- /dev/null +++ b/web-modules/ninja/src/main/java/conf/messages_fr.properties @@ -0,0 +1,2 @@ +header.home=Accueil! +helloMsg=Bonjour, bienvenue dans Ninja Framework! \ No newline at end of file diff --git a/web-modules/ninja/src/main/java/controllers/ApplicationController.java b/web-modules/ninja/src/main/java/controllers/ApplicationController.java new file mode 100644 index 0000000000..38dd598694 --- /dev/null +++ b/web-modules/ninja/src/main/java/controllers/ApplicationController.java @@ -0,0 +1,102 @@ +package controllers; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.persistence.Query; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.google.inject.Provider; +import com.google.inject.Singleton; +import com.google.inject.persist.Transactional; + +import models.User; +import ninja.Context; +import ninja.Result; +import ninja.Results; +import ninja.i18n.Lang; +import ninja.i18n.Messages; +import ninja.jpa.UnitOfWork; +import ninja.session.FlashScope; +import ninja.validation.JSR303Validation; +import ninja.validation.Validation; +import services.UserService; + +@Singleton +public class ApplicationController { + + @Inject + Lang lang; + + @Inject + Messages msg; + + private static Log logger = LogFactory.getLog(ApplicationController.class); + + @Inject + Provider entityManagerProvider; + + @Inject + UserService userService; + + public Result index() { + return Results.html(); + } + + public Result userJson() { + HashMap userMap = userService.getUserMap(); + logger.info(userMap); + return Results.json().render(userMap); + } + + public Result helloWorld(Context context) { + Optional language = Optional.of("fr"); + String helloMsg = msg.get("helloMsg", language).get(); + return Results.text().render(helloMsg); + } + + public Result showFlashMsg(FlashScope flashScope) { + flashScope.success("Success message"); + flashScope.error("Error message"); + return Results.redirect("/home"); + } + + public Result home() { + return Results.html(); + } + + public Result createUser() { + return Results.html(); + } + + @UnitOfWork + public Result fetchUsers() { + EntityManager entityManager = entityManagerProvider.get(); + Query q = entityManager.createQuery("SELECT x FROM User x"); + List users = (List) q.getResultList(); + return Results.json().render(users); + } + + @Transactional + public Result insertUser(FlashScope flashScope, @JSR303Validation User user, Validation validation) { + logger.info("Inserting User : " +user); + + if (validation.getViolations().size() > 0) { + flashScope.error("Validation Error: User can't be created"); + } else { + EntityManager entityManager = entityManagerProvider.get(); + entityManager.persist(user); + entityManager.flush(); + flashScope.success("User '" + user + "' is created successfully"); + } + + return Results.redirect("/home"); + } + +} diff --git a/web-modules/ninja/src/main/java/ehcache.xml b/web-modules/ninja/src/main/java/ehcache.xml new file mode 100644 index 0000000000..b401b61a36 --- /dev/null +++ b/web-modules/ninja/src/main/java/ehcache.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/web-modules/ninja/src/main/java/logback.xml b/web-modules/ninja/src/main/java/logback.xml new file mode 100644 index 0000000000..ebdcf56f76 --- /dev/null +++ b/web-modules/ninja/src/main/java/logback.xml @@ -0,0 +1,33 @@ + + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + diff --git a/web-modules/ninja/src/main/java/models/User.java b/web-modules/ninja/src/main/java/models/User.java new file mode 100644 index 0000000000..e021567bca --- /dev/null +++ b/web-modules/ninja/src/main/java/models/User.java @@ -0,0 +1,25 @@ +package models; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.validation.constraints.NotNull; + +@Entity +public class User { + + @Id + @GeneratedValue(strategy=GenerationType.AUTO) + Long id; + + @NotNull + public String firstName; + + public String email; + + public String toString() { + return firstName + " : " + email; + } + +} diff --git a/web-modules/ninja/src/main/java/services/UserService.java b/web-modules/ninja/src/main/java/services/UserService.java new file mode 100644 index 0000000000..10d625c66f --- /dev/null +++ b/web-modules/ninja/src/main/java/services/UserService.java @@ -0,0 +1,9 @@ +package services; + +import java.util.HashMap; + +public interface UserService { + + HashMap getUserMap(); + +} diff --git a/web-modules/ninja/src/main/java/services/UserServiceImpl.java b/web-modules/ninja/src/main/java/services/UserServiceImpl.java new file mode 100644 index 0000000000..0f8c2214cf --- /dev/null +++ b/web-modules/ninja/src/main/java/services/UserServiceImpl.java @@ -0,0 +1,15 @@ +package services; + +import java.util.HashMap; + +public class UserServiceImpl implements UserService { + + @Override + public HashMap getUserMap() { + HashMap userMap = new HashMap<>(); + userMap.put("name", "Norman Lewis"); + userMap.put("email", "norman@email.com"); + return userMap; + } + +} diff --git a/web-modules/ninja/src/main/java/views/ApplicationController/createUser.ftl.html b/web-modules/ninja/src/main/java/views/ApplicationController/createUser.ftl.html new file mode 100644 index 0000000000..9156f7dbf2 --- /dev/null +++ b/web-modules/ninja/src/main/java/views/ApplicationController/createUser.ftl.html @@ -0,0 +1,12 @@ +<#import "../layout/defaultLayout.ftl.html" as layout> +<@layout.myLayout "Create User"> + +
+ + First Name : +
+ Email : +
+ + + \ No newline at end of file diff --git a/web-modules/ninja/src/main/java/views/ApplicationController/home.ftl.html b/web-modules/ninja/src/main/java/views/ApplicationController/home.ftl.html new file mode 100644 index 0000000000..10f6612d54 --- /dev/null +++ b/web-modules/ninja/src/main/java/views/ApplicationController/home.ftl.html @@ -0,0 +1,9 @@ +<#import "../layout/defaultLayout.ftl.html" as layout> +<@layout.myLayout "Home page"> + + +

${i18n("helloMsg")}

+ +User Json + + \ No newline at end of file diff --git a/web-modules/ninja/src/main/java/views/ApplicationController/index.ftl.html b/web-modules/ninja/src/main/java/views/ApplicationController/index.ftl.html new file mode 100644 index 0000000000..25d0a31229 --- /dev/null +++ b/web-modules/ninja/src/main/java/views/ApplicationController/index.ftl.html @@ -0,0 +1,9 @@ + + + Ninja: Index + + +

${i18n("helloMsg")}

+ User Json + + \ No newline at end of file diff --git a/web-modules/ninja/src/main/java/views/layout/defaultLayout.ftl.html b/web-modules/ninja/src/main/java/views/layout/defaultLayout.ftl.html new file mode 100644 index 0000000000..a61edd19e6 --- /dev/null +++ b/web-modules/ninja/src/main/java/views/layout/defaultLayout.ftl.html @@ -0,0 +1,58 @@ +<#macro myLayout title="Layout example"> + + + + + ${title} + + + + + + + + + + + + + + + + + + +
+ + <#include "header.ftl.html"/> + + <#if (flash.error)??> +
+ ${flash.error} +
+ + + <#if (flash.success)??> +
+ ${flash.success} +
+ + + <#nested/> + + <#include "footer.ftl.html"/> + +
+ + + + + \ No newline at end of file diff --git a/web-modules/ninja/src/main/java/views/layout/footer.ftl.html b/web-modules/ninja/src/main/java/views/layout/footer.ftl.html new file mode 100644 index 0000000000..0a2cb2721e --- /dev/null +++ b/web-modules/ninja/src/main/java/views/layout/footer.ftl.html @@ -0,0 +1,5 @@ +
+ + diff --git a/web-modules/ninja/src/main/java/views/layout/header.ftl.html b/web-modules/ninja/src/main/java/views/layout/header.ftl.html new file mode 100644 index 0000000000..af79449bf2 --- /dev/null +++ b/web-modules/ninja/src/main/java/views/layout/header.ftl.html @@ -0,0 +1,20 @@ + \ No newline at end of file diff --git a/web-modules/ninja/src/main/java/views/system/403forbidden.ftl.html b/web-modules/ninja/src/main/java/views/system/403forbidden.ftl.html new file mode 100644 index 0000000000..0f4efd160a --- /dev/null +++ b/web-modules/ninja/src/main/java/views/system/403forbidden.ftl.html @@ -0,0 +1,18 @@ +<#import "../layout/defaultLayout.ftl.html" as layout> +<@layout.myLayout "Error. Forbidden."> +
+
+
+
+

+ Oops!

+

+ 403 Forbidden

+
+ Sorry, an error has occured. Requested page is forbidden! +
+
+
+
+
+ \ No newline at end of file diff --git a/web-modules/ninja/src/main/java/views/system/404notFound.ftl.html b/web-modules/ninja/src/main/java/views/system/404notFound.ftl.html new file mode 100644 index 0000000000..c10e7c3949 --- /dev/null +++ b/web-modules/ninja/src/main/java/views/system/404notFound.ftl.html @@ -0,0 +1,18 @@ +<#import "../layout/defaultLayout.ftl.html" as layout> +<@layout.myLayout "Error. Not found."> +
+
+
+
+

+ Oops!

+

+ 404 Not Found

+
+ Sorry, an error has occured. Requested page not found! +
+
+
+
+
+ \ No newline at end of file diff --git a/web-modules/ninja/src/main/webapp/WEB-INF/web.xml b/web-modules/ninja/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..fe4b2c95bf --- /dev/null +++ b/web-modules/ninja/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,41 @@ + + + + + + ninja + + + ninja.servlet.NinjaServletListener + + + + guiceFilter + com.google.inject.servlet.GuiceFilter + + + guiceFilter + /* + + + diff --git a/web-modules/ninja/src/test/java/controllers/ApiControllerDocTesterUnitTest.java b/web-modules/ninja/src/test/java/controllers/ApiControllerDocTesterUnitTest.java new file mode 100644 index 0000000000..64812f6935 --- /dev/null +++ b/web-modules/ninja/src/test/java/controllers/ApiControllerDocTesterUnitTest.java @@ -0,0 +1,27 @@ +package controllers; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.junit.Assert.assertThat; +import org.doctester.testbrowser.Request; +import org.doctester.testbrowser.Response; +import org.junit.Test; +import ninja.NinjaDocTester; + +public class ApiControllerDocTesterUnitTest extends NinjaDocTester { + + String URL_INDEX = "/"; + String URL_HELLO = "/hello"; + + @Test + public void testGetIndex() { + Response response = makeRequest(Request.GET().url(testServerUrl().path(URL_INDEX))); + assertThat(response.payload, containsString("Hello, welcome to Ninja Framework!")); + } + + @Test + public void testGetHello() { + Response response = makeRequest(Request.GET().url(testServerUrl().path(URL_HELLO))); + assertThat(response.payload, containsString("Bonjour, bienvenue dans Ninja Framework!")); + } + +} diff --git a/web-modules/ninja/src/test/java/controllers/ApiControllerMockUnitTest.java b/web-modules/ninja/src/test/java/controllers/ApiControllerMockUnitTest.java new file mode 100644 index 0000000000..8534fa0b0f --- /dev/null +++ b/web-modules/ninja/src/test/java/controllers/ApiControllerMockUnitTest.java @@ -0,0 +1,32 @@ +package controllers; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +import ninja.NinjaTest; +import ninja.Result; +import services.UserService; + +public class ApiControllerMockUnitTest extends NinjaTest { + + private UserService userService; + + private ApplicationController applicationController; + + @Before + public void setupTest() { + userService = this.ninjaTestServer.getInjector().getInstance(UserService.class); + applicationController = new ApplicationController(); + applicationController.userService = userService; + } + + @Test + public void testThatGetUserJson() { + Result result = applicationController.userJson(); + System.out.println(result.getRenderable()); + assertEquals(userService.getUserMap().toString(), result.getRenderable().toString()); + } + +} diff --git a/web-modules/play-modules/README.md b/web-modules/play-modules/README.md new file mode 100644 index 0000000000..d1ac7eb2d4 --- /dev/null +++ b/web-modules/play-modules/README.md @@ -0,0 +1,8 @@ +## Play Framework + +This module contains articles about the Play Framework. + +### Relevant Articles: +- [REST API with Play Framework in Java](https://www.baeldung.com/rest-api-with-play) +- [Routing in Play Applications in Java](https://www.baeldung.com/routing-in-play) +- [Introduction to Play in Java](https://www.baeldung.com/java-intro-to-the-play-framework) diff --git a/web-modules/play-modules/async-http/.g8/form/app/controllers/$model__Camel$Controller.java b/web-modules/play-modules/async-http/.g8/form/app/controllers/$model__Camel$Controller.java new file mode 100644 index 0000000000..1ac4fe547d --- /dev/null +++ b/web-modules/play-modules/async-http/.g8/form/app/controllers/$model__Camel$Controller.java @@ -0,0 +1,43 @@ +package controllers; + +import play.data.Form; +import play.data.FormFactory; +import play.mvc.Controller; +import play.mvc.Result; + +import javax.inject.Inject; + +// Add the following to conf/routes +/* +GET /$model;format="camel"$ controllers.$model;format="Camel"$Controller.$model;format="camel"$Get +POST /$model;format="camel"$ controllers.$model;format="Camel"$Controller.$model;format="camel"$Post +*/ + +/** + * $model;format="Camel"$ form controller for Play Java + */ +public class $model;format="Camel"$Controller extends Controller { + + private final Form<$model;format="Camel"$Data> $model;format="camel"$Form; + + @Inject + public $model;format="Camel"$Controller(FormFactory formFactory) { + this.$model;format="camel"$Form = formFactory.form($model;format="Camel"$Data.class); + } + + public Result $model;format="camel"$Get() { + return ok(views.html.$model;format="camel"$.form.render($model;format="camel"$Form)); + } + + public Result $model;format="camel"$Post() { + Form<$model;format="Camel"$Data> boundForm = $model;format="camel"$Form.bindFromRequest(); + if (boundForm.hasErrors()) { + return badRequest(views.html.$model;format="camel"$.form.render(boundForm)); + } else { + $model;format="Camel"$Data $model;format="camel"$ = boundForm.get(); + flash("success", "$model;format="Camel"$ " + $model;format="camel"$); + return redirect(routes.$model;format="Camel"$Controller.$model;format="camel"$Get()); + } + } + +} diff --git a/web-modules/play-modules/async-http/.g8/form/app/controllers/$model__Camel$Data.java b/web-modules/play-modules/async-http/.g8/form/app/controllers/$model__Camel$Data.java new file mode 100644 index 0000000000..50dc06f478 --- /dev/null +++ b/web-modules/play-modules/async-http/.g8/form/app/controllers/$model__Camel$Data.java @@ -0,0 +1,37 @@ +package controllers; + +import play.data.validation.Constraints; + +public class $model;format="Camel"$Data { + + @Constraints.Required + private String name; + + @Constraints.Required + private Integer age; + + public $model;format="Camel"$Data() { + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + @Override + public String toString() { + return String.format("$model;format="Camel"$Data(%s, %s)", name, age); + } + +} diff --git a/web-modules/play-modules/async-http/.g8/form/app/views/$model__camel$/form.scala.html b/web-modules/play-modules/async-http/.g8/form/app/views/$model__camel$/form.scala.html new file mode 100644 index 0000000000..7bf9fd5427 --- /dev/null +++ b/web-modules/play-modules/async-http/.g8/form/app/views/$model__camel$/form.scala.html @@ -0,0 +1,12 @@ +@($model;format="camel"$Form: Form[$model;format="Camel"$Data]) + +

$model;format="camel"$ form

+ +@flash.getOrDefault("success", "") + +@helper.form(action = routes.$model;format="Camel"$Controller.$model;format="camel"$Post()) { + @helper.CSRF.formField + @helper.inputText($model;format="camel"$Form("name")) + @helper.inputText($model;format="camel"$Form("age")) + +} diff --git a/web-modules/play-modules/async-http/.g8/form/default.properties b/web-modules/play-modules/async-http/.g8/form/default.properties new file mode 100644 index 0000000000..32090f30cb --- /dev/null +++ b/web-modules/play-modules/async-http/.g8/form/default.properties @@ -0,0 +1,2 @@ +description = Generates a Controller with form handling +model = user diff --git a/web-modules/play-modules/async-http/.g8/form/generated-test/README.md b/web-modules/play-modules/async-http/.g8/form/generated-test/README.md new file mode 100644 index 0000000000..db01c87f30 --- /dev/null +++ b/web-modules/play-modules/async-http/.g8/form/generated-test/README.md @@ -0,0 +1 @@ +Temporary file until g8-scaffold will generate "test" directory diff --git a/web-modules/play-modules/async-http/.g8/form/generated-test/controllers/$model__Camel$ControllerTest.java b/web-modules/play-modules/async-http/.g8/form/generated-test/controllers/$model__Camel$ControllerTest.java new file mode 100644 index 0000000000..7cdb87068b --- /dev/null +++ b/web-modules/play-modules/async-http/.g8/form/generated-test/controllers/$model__Camel$ControllerTest.java @@ -0,0 +1,50 @@ +package controllers; + +import org.junit.Test; +import play.Application; +import play.filters.csrf.*; +import play.inject.guice.GuiceApplicationBuilder; +import play.mvc.*; +import play.test.WithApplication; + +import java.util.HashMap; + +import static org.junit.Assert.assertEquals; +import static play.mvc.Http.RequestBuilder; +import static play.mvc.Http.Status.OK; +import static play.test.Helpers.*; +import static play.api.test.CSRFTokenHelper.*; + +public class $model;format="Camel"$ControllerTest extends WithApplication { + + @Override + protected Application provideApplication() { + return new GuiceApplicationBuilder().build(); + } + + @Test + public void test$model;format="Camel"$Get() { + RequestBuilder request = new RequestBuilder() + .method(GET) + .uri("/$model;format="camel"$"); + + Result result = route(app, request); + assertEquals(OK, result.status()); + } + + @Test + public void test$model;format="Camel"$Post() { + HashMap formData = new HashMap<>(); + formData.put("name", "play"); + formData.put("age", "4"); + RequestBuilder request = addCSRFToken(new RequestBuilder() + .header(Http.HeaderNames.HOST, "localhost") + .method(POST) + .bodyForm(formData) + .uri("/$model;format="camel"$")); + + Result result = route(app, request); + assertEquals(SEE_OTHER, result.status()); + } + +} diff --git a/web-modules/play-modules/async-http/.gitignore b/web-modules/play-modules/async-http/.gitignore new file mode 100644 index 0000000000..eb372fc719 --- /dev/null +++ b/web-modules/play-modules/async-http/.gitignore @@ -0,0 +1,8 @@ +logs +target +/.idea +/.idea_modules +/.classpath +/.project +/.settings +/RUNNING_PID diff --git a/web-modules/play-modules/async-http/README.md b/web-modules/play-modules/async-http/README.md new file mode 100644 index 0000000000..c42b86ad4e --- /dev/null +++ b/web-modules/play-modules/async-http/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Asynchronous HTTP Programming with Play Framework](https://www.baeldung.com/java-play-asynchronous-http-programming) diff --git a/web-modules/play-modules/async-http/app/controllers/HomeController.java b/web-modules/play-modules/async-http/app/controllers/HomeController.java new file mode 100644 index 0000000000..5c791dcd22 --- /dev/null +++ b/web-modules/play-modules/async-http/app/controllers/HomeController.java @@ -0,0 +1,38 @@ +package controllers; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.ImmutableMap; +import java.util.Collections; +import java.util.Map; +import play.mvc.Controller; +import play.mvc.Http; +import play.mvc.Result; + +/** + * This controller contains an action to handle HTTP requests to the application's home page. + */ +public class HomeController extends Controller { + + /** + * An action that renders an HTML page with a welcome message. The configuration in the + * routes file means that this method will be called when the application receives + * a + * GET request with a path of /. + */ + public Result index(Http.Request request) throws JsonProcessingException { + return ok(printStats(request)); + } + + private String printStats(Http.Request request) throws JsonProcessingException { + Map stringMap = request.body() + .asFormUrlEncoded(); + Map map = ImmutableMap.of( + "Result", "ok", + "GetParams", request.queryString(), + "PostParams", stringMap == null ? Collections.emptyMap() : stringMap, + "Headers", request.getHeaders().toMap() + ); + return new ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(map); + } +} diff --git a/web-modules/play-modules/async-http/build.sbt b/web-modules/play-modules/async-http/build.sbt new file mode 100644 index 0000000000..eea47ffe88 --- /dev/null +++ b/web-modules/play-modules/async-http/build.sbt @@ -0,0 +1,12 @@ +name := """async""" +organization := "com.example" + +version := "1.0-SNAPSHOT" + +lazy val root = (project in file(".")).enablePlugins(PlayJava) + +scalaVersion := "2.13.1" + +// comment out the original line +libraryDependencies += guice +libraryDependencies += javaWs diff --git a/web-modules/play-modules/async-http/conf/application.conf b/web-modules/play-modules/async-http/conf/application.conf new file mode 100644 index 0000000000..492f37fed7 --- /dev/null +++ b/web-modules/play-modules/async-http/conf/application.conf @@ -0,0 +1,11 @@ +# This is the main configuration file for the application. +# https://www.playframework.com/documentation/latest/ConfigFile +play.ws.followRedirects=false +play.ws.useragent=MyPlayApplication +play.ws.compressionEnabled=true +# time to wait for the connection to be established +play.ws.timeout.connection=30.seconds +# time to wait for data after the connection is open +play.ws.timeout.idle=30.seconds +# max time available to complete the request +play.ws.timeout.request=300.seconds diff --git a/web-modules/play-modules/async-http/conf/logback.xml b/web-modules/play-modules/async-http/conf/logback.xml new file mode 100644 index 0000000000..55441d39e2 --- /dev/null +++ b/web-modules/play-modules/async-http/conf/logback.xml @@ -0,0 +1,36 @@ + + + + + + + ${application.home:-.}/logs/application.log + + %date [%level] from %logger in %thread - %message%n%xException + + + + + + %coloredLevel %logger{15} - %message%n%xException{10} + + + + + + + + + + + + + + + + + + + + + diff --git a/web-modules/play-modules/async-http/conf/routes b/web-modules/play-modules/async-http/conf/routes new file mode 100644 index 0000000000..4f5162a8e7 --- /dev/null +++ b/web-modules/play-modules/async-http/conf/routes @@ -0,0 +1,10 @@ +# Routes +# This file defines all application routes (Higher priority routes first) +# ~~~~ + +# An example controller showing a sample home page +GET / controllers.HomeController.index(request: Request) +POST / controllers.HomeController.index(request: Request) + +# Map static resources from the /public folder to the /assets URL path +GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset) diff --git a/web-modules/play-modules/async-http/project/build.properties b/web-modules/play-modules/async-http/project/build.properties new file mode 100644 index 0000000000..6adcdc753f --- /dev/null +++ b/web-modules/play-modules/async-http/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.3.3 diff --git a/web-modules/play-modules/async-http/public/javascripts/main.js b/web-modules/play-modules/async-http/public/javascripts/main.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web-modules/play-modules/async-http/public/stylesheets/main.css b/web-modules/play-modules/async-http/public/stylesheets/main.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web-modules/play-modules/async-http/test/controllers/HomeControllerTest.java b/web-modules/play-modules/async-http/test/controllers/HomeControllerTest.java new file mode 100644 index 0000000000..a232dbfde0 --- /dev/null +++ b/web-modules/play-modules/async-http/test/controllers/HomeControllerTest.java @@ -0,0 +1,232 @@ +package controllers; + +import static java.time.temporal.ChronoUnit.SECONDS; +import static org.junit.Assert.assertEquals; +import static play.mvc.Http.Status.SERVICE_UNAVAILABLE; + +import akka.Done; +import akka.actor.ActorSystem; +import akka.stream.ActorMaterializer; +import akka.stream.javadsl.Sink; +import akka.util.ByteString; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.Duration; +import java.util.OptionalInt; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.IntStream; +import org.apache.http.HttpStatus; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import play.Application; +import play.inject.guice.GuiceApplicationBuilder; +import play.libs.concurrent.Futures; +import play.libs.ws.WSClient; +import play.libs.ws.WSResponse; +import play.libs.ws.ahc.AhcCurlRequestLogger; +import play.mvc.Result; +import play.mvc.Results; +import play.test.WithServer; + +public class HomeControllerTest extends WithServer { + + private final Logger log = LoggerFactory.getLogger(HomeControllerTest.class); + private String url; + private int port; + + @Override + protected Application provideApplication() { + return new GuiceApplicationBuilder().build(); + } + + @Before + public void setup() { + OptionalInt optHttpsPort = testServer.getRunningHttpsPort(); + if (optHttpsPort.isPresent()) { + port = optHttpsPort.getAsInt(); + url = "https://localhost:" + port; + } else { + port = testServer.getRunningHttpPort() + .getAsInt(); + url = "http://localhost:" + port; + } + } + + @Test + public void givenASingleGetRequestWhenResponseThenBlockWithCompletableAndLog() + throws Exception { + WSClient ws = play.test.WSTestClient.newClient(port); + WSResponse wsResponse = ws.url(url) + .setRequestFilter(new AhcCurlRequestLogger()) + .addHeader("key", "value") + .addQueryParameter("num", "" + 1) + .get() + .toCompletableFuture() + .get(); + + log.debug("Thread#" + Thread.currentThread() + .getId() + " Request complete: Response code = " + + wsResponse.getStatus() + + " | Response: " + wsResponse.getBody() + " | Current Time:" + + System.currentTimeMillis()); + assert (HttpStatus.SC_OK == wsResponse.getStatus()); + } + + @Test + public void givenASingleGetRequestWhenResponseThenLog() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + WSClient ws = play.test.WSTestClient.newClient(port); + ws.url(url) + .setRequestFilter(new AhcCurlRequestLogger()) + .addHeader("key", "value") + .addQueryParameter("num", "" + 1) + .get() + .thenAccept(r -> { + log.debug("Thread#" + Thread.currentThread() + .getId() + " Request complete: Response code = " + + r.getStatus() + + " | Response: " + r.getBody() + " | Current Time:" + System.currentTimeMillis()); + latch.countDown(); + }); + + log.debug( + "Waiting for requests to be completed. Current Time: " + System.currentTimeMillis()); + latch.await(5, TimeUnit.SECONDS ); + assertEquals(0, latch.getCount()); + log.debug("All requests have been completed. Exiting test."); + } + + @Test + public void givenASinglePostRequestWhenResponseThenLog() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + WSClient ws = play.test.WSTestClient.newClient(port); + ws.url(url) + .setContentType("application/x-www-form-urlencoded") + .post("key1=value1&key2=value2") + .thenAccept(r -> { + log.debug("Thread#" + Thread.currentThread() + .getId() + " Request complete: Response code = " + + r.getStatus() + + " | Response: " + r.getBody() + " | Current Time:" + System.currentTimeMillis()); + latch.countDown(); + }); + + log.debug( + "Waiting for requests to be completed. Current Time: " + System.currentTimeMillis()); + latch.await(5, TimeUnit.SECONDS ); + assertEquals(0, latch.getCount()); + log.debug("All requests have been completed. Exiting test."); + } + + @Test + public void givenMultipleRequestsWhenResponseThenLog() throws Exception { + CountDownLatch latch = new CountDownLatch(100); + WSClient ws = play.test.WSTestClient.newClient(port); + IntStream.range(0, 100) + .parallel() + .forEach(num -> + ws.url(url) + .setRequestFilter(new AhcCurlRequestLogger()) + .addHeader("key", "value") + .addQueryParameter("num", "" + num) + .get() + .thenAccept(r -> { + log.debug( + "Thread#" + num + " Request complete: Response code = " + r.getStatus() + + " | Response: " + r.getBody() + " | Current Time:" + + System.currentTimeMillis()); + latch.countDown(); + }) + ); + + log.debug( + "Waiting for requests to be completed. Current Time: " + System.currentTimeMillis()); + latch.await(5, TimeUnit.SECONDS ); + assertEquals(0, latch.getCount()); + log.debug("All requests have been completed. Exiting test."); + } + + @Test + public void givenLongResponseWhenTimeoutThenHandle() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + WSClient ws = play.test.WSTestClient.newClient(port); + Futures futures = app.injector() + .instanceOf(Futures.class); + CompletionStage f = futures.timeout( + ws.url(url) + .setRequestTimeout(Duration.of(1, SECONDS)) + .get() + .thenApply(result -> { + try { + Thread.sleep(2000L); + return Results.ok(); + } catch (InterruptedException e) { + return Results.status( + SERVICE_UNAVAILABLE); + } + }), 1L, TimeUnit.SECONDS + ); + CompletionStage res = f.handleAsync((result, e) -> { + if (e != null) { + log.error("Exception thrown", e); + latch.countDown(); + return e.getCause(); + } else { + return result; + } + }); + res.thenAccept(result -> assertEquals(TimeoutException.class, result)); + + log.debug( + "Waiting for requests to be completed. Current Time: " + System.currentTimeMillis()); + latch.await(5, TimeUnit.SECONDS ); + assertEquals(0, latch.getCount()); + log.debug("All requests have been completed. Exiting test."); + } + + @Test + public void givenMultigigabyteResponseConsumeWithStreams() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + final ActorSystem system = ActorSystem.create(); + final ActorMaterializer materializer = ActorMaterializer.create(system); + final Path path = Files.createTempFile("tmp_", ".out"); + + WSClient ws = play.test.WSTestClient.newClient(port); + log.info("Starting test server on url: " + url); + ws.url(url) + .stream() + .thenAccept( + response -> { + try { + OutputStream outputStream = java.nio.file.Files.newOutputStream(path); + Sink> outputWriter = + Sink.foreach(bytes -> { + log.info("Reponse: " + bytes.utf8String()); + outputStream.write(bytes.toArray()); + }); + + response.getBodyAsSource() + .runWith(outputWriter, materializer); + + } catch (IOException e) { + log.error("An error happened while opening the output stream", e); + } + }) + .whenComplete((value, error) -> latch.countDown()); + + log.debug( + "Waiting for requests to be completed. Current Time: " + System.currentTimeMillis()); + latch.await(5, TimeUnit.SECONDS ); + assertEquals(0, latch.getCount()); + log.debug("All requests have been completed. Exiting test."); + } +} diff --git a/web-modules/play-modules/introduction/public/javascripts/main.js b/web-modules/play-modules/introduction/public/javascripts/main.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web-modules/play-modules/introduction/public/stylesheets/main.css b/web-modules/play-modules/introduction/public/stylesheets/main.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web-modules/play-modules/routing-in-play/app/views/index.scala.html b/web-modules/play-modules/routing-in-play/app/views/index.scala.html new file mode 100644 index 0000000000..68d37fb1d4 --- /dev/null +++ b/web-modules/play-modules/routing-in-play/app/views/index.scala.html @@ -0,0 +1,5 @@ +@() + +@main("Welcome to Play") { +

Welcome to Play!

+} diff --git a/web-modules/play-modules/routing-in-play/app/views/main.scala.html b/web-modules/play-modules/routing-in-play/app/views/main.scala.html new file mode 100644 index 0000000000..c5f755f236 --- /dev/null +++ b/web-modules/play-modules/routing-in-play/app/views/main.scala.html @@ -0,0 +1,24 @@ +@* + * This template is called from the `index` template. This template + * handles the rendering of the page header and body tags. It takes + * two arguments, a `String` for the title of the page and an `Html` + * object to insert into the body of the page. + *@ +@(title: String)(content: Html) + + + + + @* Here's where we render the page title `String`. *@ + @title + + + + + @* And here's where we render the `Html` object containing + * the page content. *@ + @content + + + + diff --git a/web-modules/play-modules/routing-in-play/public/images/favicon.png b/web-modules/play-modules/routing-in-play/public/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..c7d92d2ae47434d9a61c90bc205e099b673b9dd5 GIT binary patch literal 687 zcmV;g0#N;lP)ezT{T_ZJ?}AL z5NC{NW(ESID=>(O3&Eg8 zmA9J&6c`h4_f6L;=bU>_H8aNG`kfvCj9zomNt)?O;rzWqZs0LEt%1WB218%1fo9uB zsW^yhBR7C(mqN%GEK9&msg0~ zWY?#bf4q8G-~2KttQZ($odJvy&_-~f?9*ThK@fwR$U^1)p*8=_+^3BXx0$i1BC8XC zr21u6D5nVK&^!dOAw&|1E;qC3uFNj3*Jj#&%Oje@0D-nhfmM*o%^5f}-pxQ07(95H z3|LoV>V19w#rLgmRmtVy9!T3M3FUE3><0T8&b3yEsWcLW`0(=1+qsqc(k(ymBLK0h zK!6(6$7MX~M`-QA2$wk7n(7hhkJ}4Rwi-Vd(_ZFX1Yk7TXuB0IJYpo@kLb2G8m)E{ z`9v=!hi}fOytKckfN^C@6+Z*+MVI9-W_p@_3yyR#UYc0FTpD}i#k>c!wYCS)4v@E$ zchZCo=zV@)`v^$;V18ixdjFMY#q^2$wEX%{f(XD8POnsn$bpbClpC@hPxjzyO>pY|*pF3UU2tYcCN?rUk{Sskej70Mmu9vPwMYhO1m{AxAt(zqDT|0jP7FaX=6 V`?~}E4H^Id002ovPDHLkV1hC)G==~G literal 0 HcmV?d00001 diff --git a/web-modules/play-modules/routing-in-play/public/javascripts/main.js b/web-modules/play-modules/routing-in-play/public/javascripts/main.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web-modules/play-modules/routing-in-play/public/stylesheets/main.css b/web-modules/play-modules/routing-in-play/public/stylesheets/main.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web-modules/play-modules/student-api/project/plugins.sbt b/web-modules/play-modules/student-api/project/plugins.sbt new file mode 100644 index 0000000000..1c8c62a0d5 --- /dev/null +++ b/web-modules/play-modules/student-api/project/plugins.sbt @@ -0,0 +1,7 @@ +// The Play plugin +addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.3") + +// Defines scaffolding (found under .g8 folder) +// http://www.foundweekends.org/giter8/scaffolding.html +// sbt "g8Scaffold form" +addSbtPlugin("org.foundweekends.giter8" % "sbt-giter8-scaffold" % "0.11.0") diff --git a/web-modules/play-modules/websockets/README.md b/web-modules/play-modules/websockets/README.md new file mode 100644 index 0000000000..d056b8f059 --- /dev/null +++ b/web-modules/play-modules/websockets/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [WebSockets with the Play Framework and Akka](https://www.baeldung.com/akka-play-websockets) diff --git a/web-modules/play-modules/websockets/app/actors/Messenger.java b/web-modules/play-modules/websockets/app/actors/Messenger.java new file mode 100644 index 0000000000..1c9335b82e --- /dev/null +++ b/web-modules/play-modules/websockets/app/actors/Messenger.java @@ -0,0 +1,111 @@ +package actors; + +import akka.actor.AbstractActor; +import akka.actor.ActorRef; +import akka.actor.PoisonPill; +import akka.actor.Props; +import akka.event.Logging; +import akka.event.LoggingAdapter; +import akka.http.javadsl.Http; +import akka.http.javadsl.marshallers.jackson.Jackson; +import akka.http.javadsl.model.HttpMessage; +import akka.http.javadsl.model.HttpRequest; +import akka.http.javadsl.model.HttpResponse; +import akka.stream.Materializer; +import com.fasterxml.jackson.databind.JsonNode; +import dto.MessageDTO; +import dto.RequestDTO; +import utils.MessageConverter; + +import java.time.OffsetDateTime; +import java.time.format.DateTimeFormatter; +import java.util.UUID; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ThreadLocalRandom; + +public class Messenger extends AbstractActor { + private LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this); + + private ActorRef out; + + public Messenger(ActorRef out) { + this.out = out; + } + + public static Props props(ActorRef out) { + return Props.create(Messenger.class, () -> new Messenger(out)); + } + + @Override + public void preStart() throws Exception { + log.info("Messenger actor started at {}", + OffsetDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)); + } + + @Override + public void postStop() throws Exception { + log.info("Messenger actor stopped at {}", + OffsetDateTime.now().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)); + } + + private void onSendMessage(JsonNode jsonNode) { + RequestDTO requestDTO = MessageConverter.jsonNodeToRequest(jsonNode); + String message = requestDTO.getMessage().toLowerCase(); + if("stop".equals(message)) { + MessageDTO messageDTO = createMessageDTO("1", "1", "Stop", "Stopping actor"); + out.tell(MessageConverter.messageToJsonNode(messageDTO), getSelf()); + self().tell(PoisonPill.getInstance(), getSelf()); + } else { + log.info("Actor received. {}", requestDTO); + processMessage(requestDTO); + } + } + + private MessageDTO createMessageDTO(String userId, String id, String title, String message) { + MessageDTO messageDTO = new MessageDTO(); + messageDTO.setUserId(UUID.randomUUID().toString()); + messageDTO.setId(UUID.randomUUID().toString()); + messageDTO.setTitle("Self Kill"); + messageDTO.setBody("Stopping actor"); + return messageDTO; + } + + private void processMessage(RequestDTO requestDTO) { + CompletionStage responseFuture = getRandomMessage(); + responseFuture.thenCompose(this::consumeHttpResponse) + .thenAccept(messageDTO -> + out.tell(MessageConverter.messageToJsonNode(messageDTO), getSelf())); + } + + private CompletionStage getRandomMessage() { + int postId = ThreadLocalRandom.current().nextInt(0, 100); + return Http.get(getContext().getSystem()).singleRequest( + HttpRequest.create("https://jsonplaceholder.typicode.com/posts/" + postId) + ); + } + + private void discardEntity(HttpResponse httpResponse, Materializer materializer) { + httpResponse.discardEntityBytes(materializer) + .completionStage() + .whenComplete((done, ex) -> log.info("Entity discarded completely!")); + } + + private CompletionStage consumeHttpResponse(HttpResponse httpResponse) { + Materializer materializer = Materializer.matFromSystem(getContext().getSystem()); + return Jackson.unmarshaller(MessageDTO.class) + .unmarshal(httpResponse.entity(), materializer) + .thenApply(messageDTO -> { + log.info("Received message: {}", messageDTO); + discardEntity(httpResponse, materializer); + return messageDTO; + }); + } + + @Override + public Receive createReceive() { + return receiveBuilder() + .match(JsonNode.class, this::onSendMessage) + .matchAny(o -> log.error("Received unknown message: {}", o.getClass())) + .build(); + } +} diff --git a/web-modules/play-modules/websockets/app/controllers/HomeController.java b/web-modules/play-modules/websockets/app/controllers/HomeController.java new file mode 100644 index 0000000000..39c670fe59 --- /dev/null +++ b/web-modules/play-modules/websockets/app/controllers/HomeController.java @@ -0,0 +1,79 @@ +package controllers; + +import actors.Messenger; +import akka.actor.ActorSystem; +import akka.stream.Materializer; +import akka.stream.javadsl.Flow; +import akka.stream.javadsl.Sink; +import akka.stream.javadsl.Source; +import com.fasterxml.jackson.databind.JsonNode; +import dto.MessageDTO; +import lombok.extern.slf4j.Slf4j; +import play.libs.F; +import play.libs.streams.ActorFlow; +import play.mvc.*; +import utils.MessageConverter; + +import javax.inject.Inject; + +import java.time.Duration; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; + +@Slf4j +public class HomeController extends Controller { + private ActorSystem actorSystem; + private Materializer materializer; + + @Inject + public HomeController(ActorSystem actorSystem, Materializer materializer) { + this.actorSystem = actorSystem; + this.materializer = materializer; + } + + public Result index(Http.Request request) { + String url = routes.HomeController.socket().webSocketURL(request); + //To test WebSockets with akka streams, uncomment the next line and comment out the previous + //String url = routes.HomeController.akkaStreamsSocket().webSocketURL(request); + return ok(views.html.index.render(url)); + } + + + public WebSocket socket() { + return WebSocket.Json.acceptOrResult(this::createActorFlow); + } + + private CompletionStage>> createActorFlow( + Http.RequestHeader request) { + return CompletableFuture.completedFuture(F.Either.Right(createFlowForActor())); + } + + private CompletionStage>> + createActorFlow2(Http.RequestHeader request) { + return CompletableFuture.completedFuture( + request.session() + .getOptional("username") + .map(username -> + F.Either.>Right( + createFlowForActor())) + .orElseGet(() -> F.Either.Left(forbidden()))); + } + + private Flow createFlowForActor() { + return ActorFlow.actorRef(out -> Messenger.props(out), actorSystem, materializer); + } + + public WebSocket akkaStreamsSocket() { + return WebSocket.Json.accept( + request -> { + Sink in = Sink.foreach(System.out::println); + MessageDTO messageDTO = new MessageDTO("1", "1", "Title", "Test Body"); + Source out = Source.tick( + Duration.ofSeconds(2), + Duration.ofSeconds(2), + MessageConverter.messageToJsonNode(messageDTO) + ); + return Flow.fromSinkAndSource(in, out); + }); + } +} diff --git a/web-modules/play-modules/websockets/app/dto/MessageDTO.java b/web-modules/play-modules/websockets/app/dto/MessageDTO.java new file mode 100644 index 0000000000..e6b2bac1af --- /dev/null +++ b/web-modules/play-modules/websockets/app/dto/MessageDTO.java @@ -0,0 +1,60 @@ +package dto; + +public class MessageDTO { + private String userId; + private String id; + private String title; + private String body; + + public MessageDTO() { + } + + public MessageDTO(String userId, String id, String title, String body) { + this.userId = userId; + this.id = id; + this.title = title; + this.body = body; + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } + + @Override + public String toString() { + return "MessageDTO{" + + "userId='" + userId + '\'' + + ", id='" + id + '\'' + + ", title='" + title + '\'' + + ", body='" + body + '\'' + + '}'; + } +} diff --git a/web-modules/play-modules/websockets/app/dto/RequestDTO.java b/web-modules/play-modules/websockets/app/dto/RequestDTO.java new file mode 100644 index 0000000000..a85d3770a4 --- /dev/null +++ b/web-modules/play-modules/websockets/app/dto/RequestDTO.java @@ -0,0 +1,27 @@ +package dto; + +public class RequestDTO { + private String message; + + public RequestDTO() { + } + + public RequestDTO(String message) { + this.message = message; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + @Override + public String toString() { + return "RequestDTO{" + + "message='" + message + '\'' + + '}'; + } +} diff --git a/web-modules/play-modules/websockets/app/utils/MessageConverter.java b/web-modules/play-modules/websockets/app/utils/MessageConverter.java new file mode 100644 index 0000000000..85729cd1da --- /dev/null +++ b/web-modules/play-modules/websockets/app/utils/MessageConverter.java @@ -0,0 +1,24 @@ +package utils; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import dto.MessageDTO; +import dto.RequestDTO; + +public class MessageConverter { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + public static MessageDTO jsonNodeToMessage(JsonNode jsonNode) { + return OBJECT_MAPPER.convertValue(jsonNode, MessageDTO.class); + } + + public static JsonNode messageToJsonNode(MessageDTO messageDTO) { + return OBJECT_MAPPER.convertValue(messageDTO, JsonNode.class); + } + public static RequestDTO jsonNodeToRequest(JsonNode jsonNode) { + return OBJECT_MAPPER.convertValue(jsonNode, RequestDTO.class); + } + + public static JsonNode requestToJsonNode(RequestDTO requestDTO) { + return OBJECT_MAPPER.convertValue(requestDTO, JsonNode.class); + } +} diff --git a/web-modules/play-modules/websockets/app/views/index.scala.html b/web-modules/play-modules/websockets/app/views/index.scala.html new file mode 100644 index 0000000000..b837fc6f74 --- /dev/null +++ b/web-modules/play-modules/websockets/app/views/index.scala.html @@ -0,0 +1,97 @@ +@(url: String) +@main("Welcome to Play") { +

Welcome to Play WebSockets!

+
+ + + + + + + + +} diff --git a/web-modules/play-modules/websockets/app/views/main.scala.html b/web-modules/play-modules/websockets/app/views/main.scala.html new file mode 100644 index 0000000000..be5dd8f09d --- /dev/null +++ b/web-modules/play-modules/websockets/app/views/main.scala.html @@ -0,0 +1,14 @@ +@(title: String)(content: Html) + + + + + @title + + + + + @content + + + diff --git a/web-modules/play-modules/websockets/build.sbt b/web-modules/play-modules/websockets/build.sbt new file mode 100644 index 0000000000..a076daa4f0 --- /dev/null +++ b/web-modules/play-modules/websockets/build.sbt @@ -0,0 +1,22 @@ +name := """websockets""" +organization := "com.baeldung" + +version := "1.0-SNAPSHOT" + +lazy val root = (project in file(".")).enablePlugins(PlayJava) + +scalaVersion := "2.13.0" + +lazy val akkaVersion = "2.6.0-M8" +lazy val akkaHttpVersion = "10.1.10" + +libraryDependencies += guice +libraryDependencies += "com.typesafe.akka" %% "akka-actor" % akkaVersion +libraryDependencies += "com.typesafe.akka" %% "akka-testkit" % akkaVersion +libraryDependencies += "com.typesafe.akka" %% "akka-stream" % akkaVersion +libraryDependencies += "com.typesafe.akka" %% "akka-http-jackson" % akkaHttpVersion +libraryDependencies += "com.typesafe.akka" %% "akka-http" % akkaHttpVersion +libraryDependencies += "org.projectlombok" % "lombok" % "1.18.8" % "provided" +libraryDependencies += "junit" % "junit" % "4.12" + +PlayKeys.devSettings += "play.server.http.idleTimeout" -> "infinite" diff --git a/web-modules/play-modules/websockets/conf/application.conf b/web-modules/play-modules/websockets/conf/application.conf new file mode 100644 index 0000000000..87cb978051 --- /dev/null +++ b/web-modules/play-modules/websockets/conf/application.conf @@ -0,0 +1,7 @@ +# This is the main configuration file for the application. +# https://www.playframework.com/documentation/latest/ConfigFile +######################################## +# akka-http-core Reference Config File # +######################################## + +play.server.http.idleTimeout = "infinite" \ No newline at end of file diff --git a/web-modules/play-modules/websockets/conf/logback.xml b/web-modules/play-modules/websockets/conf/logback.xml new file mode 100644 index 0000000000..8efb66cda3 --- /dev/null +++ b/web-modules/play-modules/websockets/conf/logback.xml @@ -0,0 +1,37 @@ + + + + + + + ${application.home:-.}/logs/application.log + + %date [%level] from %logger in %thread - %message%n%xException + + + + + + %coloredLevel %logger{15} - %message%n%xException{10} + + + + + + + + + + + + + + + + + + + + + + diff --git a/web-modules/play-modules/websockets/conf/routes b/web-modules/play-modules/websockets/conf/routes new file mode 100644 index 0000000000..674aba00bd --- /dev/null +++ b/web-modules/play-modules/websockets/conf/routes @@ -0,0 +1,11 @@ +# Routes +# This file defines all application routes (Higher priority routes first) +# ~~~~ + +# An example controller showing a sample home page +GET / controllers.HomeController.index(request: Request) +GET /chat controllers.HomeController.socket +GET /chat/with/streams controllers.HomeController.akkaStreamsSocket + +# Map static resources from the /public folder to the /assets URL path +GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset) diff --git a/web-modules/play-modules/websockets/project/build.properties b/web-modules/play-modules/websockets/project/build.properties new file mode 100644 index 0000000000..c0bab04941 --- /dev/null +++ b/web-modules/play-modules/websockets/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.2.8 diff --git a/web-modules/play-modules/websockets/project/plugins.sbt b/web-modules/play-modules/websockets/project/plugins.sbt new file mode 100644 index 0000000000..1c8c62a0d5 --- /dev/null +++ b/web-modules/play-modules/websockets/project/plugins.sbt @@ -0,0 +1,7 @@ +// The Play plugin +addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.7.3") + +// Defines scaffolding (found under .g8 folder) +// http://www.foundweekends.org/giter8/scaffolding.html +// sbt "g8Scaffold form" +addSbtPlugin("org.foundweekends.giter8" % "sbt-giter8-scaffold" % "0.11.0") diff --git a/web-modules/play-modules/websockets/public/images/favicon.png b/web-modules/play-modules/websockets/public/images/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..c7d92d2ae47434d9a61c90bc205e099b673b9dd5 GIT binary patch literal 687 zcmV;g0#N;lP)ezT{T_ZJ?}AL z5NC{NW(ESID=>(O3&Eg8 zmA9J&6c`h4_f6L;=bU>_H8aNG`kfvCj9zomNt)?O;rzWqZs0LEt%1WB218%1fo9uB zsW^yhBR7C(mqN%GEK9&msg0~ zWY?#bf4q8G-~2KttQZ($odJvy&_-~f?9*ThK@fwR$U^1)p*8=_+^3BXx0$i1BC8XC zr21u6D5nVK&^!dOAw&|1E;qC3uFNj3*Jj#&%Oje@0D-nhfmM*o%^5f}-pxQ07(95H z3|LoV>V19w#rLgmRmtVy9!T3M3FUE3><0T8&b3yEsWcLW`0(=1+qsqc(k(ymBLK0h zK!6(6$7MX~M`-QA2$wk7n(7hhkJ}4Rwi-Vd(_ZFX1Yk7TXuB0IJYpo@kLb2G8m)E{ z`9v=!hi}fOytKckfN^C@6+Z*+MVI9-W_p@_3yyR#UYc0FTpD}i#k>c!wYCS)4v@E$ zchZCo=zV@)`v^$;V18ixdjFMY#q^2$wEX%{f(XD8POnsn$bpbClpC@hPxjzyO>pY|*pF3UU2tYcCN?rUk{Sskej70Mmu9vPwMYhO1m{AxAt(zqDT|0jP7FaX=6 V`?~}E4H^Id002ovPDHLkV1hC)G==~G literal 0 HcmV?d00001 diff --git a/web-modules/play-modules/websockets/public/javascripts/main.js b/web-modules/play-modules/websockets/public/javascripts/main.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web-modules/play-modules/websockets/public/stylesheets/main.css b/web-modules/play-modules/websockets/public/stylesheets/main.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web-modules/play-modules/websockets/test/controllers/HomeControllerTest.java b/web-modules/play-modules/websockets/test/controllers/HomeControllerTest.java new file mode 100644 index 0000000000..b006feab8c --- /dev/null +++ b/web-modules/play-modules/websockets/test/controllers/HomeControllerTest.java @@ -0,0 +1,32 @@ +package controllers; + +import org.junit.Test; +import play.Application; +import play.inject.guice.GuiceApplicationBuilder; +import play.mvc.Http; +import play.mvc.Result; +import play.test.WithApplication; + +import static org.junit.Assert.assertEquals; +import static play.mvc.Http.Status.OK; +import static play.test.Helpers.GET; +import static play.test.Helpers.route; + +public class HomeControllerTest extends WithApplication { + + @Override + protected Application provideApplication() { + return new GuiceApplicationBuilder().build(); + } + + @Test + public void giveRequest_whenRootPath_ThenStatusOkay() { + Http.RequestBuilder request = new Http.RequestBuilder() + .method(GET) + .uri("/"); + + Result result = route(app, request); + assertEquals(OK, result.status()); + } + +} diff --git a/web-modules/pom.xml b/web-modules/pom.xml new file mode 100644 index 0000000000..2dcec681ad --- /dev/null +++ b/web-modules/pom.xml @@ -0,0 +1,52 @@ + + + 4.0.0 + web-modules + web-modules + pom + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + + + apache-tapestry + blade + bootique + dropwizard + google-web-toolkit + jakarta-ee + + javax-servlets + javax-servlets-2 + jee-7 + jooby + linkrest + + + + ratpack + resteasy + + spark-java + struts-2 + vraptor + wicket + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + diff --git a/web-modules/raml-modules/annotations/README.md b/web-modules/raml-modules/annotations/README.md new file mode 100644 index 0000000000..809a7a0ab1 --- /dev/null +++ b/web-modules/raml-modules/annotations/README.md @@ -0,0 +1,7 @@ +========= + +## Define Custom RAML + + +### Relevant Articles: +- [Define Custom RAML Properties Using Annotations](https://www.baeldung.com/raml-custom-properties-with-annotations) diff --git a/web-modules/raml-modules/modularization/README.md b/web-modules/raml-modules/modularization/README.md new file mode 100644 index 0000000000..bb7a3e889c --- /dev/null +++ b/web-modules/raml-modules/modularization/README.md @@ -0,0 +1,6 @@ +========= + +## Modular RESTful API Modeling Language + +### Relevant Articles: +- [Modular RAML Using Includes, Libraries, Overlays and Extensions](https://www.baeldung.com/modular-raml-includes-overlays-libraries-extensions) diff --git a/web-modules/raml-modules/resource-types-and-traits/README.md b/web-modules/raml-modules/resource-types-and-traits/README.md new file mode 100644 index 0000000000..973e59d7a5 --- /dev/null +++ b/web-modules/raml-modules/resource-types-and-traits/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Eliminate Redundancies in RAML with Resource Types and Traits](https://www.baeldung.com/simple-raml-with-resource-types-and-traits) diff --git a/web-modules/ratpack/README.md b/web-modules/ratpack/README.md new file mode 100644 index 0000000000..f42d4c030b --- /dev/null +++ b/web-modules/ratpack/README.md @@ -0,0 +1,14 @@ +## Ratpack + +This module contains articles about Ratpack. + +### Relevant articles + +- [Introduction to Ratpack](https://www.baeldung.com/ratpack) +- [Ratpack Google Guice Integration](https://www.baeldung.com/ratpack-google-guice) +- [Ratpack Integration with Spring Boot](http://www.baeldung.com/ratpack-spring-boot) +- [Ratpack with Hystrix](https://www.baeldung.com/ratpack-hystrix) +- [Ratpack HTTP Client](https://www.baeldung.com/ratpack-http-client) +- [Ratpack with RxJava](https://www.baeldung.com/ratpack-rxjava) +- [Ratpack with Groovy](https://www.baeldung.com/ratpack-groovy) +- [Reactive Streams API with Ratpack](https://www.baeldung.com/ratpack-reactive-streams-api) diff --git a/web-modules/ratpack/build.gradle b/web-modules/ratpack/build.gradle new file mode 100644 index 0000000000..f50c5b3800 --- /dev/null +++ b/web-modules/ratpack/build.gradle @@ -0,0 +1,37 @@ +buildscript { + repositories { + jcenter() + } + dependencies { + classpath "io.ratpack:ratpack-gradle:1.5.4" + classpath "com.h2database:h2:1.4.193" + } +} + +if (!JavaVersion.current().java8Compatible) { + throw new IllegalStateException("Must be built with Java 8 or higher") +} + +apply plugin: "io.ratpack.ratpack-java" +apply plugin: 'java' +apply plugin: 'groovy' +apply plugin: 'io.ratpack.ratpack-groovy' + +repositories { + jcenter() +} + +dependencies { + compile ratpack.dependency('hikari') + compile 'com.h2database:h2:1.4.193' + testCompile 'junit:junit:4.11' + runtime "org.slf4j:slf4j-simple:1.7.21" +} + +test { + testLogging { + events 'started', 'passed' + } +} + +mainClassName = "com.baeldung.Application" diff --git a/web-modules/ratpack/pom.xml b/web-modules/ratpack/pom.xml new file mode 100644 index 0000000000..1ef358cc55 --- /dev/null +++ b/web-modules/ratpack/pom.xml @@ -0,0 +1,111 @@ + + + 4.0.0 + ratpack + 1.0-SNAPSHOT + ratpack + jar + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + io.ratpack + ratpack-spring-boot-starter + ${ratpack.version} + pom + + + io.ratpack + ratpack-core + ${ratpack.version} + + + org.codehaus.groovy + groovy-sql + ${groovy.sql.version} + + + io.ratpack + ratpack-hikari + ${ratpack.version} + + + io.ratpack + ratpack-groovy-test + ${ratpack.test.latest.version} + + + io.ratpack + ratpack-hystrix + ${ratpack.version} + + + com.netflix.hystrix + hystrix-core + + + + + com.netflix.hystrix + hystrix-core + ${hystrix.version} + + + io.ratpack + ratpack-rx + ${ratpack.version} + + + io.ratpack + ratpack-test + ${ratpack.version} + test + + + com.h2database + h2 + ${h2.version} + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + org.apache.httpcomponents + httpcore + ${httpcore.version} + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + --add-opens java.base/java.lang=ALL-UNNAMED + + + + + + + + 1.9.0 + 4.5.3 + 4.4.6 + 1.5.12 + 2.4.15 + 1.6.1 + + + \ No newline at end of file diff --git a/web-modules/ratpack/src/main/java/com/baeldung/Application.java b/web-modules/ratpack/src/main/java/com/baeldung/Application.java new file mode 100644 index 0000000000..8035a1d0e3 --- /dev/null +++ b/web-modules/ratpack/src/main/java/com/baeldung/Application.java @@ -0,0 +1,82 @@ +package com.baeldung; + +import com.baeldung.filter.RequestValidatorFilter; +import com.baeldung.handler.EmployeeHandler; +import com.baeldung.handler.RedirectHandler; +import com.baeldung.model.Employee; +import com.baeldung.repository.EmployeeRepository; +import com.baeldung.repository.EmployeeRepositoryImpl; +import com.zaxxer.hikari.HikariConfig; +import io.netty.buffer.PooledByteBufAllocator; +import ratpack.exec.internal.DefaultExecController; +import ratpack.func.Action; +import ratpack.func.Function; +import ratpack.guice.BindingsSpec; +import ratpack.guice.Guice; +import ratpack.handling.Chain; +import ratpack.hikari.HikariModule; +import ratpack.http.client.HttpClient; +import ratpack.jackson.Jackson; +import ratpack.registry.Registry; +import ratpack.server.RatpackServer; +import ratpack.server.RatpackServerSpec; +import ratpack.server.ServerConfig; + +import java.time.Duration; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.List; + +public class Application { + + public static void main(String[] args) throws Exception { + + final Action hikariConfigAction = hikariConfig -> { + hikariConfig.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource"); + hikariConfig.addDataSourceProperty("URL", "jdbc:h2:mem:baeldung;INIT=RUNSCRIPT FROM 'classpath:/DDL.sql'"); + }; + + final Action bindingsSpecAction = bindings -> bindings.module(HikariModule.class, hikariConfigAction); + final HttpClient httpClient = HttpClient.of(httpClientSpec -> { + httpClientSpec.poolSize(10) + .connectTimeout(Duration.of(60, ChronoUnit.SECONDS)) + .maxContentLength(ServerConfig.DEFAULT_MAX_CONTENT_LENGTH) + .responseMaxChunkSize(16384) + .readTimeout(Duration.of(60, ChronoUnit.SECONDS)) + .byteBufAllocator(PooledByteBufAllocator.DEFAULT).execController(new DefaultExecController(2)); + }); + final Function registryFunction = Guice.registry(bindingsSpecAction); + + final Action chainAction = chain -> chain.all(new RequestValidatorFilter()) + .get(ctx -> ctx.render("Welcome to baeldung ratpack!!!")) + .get("data/employees", ctx -> ctx.render(Jackson.json(createEmpList()))) + .get(":name", ctx -> ctx.render("Hello " + ctx.getPathTokens() + .get("name") + "!!!")) + .post(":amount", ctx -> ctx.render(" Amount $" + ctx.getPathTokens() + .get("amount") + " added successfully !!!")); + + final Action routerChainAction = routerChain -> { + routerChain.path("redirect", new RedirectHandler()) + .prefix("employee", empChain -> { + empChain.get(":id", new EmployeeHandler()); + }); + }; + final Action ratpackServerSpecAction = serverSpec -> serverSpec.registry(registryFunction) + .registryOf(registrySpec -> { + registrySpec.add(EmployeeRepository.class, new EmployeeRepositoryImpl()); + registrySpec.add(HttpClient.class, httpClient); + }) + .handlers(chain -> chain.insert(routerChainAction) + .insert(chainAction)); + + RatpackServer.start(ratpackServerSpecAction); + } + + private static List createEmpList() { + List employees = new ArrayList<>(); + employees.add(new Employee(1L, "Mr", "John Doe")); + employees.add(new Employee(2L, "Mr", "White Snow")); + return employees; + } + +} diff --git a/web-modules/ratpack/src/main/java/com/baeldung/model/Quote.java b/web-modules/ratpack/src/main/java/com/baeldung/model/Quote.java new file mode 100644 index 0000000000..009a85fa11 --- /dev/null +++ b/web-modules/ratpack/src/main/java/com/baeldung/model/Quote.java @@ -0,0 +1,107 @@ +package com.baeldung.model; + +import java.time.Instant; + +public class Quote { + + private Instant ts; + private String symbol; + private double value; + + public Quote() {} + + + public Quote(Instant ts, String symbol, double value) { + this.ts = ts; + this.symbol = symbol; + this.value = value; + } + + + /** + * @return the ts + */ + public Instant getTs() { + return ts; + } + + /** + * @param ts the ts to set + */ + public void setTs(Instant ts) { + this.ts = ts; + } + + /** + * @return the symbol + */ + public String getSymbol() { + return symbol; + } + + /** + * @param symbol the symbol to set + */ + public void setSymbol(String symbol) { + this.symbol = symbol; + } + + /** + * @return the value + */ + public double getValue() { + return value; + } + + /** + * @param value the value to set + */ + public void setValue(double value) { + this.value = value; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((symbol == null) ? 0 : symbol.hashCode()); + result = prime * result + ((ts == null) ? 0 : ts.hashCode()); + long temp; + temp = Double.doubleToLongBits(value); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Quote other = (Quote) obj; + if (symbol == null) { + if (other.symbol != null) + return false; + } else if (!symbol.equals(other.symbol)) + return false; + if (ts == null) { + if (other.ts != null) + return false; + } else if (!ts.equals(other.ts)) + return false; + if (Double.doubleToLongBits(value) != Double.doubleToLongBits(other.value)) + return false; + return true; + } + + + @Override + public String toString() { + return "Quote [ts=" + ts + ", symbol=" + symbol + ", value=" + value + "]"; + } + + +} diff --git a/web-modules/ratpack/src/main/java/com/baeldung/repository/EmployeeRepository.java b/web-modules/ratpack/src/main/java/com/baeldung/repository/EmployeeRepository.java new file mode 100644 index 0000000000..2b23f91877 --- /dev/null +++ b/web-modules/ratpack/src/main/java/com/baeldung/repository/EmployeeRepository.java @@ -0,0 +1,10 @@ +package com.baeldung.repository; + +import com.baeldung.model.Employee; +import ratpack.exec.Promise; + +public interface EmployeeRepository { + + Promise findEmployeeById(Long id) throws Exception; + +} diff --git a/web-modules/ratpack/src/main/java/com/baeldung/rxjava/service/QuotesService.java b/web-modules/ratpack/src/main/java/com/baeldung/rxjava/service/QuotesService.java new file mode 100644 index 0000000000..7c073ee1de --- /dev/null +++ b/web-modules/ratpack/src/main/java/com/baeldung/rxjava/service/QuotesService.java @@ -0,0 +1,44 @@ +package com.baeldung.rxjava.service; + +import java.time.Duration; +import java.time.Instant; +import java.util.Random; +import java.util.concurrent.ScheduledExecutorService; + +import org.reactivestreams.Publisher; + +import com.baeldung.model.Quote; + +import ratpack.stream.Streams; + +public class QuotesService { + + private final ScheduledExecutorService executorService; + private static Random rnd = new Random(); + private static String[] symbols = new String[] { + "MSFT", + "ORCL", + "GOOG", + "AAPL", + "CSCO" + }; + + public QuotesService(ScheduledExecutorService executorService) { + this.executorService = executorService; + } + + public Publisher newTicker() { + return Streams.periodically(executorService, Duration.ofSeconds(2), (t) -> { + + return randomQuote(); + }); + } + + private static Quote randomQuote() { + return new Quote ( + Instant.now(), + symbols[rnd.nextInt(symbols.length)], + Math.round(rnd.nextDouble()*100) + ); + } +} diff --git a/web-modules/ratpack/src/main/java/com/baeldung/spring/EmbedRatpackStreamsApp.java b/web-modules/ratpack/src/main/java/com/baeldung/spring/EmbedRatpackStreamsApp.java new file mode 100644 index 0000000000..dc66efbecb --- /dev/null +++ b/web-modules/ratpack/src/main/java/com/baeldung/spring/EmbedRatpackStreamsApp.java @@ -0,0 +1,206 @@ +package com.baeldung.spring; + +import java.util.Random; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.atomic.AtomicLong; + +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; + +import com.baeldung.model.Quote; +import com.baeldung.rxjava.service.QuotesService; + +import groovy.util.logging.Slf4j; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import ratpack.func.Action; +import ratpack.handling.Chain; +import ratpack.http.ResponseChunks; +import ratpack.http.Status; +import ratpack.server.ServerConfig; +import ratpack.spring.config.EnableRatpack; +import ratpack.sse.ServerSentEvents; +import ratpack.stream.Streams; +import ratpack.stream.TransformablePublisher; +import ratpack.websocket.WebSockets; +import rx.subscriptions.Subscriptions; + +/** + * @author psevestre + */ +@SpringBootApplication +@EnableRatpack +public class EmbedRatpackStreamsApp { + + private static final Logger log = LoggerFactory.getLogger(EmbedRatpackStreamsApp.class); + + @Autowired + private QuotesService quotesService; + + private AtomicLong idSeq = new AtomicLong(0); + + + @Bean + public ScheduledExecutorService executorService() { + return Executors.newScheduledThreadPool(1); + } + + @Bean + public QuotesService quotesService(ScheduledExecutorService executor) { + return new QuotesService(executor); + } + + @Bean + public Action quotes() { + ServerSentEvents sse = ServerSentEvents.serverSentEvents(quotesService.newTicker(), (evt) -> { + evt + .id(Long.toString(idSeq.incrementAndGet())) + .event("quote") + .data( q -> q.toString()); + }); + + return chain -> chain.get("quotes", ctx -> ctx.render(sse)); + } + + @Bean + public Action quotesWS() { + Publisher pub = Streams.transformable(quotesService.newTicker()) + .map(Quote::toString); + return chain -> chain.get("quotes-ws", ctx -> WebSockets.websocketBroadcast(ctx, pub)); + } + + @Bean + public Action uploadFile() { + + return chain -> chain.post("upload", ctx -> { + TransformablePublisher pub = ctx.getRequest().getBodyStream(); + pub.subscribe(new Subscriber() { + private Subscription sub; + @Override + public void onSubscribe(Subscription sub) { + this.sub = sub; + sub.request(1); + } + + @Override + public void onNext(ByteBuf t) { + try { + int len = t.readableBytes(); + log.info("Got {} bytes", len); + + // Do something useful with data + + // Request next chunk + sub.request(1); + } + finally { + // DO NOT FORGET to RELEASE ! + t.release(); + } + } + + @Override + public void onError(Throwable t) { + ctx.getResponse().status(500); + } + + @Override + public void onComplete() { + ctx.getResponse().status(202); + } + }); + }); + } + + @Bean + public Action download() { + return chain -> chain.get("download", ctx -> { + ctx.getResponse().sendStream(new RandomBytesPublisher(1024,512)); + }); + } + + @Bean + public Action downloadChunks() { + return chain -> chain.get("downloadChunks", ctx -> { + ctx.render(ResponseChunks.bufferChunks("application/octetstream", + new RandomBytesPublisher(1024,512))); + }); + } + + @Bean + public ServerConfig ratpackServerConfig() { + return ServerConfig + .builder() + .findBaseDir("public") + .build(); + } + + public static void main(String[] args) { + SpringApplication.run(EmbedRatpackStreamsApp.class, args); + } + + + public static class RandomBytesPublisher implements Publisher { + + private int bufCount; + private int bufSize; + private Random rnd = new Random(); + + + RandomBytesPublisher(int bufCount, int bufSize) { + this.bufCount = bufCount; + this.bufSize = bufSize; + } + + @Override + public void subscribe(Subscriber s) { + s.onSubscribe(new Subscription() { + + private boolean cancelled = false; + private boolean recurse; + private long requested = 0; + + @Override + public void request(long n) { + if ( bufCount == 0 ) { + s.onComplete(); + return; + } + + requested += n; + if ( recurse ) { + return; + } + + recurse = true; + try { + while ( requested-- > 0 && !cancelled && bufCount-- > 0 ) { + byte[] data = new byte[bufSize]; + rnd.nextBytes(data); + ByteBuf buf = Unpooled.wrappedBuffer(data); + s.onNext(buf); + } + } + finally { + recurse = false; + } + } + + @Override + public void cancel() { + cancelled = true; + } + }); + + } + } + +} diff --git a/web-modules/ratpack/src/main/resources/logback.xml b/web-modules/ratpack/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/web-modules/ratpack/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/web-modules/ratpack/src/test/java/com/baeldung/ratpack/CompliantPublisher.java b/web-modules/ratpack/src/test/java/com/baeldung/ratpack/CompliantPublisher.java new file mode 100644 index 0000000000..5526a630ff --- /dev/null +++ b/web-modules/ratpack/src/test/java/com/baeldung/ratpack/CompliantPublisher.java @@ -0,0 +1,63 @@ +package com.baeldung.ratpack; + +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +// Non-thread safe !!! +class CompliantPublisher implements Publisher { + String name; + + private static final Logger log = LoggerFactory.getLogger(CompliantPublisher.class); + private long available; + + + public CompliantPublisher(long available) { + this.available = available; + } + + @Override + public void subscribe(Subscriber subscriber) { + log.info("subscribe"); + subscriber.onSubscribe(new CompliantSubscription(subscriber)); + + } + + + private class CompliantSubscription implements Subscription { + + private Subscriber subscriber; + private int recurseLevel; + private long requested; + private boolean cancelled; + + public CompliantSubscription(Subscriber subscriber) { + this.subscriber = subscriber; + } + + @Override + public void request(long n) { + log.info("request: requested={}, available={}", n, available); + requested += n; + if ( recurseLevel > 0 ) { + return; + } + + recurseLevel++; + for (int i = 0 ; i < (requested) && !cancelled && available > 0 ; i++, available-- ) { + subscriber.onNext(i); + } + subscriber.onComplete(); + } + + @Override + public void cancel() { + cancelled = true; + } + + } + +} \ No newline at end of file diff --git a/web-modules/ratpack/src/test/java/com/baeldung/ratpack/LoggingSubscriber.java b/web-modules/ratpack/src/test/java/com/baeldung/ratpack/LoggingSubscriber.java new file mode 100644 index 0000000000..0d58b7c05e --- /dev/null +++ b/web-modules/ratpack/src/test/java/com/baeldung/ratpack/LoggingSubscriber.java @@ -0,0 +1,67 @@ +package com.baeldung.ratpack; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class LoggingSubscriber implements Subscriber { + private static final Logger log = LoggerFactory.getLogger(LoggingSubscriber.class); + + private Subscription subscription; + private long requested; + private long received; + private CountDownLatch finished = new CountDownLatch(1); + + @Override + public void onComplete() { + log.info("onComplete: sub={}", subscription.hashCode()); + finished.countDown(); + } + + @Override + public void onError(Throwable t) { + log.error("Error: sub={}, message={}", subscription.hashCode(), t.getMessage(),t); + finished.countDown(); + } + + @Override + public void onNext(T value) { + log.info("onNext: sub={}, value={}", subscription.hashCode(), value); + this.received++; + this.requested++; + subscription.request(1); + } + + @Override + public void onSubscribe(Subscription sub) { + log.info("onSubscribe: sub={}", sub.hashCode()); + this.subscription = sub; + this.received = 0; + this.requested = 1; + sub.request(1); + } + + + public long getRequested() { + return requested; + } + + public long getReceived() { + return received; + } + + public void block() { + try { + finished.await(10, TimeUnit.SECONDS); + } + catch(InterruptedException iex) { + throw new RuntimeException(iex); + } + } + +} diff --git a/web-modules/ratpack/src/test/java/com/baeldung/ratpack/NonCompliantPublisher.java b/web-modules/ratpack/src/test/java/com/baeldung/ratpack/NonCompliantPublisher.java new file mode 100644 index 0000000000..03b94d429d --- /dev/null +++ b/web-modules/ratpack/src/test/java/com/baeldung/ratpack/NonCompliantPublisher.java @@ -0,0 +1,46 @@ +package com.baeldung.ratpack; + +import org.reactivestreams.Publisher; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class NonCompliantPublisher implements Publisher { + + private static final Logger log = LoggerFactory.getLogger(NonCompliantPublisher.class); + + @Override + public void subscribe(Subscriber subscriber) { + log.info("subscribe"); + subscriber.onSubscribe(new NonCompliantSubscription(subscriber)); + } + + private class NonCompliantSubscription implements Subscription { + private Subscriber subscriber; + private int recurseLevel = 0; + + public NonCompliantSubscription(Subscriber subscriber) { + this.subscriber = subscriber; + } + + @Override + public void request(long n) { + log.info("request: n={}", n); + if ( recurseLevel > 0 ) { + return; + } + + recurseLevel++; + for (int i = 0 ; i < (n + 5) ; i ++ ) { + subscriber.onNext(i); + } + subscriber.onComplete(); + } + + @Override + public void cancel() { + } + } +} \ No newline at end of file diff --git a/web-modules/ratpack/src/test/java/com/baeldung/ratpack/RatpackStreamsUnitTest.java b/web-modules/ratpack/src/test/java/com/baeldung/ratpack/RatpackStreamsUnitTest.java new file mode 100644 index 0000000000..54cc71c328 --- /dev/null +++ b/web-modules/ratpack/src/test/java/com/baeldung/ratpack/RatpackStreamsUnitTest.java @@ -0,0 +1,140 @@ +package com.baeldung.ratpack; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.time.Duration; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; + +import org.junit.jupiter.api.Test; +import org.reactivestreams.Publisher; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import ratpack.exec.ExecResult; +import ratpack.func.Action; +import ratpack.stream.StreamEvent; +import ratpack.stream.Streams; +import ratpack.stream.TransformablePublisher; +import ratpack.test.exec.ExecHarness; + +public class RatpackStreamsUnitTest { + + private static Logger log = LoggerFactory.getLogger(RatpackStreamsUnitTest.class); + + @Test + public void whenPublish_thenSuccess() { + + Publisher pub = Streams.publish(Arrays.asList("hello", "hello again")); + LoggingSubscriber sub = new LoggingSubscriber(); + pub.subscribe(sub); + sub.block(); + } + + + @Test + public void whenYield_thenSuccess() { + + Publisher pub = Streams.yield((t) -> { + return t.getRequestNum() < 5 ? "hello" : null; + }); + + LoggingSubscriber sub = new LoggingSubscriber(); + pub.subscribe(sub); + sub.block(); + assertEquals(5, sub.getReceived()); + } + + @Test + public void whenPeriodic_thenSuccess() { + ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); + Publisher pub = Streams.periodically(executor, Duration.ofSeconds(1), (t) -> { + return t < 5 ? String.format("hello %d",t): null; + }); + + LoggingSubscriber sub = new LoggingSubscriber(); + pub.subscribe(sub); + sub.block(); + assertEquals(5, sub.getReceived()); + } + + @Test + public void whenMap_thenSuccess() throws Exception { + + TransformablePublisher pub = Streams.yield( t -> { + return t.getRequestNum() < 5 ? t.getRequestNum() : null; + }) + .map(v -> String.format("item %d", v)); + + ExecResult> result = ExecHarness.yieldSingle((c) -> pub.toList() ); + assertTrue("should succeed", result.isSuccess()); + assertEquals("should have 5 items",5,result.getValue().size()); + } + + @Test + public void whenNonCompliantPublisherWithBuffer_thenSuccess() throws Exception { + + TransformablePublisher pub = Streams.transformable(new NonCompliantPublisher()) + .wiretap(new LoggingAction("before buffer")) + .buffer() + .wiretap(new LoggingAction("after buffer")) + .take(1); + + LoggingSubscriber sub = new LoggingSubscriber<>(); + pub.subscribe(sub); + sub.block(); + } + + @Test + public void whenNonCompliantPublisherWithoutBuffer_thenSuccess() throws Exception { + TransformablePublisher pub = Streams.transformable(new NonCompliantPublisher()) + .wiretap(new LoggingAction("")) + .take(1); + + LoggingSubscriber sub = new LoggingSubscriber<>(); + pub.subscribe(sub); + sub.block(); + } + +@Test +public void whenCompliantPublisherWithoutBatch_thenSuccess() throws Exception { + + TransformablePublisher pub = Streams.transformable(new CompliantPublisher(10)) + .wiretap(new LoggingAction("")); + + LoggingSubscriber sub = new LoggingSubscriber<>(); + pub.subscribe(sub); + sub.block(); +} + +@Test +public void whenCompliantPublisherWithBatch_thenSuccess() throws Exception { + + TransformablePublisher pub = Streams.transformable(new CompliantPublisher(10)) + .wiretap(new LoggingAction("before batch")) + .batch(5, Action.noop()) + .wiretap(new LoggingAction("after batch")); + + LoggingSubscriber sub = new LoggingSubscriber<>(); + pub.subscribe(sub); + sub.block(); +} + + private static class LoggingAction implements Action>{ + private final String label; + + public LoggingAction(String label) { + this.label = label; + } + + @Override + public void execute(StreamEvent e) throws Exception { + log.info("{}: event={}", label,e); + } + + } + +} diff --git a/web-modules/resteasy/pom.xml b/web-modules/resteasy/pom.xml new file mode 100644 index 0000000000..355dcdb9b5 --- /dev/null +++ b/web-modules/resteasy/pom.xml @@ -0,0 +1,135 @@ + + + 4.0.0 + resteasy + 1.0 + resteasy + war + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + + org.jboss.resteasy + resteasy-servlet-initializer + ${resteasy.version} + + + org.jboss.resteasy + resteasy-client + ${resteasy.version} + + + + org.jboss.resteasy + resteasy-jaxb-provider + ${resteasy.version} + + + org.jboss.resteasy + resteasy-jackson2-provider + ${resteasy.version} + + + javax.servlet + javax.servlet-api + 4.0.1 + + + + + resteasy + + + org.codehaus.cargo + cargo-maven2-plugin + ${cargo-maven2-plugin.version} + + true + + jetty8x + embedded + + + + 8082 + + + + + + + + + + live + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*IntegrationTest.java + **/*IntTest.java + + + **/*LiveTest.java + + + + + + + json + + + + + org.codehaus.cargo + cargo-maven2-plugin + ${cargo-maven2-plugin.version} + + false + + + + start-server + pre-integration-test + + start + + + + stop-server + post-integration-test + + stop + + + + + + + + + + + 4.7.2.Final + 1.6.1 + + + \ No newline at end of file diff --git a/web-modules/resteasy/src/main/resources/logback.xml b/web-modules/resteasy/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/web-modules/resteasy/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/web-modules/resteasy/src/main/webapp/WEB-INF/classes/logback.xml b/web-modules/resteasy/src/main/webapp/WEB-INF/classes/logback.xml new file mode 100644 index 0000000000..ec0dc2469a --- /dev/null +++ b/web-modules/resteasy/src/main/webapp/WEB-INF/classes/logback.xml @@ -0,0 +1,19 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + + + + + + \ No newline at end of file diff --git a/web-modules/restx/pom.xml b/web-modules/restx/pom.xml new file mode 100644 index 0000000000..0e6cb3fa78 --- /dev/null +++ b/web-modules/restx/pom.xml @@ -0,0 +1,144 @@ + + + 4.0.0 + restx + 0.1-SNAPSHOT + restx + war + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + io.restx + restx-core + ${restx.version} + + + io.restx + restx-security-basic + ${restx.version} + + + io.restx + restx-core-annotation-processor + ${restx.version} + + + io.restx + restx-factory + ${restx.version} + + + io.restx + restx-factory-admin + ${restx.version} + + + io.restx + restx-validation + ${restx.version} + + + io.restx + restx-monitor-codahale + ${restx.version} + + + io.restx + restx-monitor-admin + ${restx.version} + + + io.restx + restx-log-admin + ${restx.version} + + + io.restx + restx-i18n-admin + ${restx.version} + + + io.restx + restx-stats-admin + ${restx.version} + + + io.restx + restx-servlet + ${restx.version} + + + io.restx + restx-server-jetty8 + ${restx.version} + true + + + io.restx + restx-apidocs + ${restx.version} + + + io.restx + restx-specs-admin + ${restx.version} + + + io.restx + restx-admin + ${restx.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + io.restx + restx-specs-tests + ${restx.version} + test + + + junit + junit + + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-docs + + + + prepare-package + + jar + + + + + + + + + 0.35-rc4 + 1.6.0 + + + \ No newline at end of file diff --git a/web-modules/restx/src/main/resources/restx/demo/settings.properties b/web-modules/restx/src/main/resources/restx/demo/settings.properties new file mode 100644 index 0000000000..3b2b591922 --- /dev/null +++ b/web-modules/restx/src/main/resources/restx/demo/settings.properties @@ -0,0 +1,2 @@ +app.name=restx-demo +restx.stats.share.enable=false \ No newline at end of file diff --git a/web-modules/restx/src/test/java/restx/demo/rest/HelloResourceSpecIntegrationTest.java b/web-modules/restx/src/test/java/restx/demo/rest/HelloResourceSpecIntegrationTest.java new file mode 100644 index 0000000000..6ff1a7aad4 --- /dev/null +++ b/web-modules/restx/src/test/java/restx/demo/rest/HelloResourceSpecIntegrationTest.java @@ -0,0 +1,23 @@ +package restx.demo.rest; + +import org.junit.runner.RunWith; + +import restx.tests.FindSpecsIn; +import restx.tests.RestxSpecTestsRunner; + +@RunWith(RestxSpecTestsRunner.class) +@FindSpecsIn("specs/hello") +public class HelloResourceSpecIntegrationTest { + + /** + * Useless, thanks to both @RunWith(RestxSpecTestsRunner.class) & @FindSpecsIn() + * + * @Rule + * public RestxSpecRule rule = new RestxSpecRule(); + * + * @Test + * public void test_spec() throws Exception { + * rule.runTest(specTestPath); + * } + */ +} diff --git a/web-modules/spark-java/pom.xml b/web-modules/spark-java/pom.xml new file mode 100644 index 0000000000..da09467212 --- /dev/null +++ b/web-modules/spark-java/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + spark-java + 0.1.0-SNAPSHOT + spark-java + http://maven.apache.org + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + com.sparkjava + spark-core + ${sparkjava.spark-core.version} + + + + com.google.code.gson + gson + ${google.code.gson.version} + + + + + 2.5.4 + 2.8.0 + + + \ No newline at end of file diff --git a/web-modules/spark-java/src/main/resources/logback.xml b/web-modules/spark-java/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/web-modules/spark-java/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/web-modules/struts-2/WebContent/result.jsp b/web-modules/struts-2/WebContent/result.jsp new file mode 100644 index 0000000000..d095a493ec --- /dev/null +++ b/web-modules/struts-2/WebContent/result.jsp @@ -0,0 +1,11 @@ +<%@ page contentType="text/html; charset=UTF-8" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + +Hello World + + +

Hello Baeldung User

+

You are a

+ + diff --git a/web-modules/struts-2/pom.xml b/web-modules/struts-2/pom.xml new file mode 100644 index 0000000000..8b19bd530f --- /dev/null +++ b/web-modules/struts-2/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + struts-2 + struts-2 + pom + + + com.baeldung + parent-spring-4 + 0.0.1-SNAPSHOT + ../../parent-spring-4 + + + + + org.apache.struts + struts2-core + ${struts2.version} + + + org.apache.struts + struts2-junit-plugin + ${struts2.version} + + + org.apache.struts + struts2-convention-plugin + ${struts2-convention-plugin.version} + + + javax.servlet + javax.servlet-api + ${javax.servlet-api.version} + + + org.springframework + spring-core + ${spring.version} + + + commons-logging + commons-logging + + + + + + + src/main/java + + + src/main/resources + + + + + maven-war-plugin + ${maven-war-plugin.version} + + WebContent + + + + + + + 2.5.5 + 2.5.8 + 4.3.6.RELEASE + + + \ No newline at end of file diff --git a/web-modules/struts-2/src/main/resources/logback.xml b/web-modules/struts-2/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/web-modules/struts-2/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/web-modules/vraptor/pom.xml b/web-modules/vraptor/pom.xml new file mode 100644 index 0000000000..ecc6fe3313 --- /dev/null +++ b/web-modules/vraptor/pom.xml @@ -0,0 +1,127 @@ + + + 4.0.0 + vraptor + vraptor + war + A demo project to start using VRaptor 4 + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + br.com.caelum + vraptor + ${vraptor.version} + + + org.jboss.weld.servlet + weld-servlet-core + ${weld.version} + + + org.jboss.spec.javax.el + jboss-el-api_3.0_spec + + + + + org.jboss.weld + weld-core-impl + ${weld.version} + + + org.jboss.spec.javax.el + jboss-el-api_3.0_spec + + + + + javax.el + el-api + ${el.version} + provided + + + org.hibernate + hibernate-validator-cdi + ${hibernate-validator.version} + + + javax.servlet + jstl + ${jstl.version} + + + javax.servlet + javax.servlet-api + ${javax.servlet-api.version} + provided + + + org.slf4j + slf4j-log4j12 + ${org.slf4j.version} + + + br.com.caelum.vraptor + vraptor-freemarker + ${vraptor-freemarker.version} + + + br.com.caelum.vraptor + vraptor-hibernate + ${vraptor-hibernate.version} + + + mysql + mysql-connector-java + ${mysql-connector.version} + + + org.mindrot + jbcrypt + ${jbcrypt.version} + + + org.freemarker + freemarker + ${freemarker.version} + + + + + vraptor + src/main/webapp/WEB-INF/classes + + + org.apache.tomcat.maven + tomcat7-maven-plugin + ${tomcat7-maven-plugin.version} + + / + + + + + + + 4.2.0.Final + 2.1.2.Final + 2.2 + 5.1.1.Final + 4.1.0-RC3 + 4.0.4 + 8.0.8-dmr + 0.4 + 2.3.27-incubating + 2.1 + + + \ No newline at end of file diff --git a/web-modules/vraptor/src/main/java/com/baeldung/daos/UserDao.java b/web-modules/vraptor/src/main/java/com/baeldung/daos/UserDao.java new file mode 100644 index 0000000000..f5d5a46de9 --- /dev/null +++ b/web-modules/vraptor/src/main/java/com/baeldung/daos/UserDao.java @@ -0,0 +1,47 @@ +package com.baeldung.daos; + +import com.baeldung.models.User; +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.criterion.Restrictions; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; + +@RequestScoped +public class UserDao { + + SessionFactory sessionFactory; + + public UserDao() { + this(null); + } + + @Inject + public UserDao(SessionFactory sessionFactory) { + this.sessionFactory = sessionFactory; + } + + + public Object add(User user) { + Session session = sessionFactory.openSession(); + session.beginTransaction(); + Object Id = session.save(user); + session.getTransaction().commit(); + return Id; + } + + public User findByEmail(String email) { + Session session = sessionFactory.openSession(); + session.beginTransaction(); + Criteria criteria = session.createCriteria(User.class); + criteria.add(Restrictions.eq("email", email)); + criteria.setMaxResults(1); + User u = (User) criteria.uniqueResult(); + session.getTransaction().commit(); + session.close(); + return u; + } + +} diff --git a/web-modules/wicket/pom.xml b/web-modules/wicket/pom.xml new file mode 100644 index 0000000000..244d176e25 --- /dev/null +++ b/web-modules/wicket/pom.xml @@ -0,0 +1,89 @@ + + + 4.0.0 + com.baeldung.wicket.examples + wicket + 1.0-SNAPSHOT + wicket + war + + + com.baeldung + web-modules + 1.0.0-SNAPSHOT + + + + + + org.apache.wicket + wicket-core + ${wicket.version} + + + + org.eclipse.jetty.aggregate + jetty-all + ${jetty9.version} + test + + + + + + + false + src/main/resources + + + false + src/main/java + + ** + + + **/*.java + + + + + + false + src/test/resources + + + false + src/test/java + + ** + + + **/*.java + + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + false + + + + org.eclipse.jetty + jetty-maven-plugin + ${jetty9.version} + + + + + + 7.5.0 + 9.2.13.v20150730 + + + \ No newline at end of file diff --git a/web-modules/wicket/src/main/resources/logback.xml b/web-modules/wicket/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/web-modules/wicket/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file