Jelajahi Sumber

Merge branch 'master' of https://github.com/TechEmpower/FrameworkBenchmarks

Adam Chlipala 10 tahun lalu
induk
melakukan
21dce8a056
100 mengubah file dengan 2315 tambahan dan 718 penghapusan
  1. 15 10
      .travis.yml
  2. 24 0
      frameworks/Clojure/aleph/README.md
  3. 24 0
      frameworks/Clojure/aleph/benchmark_config.json
  4. 11 0
      frameworks/Clojure/aleph/hello/.gitignore
  5. 9 0
      frameworks/Clojure/aleph/hello/project.clj
  6. 44 0
      frameworks/Clojure/aleph/hello/src/hello/handler.clj
  7. 0 0
      frameworks/Clojure/aleph/hello/src/log4j.xml
  8. 3 0
      frameworks/Clojure/aleph/install.sh
  9. 10 0
      frameworks/Clojure/aleph/setup.sh
  10. 2 0
      frameworks/Clojure/aleph/source_code
  11. 10 29
      frameworks/Clojure/luminus/benchmark_config.json
  12. 3 4
      frameworks/Clojure/luminus/hello/.gitignore
  13. 1 0
      frameworks/Clojure/luminus/hello/Procfile
  14. 1 1
      frameworks/Clojure/luminus/hello/README.md
  15. 34 0
      frameworks/Clojure/luminus/hello/env/dev/clj/hello/repl.clj
  16. 48 39
      frameworks/Clojure/luminus/hello/project.clj
  17. 5 54
      frameworks/Clojure/luminus/hello/resources/public/css/screen.css
  18. 20 0
      frameworks/Clojure/luminus/hello/resources/sql/queries.sql
  19. 0 0
      frameworks/Clojure/luminus/hello/resources/templates/base.html
  20. 3 3
      frameworks/Clojure/luminus/hello/resources/templates/home.html
  21. 30 0
      frameworks/Clojure/luminus/hello/src/hello/core.clj
  22. 69 0
      frameworks/Clojure/luminus/hello/src/hello/db/core.clj
  23. 34 34
      frameworks/Clojure/luminus/hello/src/hello/handler.clj
  24. 37 0
      frameworks/Clojure/luminus/hello/src/hello/layout.clj
  25. 37 0
      frameworks/Clojure/luminus/hello/src/hello/middleware.clj
  26. 0 94
      frameworks/Clojure/luminus/hello/src/hello/models/db.clj
  27. 0 39
      frameworks/Clojure/luminus/hello/src/hello/models/schema.clj
  28. 24 50
      frameworks/Clojure/luminus/hello/src/hello/routes/home.clj
  29. 21 0
      frameworks/Clojure/luminus/hello/src/hello/session.clj
  30. 0 10
      frameworks/Clojure/luminus/hello/src/hello/views/layout.clj
  31. 2 4
      frameworks/Clojure/luminus/hello/test/hello/test/handler.clj
  32. 6 12
      frameworks/Clojure/luminus/setup.sh
  33. 23 14
      frameworks/Clojure/luminus/source_code
  34. 2 2
      frameworks/Java/netty/pom.xml
  35. 1 1
      frameworks/Java/play2-java/install.sh
  36. 2 2
      frameworks/Java/play2-java/play2-java-ebean-bonecp/build.sbt
  37. 1 1
      frameworks/Java/play2-java/play2-java-ebean-bonecp/project/plugins.sbt
  38. 3 3
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/build.sbt
  39. 46 18
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/conf/application.conf
  40. 1 1
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/project/plugins.sbt
  41. 3 3
      frameworks/Java/play2-java/play2-java-jpa-bonecp/build.sbt
  42. 1 1
      frameworks/Java/play2-java/play2-java-jpa-bonecp/project/plugins.sbt
  43. 4 4
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/build.sbt
  44. 47 19
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf
  45. 1 1
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/plugins.sbt
  46. 1 1
      frameworks/Java/play2-java/play2-java/build.sbt
  47. 1 1
      frameworks/Java/play2-java/play2-java/project/plugins.sbt
  48. 1 1
      frameworks/Java/play2-java/setup_java.sh
  49. 1 1
      frameworks/Java/play2-java/setup_java_ebean_bonecp.sh
  50. 1 1
      frameworks/Java/play2-java/setup_java_ebean_hikaricp.sh
  51. 1 1
      frameworks/Java/play2-java/setup_java_jpa_bonecp.sh
  52. 1 1
      frameworks/Java/play2-java/setup_java_jpa_hikaricp.sh
  53. 78 2
      frameworks/Java/sabina/benchmark_config.json
  54. 3 0
      frameworks/Java/sabina/jetty-mongodb.sh
  55. 3 0
      frameworks/Java/sabina/jetty.sh
  56. 6 1
      frameworks/Java/sabina/pom.xml
  57. 1 1
      frameworks/Java/sabina/setup.sh
  58. 59 134
      frameworks/Java/sabina/src/main/java/sabina/benchmark/Application.java
  59. 0 5
      frameworks/Java/sabina/src/main/java/sabina/benchmark/Fortune.java
  60. 91 0
      frameworks/Java/sabina/src/main/java/sabina/benchmark/MongoDbRepository.java
  61. 139 0
      frameworks/Java/sabina/src/main/java/sabina/benchmark/MySqlRepository.java
  62. 22 0
      frameworks/Java/sabina/src/main/java/sabina/benchmark/Repository.java
  63. 5 2
      frameworks/Java/sabina/src/main/resources/server.properties
  64. 13 28
      frameworks/Java/sabina/src/test/java/sabina/benchmark/ApplicationTest.java
  65. 3 0
      frameworks/Java/sabina/undertow-mongodb.sh
  66. 3 0
      frameworks/Java/sabina/undertow.sh
  67. 1 1
      frameworks/Java/undertow/install.sh
  68. 10 10
      frameworks/Java/undertow/pom.xml
  69. 2 2
      frameworks/Java/undertow/setup.sh
  70. 2 0
      frameworks/Java/undertow/src/main/java/hello/HelloWebServer.java
  71. 43 6
      frameworks/Java/vertx/README.md
  72. 139 38
      frameworks/Java/vertx/WebServer.java
  73. 1 1
      frameworks/Java/vertx/app.js
  74. 2 0
      frameworks/Java/vertx/benchmark_config.json
  75. 1 1
      frameworks/Java/vertx/install.sh
  76. 51 21
      frameworks/Lua/openresty/app.lua
  77. 2 1
      frameworks/Lua/openresty/benchmark_config.json
  78. 3 1
      frameworks/Lua/openresty/install.sh
  79. 11 2
      frameworks/Lua/openresty/nginx.conf
  80. 1 1
      frameworks/PHP/codeigniter/install.sh
  81. 63 0
      frameworks/PHP/cygnite-php-framework/.gitignore
  82. 28 0
      frameworks/PHP/cygnite-php-framework/.htaccess
  83. 8 0
      frameworks/PHP/cygnite-php-framework/.travis.yml
  84. 20 0
      frameworks/PHP/cygnite-php-framework/LICENSE
  85. 54 0
      frameworks/PHP/cygnite-php-framework/README.md
  86. 1 0
      frameworks/PHP/cygnite-php-framework/apps/.htaccess
  87. 0 0
      frameworks/PHP/cygnite-php-framework/apps/components/authentication/.gitkeep
  88. 0 0
      frameworks/PHP/cygnite-php-framework/apps/components/form/.gitkeep
  89. 235 0
      frameworks/PHP/cygnite-php-framework/apps/configs/application.php
  90. 35 0
      frameworks/PHP/cygnite-php-framework/apps/configs/autoload.php
  91. 55 0
      frameworks/PHP/cygnite-php-framework/apps/configs/database.php
  92. 77 0
      frameworks/PHP/cygnite-php-framework/apps/configs/definitions/DefinitionManager.php
  93. 69 0
      frameworks/PHP/cygnite-php-framework/apps/configs/migration.php
  94. 27 0
      frameworks/PHP/cygnite-php-framework/apps/configs/services.php
  95. 105 0
      frameworks/PHP/cygnite-php-framework/apps/configs/session.php
  96. 94 0
      frameworks/PHP/cygnite-php-framework/apps/controllers/BenchController.php
  97. 80 0
      frameworks/PHP/cygnite-php-framework/apps/controllers/HomeController.php
  98. 0 0
      frameworks/PHP/cygnite-php-framework/apps/database/.gitkeep
  99. 0 0
      frameworks/PHP/cygnite-php-framework/apps/database/migrations/.gitkeep
  100. 0 0
      frameworks/PHP/cygnite-php-framework/apps/extensions/.gitkeep

+ 15 - 10
.travis.yml

@@ -1,5 +1,5 @@
 language: python
-python: 
+python:
   - "2.7"
 
 env:
@@ -9,12 +9,12 @@ env:
     # we end up starting ~200+ different workers. Seems that ~100 is the limit
     # before their website starts to lag heavily
     #
-    # Here's the bash if you need to update this. Be sure to maintain the 
+    # Here's the bash if you need to update this. Be sure to maintain the
     # lines that are currently commented out (these cannot run in Travis)
-    #   cd frameworks 
+    #   cd frameworks
     #   find . -type d -depth 2 | sed 's|./|    - "TESTDIR=|' | sed 's/$/"/g'
     #
-    #  
+    #
     - "TESTDIR=C/lwan"
     - "TESTDIR=C/duda"
     - "TESTDIR=C/haywire"
@@ -34,6 +34,7 @@ env:
     - "TESTDIR=Clojure/http-kit"
     - "TESTDIR=Clojure/luminus"
     - "TESTDIR=Clojure/pedestal"
+    - "TESTDIR=Clojure/aleph"
     - "TESTDIR=Dart/dart"
     - "TESTDIR=Dart/dart-redstone"
     - "TESTDIR=Dart/dart-start"
@@ -98,6 +99,7 @@ env:
     - "TESTDIR=PHP/cakephp"
     - "TESTDIR=PHP/hhvm"
     - "TESTDIR=PHP/php"
+    - "TESTDIR=PHP/cygnite-php-framework"
     - "TESTDIR=PHP/codeigniter"
     - "TESTDIR=PHP/php-fatfree"
     - "TESTDIR=PHP/fuel"
@@ -126,6 +128,7 @@ env:
     - "TESTDIR=Python/django"
     - "TESTDIR=Python/falcon"
     - "TESTDIR=Python/flask"
+    - "TESTDIR=Python/historical"
     - "TESTDIR=Python/klein"
     - "TESTDIR=Python/pyramid"
     - "TESTDIR=Python/tornado"
@@ -142,6 +145,8 @@ env:
     - "TESTDIR=Ruby/rails"
     - "TESTDIR=Ruby/rails-stripped"
     - "TESTDIR=Ruby/sinatra"
+    - "TESTDIR=Scala/akka-http"
+    - "TESTDIR=Scala/colossus"
     - "TESTDIR=Scala/finagle"
     - "TESTDIR=Scala/lift-stateless"
     - "TESTDIR=Scala/plain"
@@ -155,7 +160,7 @@ env:
     - "TESTDIR=Ur/urweb"
 
 before_install:
-  # Need to install python modules before using 
+  # Need to install python modules before using
   # python
   - pip install -r requirements.txt
 
@@ -164,15 +169,15 @@ before_install:
   - ./toolset/run-ci.py cisetup "$TESTDIR"
 
 addons:
-  postgresql: "9.3" 
+  postgresql: "9.3"
 
 install:
   # Install prerequisites
   - ./toolset/run-ci.py prereq "$TESTDIR"
-  
-  # Install software for this framework  
+
+  # Install software for this framework
   - ./toolset/run-ci.py install "$TESTDIR"
-   
-script: 
+
+script:
   # Pick one test in this directory and verify
   - time ./toolset/run-ci.py verify "$TESTDIR"

+ 24 - 0
frameworks/Clojure/aleph/README.md

@@ -0,0 +1,24 @@
+# Compojure Benchmarking Test
+
+This is the [Aleph](https;//github.com/ztellman/aleph) portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+
+* [JSON test source](hello/src/hello/handler.clj)
+
+## Infrastructure Software Versions
+The dependencies are documented in [project.clj](hello/project.clj),
+but the main ones are:
+
+* [Aleph 0.4.0](https://github.com/ztellman/aleph)
+* [Clojure 1.7.0-beta2](http://clojure.org/)
+* [Cheshire 5.4.0](https://github.com/dakrone/cheshire), which in turn uses [Jackson](http://jackson.codehaus.org/)
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost/json
+
+### Plaintext Test
+
+http://localhost/plaintext

+ 24 - 0
frameworks/Clojure/aleph/benchmark_config.json

@@ -0,0 +1,24 @@
+{
+  "framework": "aleph",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "None",
+      "framework": "aleph",
+      "language": "Clojure",
+      "orm": "Raw",
+      "platform": "Netty",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "aleph",
+      "notes": "",
+      "versus": "netty"
+    }
+  }]
+}

+ 11 - 0
frameworks/Clojure/aleph/hello/.gitignore

@@ -0,0 +1,11 @@
+/target
+/lib
+/classes
+/checkouts
+pom.xml
+*.jar
+*.class
+.lein-deps-sum
+.lein-failures
+.lein-plugins
+.lein-env

+ 9 - 0
frameworks/Clojure/aleph/hello/project.clj

@@ -0,0 +1,9 @@
+(defproject hello "aleph"
+  :description "JSON/plaintext tests"
+  :dependencies [[org.clojure/clojure "1.7.0-beta2"]
+                 [clj-tuple "0.2.1"]
+                 [org.clojure/tools.cli "0.3.1"]
+                 [aleph "0.4.0"]
+                 [cheshire "5.4.0"]]
+  :main hello.handler
+  :aot :all)

+ 44 - 0
frameworks/Clojure/aleph/hello/src/hello/handler.clj

@@ -0,0 +1,44 @@
+(ns hello.handler
+  (:require
+    [byte-streams :as bs]
+    [clojure.tools.cli :as cli]
+    [aleph.http :as http]
+    [cheshire.core :as json]
+    [clj-tuple :as t])
+  (:gen-class))
+
+(def plaintext-response
+  (t/hash-map
+    :status 200
+    :headers (t/hash-map "content-type" "text/plain; charset=utf-8")
+    :body (bs/to-byte-array "Hello, World!")))
+
+(def json-response
+  (t/hash-map
+    :status 200
+    :headers (t/hash-map "content-type" "application/json")))
+
+(defn handler [{:keys [uri] :as req}]
+  (cond
+    (= "/plaintext" uri) plaintext-response
+    (= "/json" uri) (assoc json-response
+                      :body (json/encode (t/hash-map :message "Hello, World!")))
+    :else {:status 404}))
+
+;;;
+
+(defn -main [& args]
+
+  (let [[{:keys [help port]} _ banner]
+        (cli/cli args
+          ["-p" "--port" "Server port"
+           :default 8080
+           :parse-fn #(Integer/parseInt %)]
+          ["-h" "--[no-]help"])]
+
+    (when help
+      (println banner)
+      (System/exit 0))
+
+    (aleph.netty/leak-detector-level! :disabled)
+    (http/start-server handler {:port port, :executor :none})))

+ 0 - 0
frameworks/Clojure/luminus/hello/src/log4j.xml → frameworks/Clojure/aleph/hello/src/log4j.xml


+ 3 - 0
frameworks/Clojure/aleph/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends java7 leiningen

+ 10 - 0
frameworks/Clojure/aleph/setup.sh

@@ -0,0 +1,10 @@
+#!/bin/bash
+
+source $IROOT/java7.installed
+
+source $IROOT/lein.installed
+
+cd hello
+lein clean
+lein uberjar
+java -server -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=10 -jar target/*-standalone.jar &

+ 2 - 0
frameworks/Clojure/aleph/source_code

@@ -0,0 +1,2 @@
+./aleph/hello/src/hello/handler.clj
+./aleph/hello/project.clj

+ 10 - 29
frameworks/Clojure/luminus/benchmark_config.json

@@ -3,45 +3,26 @@
   "tests": [{
     "default": {
       "setup_file": "setup",
-      "json_url": "/luminus/json",
-      "db_url": "/luminus/db",
-      "query_url": "/luminus/db/",
-      "fortune_url": "/luminus/fortune",
-      "update_url": "/luminus/update/",
-      "plaintext_url": "/luminus/plaintext",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries/",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates/",
+      "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MySQL",
-      "framework": "luminus",
-      "language": "Clojure",
-      "orm": "Full",
-      "platform": "Servlet",
-      "webserver": "Resin",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "luminus",
-      "notes": "",
-      "versus": "servlet"
-    },
-    "raw": {
-      "setup_file": "setup",
-      "db_url": "/luminus/dbraw",
-      "query_url": "/luminus/dbraw/",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Micro",
+      "classification": "Platform",
       "database": "MySQL",
       "framework": "luminus",
       "language": "Clojure",
       "orm": "Raw",
-      "platform": "Servlet",
-      "webserver": "Resin",
+      "platform": "http-kit",
+      "webserver": "None",
       "os": "Linux",
       "database_os": "Linux",
       "display_name": "luminus",
       "notes": "",
-      "versus": "servlet"
+      "versus": ""
     }
   }]
 }

+ 3 - 4
frameworks/Clojure/luminus/hello/.gitignore

@@ -5,7 +5,6 @@
 pom.xml
 *.jar
 *.class
-.lein-deps-sum
-.lein-failures
-.lein-plugins
-.lein-env
+/.lein-*
+/.env
+*.log

+ 1 - 0
frameworks/Clojure/luminus/hello/Procfile

@@ -0,0 +1 @@
+web: java $JVM_OPTS -cp target/hello.jar clojure.main -m hello.core

+ 1 - 1
frameworks/Clojure/luminus/hello/README.md

@@ -16,4 +16,4 @@ To start a web server for the application, run:
 
 ## License
 
-Copyright © 2013 FIXME
+Copyright © 2015 FIXME

+ 34 - 0
frameworks/Clojure/luminus/hello/env/dev/clj/hello/repl.clj

@@ -0,0 +1,34 @@
+(ns hello.repl
+  (:use hello.handler
+    ring.server.standalone
+    [ring.middleware file-info file]))
+
+(defonce server (atom nil))
+
+(defn get-handler []
+  ;; #'app expands to (var app) so that when we reload our code,
+  ;; the server is forced to re-resolve the symbol in the var
+  ;; rather than having its own copy. When the root binding
+  ;; changes, the server picks it up without having to restart.
+  (-> #'app
+      ; Makes static assets in $PROJECT_DIR/resources/public/ available.
+      (wrap-file "resources")
+      ; Content-Type, Content-Length, and Last Modified headers for files in body
+      (wrap-file-info)))
+
+(defn start-server
+  "used for starting the server in development mode from REPL"
+  [& [port]]
+  (let [port (if port (Integer/parseInt port) 3000)]
+    (reset! server
+            (serve (get-handler)
+                   {:port port
+                    :init init
+                    :auto-reload? true
+                    :destroy destroy
+                    :join? false}))
+    (println (str "You can view the site at http://localhost:" port))))
+
+(defn stop-server []
+  (.stop @server)
+  (reset! server nil))

+ 48 - 39
frameworks/Clojure/luminus/hello/project.clj

@@ -1,40 +1,49 @@
-(defproject
-  hello
-  "luminus"
-  :dependencies
-  [[org.clojure/clojure "1.5.1"]
-   [lib-noir "0.8.2"]
-   [compojure "1.1.6"]
-   [ring-server "0.3.1"]
-   [selmer "0.5.7"]
-   [com.taoensso/timbre "2.7.1"]
-   [com.postspectacular/rotor "0.1.0"]
-   [com.taoensso/tower "2.0.2"]
-   [mysql/mysql-connector-java "5.1.28"]
-   [korma "0.3.0-RC6"]
-   [c3p0/c3p0 "0.9.1.2"]
-   [log4j
-    "1.2.17"
-    :exclusions
-    [javax.mail/mail
-     javax.jms/jms
-     com.sun.jdmk/jmxtools
-     com.sun.jmx/jmxri]]]
-  :ring
-  {:handler hello.handler/app,
-   :init hello.handler/init,
-   :destroy hello.handler/destroy}
+(defproject hello "luminus"
+
+  :description "Luminus framework benchmarks"
+  :url "https://github.com/TechEmpower/FrameworkBenchmarks/tree/master/frameworks/Clojure/luminus"
+
+  :dependencies [[org.clojure/clojure "1.6.0"]
+                 [ring-server "0.4.0"]
+                 [selmer "0.8.2"]
+                 [com.taoensso/timbre "3.4.0"]
+                 [com.taoensso/tower "3.0.2"]
+                 [markdown-clj "0.9.65"]
+                 [environ "1.0.0"]
+                 [im.chit/cronj "1.4.3"]
+                 [compojure "1.3.3"]
+                 [ring/ring-defaults "0.1.4"]
+                 [ring/ring-session-timeout "0.1.0"]
+                 [ring-middleware-format "0.5.0"]
+                 [noir-exception "0.2.3"]
+                 [bouncer "0.3.2"]
+                 [prone "0.8.1"]
+                 [org.clojure/tools.nrepl "0.2.8"]
+                 [yesql "0.5.0-rc2"]
+                 [mysql/mysql-connector-java "5.1.6"]
+                 [c3p0/c3p0 "0.9.1.2"]
+                 [http-kit "2.1.19"]
+                 [org.clojure/tools.cli "0.2.1"]]
+
+  :min-lein-version "2.0.0"
+  :uberjar-name "hello.jar"
+  :jvm-opts ["-server"]
+
+  :main hello.core
+
+  :plugins [[lein-ring "0.9.1"]
+            [lein-environ "1.0.0"]]
+
   :profiles
-  {:uberjar {:aot :all}
-   :production
-   {:ring
-    {:open-browser? false, :stacktraces? false, :auto-reload? false}},
-   :dev
-   {:dependencies [[ring-mock "0.1.5"] [ring/ring-devel "1.2.2"]]}}
-  :url
-  "http://example.com/FIXME"
-  :plugins
-  [[lein-ring "0.8.10"]]
-  :description
-  "FIXME: write description"
-  :min-lein-version "2.0.0")
+  {:uberjar {:omit-source true
+             :env {:production true}
+             :aot :all}
+   :dev {:dependencies [[ring-mock "0.1.5"]
+                        [ring/ring-devel "1.3.2"]
+                        [pjstadig/humane-test-output "0.7.0"]]
+         :source-paths ["env/dev/clj"]
+
+         :repl-options {:init-ns hello.repl}
+         :injections [(require 'pjstadig.humane-test-output)
+                      (pjstadig.humane-test-output/activate!)]
+         :env {:dev true}}})

+ 5 - 54
frameworks/Clojure/luminus/hello/resources/public/css/screen.css

@@ -1,55 +1,6 @@
-body {	
-    background-color: #fff;
-    color: #333;
-    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+html,
+body {
+	font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
+    height: 100%;
+    padding-top: 40px;
 }
-
-#register {
-    float: left;
-    display: inline-block;
-}
-
-h1 {
-    -webkit-border-radius: 4px;
-    -moz-border-radius: 4px;
-	background-color: #E9E9E9;
-	border: 1px solid #CFCFCF;
-	border-radius: 4px;
-}
-
-.nav li {
-    float: left;
-    list-style: none;
-    padding: 5px;
-}
-
-.navbar {
-    text-align: right;
-    padding: 5px;
-    margin-bottom: 10px;
-}
-
-#container {
-    height: auto;
-    margin-bottom: 10px;
-}
-
-#footer {    
-    width: 95%;
-    margin-left: 1%;
-    margin-right: 1%;
-    position:absolute;
-    bottom:0;
-    font-size: 11px;
-    font-weight: bold;
-    height: auto;    
-    text-align: center;
-    
-	padding-top: 10px;
-	
-	-webkit-border-radius: 4px;
-    -moz-border-radius: 4px;
-	background-color: #E9E9E9;
-	border: 1px solid #CFCFCF;
-	border-radius: 4px;
-}

+ 20 - 0
frameworks/Clojure/luminus/hello/resources/sql/queries.sql

@@ -0,0 +1,20 @@
+--name: get-world
+-- Query a World record from the database
+SELECT * FROM world
+WHERE id = :id
+
+--name: get-all-fortunes
+-- select all records from the fortune table
+SELECT * FROM fortune
+
+--name: update-world<!
+-- update an existing world record
+UPDATE world
+SET randomNumber = :randomNumber
+WHERE id = :id
+
+--name: get-all-fortunes
+-- query all fortune records
+SELECT id, message FROM fortune
+
+

+ 0 - 0
frameworks/Clojure/luminus/hello/src/hello/views/templates/base.html → frameworks/Clojure/luminus/hello/resources/templates/base.html


+ 3 - 3
frameworks/Clojure/luminus/hello/src/hello/views/templates/home.html → frameworks/Clojure/luminus/hello/resources/templates/home.html

@@ -1,4 +1,4 @@
-{% extends "hello/views/templates/base.html" %}
+{% extends "base.html" %}
 
 {% block content %}
 
@@ -13,6 +13,6 @@
     <td>{{message.message}}</td>
   </tr>
   {% endfor %}
-</table>  
-  
+</table>
+
 {% endblock %}

+ 30 - 0
frameworks/Clojure/luminus/hello/src/hello/core.clj

@@ -0,0 +1,30 @@
+(ns hello.core
+  (:require [hello.handler :refer [app init]]
+            [clojure.tools.cli :refer [cli]]
+            [org.httpkit.server :refer [run-server]])
+  (:gen-class))
+
+(defn parse-port [s]
+  "Convert stringy port number int. Defaults to 8080."
+  (cond
+    (string? s) (Integer/parseInt s)
+    (instance? Integer s) s
+    (instance? Long s) (.intValue ^Long s)
+    :else 8080))
+
+(defn start-server [{:keys [port]}]
+  (let [cpu (.availableProcessors (Runtime/getRuntime))]
+    ;; double worker threads should increase database access performance
+    (init)
+    (run-server app {:port port :thread (* 2 cpu)})
+    (println (str "http-kit server listens at :" port))))
+
+(defn -main [& args]
+  (let [[options _ banner]
+        (cli args
+             ["-p" "--port" "Port to listen" :default 8080 :parse-fn parse-port]
+             ["--[no-]help" "Print this help"])]
+    (when (:help options)
+          (println banner)
+          (System/exit 0))
+    (start-server options)))

+ 69 - 0
frameworks/Clojure/luminus/hello/src/hello/db/core.clj

@@ -0,0 +1,69 @@
+(ns hello.db.core
+  (:require
+    [yesql.core :refer [defqueries]])
+  (:import com.mchange.v2.c3p0.ComboPooledDataSource))
+
+(def db-spec
+  {:classname "com.mysql.jdbc.Driver"
+   :subprotocol "mysql"
+   :subname "//localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
+   :user "benchmarkdbuser"
+   :password "benchmarkdbpass"})
+
+(defn pool
+  [spec]
+  {:datasource
+   (doto (ComboPooledDataSource.)
+     (.setDriverClass (:classname spec))
+     (.setJdbcUrl (str "jdbc:" (:subprotocol spec) ":" (:subname spec)))
+     (.setUser (:user spec))
+     (.setPassword (:password spec))
+     ;; expire excess connections after 30 minutes of inactivity:
+     (.setMaxIdleTimeExcessConnections (* 30 60))
+     ;; expire connections after 3 hours of inactivity:
+     (.setMaxIdleTime (* 3 60 60)))})
+
+(defonce db (atom nil))
+
+(defn connect! []
+  (reset! db (pool db-spec)))
+
+(defqueries "sql/queries.sql")
+
+(defn get-world-random
+  "Query a random World record between 1 and 10,000 from the database"
+  []
+  (get-world {:id (inc (rand-int 9999))} {:connection @db}))
+
+(defn get-query-count [queries]
+  "Parse provided string value of query count, clamping values to between 1 and 500."
+  (let [n (try (Integer/parseInt queries)
+               (catch Exception e 1))] ; default to 1 on parse failure
+    (cond
+      (< n 1) 1
+      (> n 500) 500
+      :else n)))
+
+(defn run-queries
+  "Run the specified number of queries, return the results"
+  [queries]
+  (flatten (repeatedly (get-query-count queries) get-world-random)))
+
+(defn get-fortunes []
+   "Fetch the full list of Fortunes from the database, sort them by the fortune
+  message text, and then return the results."
+  (sort-by
+   :message
+   (conj (get-all-fortunes {} {:connection @db})
+         {:id 0 :message "Additional fortune added at request time."})))
+
+(defn update-and-persist
+  "Changes the :randomNumber of a number of world entities.
+  Persists the changes to sql then returns the updated entities"
+  [queries]
+  (for [world (-> queries run-queries)]
+    (let [updated-world (assoc world :randomNumber (inc (rand-int 9999)))]
+      (update-world<! updated-world {:connection @db})
+      updated-world)))
+
+

+ 34 - 34
frameworks/Clojure/luminus/hello/src/hello/handler.clj

@@ -1,20 +1,20 @@
 (ns hello.handler
-  (:use hello.routes.home
-        compojure.core)
-  (:require [noir.util.middleware :as middleware]
+  (:require [compojure.core :refer [defroutes routes]]
+            [hello.routes.home :refer [home-routes]]
+            [hello.db.core :as db]
+            [hello.middleware
+             :refer [development-middleware production-middleware]]
+            [hello.session :as session]
             [compojure.route :as route]
             [taoensso.timbre :as timbre]
-            [taoensso.timbre.appenders.rotor :as rotor]))
-
-
-(defroutes app-routes
-  (route/resources "/")
-  (route/not-found "Not Found"))
-
-
-(defn destroy []
-  (timbre/info "picture-gallery is shutting down"))
+            [taoensso.timbre.appenders.rotor :as rotor]
+            [selmer.parser :as parser]
+            [environ.core :refer [env]]
+            [cronj.core :as cronj]))
 
+(defroutes base-routes
+           (route/resources "/")
+           (route/not-found "Not Found"))
 
 (defn init
   "init will be called once when
@@ -24,34 +24,34 @@
   []
   (timbre/set-config!
     [:appenders :rotor]
-    {:min-level :info
-     :enabled? true
-     :async? false ; should be always false for rotor
+    {:min-level             :info
+     :enabled?              true
+     :async?                false ; should be always false for rotor
      :max-message-per-msecs nil
-     :fn rotor/appender-fn})
+     :fn                    rotor/appender-fn})
 
   (timbre/set-config!
     [:shared-appender-config :rotor]
-    {:path "{{sanitized}}.log" :max-size (* 512 1024) :backlog 10})
-
-  (timbre/info "hello started successfully"))
+    {:path "hello.log" :max-size (* 512 1024) :backlog 10})
 
+  (if (env :dev) (parser/cache-off!))
+  (db/connect!)
+  ;;start the expired session cleanup job
+  (cronj/start! session/cleanup-job)
+  (timbre/info "\n-=[ hello started successfully"
+               (when (env :dev) "using the development profile") "]=-"))
 
 (defn destroy
   "destroy will be called when your application
    shuts down, put any clean up code here"
   []
-  (timbre/info "hello is shutting down..."))
-
-
-(def app (middleware/app-handler
-           ;; add your application routes here
-           [home-routes app-routes]
-           ;; add custom middleware here
-           :middleware []
-           ;; add access rules here
-           :access-rules []
-           ;; serialize/deserialize the following data formats
-           ;; available formats:
-           ;; :json :json-kw :yaml :yaml-kw :edn :yaml-in-html
-           :formats [:json-kw :edn]))
+  (timbre/info "hello is shutting down...")
+  (cronj/shutdown! session/cleanup-job)
+  (timbre/info "shutdown complete!"))
+
+(def app
+  (-> (routes
+        home-routes
+        base-routes)
+      development-middleware
+      production-middleware))

+ 37 - 0
frameworks/Clojure/luminus/hello/src/hello/layout.clj

@@ -0,0 +1,37 @@
+(ns hello.layout
+  (:require [selmer.parser :as parser]
+            [selmer.filters :as filters]
+            [markdown.core :refer [md-to-html-string]]
+            [ring.util.response :refer [content-type response]]
+            [compojure.response :refer [Renderable]]
+            [ring.util.anti-forgery :refer [anti-forgery-field]]
+            [ring.middleware.anti-forgery :refer [*anti-forgery-token*]]
+            [environ.core :refer [env]]))
+
+(parser/set-resource-path!  (clojure.java.io/resource "templates"))
+
+(parser/add-tag! :csrf-field (fn [_ _] (anti-forgery-field)))
+(filters/add-filter! :markdown (fn [content] [:safe (md-to-html-string content)]))
+
+(deftype RenderableTemplate [template params]
+  Renderable
+  (render [this request]
+    (content-type
+      (->> (assoc params
+                  :page template
+                  :dev (env :dev)
+                  :csrf-token *anti-forgery-token*
+                  :servlet-context
+                  (if-let [context (:servlet-context request)]
+                    ;; If we're not inside a serlvet environment (for
+                    ;; example when using mock requests), then
+                    ;; .getContextPath might not exist
+                    (try (.getContextPath context)
+                         (catch IllegalArgumentException _ context))))
+        (parser/render-file (str template))
+        response)
+      "text/html; charset=utf-8")))
+
+(defn render [template & [params]]
+  (RenderableTemplate. template params))
+

+ 37 - 0
frameworks/Clojure/luminus/hello/src/hello/middleware.clj

@@ -0,0 +1,37 @@
+(ns hello.middleware
+  (:require [hello.session :as session]
+            [taoensso.timbre :as timbre]
+            [environ.core :refer [env]]
+            [selmer.middleware :refer [wrap-error-page]]
+            [prone.middleware :refer [wrap-exceptions]]
+            [ring.util.response :refer [redirect]]
+            [ring.middleware.defaults :refer [site-defaults wrap-defaults]]
+            [ring.middleware.session-timeout :refer [wrap-idle-session-timeout]]
+            [noir-exception.core :refer [wrap-internal-error]]
+            [ring.middleware.session.memory :refer [memory-store]]
+            [ring.middleware.format :refer [wrap-restful-format]]
+            
+            ))
+
+(defn log-request [handler]
+  (fn [req]
+    (timbre/debug req)
+    (handler req)))
+
+(defn development-middleware [handler]
+  (if (env :dev)
+    (-> handler
+        wrap-error-page
+        wrap-exceptions)
+    handler))
+
+(defn production-middleware [handler]
+  (-> handler
+      
+      (wrap-restful-format :formats [:json-kw :edn :transit-json :transit-msgpack])
+      (wrap-idle-session-timeout
+        {:timeout (* 60 30)
+         :timeout-response (redirect "/")})
+      (wrap-defaults
+        (assoc-in site-defaults [:session :store] (memory-store session/mem)))
+      (wrap-internal-error :log #(timbre/error %))))

+ 0 - 94
frameworks/Clojure/luminus/hello/src/hello/models/db.clj

@@ -1,94 +0,0 @@
-(ns hello.models.db
-  (:use korma.core
-         hello.models.schema)
-  (:require [clojure.java.jdbc :as jdbc]))
-
-
-
-; Set up entity World and the database representation
-(defentity world
-  (pk :id)
-  (table :world)
-  (entity-fields :id :randomNumber)
-  (database db))
-
-
-(defn get-world
-  "Query a random World record from the database"
-  []
-  (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
-    (select world
-            (fields :id :randomNumber)
-            (where {:id id }))))
-
-
-(defn get-world-raw
-  "Query a random World record from the database"
-  []
-  (let [id (inc (rand-int 9999))] ; Num between 1 and 10,000
-    (jdbc/with-connection (db-raw)
-      ; Set a naming strategy to preserve column name case
-      (jdbc/with-naming-strategy {:keyword identity}
-        (jdbc/with-query-results rs [(str "select * from world where id = ?") id]
-          (doall rs))))))
-
-
-(defn run-queries
-  "Run the specified number of queries, return the results"
-  [queries]
-  (flatten ; Make it a list of maps
-    (take queries
-          (repeatedly get-world))))
-
-
-(defn run-queries-raw [queries]
-  "Run the specified number of queries, return the results"
-  (flatten ; Make it a list of maps
-    (take queries
-          (repeatedly get-world-raw))))
-
-
-(defn get-query-count [queries]
-  "Parse provided string value of query count, clamping values to between 1 and 500."
-  (let [q (try (Integer/parseInt queries)
-               (catch Exception e 1))] ; default to 1 on parse failure
-    (if (> q 500)
-      500 ; clamp to 500 max
-      (if (< q 1)
-        1 ; clamp to 1 min
-        q)))) ; otherwise use provided value
-
-
-; Set up entity World and the database representation
-(defentity fortune
-  (pk :id)
-  (table :fortune)
-  (entity-fields :id :message)
-  (database db))
-
-
-(def get-all-fortunes
-  "Query all Fortune records from the database."
-  (select fortune
-          (fields :id :message)))
-
-
-(def get-fortunes
-  "Fetch the full list of Fortunes from the database. Insert an additional fortune at runtime.
-  Then sort all by fortune message text. Return the results."
-  (let [fortunes (conj get-all-fortunes
-                       {:id 0 :message "Additional fortune added at request time."})]
-    (sort-by :message fortunes)))
-
-
-(defn update-and-persist
-  "Changes the :randomNumber of a number of world entities.
-  Persists the changes to sql then returns the updated entities"
-  [queries]
-  (let [results (run-queries queries)]
-    (for [w results]
-      (update-in w [:randomNumber (inc (rand-int 9999))]
-        (update world
-                (set-fields {:randomNumber (:randomNumber w)})
-                (where {:id [:id w]}))))
-    results))

+ 0 - 39
frameworks/Clojure/luminus/hello/src/hello/models/schema.clj

@@ -1,39 +0,0 @@
-(ns hello.models.schema
-  (:require [korma.db :refer [defdb mysql]]
-            [clojure.java.jdbc :as sql])
-  (:import com.mchange.v2.c3p0.ComboPooledDataSource))
-
-; Database connection for java.jdbc "raw"
-; https://github.com/clojure/java.jdbc/blob/master/doc/clojure/java/jdbc/ConnectionPooling.md
-(def db-spec-mysql-raw
-  {:classname "com.mysql.jdbc.Driver"
-   :subprotocol "mysql"
-   :subname "//localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
-   :user "benchmarkdbuser"
-   :password "benchmarkdbpass"})
-
-; Database connection
-(defdb db (mysql {:subname "//localhost:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
-                  :user "benchmarkdbuser"
-                  :password "benchmarkdbpass"
-                  ;;OPTIONAL KEYS
-                  :delimiters "" ;; remove delimiters
-                  :maximum-pool-size 256
-                  }))
-                  
-(defn pool
-  [spec]
-  (let [cpds (doto (ComboPooledDataSource.)
-               (.setDriverClass (:classname spec))
-               (.setJdbcUrl (str "jdbc:" (:subprotocol spec) ":" (:subname spec)))
-               (.setUser (:user spec))
-               (.setPassword (:password spec))
-               ;; expire excess connections after 30 minutes of inactivity:
-               (.setMaxIdleTimeExcessConnections (* 30 60))
-               ;; expire connections after 3 hours of inactivity:
-               (.setMaxIdleTime (* 3 60 60)))]
-    {:datasource cpds}))
-
-(def pooled-db (delay (pool db-spec-mysql-raw)))
-
-(defn db-raw [] @pooled-db)

+ 24 - 50
frameworks/Clojure/luminus/hello/src/hello/routes/home.clj

@@ -1,75 +1,49 @@
 (ns hello.routes.home
-  (:use compojure.core
-        hello.models.db)
-  (:require [hello.views.layout :as layout]
-            [noir.response :as response]))
-
+  (:require [hello.layout :as layout]
+            [hello.db.core :as db]
+            [compojure.core :refer [defroutes GET]]
+            [ring.util.response :refer [response]]
+            [clojure.java.io :as io]))
 
 (def json-serialization
   "Test 1: JSON serialization"
-  (response/json {:message "Hello, World!"}))
-
+  (response {:message "Hello, World!"}))
 
-(def single-query-test
+(defn single-query-test
   "Test 2: Single database query"
-  (response/json (first (run-queries 1))))
-
+  []
+  (-> 1 db/run-queries first response))
 
 (defn multiple-query-test
   "Test 3: Multiple database query"
   [queries]
   (-> queries
-      (get-query-count)
-      (run-queries)
-      (response/json)))
-
+      db/run-queries
+      response))
 
-(def single-query-test-raw
-  "Test 2: Single database query (raw)"
-  (-> 1
-      (run-queries-raw)
-      (first)
-      (response/json)))
-
-
-(defn multiple-query-test-raw
-  "Test 3: Multiple database query (raw)"
-  [queries]
-  (-> queries
-      (get-query-count)
-      (run-queries-raw)
-      (response/json)))
-
-
-(def fortunes
+(defn fortunes
   "Test 4: Fortunes"
-  (layout/render "home.html"
-                 {:messages get-fortunes}))
-
+  []
+  (layout/render "home.html" {:messages (db/get-fortunes)}))
 
 (defn db-update
   "Test 5: Database updates"
   [queries]
   (-> queries
-      (get-query-count)
-      (update-and-persist)
-      (response/json)))
-
+      db/update-and-persist
+      response))
 
 (def plaintext
   "Test 6: Plaintext"
   {:status 200
-   :headers {"Content-Type" "text/plain; charset=utf-8"}
+   :headers {"Content-Type" "text/plain"}
    :body "Hello, World!"})
 
-
 (defroutes home-routes
-  (GET "/"                [] "Hello, World!")
-  (GET "/plaintext"       [] plaintext)
-  (GET "/json"            [] json-serialization)
-  (GET "/db"              [] single-query-test)
-  (GET "/db/:queries"     [queries] (multiple-query-test queries))
-  (GET "/dbraw"           [] single-query-test-raw)
-  (GET "/dbraw/:queries"  [queries] (multiple-query-test-raw queries))
-  (GET "/fortune"         [] fortunes)
-  (GET "/update/:queries" [queries] (db-update queries)))
+  (GET "/"                 [] "Hello, World!")
+  (GET "/plaintext"        [] plaintext)
+  (GET "/json"             [] json-serialization)
+  (GET "/db"               [] (single-query-test))
+  (GET "/queries/:queries" [queries] (multiple-query-test queries))
+  (GET "/fortunes"         [] (fortunes))
+  (GET "/updates/:queries"  [queries] (db-update queries)))

+ 21 - 0
frameworks/Clojure/luminus/hello/src/hello/session.clj

@@ -0,0 +1,21 @@
+(ns hello.session
+  (:require [cronj.core :refer [cronj]]))
+
+(defonce mem (atom {}))
+
+(defn- current-time []
+  (quot (System/currentTimeMillis) 1000))
+
+(defn- expired? [[id session]]
+  (pos? (- (:ring.middleware.session-timeout/idle-timeout session) (current-time))))
+
+(defn clear-expired-sessions []
+  (clojure.core/swap! mem #(->> % (filter expired?) (into {}))))
+
+(def cleanup-job
+  (cronj
+    :entries
+    [{:id "session-cleanup"
+      :handler (fn [_ _] (clear-expired-sessions))
+      :schedule "* /30 * * * * *"
+      :opts {}}]))

+ 0 - 10
frameworks/Clojure/luminus/hello/src/hello/views/layout.clj

@@ -1,10 +0,0 @@
-(ns hello.views.layout
-  (:use noir.request)
-  (:require [selmer.parser :as parser]))
-
-(def template-path "hello/views/templates/")
-
-(defn render [template & [params]]
-  (parser/render-file (str template-path template)
-                      (assoc params :context (:context *request*))))
-

+ 2 - 4
frameworks/Clojure/luminus/hello/test/hello/test/handler.clj

@@ -6,10 +6,8 @@
 (deftest test-app
   (testing "main route"
     (let [response (app (request :get "/"))]
-      (is (= (:status response) 200))
-      (is (= (:body response)
-             "Hello, World!"))))
+      (is (= 200 (:status response)))))
 
   (testing "not-found route"
     (let [response (app (request :get "/invalid"))]
-      (is (= (:status response) 404)))))
+      (is (= 404 (:status response))))))

+ 6 - 12
frameworks/Clojure/luminus/setup.sh

@@ -1,19 +1,13 @@
 #!/bin/bash
-
 source $IROOT/java7.installed
-
 source $IROOT/lein.installed
 
-export RESIN_HOME=${IROOT}/resin-4.0.41
-
-# Path vars must be set here
-export PATH="$JAVA_HOME/bin:$PATH"
-
-sed -i 's|:subname "//.*:3306|:subname "//'"${DBHOST}"':3306|g' hello/src/hello/models/schema.clj
+# Update db host in the source file
+sed -i 's|:subname "//.*:3306|:subname "//'"${DBHOST}"':3306|g' hello/src/hello/db/core.clj
 
 cd hello
 lein clean
-lein ring uberwar
-rm -rf $RESIN_HOME/webapps/*
-cp target/hello-luminus-standalone.war $RESIN_HOME/webapps/luminus.war
-$RESIN_HOME/bin/resinctl start
+rm -rf target
+# pack all dependencies into a single jar: target/http-kit-standalone.jar
+lein uberjar
+java -server -jar target/hello.jar  &

+ 23 - 14
frameworks/Clojure/luminus/source_code

@@ -1,23 +1,32 @@
+./luminus/hello/Procfile
+./luminus/hello/README.md
 ./luminus/hello/project.clj
-./luminus/hello/src/
-./luminus/hello/src/log4j.xml
-./luminus/hello/src/hello
-./luminus/hello/src/hello/routes
-./luminus/hello/src/hello/routes/home.clj
-./luminus/hello/src/hello/views
-./luminus/hello/src/hello/views/templates
-./luminus/hello/src/hello/views/templates/base.html
-./luminus/hello/src/hello/views/templates/home.html
-./luminus/hello/src/hello/views/layout.clj
-./luminus/hello/src/hello/handler.clj
-./luminus/hello/src/hello/models
-./luminus/hello/src/hello/models/schema.clj
-./luminus/hello/src/hello/models/db.clj
+./luminus/hello/env/
+./luminus/hello/env/dev/clj
+./luminus/hello/env/dev/clj/hello
+./luminus/hello/env/dev/clj/hello/repl.clj
 ./luminus/hello/resources/
 ./luminus/hello/resources/public
 ./luminus/hello/resources/public/css
 ./luminus/hello/resources/public/css/screen.css
+./luminus/hello/resources/sql
+./luminus/hello/resources/sql/queries.sql
+./luminus/hello//resources/templates
+./luminus/hello//resources/templates/base.html
+./luminus/hello//resources/templates/home.html
+./luminus/hello/src/
+./luminus/hello/src/hello
+./luminus/hello/src/hello/core.clj
+./luminus/hello/src/hello/handler.clj
+./luminus/hello/src/hello/layout.clj
+./luminus/hello/src/hello/middleware.clj
+./luminus/hello/src/hello/session.clj
+./luminus/hello/src/hello/db
+./luminus/hello/src/hello/db/core.clj
+./luminus/hello/src/hello/routes
+./luminus/hello/src/hello/routes/home.clj
 ./luminus/hello/test/
 ./luminus/hello/test/hello
 ./luminus/hello/test/hello/test
 ./luminus/hello/test/hello/test/handler.clj
+

+ 2 - 2
frameworks/Java/netty/pom.xml

@@ -13,12 +13,12 @@
 		<dependency>
 			<groupId>io.netty</groupId>
 			<artifactId>netty-codec-http</artifactId>
-			<version>4.0.26.Final</version>
+			<version>4.0.28.Final</version>
 		</dependency>
 		<dependency>
 			<groupId>io.netty</groupId>
 			<artifactId>netty-transport-native-epoll</artifactId>
-			<version>4.0.26.Final</version>
+			<version>4.0.28.Final</version>
 			<classifier>linux-x86_64</classifier>
 		</dependency>
 		<dependency>

+ 1 - 1
frameworks/Java/play2-java/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-fw_depends java7 sbt
+fw_depends java8 sbt

+ 2 - 2
frameworks/Java/play2-java/play2-java-ebean-bonecp/build.sbt

@@ -4,10 +4,10 @@ version := "1.0-SNAPSHOT"
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
-scalaVersion := "2.11.4"
+scalaVersion := "2.11.6"
 
 libraryDependencies ++= Seq(
   javaJdbc,
   javaEbean,
-  "mysql" % "mysql-connector-java" % "5.1.33"
+  "mysql" % "mysql-connector-java" % "5.1.35"
 )

+ 1 - 1
frameworks/Java/play2-java/play2-java-ebean-bonecp/project/plugins.sbt

@@ -5,4 +5,4 @@ logLevel := Level.Warn
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 // Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.7")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.9")

+ 3 - 3
frameworks/Java/play2-java/play2-java-ebean-hikaricp/build.sbt

@@ -4,13 +4,13 @@ version := "1.0-SNAPSHOT"
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
-scalaVersion := "2.11.4"
+scalaVersion := "2.11.6"
 
 libraryDependencies ++= Seq(
   javaJdbc,
   javaEbean,
-  "mysql" % "mysql-connector-java" % "5.1.33",
-  "com.edulify" %% "play-hikaricp" % "1.5.0"
+  "mysql" % "mysql-connector-java" % "5.1.35",
+  "com.edulify" %% "play-hikaricp" % "2.0.4"
 )
 
 resolvers += Resolver.url("Edulify Repository", url("http://edulify.github.io/modules/releases/"))(Resolver.ivyStylePatterns)

+ 46 - 18
frameworks/Java/play2-java/play2-java-ebean-hikaricp/conf/application.conf

@@ -29,25 +29,53 @@ application.langs="en"
 #
 # You can expose this datasource via JNDI if needed (Useful for JPA)
 # db.default.jndiName=DefaultDS
-db.default.driver= com.mysql.jdbc.Driver
-db.default.url="jdbc:mysql://127.0.0.1:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
-db.default.user=benchmarkdbuser
-db.default.password=benchmarkdbpass
-db.default.jndiName=DefaultDS
 
-db.default.partitionCount=4
-
-# The number of connections to create per partition. Setting this to 
-# 5 with 3 partitions means you will have 15 unique connections to the 
-# database.
-
-# This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition)
-db.default.maxConnectionsPerPartition=64
-
-# The number of initial connections, per partition.
-#
-# This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition)
-db.default.minConnectionsPerPartition=64
+db {
+  default {
+
+    jndiName="DefaultDS"
+
+    dataSourceClassName=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
+    dataSource {
+      user=benchmarkdbuser
+      password=benchmarkdbpass
+      databaseName=hello_world
+      serverName=127.0.0.1
+      port=3306
+
+      jdbcCompliantTruncation=false
+      elideSetAutoCommits=true
+      useLocalSessionState=true
+      cachePrepStmts=true
+      cacheCallableStmts=true
+      cacheServerConfiguration=true
+      cacheResultSetMetadata=true
+      alwaysSendSetIsolation=false
+      prepStmtCacheSize=4096
+      prepStmtCacheSqlLimit=2048
+      zeroDateTimeBehavior=convertToNull
+      traceProtocol=false
+      useUnbufferedInput=false
+      useReadAheadInput=false
+      maintainTimeStats=false
+      useServerPrepStmts=true
+    }
+
+    partitionCount=4
+
+    # The number of connections to create per partition. Setting this to
+    # 5 with 3 partitions means you will have 15 unique connections to the
+    # database.
+
+    # This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition)
+    maxConnectionsPerPartition=64
+
+    # The number of initial connections, per partition.
+    #
+    # This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition)
+    minConnectionsPerPartition=64
+  }
+}
 
 dbplugin=disabled
 

+ 1 - 1
frameworks/Java/play2-java/play2-java-ebean-hikaricp/project/plugins.sbt

@@ -5,4 +5,4 @@ logLevel := Level.Warn
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 // Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.7")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.9")

+ 3 - 3
frameworks/Java/play2-java/play2-java-jpa-bonecp/build.sbt

@@ -2,15 +2,15 @@ name := "play2-java-jpa-bonecp"
 
 version := "1.0-SNAPSHOT"
 
-scalaVersion := "2.11.4"
+scalaVersion := "2.11.6"
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
 libraryDependencies ++= Seq(
   javaJdbc,
   javaJpa,
-  "mysql" % "mysql-connector-java" % "5.1.33",
-  "org.hibernate" % "hibernate-entitymanager" % "4.3.6.Final"
+  "mysql" % "mysql-connector-java" % "5.1.35",
+  "org.hibernate" % "hibernate-entitymanager" % "4.3.9.Final"
   )
 
 dependencyOverrides += "com.jolbox" % "bonecp" % "0.8.0.RELEASE"

+ 1 - 1
frameworks/Java/play2-java/play2-java-jpa-bonecp/project/plugins.sbt

@@ -5,4 +5,4 @@ logLevel := Level.Warn
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 // Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.7")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.9")

+ 4 - 4
frameworks/Java/play2-java/play2-java-jpa-hikaricp/build.sbt

@@ -4,14 +4,14 @@ version := "1.0-SNAPSHOT"
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
-scalaVersion := "2.11.4"
+scalaVersion := "2.11.6"
 
 libraryDependencies ++= Seq(
   javaJdbc,
   javaJpa,
-  "mysql" % "mysql-connector-java" % "5.1.33",
-  "org.hibernate" % "hibernate-entitymanager" % "4.3.6.Final",
-  "com.edulify" %% "play-hikaricp" % "1.5.0"
+  "mysql" % "mysql-connector-java" % "5.1.35",
+  "org.hibernate" % "hibernate-entitymanager" % "4.3.9.Final",
+  "com.edulify" %% "play-hikaricp" % "2.0.4"
 )
 
 resolvers += Resolver.url("Edulify Repository", url("http://edulify.github.io/modules/releases/"))(Resolver.ivyStylePatterns)

+ 47 - 19
frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf

@@ -44,26 +44,54 @@ application.langs="en"
 # You can expose this datasource via JNDI if needed (Useful for JPA)
 # db.default.jndiName=DefaultDS
 
-db.default.driver= com.mysql.jdbc.Driver
-db.default.url="jdbc:mysql://127.0.0.1:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
-db.default.user=benchmarkdbuser
-db.default.password=benchmarkdbpass
-db.default.jndiName=DefaultDS
-jpa.default=defaultPersistenceUnit
-
-db.default.partitionCount=4
-
-# The number of connections to create per partition. Setting this to
-# 5 with 3 partitions means you will have 15 unique connections to the
-# database..
-#
-# This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition)
-db.default.maxConnectionsPerPartition=64
+db {
+  default {
+
+    jndiName="DefaultDS"
+
+    dataSourceClassName=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
+    dataSource {
+      user=benchmarkdbuser
+      password=benchmarkdbpass
+      databaseName=hello_world
+      serverName=127.0.0.1
+      port=3306
+
+      jdbcCompliantTruncation=false
+      elideSetAutoCommits=true
+      useLocalSessionState=true
+      cachePrepStmts=true
+      cacheCallableStmts=true
+      cacheServerConfiguration=true
+      cacheResultSetMetadata=true
+      alwaysSendSetIsolation=false
+      prepStmtCacheSize=4096
+      prepStmtCacheSqlLimit=2048
+      zeroDateTimeBehavior=convertToNull
+      traceProtocol=false
+      useUnbufferedInput=false
+      useReadAheadInput=false
+      maintainTimeStats=false
+      useServerPrepStmts=true
+    }
+
+    partitionCount=4
+
+    # The number of connections to create per partition. Setting this to
+    # 5 with 3 partitions means you will have 15 unique connections to the
+    # database.
+
+    # This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition)
+    maxConnectionsPerPartition=64
+
+    # The number of initial connections, per partition.
+    #
+    # This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition)
+    minConnectionsPerPartition=64
+  }
+}
 
-# The number of initial connections, per partition.
-#
-# This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition)
-db.default.minConnectionsPerPartition=64
+jpa.default=defaultPersistenceUnit
 
 dbplugin=disabled
 

+ 1 - 1
frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/plugins.sbt

@@ -1,4 +1,4 @@
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 // The Play plugin
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.7")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.9")

+ 1 - 1
frameworks/Java/play2-java/play2-java/build.sbt

@@ -4,4 +4,4 @@ version := "1.0-SNAPSHOT"
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
-scalaVersion := "2.11.4"
+scalaVersion := "2.11.6"

+ 1 - 1
frameworks/Java/play2-java/play2-java/project/plugins.sbt

@@ -5,4 +5,4 @@ logLevel := Level.Warn
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 // Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.7")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.9")

+ 1 - 1
frameworks/Java/play2-java/setup_java.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 cd play2-java
 

+ 1 - 1
frameworks/Java/play2-java/setup_java_ebean_bonecp.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 cd play2-java-ebean-bonecp
 

+ 1 - 1
frameworks/Java/play2-java/setup_java_ebean_hikaricp.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 cd play2-java-ebean-hikaricp
 

+ 1 - 1
frameworks/Java/play2-java/setup_java_jpa_bonecp.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 cd play2-java-jpa-bonecp
 

+ 1 - 1
frameworks/Java/play2-java/setup_java_jpa_hikaricp.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 cd play2-java-jpa-hikaricp
 

+ 78 - 2
frameworks/Java/sabina/benchmark_config.json

@@ -8,8 +8,59 @@
       "fortune_url": "/fortune",
       "update_url": "/update?queries=",
       "plaintext_url": "/plaintext",
+
       "port": 5050,
-      "setup_file": "setup",
+      "setup_file": "undertow-mongodb",
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MongoDB",
+      "framework": "Sabina",
+      "language": "Java",
+      "orm": "Raw",
+      "platform": "Servlet",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Sabina Undertow MongoDB",
+      "notes": "",
+      "versus": "servlet"
+    }
+  }, {
+    "undertow-mysql": {
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/query?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "plaintext_url": "/plaintext",
+
+      "port": 5050,
+      "setup_file": "undertow",
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "Sabina",
+      "language": "Java",
+      "orm": "Raw",
+      "platform": "Servlet",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Sabina Undertow MySQL",
+      "notes": "",
+      "versus": "servlet"
+    }
+  }, {
+    "jetty-mysql": {
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/query?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "plaintext_url": "/plaintext",
+
+      "port": 5050,
+      "setup_file": "jetty",
       "approach": "Realistic",
       "classification": "Micro",
       "database": "MySQL",
@@ -20,7 +71,32 @@
       "webserver": "None",
       "os": "Linux",
       "database_os": "Linux",
-      "display_name": "Sabina",
+      "display_name": "Sabina Jetty MySQL",
+      "notes": "",
+      "versus": "servlet"
+    }
+  }, {
+    "jetty-mongodb": {
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/query?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "plaintext_url": "/plaintext",
+
+      "port": 5050,
+      "setup_file": "jetty-mongodb",
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MongoDB",
+      "framework": "Sabina",
+      "language": "Java",
+      "orm": "Raw",
+      "platform": "Servlet",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Sabina Jetty MongoDB",
       "notes": "",
       "versus": "servlet"
     }

+ 3 - 0
frameworks/Java/sabina/jetty-mongodb.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+./setup.sh -Dsabina.backend=jetty -Dsabina.benchmark.repository=mongodb

+ 3 - 0
frameworks/Java/sabina/jetty.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+./setup.sh -Dsabina.backend=jetty -Dsabina.benchmark.repository=mysql

+ 6 - 1
frameworks/Java/sabina/pom.xml

@@ -36,7 +36,7 @@
 
         <db.host>localhost</db.host>
 
-        <sabina-version>1.1.1</sabina-version>
+        <sabina-version>1.3.0</sabina-version>
     </properties>
 
     <repositories>
@@ -92,6 +92,11 @@
             <artifactId>mysql-connector-java</artifactId>
             <version>5.1.28</version>
         </dependency>
+        <dependency>
+            <groupId>org.mongodb</groupId>
+            <artifactId>mongo-java-driver</artifactId>
+            <version>3.0.0</version>
+        </dependency>
 
         <dependency>
             <groupId>org.testng</groupId>

+ 1 - 1
frameworks/Java/sabina/setup.sh

@@ -4,4 +4,4 @@
 source $IROOT/java8.installed
 
 mvn clean package -DskipTests -Ddb.host=${DBHOST}
-${JAVA_HOME}/bin/java -jar target/sabina-1.0.0.jar &
+${JAVA_HOME}/bin/java $@ -jar target/sabina-1.0.0.jar

+ 59 - 134
frameworks/Java/sabina/src/main/java/sabina/benchmark/Application.java

@@ -20,39 +20,29 @@ import static sabina.Sabina.*;
 import static sabina.content.JsonContent.toJson;
 import static sabina.view.MustacheView.renderMustache;
 
-import com.mchange.v2.c3p0.ComboPooledDataSource;
 import sabina.Request;
+import sabina.server.MatcherFilter;
 
-import java.sql.*;
 import java.util.*;
 import java.util.Date;
-import java.util.concurrent.ThreadLocalRandom;
-
-import javax.sql.DataSource;
+import javax.servlet.FilterConfig;
+import javax.servlet.annotation.WebFilter;
 
 /**
  * .
  */
-final class Application {
-    private static final String SETTINGS_RESOURCE = "/server.properties";
-    private static final Properties SETTINGS = loadConfiguration ();
-
-    private static final String JDBC_URL = SETTINGS.getProperty ("mysql.uri")
-        .replace ("${db.host}", "localhost"); // TODO Move this to Gradle build
-    private static final DataSource DATA_SOURCE = createSessionFactory ();
-    private static final int DB_ROWS = 10000;
-
-    private static final boolean AUTOCOMMIT = getProperty ("sabina.benchmark.autocommit") != null;
-    private static final String SELECT_WORLD = "select * from world where id = ?";
-    private static final String UPDATE_WORLD = "update world set randomNumber = ? where id = ?";
-    private static final String SELECT_FORTUNES = "select * from fortune";
+@WebFilter ("/*")
+final class Application extends MatcherFilter {
+    static final String SETTINGS_RESOURCE = "/server.properties";
+    static final Repository REPOSITORY = loadRepository ();
+    static final int DB_ROWS = 10000;
 
     private static final String MESSAGE = "Hello, World!";
     private static final String CONTENT_TYPE_TEXT = "text/plain";
     private static final String CONTENT_TYPE_JSON = "application/json";
     private static final String QUERIES_PARAM = "queries";
 
-    private static Properties loadConfiguration () {
+    static Properties loadConfiguration () {
         try {
             Properties settings = new Properties ();
             settings.load (Class.class.getResourceAsStream (SETTINGS_RESOURCE));
@@ -63,21 +53,43 @@ final class Application {
         }
     }
 
-    private static DataSource createSessionFactory () {
+    static Repository loadRepository () {
+        switch (getProperty ("sabina.benchmark.repository", "mysql")) {
+            case "mongodb":
+                return new MongoDbRepository (loadConfiguration ());
+            case "mysql":
+            default:
+                return new MySqlRepository (loadConfiguration ());
+        }
+    }
+
+    private static Object getDb (Request it) {
         try {
-            ComboPooledDataSource dataSource = new ComboPooledDataSource ();
-            dataSource.setMinPoolSize (32);
-            dataSource.setMaxPoolSize (256);
-            dataSource.setCheckoutTimeout (1800);
-            dataSource.setMaxStatements (50);
-            dataSource.setJdbcUrl (JDBC_URL);
-            return dataSource;
+            final World[] worlds = REPOSITORY.getWorlds (getQueries (it), false);
+            it.response.type (CONTENT_TYPE_JSON);
+            return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
         }
-        catch (Exception ex) {
-            throw new RuntimeException (ex);
+        catch (Exception e){
+            e.printStackTrace ();
+            throw e;
         }
     }
 
+    private static Object getFortunes (Request it) {
+        List<Fortune> fortunes = REPOSITORY.getFortunes ();
+        fortunes.add (new Fortune (0, "Additional fortune added at request time."));
+        fortunes.sort ((a, b) -> a.message.compareTo (b.message));
+
+        it.response.type ("text/html; charset=utf-8");
+        return renderMustache ("/fortunes.mustache", fortunes);
+    }
+
+    private static Object getUpdates (Request it) {
+        World[] worlds = REPOSITORY.getWorlds (getQueries (it), true);
+        it.response.type (CONTENT_TYPE_JSON);
+        return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
+    }
+
     private static int getQueries (final Request request) {
         try {
             String parameter = request.queryParams (QUERIES_PARAM);
@@ -97,118 +109,22 @@ final class Application {
         }
     }
 
-    private static Object getJson (Request it) {
-        it.response.type (CONTENT_TYPE_JSON);
-        return toJson (new Message ());
-    }
-
-    private static Object getDb (Request it) {
-        final int queries = getQueries (it);
-        final World[] worlds = new World[queries];
-
-        try (final Connection con = DATA_SOURCE.getConnection ()) {
-            final Random random = ThreadLocalRandom.current ();
-            final PreparedStatement stmt = con.prepareStatement (SELECT_WORLD);
-
-            for (int ii = 0; ii < queries; ii++) {
-                stmt.setInt (1, random.nextInt (DB_ROWS) + 1);
-                final ResultSet rs = stmt.executeQuery ();
-                while (rs.next ())
-                    worlds[ii] = new World (rs.getInt (1), rs.getInt (2));
-            }
-        }
-        catch (SQLException e) {
-            e.printStackTrace ();
-        }
-
-        it.response.type (CONTENT_TYPE_JSON);
-        return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
-    }
-
-    private static Object getFortunes (Request it) {
-        final List<Fortune> fortunes = new ArrayList<> ();
-
-        try (final Connection con = DATA_SOURCE.getConnection ()) {
-            final ResultSet rs = con.prepareStatement (SELECT_FORTUNES).executeQuery ();
-            while (rs.next ())
-                fortunes.add (new Fortune (rs.getInt (1), rs.getString (2)));
-        }
-        catch (SQLException e) {
-            e.printStackTrace ();
-        }
-
-        fortunes.add (new Fortune (0, "Additional fortune added at request time."));
-        fortunes.sort ((a, b) -> a.message.compareTo (b.message));
-
-        it.response.type ("text/html; charset=utf-8");
-        return renderMustache ("/fortunes.mustache", fortunes);
-    }
-
-    private static Object getUpdates (Request it) {
-        final int queries = getQueries (it);
-        final World[] worlds = new World[queries];
-
-        try (final Connection con = DATA_SOURCE.getConnection ()) {
-            con.setAutoCommit (AUTOCOMMIT);
-
-            final Random random = ThreadLocalRandom.current ();
-            final PreparedStatement stmtSelect = con.prepareStatement (SELECT_WORLD);
-            final PreparedStatement stmtUpdate = con.prepareStatement (UPDATE_WORLD);
-
-            for (int ii = 0; ii < queries; ii++) {
-                stmtSelect.setInt (1, random.nextInt (DB_ROWS) + 1);
-                final ResultSet rs = stmtSelect.executeQuery ();
-                while (rs.next ()) {
-                    worlds[ii] = new World (rs.getInt (1), rs.getInt (2));
-                    stmtUpdate.setInt (1, random.nextInt (DB_ROWS) + 1);
-                    stmtUpdate.setInt (2, worlds[ii].id);
-
-                    if (AUTOCOMMIT) {
-                        stmtUpdate.executeUpdate ();
-                    }
-                    else {
-                        stmtUpdate.addBatch ();
-                    }
-                }
-            }
-
-            if (!AUTOCOMMIT) {
-                int count = 0;
-                boolean retrying;
-
-                do {
-                    try {
-                        stmtUpdate.executeBatch ();
-                        retrying = false;
-                    }
-                    catch (BatchUpdateException e) {
-                        retrying = true;
-                    }
-                }
-                while (count++ < 10 && retrying);
-
-                con.commit ();
-            }
-        }
-        catch (SQLException e) {
-            e.printStackTrace ();
-        }
-
-        it.response.type (CONTENT_TYPE_JSON);
-        return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
-    }
-
     private static Object getPlaintext (Request it) {
         it.response.type (CONTENT_TYPE_TEXT);
         return MESSAGE;
     }
 
+    private static Object getJson (Request it) {
+        it.response.type (CONTENT_TYPE_JSON);
+        return toJson (new Message ());
+    }
+
     private static void addCommonHeaders (Request it) {
         it.header ("Server", "Undertow/1.1.2");
-        it.response.raw ().addDateHeader ("Date", new Date ().getTime ());
+        it.response.addDateHeader ("Date", new Date ().getTime ());
     }
 
-    public static void main (String[] args) {
+    private static void routes () {
         get ("/json", Application::getJson);
         get ("/db", Application::getDb);
         get ("/query", Application::getDb);
@@ -216,9 +132,18 @@ final class Application {
         get ("/update", Application::getUpdates);
         get ("/plaintext", Application::getPlaintext);
         after (Application::addCommonHeaders);
+    }
 
-        host (SETTINGS.getProperty ("web.host"));
-        port (SETTINGS.getProperty ("web.port"));
+    public static void main (String[] args) {
+        routes ();
+
+        Properties settings = loadConfiguration ();
+        host (settings.getProperty ("web.host"));
+        port (settings.getProperty ("web.port"));
         start ();
     }
+
+    @Override protected void routes (FilterConfig filterConfig) {
+        routes ();
+    }
 }

+ 0 - 5
frameworks/Java/sabina/src/main/java/sabina/benchmark/Fortune.java

@@ -14,11 +14,6 @@
 
 package sabina.benchmark;
 
-/**
- * TODO .
- *
- * @author jam
- */
 final class Fortune {
     final int id;
     final String message;

+ 91 - 0
frameworks/Java/sabina/src/main/java/sabina/benchmark/MongoDbRepository.java

@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2015 Juan José Aguililla. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+
+package sabina.benchmark;
+
+import static com.mongodb.client.model.Filters.eq;
+import static java.lang.Integer.parseInt;
+import static sabina.benchmark.Application.DB_ROWS;
+
+import java.util.*;
+import java.util.concurrent.ThreadLocalRandom;
+
+import com.mongodb.*;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import org.bson.Document;
+
+final class MongoDbRepository implements Repository {
+    private MongoCollection<Document> worldCollection;
+    private MongoCollection<Document> fortuneCollection;
+
+    MongoDbRepository (Properties settings) {
+        final int PORT = parseInt (settings.getProperty ("mongodb.port"));
+        final String HOST = settings.getProperty ("mongodb.host");
+        final String DATABASE = settings.getProperty ("mongodb.database");
+        final String WORLD = settings.getProperty ("mongodb.world.collection");
+        final String FORTUNE = settings.getProperty ("mongodb.fortune.collection");
+
+        MongoClient mongoClient = new MongoClient (HOST, PORT);
+        MongoDatabase db = mongoClient.getDatabase (DATABASE);
+        worldCollection = db.getCollection (WORLD);
+        fortuneCollection = db.getCollection (FORTUNE);
+    }
+
+    @Override public List<Fortune> getFortunes () {
+        List<Fortune> fortunes = new ArrayList<> ();
+
+        fortuneCollection.find ().forEach ((Block<Document>)doc ->
+            fortunes.add (new Fortune (doc.get ("_id", Double.class).intValue (), (String)doc.get
+                ("message")))
+        );
+
+        return fortunes;
+    }
+
+    @Override public World[] getWorlds (int queries, boolean update) {
+        final World[] worlds = new World[queries];
+        final Random random = ThreadLocalRandom.current ();
+
+        for (int ii = 0; ii < queries; ii++) {
+            int id = random.nextInt (DB_ROWS) + 1;
+            worlds[ii] = update? updateWorld (id, random.nextInt (DB_ROWS) + 1) : findWorld (id);
+        }
+
+        return worlds;
+    }
+
+    private World findWorld (int id) {
+        return createWorld (worldCollection.find(eq ("_id", (double)id)).first ());
+    }
+
+    private World createWorld (Document world) {
+        try {
+            return new World (world.get ("_id", Double.class).intValue (), world.get
+                ("randomNumber", Double.class).intValue ());
+        }
+        catch (ClassCastException e) {
+            return new World (world.get ("_id", Double.class).intValue (), world.get
+                ("randomNumber", Integer.class));
+        }
+    }
+
+    public World updateWorld (int id, int random) {
+        Document newWorld = new Document ("_id", (double)id).append ("randomNumber", (double)
+            random);
+        worldCollection.replaceOne (eq ("_id", (double)id), newWorld);
+
+        return new World (id, random);
+    }
+}

+ 139 - 0
frameworks/Java/sabina/src/main/java/sabina/benchmark/MySqlRepository.java

@@ -0,0 +1,139 @@
+/*
+ * Copyright © 2015 Juan José Aguililla. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+
+package sabina.benchmark;
+
+import static java.lang.System.getProperty;
+import static sabina.benchmark.Application.DB_ROWS;
+
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+import javax.sql.DataSource;
+
+import com.mchange.v2.c3p0.ComboPooledDataSource;
+
+final class MySqlRepository implements Repository {
+    private static final boolean AUTOCOMMIT = getProperty ("sabina.benchmark.autocommit") != null;
+    private static final String SELECT_WORLD = "select * from world where id = ?";
+    private static final String UPDATE_WORLD = "update world set randomNumber = ? where id = ?";
+    private static final String SELECT_FORTUNES = "select * from fortune";
+
+    private final DataSource DATA_SOURCE;
+
+    MySqlRepository (Properties settings) {
+        final String jdbcUrl = settings.getProperty ("mysql.uri");
+        DATA_SOURCE = createSessionFactory (jdbcUrl);
+    }
+
+    private DataSource createSessionFactory (String jdbcUrl) {
+        try {
+            ComboPooledDataSource dataSource = new ComboPooledDataSource ();
+            dataSource.setMinPoolSize (32);
+            dataSource.setMaxPoolSize (256);
+            dataSource.setCheckoutTimeout (1800);
+            dataSource.setMaxStatements (50);
+            dataSource.setJdbcUrl (jdbcUrl);
+            return dataSource;
+        }
+        catch (Exception ex) {
+            throw new RuntimeException (ex);
+        }
+    }
+
+    private void commitUpdate (Connection con, PreparedStatement stmtUpdate)
+        throws SQLException {
+        int count = 0;
+        boolean retrying;
+
+        do {
+            try {
+                stmtUpdate.executeBatch ();
+                retrying = false;
+            }
+            catch (BatchUpdateException e) {
+                retrying = true;
+            }
+        }
+        while (count++ < 10 && retrying);
+
+        con.commit ();
+    }
+
+    private void updateWorld (World world, PreparedStatement stmtUpdate)
+        throws SQLException {
+        stmtUpdate.setInt (1, world.randomNumber);
+        stmtUpdate.setInt (2, world.id);
+
+        if (AUTOCOMMIT) {
+            stmtUpdate.executeUpdate ();
+        }
+        else {
+            stmtUpdate.addBatch ();
+        }
+    }
+
+    @Override public List<Fortune> getFortunes () {
+        final List<Fortune> fortunes = new ArrayList<> ();
+
+        try (final Connection con = DATA_SOURCE.getConnection ()) {
+            final ResultSet rs = con.prepareStatement (SELECT_FORTUNES).executeQuery ();
+            while (rs.next ())
+                fortunes.add (new Fortune (rs.getInt (1), rs.getString (2)));
+        }
+        catch (SQLException e) {
+            e.printStackTrace ();
+        }
+
+        return fortunes;
+    }
+
+    @Override public World[] getWorlds (int queries, boolean update) {
+        final World[] worlds = new World[queries];
+
+        try (final Connection con = DATA_SOURCE.getConnection ()) {
+            if (update)
+                con.setAutoCommit (AUTOCOMMIT);
+
+            final Random random = ThreadLocalRandom.current ();
+            final PreparedStatement stmtSelect = con.prepareStatement (SELECT_WORLD);
+            final PreparedStatement stmtUpdate = update? con.prepareStatement (UPDATE_WORLD) : null;
+
+            for (int ii = 0; ii < queries; ii++) {
+                stmtSelect.setInt (1, random.nextInt (DB_ROWS) + 1);
+                final ResultSet rs = stmtSelect.executeQuery ();
+                while (rs.next ()) {
+                    worlds[ii] = new World (rs.getInt (1), rs.getInt (2));
+
+                    if (update) {
+                        worlds[ii] = new World (worlds[ii].id, random.nextInt (DB_ROWS) + 1);
+                        updateWorld (worlds[ii], stmtUpdate);
+                    }
+                }
+            }
+
+            if (update && !AUTOCOMMIT)
+                commitUpdate (con, stmtUpdate);
+        }
+        catch (SQLException e) {
+            e.printStackTrace ();
+        }
+
+        return worlds;
+    }
+}

+ 22 - 0
frameworks/Java/sabina/src/main/java/sabina/benchmark/Repository.java

@@ -0,0 +1,22 @@
+/*
+ * Copyright © 2015 Juan José Aguililla. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+
+package sabina.benchmark;
+
+import java.util.List;
+
+interface Repository {
+    List<Fortune> getFortunes ();
+    World[] getWorlds (int queries, boolean update);
+}

+ 5 - 2
frameworks/Java/sabina/src/main/resources/server.properties

@@ -15,8 +15,11 @@
 web.port = 5050
 web.host = 0.0.0.0
 
-mongodb.uri = ${db.host}:27017
-mongodb.name = hello_world
+mongodb.host = ${db.host}
+mongodb.port = 27017
+mongodb.database = hello_world
+mongodb.world.collection = world
+mongodb.fortune.collection = fortune
 
 mysql.uri = jdbc:mysql://${db.host}:3306/hello_world?\
 user=benchmarkdbuser&\

+ 13 - 28
frameworks/Java/sabina/src/test/java/sabina/benchmark/ApplicationTest.java

@@ -16,7 +16,6 @@ package sabina.benchmark;
 
 import static org.apache.http.client.fluent.Request.Get;
 import static org.testng.AssertJUnit.*;
-import static sabina.benchmark.Application.main;
 import static sabina.Sabina.stop;
 
 import java.io.IOException;
@@ -39,37 +38,13 @@ import org.testng.annotations.Test;
  * <p>TODO Change assert's order
  */
 public final class ApplicationTest {
-    private static final int THREADS = 16, EXECUTIONS = 32, WARM_UP = 32;
+    private static final int THREADS = 1, EXECUTIONS = 1;
 
     private static final String ENDPOINT = "http://localhost:5050";
     private static final Gson GSON = new Gson ();
 
     @BeforeClass public static void setup () {
-        main (null);
-    }
-
-    @BeforeClass public void warm_up () throws IOException {
-        for (int ii = 0; ii < WARM_UP; ii++) {
-            json ();
-            plaintext ();
-            no_query_parameter ();
-            empty_query_parameter ();
-            text_query_parameter ();
-            zero_queries ();
-            one_thousand_queries ();
-            one_query ();
-            ten_queries ();
-            five_hundred_queries ();
-            fortunes ();
-            no_updates_parameter ();
-            empty_updates_parameter ();
-            text_updates_parameter ();
-            zero_updates ();
-            one_thousand_updates ();
-            one_update ();
-            ten_updates ();
-            five_hundred_updates ();
-        }
+        Application.main (null);
     }
 
     @AfterClass public static void close () {
@@ -134,6 +109,11 @@ public final class ApplicationTest {
         checkDbRequest ("/query?queries=10", 10);
     }
 
+    @Test(threadPoolSize = THREADS, invocationCount = EXECUTIONS)
+    public void one_hundred_queries () throws IOException {
+        checkDbRequest ("/query?queries=100", 100);
+    }
+
     @Test(threadPoolSize = THREADS, invocationCount = EXECUTIONS)
     public void five_hundred_queries () throws IOException {
         checkDbRequest ("/query?queries=500", 500);
@@ -192,6 +172,11 @@ public final class ApplicationTest {
         checkDbRequest ("/update?queries=10", 10);
     }
 
+    @Test(threadPoolSize = THREADS, invocationCount = EXECUTIONS)
+    public void one_hundred_updates () throws IOException {
+        checkDbRequest ("/update?queries=100", 100);
+    }
+
     @Test(threadPoolSize = THREADS, invocationCount = EXECUTIONS)
     public void five_hundred_updates () throws IOException {
         checkDbRequest ("/update?queries=500", 500);
@@ -218,7 +203,7 @@ public final class ApplicationTest {
         assertTrue (res.getFirstHeader ("Server") != null);
         assertTrue (res.getFirstHeader ("Date") != null);
         assertEquals (content.length (), res.getEntity ().getContentLength ());
-        assertEquals (contentType, res.getEntity ().getContentType ().getValue ());
+        assertTrue (res.getEntity ().getContentType ().getValue ().contains (contentType));
     }
 
     private void checkResultItems (String result, int size) {

+ 3 - 0
frameworks/Java/sabina/undertow-mongodb.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+./setup.sh -Dsabina.backend=undertow -Dsabina.benchmark.repository=mongodb

+ 3 - 0
frameworks/Java/sabina/undertow.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+./setup.sh -Dsabina.backend=undertow -Dsabina.benchmark.repository=mysql

+ 1 - 1
frameworks/Java/undertow/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-fw_depends java7 maven
+fw_depends java8 maven

+ 10 - 10
frameworks/Java/undertow/pom.xml

@@ -15,17 +15,17 @@
         <dependency>
             <groupId>io.undertow</groupId>
             <artifactId>undertow-core</artifactId>
-            <version>1.0.14.Final</version>
+            <version>1.2.5.Final</version>
         </dependency>
         <dependency>
             <groupId>org.jboss.xnio</groupId>
             <artifactId>xnio-api</artifactId>
-            <version>3.2.2.Final</version>
+            <version>3.3.1.Final</version>
         </dependency>
         <dependency>
             <groupId>org.jboss.xnio</groupId>
             <artifactId>xnio-nio</artifactId>
-            <version>3.2.2.Final</version>
+            <version>3.3.1.Final</version>
         </dependency>
         <!-- Database drivers -->
         <dependency>
@@ -53,29 +53,29 @@
         <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
-            <version>16.0.1</version>
+            <version>18.0</version>
         </dependency>
         <!-- JSON encoding -->
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>
-            <version>2.3.3</version>
+            <version>2.5.3</version>
         </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-annotations</artifactId>
-            <version>2.3.3</version>
+            <version>2.5.3</version>
         </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-core</artifactId>
-            <version>2.3.3</version>
+            <version>2.5.3</version>
         </dependency>
         <!-- HTML templates -->
         <dependency>
             <groupId>com.github.spullara.mustache.java</groupId>
             <artifactId>compiler</artifactId>
-            <version>0.8.13</version>
+            <version>0.9.0</version>
         </dependency>
     </dependencies>
 
@@ -87,8 +87,8 @@
                 <artifactId>maven-compiler-plugin</artifactId>
                 <version>3.1</version>
                 <configuration>
-                    <source>1.7</source>
-                    <target>1.7</target>
+                    <source>1.8</source>
+                    <target>1.8</target>
                     <optimize>true</optimize>
                     <debug>false</debug>
                 </configuration>

+ 2 - 2
frameworks/Java/undertow/setup.sh

@@ -1,9 +1,9 @@
 #!/bin/bash
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 sed -i 's|DATABASE_HOST|'"${DBHOST}"'|g' src/main/resources/hello/server.properties
 
 mvn clean compile assembly:single
 cd target
-java -jar undertow-example-0.1-jar-with-dependencies.jar &
+$JAVA_HOME/bin/java -jar undertow-example-0.1-jar-with-dependencies.jar &

+ 2 - 0
frameworks/Java/undertow/src/main/java/hello/HelloWebServer.java

@@ -123,6 +123,8 @@ public final class HelloWebServer {
         .setSocketOption(Options.BACKLOG, 10000)
         .setServerOption(UndertowOptions.ALWAYS_SET_KEEP_ALIVE, false) //don't send a keep-alive header for HTTP/1.1 requests, as it is not required
         .setServerOption(UndertowOptions.ALWAYS_SET_DATE, true)
+        .setServerOption(UndertowOptions.ENABLE_CONNECTOR_STATISTICS, false)
+        .setServerOption(UndertowOptions.RECORD_REQUEST_START_TIME, false)
         .setHandler(Handlers.header(Handlers.path()
             .addPrefixPath("/json",
                 new JsonHandler(objectMapper))

+ 43 - 6
frameworks/Java/vertx/README.md

@@ -1,22 +1,43 @@
-# Vertx Benchmarking Test
+# Vertx 2.x Benchmarking Test
 
-This is the vertx portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+This is the vertx 2.x portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### Plaintext Test
+
+* [Plaintext test source](WebServer.java)
+
+### JSON Serialization Test
 
-### JSON Encoding Test
 * [JSON test source](WebServer.java)
 
-### Data-Store/Database Mapping Test
+### Database Single query Test
+
+* [Database Single query test source](WebServer.java)
+
+### Database Multiple queries Test
+
+* [Database Multiple queries test source](WebServer.java)
+
+### Database Data updates Test
+
+* [Database Data updates test source](WebServer.java)
+
+### Fortunes Test
 
-* [Database test source](WebServer.java)
+* [Fortunes test source](WebServer.java)
 
 ## Versions
 
-* [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
+* [Java OpenJDK 1.7.0_79](http://openjdk.java.net/)
 * [vertx 2.1.5](http://vertx.io/)
 
 
 ## Test URLs
 
+### Plaintext Test
+
+    http://localhost:8080/plaintext
+
 ### JSON Encoding Test
 
     http://localhost:8080/json
@@ -24,3 +45,19 @@ This is the vertx portion of a [benchmarking test suite](../) comparing a variet
 ### Database Mapping Test
 
     http://localhost:8080/db?queries=5
+
+### Database Single query Test
+
+    http://localhost:8080/db
+
+### Database Multiple queries Test
+
+    http://localhost:8080/queries?queries=5
+
+### Database Data updates Test
+
+    http://localhost:8080/updates?queries=3
+
+### Fortunes Test
+
+    http://localhost:8080/fortunes

+ 139 - 38
frameworks/Java/vertx/WebServer.java

@@ -15,38 +15,67 @@ import java.util.Date;
 import java.util.Random;
 import java.util.concurrent.ThreadLocalRandom;
 
+import freemarker.template.Template;
+import freemarker.template.Configuration;
+import java.io.StringReader;
+import java.io.Writer;
+import java.io.StringWriter;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+
 public class WebServer extends Verticle implements Handler<HttpServerRequest> {
 
   private final Buffer helloWorldBuffer = new Buffer("Hello, World!");
   private final String helloWorldContentLength = String.valueOf(helloWorldBuffer.length());
   private final DateFormat DATE_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z");
+  private final Random random = ThreadLocalRandom.current();
   private String dateString;
 
-  private final String PATH_PLAINTEXT = "/plaintext";
-  private final String PATH_JSON = "/json";
-  private final String PATH_DB = "/db";
-  private final String PATH_QUERIES = "/queries";
-  private final String RESPONSE_TYPE_PLAIN = "text/plain";
-  private final String RESPONSE_TYPE_JSON = "application/json";
-  private final String HEADER_CONTENT_TYPE = "Content-Type";
-  private final String HEADER_CONTENT_LENGTH = "Content-Length";
-  private final String HEADER_SERVER = "Server";
-  private final String HEADER_SERVER_VERTX = "vert.x";
-  private final String HEADER_DATE = "Date";
-  private final String MONGO_ADDRESS = "hello.persistor";
-  private final String UNDERSCORE_ID = "_id";
-  private final String TEXT_ID = "id";
-  private final String TEXT_RESULT = "result";
-  private final String TEXT_QUERIES = "queries";
-  private final String TEXT_MESSAGE = "message";
-  private final String TEXT_ACTION = "action";
-  private final String TEXT_FINDONE = "findone";
-  private final String TEXT_COLLECTION = "collection";
-  private final String TEXT_WORLD = "World";
-  private final String TEXT_MATCHER = "matcher";
+  private static final String PATH_PLAINTEXT = "/plaintext";
+  private static final String PATH_JSON = "/json";
+  private static final String PATH_DB = "/db";
+  private static final String PATH_QUERIES = "/queries";
+  private static final String PATH_UPDATES = "/updates";
+  private static final String PATH_FORTUNES = "/fortunes";
+  private static final String RESPONSE_TYPE_PLAIN = "text/plain";
+  private static final String RESPONSE_TYPE_HTML = "text/html";
+  private static final String RESPONSE_TYPE_JSON = "application/json";
+  private static final String HEADER_CONTENT_TYPE = "Content-Type";
+  private static final String HEADER_CONTENT_LENGTH = "Content-Length";
+  private static final String HEADER_SERVER = "Server";
+  private static final String HEADER_SERVER_VERTX = "vert.x";
+  private static final String HEADER_DATE = "Date";
+  private static final String MONGO_ADDRESS = "hello.persistor";
+  private static final String FREEMARKER_ADDRESS = "vertx.freemarker";
+  private static final String UNDERSCORE_ID = "_id";
+  private static final String TEXT_ID = "id";
+  private static final String RANDOM_NUMBER = "randomNumber";
+  private static final String TEXT_RESULT = "result";
+  private static final String TEXT_RESULTS = "results";
+  private static final String TEXT_QUERIES = "queries";
+  private static final String TEXT_MESSAGE = "message";
+  private static final String TEXT_MESSAGES = "messages";
+  private static final String ADD_FORTUNE_MESSAGE = "Additional fortune added at request time.";
+  private static final String HELLO_WORLD = "Hello, world!";
+  private static final String TEXT_ACTION = "action";
+  private static final String TEXT_CRITERIA = "criteria";
+  private static final String TEXT_UPDATE = "update";
+  private static final String TEXT_OBJ_NEW = "objNew";
+  private static final String TEXT_FINDONE = "findone";
+  private static final String TEXT_FIND = "find";
+  private static final String TEXT_COLLECTION = "collection";
+  private static final String TEXT_WORLD = "World";
+  private static final String TEXT_FORTUNE = "Fortune";
+  private static final String TEXT_MATCHER = "matcher";
+  private static final String TEMPLATE_FORTUNE = "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><#list messages as message><tr><td>${message.id?html}</td><td>${message.message?html}</td></tr></#list></table></body></html>";
+  
+  private Template ftlTemplate;
 
   @Override
   public void start() {
+    try { ftlTemplate = new Template(TEXT_FORTUNE, new StringReader(TEMPLATE_FORTUNE), new Configuration(Configuration.VERSION_2_3_22)); } catch (Exception ex) { ex.printStackTrace(); }
     vertx.createHttpServer().requestHandler(WebServer.this).listen(8080);
     vertx.setPeriodic(1000, new Handler<Long>() {
       @Override
@@ -70,7 +99,13 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
         handleDbMongo(req);
         break;
       case PATH_QUERIES:
-        handleQueriesMongo(req);
+        handleDBMongo(req,false);
+        break;
+      case PATH_UPDATES:
+        handleDBMongo(req,true);
+        break;
+      case PATH_FORTUNES:
+        handleFortunes(req);
         break;
       default:
         req.response().setStatusCode(404);
@@ -82,6 +117,40 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
     dateString = DATE_FORMAT.format(new Date());
   }
 
+  private void handleFortunes(HttpServerRequest req) {
+    final HttpServerResponse resp = req.response();
+    
+    vertx.eventBus().send(
+      MONGO_ADDRESS,
+      new JsonObject()
+          .putString(TEXT_ACTION, TEXT_FIND)
+          .putString(TEXT_COLLECTION, TEXT_FORTUNE),
+      new Handler<Message<JsonObject>>() {
+        @Override
+        public void handle(Message<JsonObject> reply) {
+          JsonArray results = reply.body().getArray(TEXT_RESULTS);
+          
+          List<Fortune> fortunes = new ArrayList<>();
+          for (Object fortune: results) {
+            fortunes.add(new Fortune(
+              ((JsonObject)fortune).getNumber(TEXT_ID).intValue(),
+              ((JsonObject)fortune).getString(TEXT_MESSAGE)));
+          }            
+          fortunes.add(new Fortune(0, ADD_FORTUNE_MESSAGE));
+          Collections.sort(fortunes);
+
+          Map model = new HashMap();
+          model.put(TEXT_MESSAGES, fortunes);
+          Writer writer = new StringWriter();
+          try { ftlTemplate.process(model, writer); } catch (Exception ex) { ex.printStackTrace(); }
+
+          Buffer buff = new Buffer(writer.toString());
+          setHeaders(resp, RESPONSE_TYPE_HTML, String.valueOf(buff.length()));
+          resp.end(buff);
+        }  
+    });
+  }
+
   private void handlePlainText(HttpServerRequest req) {
     HttpServerResponse resp = req.response();
     setHeaders(resp, RESPONSE_TYPE_PLAIN, helloWorldContentLength);
@@ -89,14 +158,14 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
   }
 
   private void handleJson(HttpServerRequest req) {
-    Buffer buff = new Buffer(Json.encode(Collections.singletonMap(TEXT_MESSAGE, "Hello, world!")));
+    Buffer buff = new Buffer(Json.encode(Collections.singletonMap(TEXT_MESSAGE, HELLO_WORLD)));
     HttpServerResponse resp = req.response();
     setHeaders(resp, RESPONSE_TYPE_JSON, String.valueOf(buff.length()));
     resp.end(buff);
   }
 
   private void handleDbMongo(final HttpServerRequest req) {
-    findRandom(ThreadLocalRandom.current(), new Handler<Message<JsonObject>>() {
+    findRandom(new Handler<Message<JsonObject>>() {
       @Override
       public void handle(Message<JsonObject> reply) {
         JsonObject world = getResultFromReply(reply);
@@ -110,15 +179,11 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
     JsonObject body = reply.body();
     JsonObject world = body.getObject(TEXT_RESULT);
     Object id = world.removeField(UNDERSCORE_ID);
-    if (id instanceof Double) {
-		world.putValue(TEXT_ID, Integer.valueOf(((Double)id).intValue()));
-	} else {
-		world.putValue(TEXT_ID, id);
-	}
+    world.putValue(TEXT_ID, Integer.valueOf(((Double)id).intValue()));
     return world;
   }
 
-  private void handleQueriesMongo(final HttpServerRequest req) {
+  private void handleDBMongo(final HttpServerRequest req, boolean randomUpdates) {
     int queriesParam = 1;
     try {
       queriesParam = Integer.parseInt(req.params().get(TEXT_QUERIES));
@@ -130,14 +195,13 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
     } else if (queriesParam > 500) {
       queriesParam = 500;
     }
-    final MongoHandler dbh = new MongoHandler(req, queriesParam);
-    final Random random = ThreadLocalRandom.current();
+    final MongoHandler dbh = new MongoHandler(req, queriesParam, randomUpdates);
     for (int i = 0; i < queriesParam; i++) {
-      findRandom(random, dbh);
+      findRandom(dbh);
     }
   }
 
-  private void findRandom(Random random, Handler<Message<JsonObject>> handler) {
+  private void findRandom(Handler<Message<JsonObject>> handler) {
     vertx.eventBus().send(
         MONGO_ADDRESS,
         new JsonObject()
@@ -147,6 +211,17 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
         handler);
   }
 
+  private void updateRandom(JsonObject json) {
+    vertx.eventBus().send(
+        MONGO_ADDRESS,
+        new JsonObject()
+            .putString(TEXT_ACTION, TEXT_UPDATE)
+            .putString(TEXT_COLLECTION, TEXT_WORLD)
+            .putObject(TEXT_CRITERIA, new JsonObject().putValue(UNDERSCORE_ID, json.getValue(TEXT_ID)))
+            .putObject(TEXT_OBJ_NEW, json)
+             );
+  }
+
   private void sendResponse(HttpServerRequest req, String result) {
     Buffer buff = new Buffer(result);
     HttpServerResponse resp = req.response();
@@ -161,20 +236,27 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
     resp.putHeader(HEADER_DATE, dateString);
   }
 
-  private class MongoHandler implements Handler<Message<JsonObject>> {
+  private final class MongoHandler implements Handler<Message<JsonObject>> {
     private final HttpServerRequest req;
     private final int queries;
     private final JsonArray worlds;
+    private final Random random;
+    private final boolean randomUpdates;
 
-    public MongoHandler(HttpServerRequest request, int queriesParam) {
+    public MongoHandler(HttpServerRequest request, int queriesParam, boolean performRandomUpdates) {
       req = request;
       queries = queriesParam;
+      randomUpdates = performRandomUpdates;
+      random = ThreadLocalRandom.current();
       worlds = new JsonArray();
     }
-
     @Override
     public void handle(Message<JsonObject> reply) {
       JsonObject world = getResultFromReply(reply);
+      if (randomUpdates) {
+        world.putValue(RANDOM_NUMBER, (random.nextInt(10000) + 1));
+        updateRandom(world);        
+      }
       worlds.add(world);
       if (worlds.size() == this.queries) {
         // All queries have completed; send the response.
@@ -183,6 +265,25 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
       }
     }
   }
+  
+  public final class Fortune implements Comparable<Fortune> {
+    public int id;
+    public String message;
 
+    public int getId() {
+      return id;
+    }
+    public String getMessage() {
+      return message;
+    }
+    public Fortune(int id, String message) {
+      this.id = id;
+      this.message = message;
+    }
+    @Override
+    public int compareTo(Fortune other) {
+      return message.compareTo(other.message);
+    }
+  }  
 }
 

+ 1 - 1
frameworks/Java/vertx/app.js

@@ -4,7 +4,7 @@ var persistorConf = {
   address: 'hello.persistor',
   db_name: 'hello_world',
   host: '127.0.0.1',
-  pool_size: 20
+  pool_size: 100
 }
 
 container.deployModule('io.vertx~mod-mongo-persistor~2.1.1', persistorConf, function (err, dep_id) {

+ 2 - 0
frameworks/Java/vertx/benchmark_config.json

@@ -7,6 +7,8 @@
       "db_url": "/db",
       "plaintext_url": "/plaintext",
       "query_url": "/queries?queries=",
+      "update_url": "/updates?queries=",
+      "fortune_url": "/fortunes",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",

+ 1 - 1
frameworks/Java/vertx/install.sh

@@ -7,5 +7,5 @@ RETCODE=$(fw_exists ${IROOT}/vert.x-2.1.5.installed)
 
 fw_get http://dl.bintray.com/vertx/downloads/vert.x-2.1.5.tar.gz?direct=true -O vert.x-2.1.5.tar.gz
 fw_untar vert.x-2.1.5.tar.gz
-
+wget http://central.maven.org/maven2/org/freemarker/freemarker/2.3.22/freemarker-2.3.22.jar -O ${IROOT}/vert.x-2.1.5/lib/freemarker-2.3.22.jar
 touch ${IROOT}/vert.x-2.1.5.installed

+ 51 - 21
frameworks/Lua/openresty/app.lua

@@ -3,6 +3,12 @@ local mysql = mysql
 local encode = encode
 local random = math.random
 local min = math.min
+local insert = table.insert
+local sort = table.sort
+local template = require'resty.template'
+template.caching(false)
+-- Compile template, disable cache, enable plain text view to skip filesystem loading
+local view = template.compile([[<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>{% for _,f in ipairs(fortunes) do %}<tr><td>{{ f.id }}</td><td>{{ f.message }}</td></tr>{% end %}</table></body></html>]], nil, true)
 
 local mysqlconn = {
 	host = "DBHOSTNAME",
@@ -11,24 +17,48 @@ local mysqlconn = {
 	user = "benchmarkdbuser",
 	password = "benchmarkdbpass"
 }
-return function(ngx)
-	local db = mysql:new()
-	assert(db:connect(mysqlconn))
-	local num_queries = tonumber(ngx.var.arg_queries) or 1
-	-- May seem like a stupid branch, but since we know that
-	-- at a benchmark it will always be taken one way,
-	-- it doesn't matter. For me, after a small warmup, the performance
-	-- is identical to a version without the branch
-	-- http://wiki.luajit.org/Numerical-Computing-Performance-Guide
-	if num_queries == 1 then
-		ngx.print(encode(db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]))
-	else
-		local worlds = {}
-		num_queries = min(500, num_queries)
-		for i=1, num_queries do
-			worlds[#worlds+1] = db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]
-		end
-		ngx.print( encode(worlds) )
-	end
-	db:set_keepalive(0, 256)
-end
+return {
+    db = function(ngx)
+        local db = mysql:new()
+        assert(db:connect(mysqlconn))
+        ngx.print(encode(db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]))
+        db:set_keepalive(0, 256)
+    end,
+    queries = function(ngx)
+        local db = mysql:new()
+        assert(db:connect(mysqlconn))
+        local num_queries = tonumber(ngx.var.arg_queries) or 1
+        -- May seem like a stupid branch, but since we know that
+        -- at a benchmark it will always be taken one way,
+        -- it doesn't matter. For me, after a small warmup, the performance
+        -- is identical to a version without the branch
+        -- http://wiki.luajit.org/Numerical-Computing-Performance-Guide
+        if num_queries < 2 then
+            ngx.print(encode({db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]}))
+        else
+            local worlds = {}
+            num_queries = min(500, num_queries)
+            for i=1, num_queries do
+                worlds[#worlds+1] = db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]
+            end
+            ngx.print( encode(worlds) )
+        end
+        db:set_keepalive(0, 256)
+    end,
+    fortunes = function(ngx)
+        local db = mysql:new()
+        assert(db:connect(mysqlconn))
+        local fortunes = db:query('SELECT * FROM Fortune')
+        insert(fortunes, {
+            id = 0,
+            message = "Additional fortune added at request time."
+        })
+        sort(fortunes, function(a, b)
+            return a.message < b.message
+        end)
+        local res = view{fortunes=fortunes}
+        ngx.header['Content-Length'] = #res
+        ngx.print(res)
+        db:set_keepalive(0, 256)
+    end
+}

+ 2 - 1
frameworks/Lua/openresty/benchmark_config.json

@@ -5,7 +5,8 @@
       "setup_file": "setup",
       "json_url": "/json",
       "db_url": "/db",
-      "query_url": "/db?queries=",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortunes",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",

+ 3 - 1
frameworks/Lua/openresty/install.sh

@@ -1,3 +1,5 @@
 #!/bin/bash
 
-fw_depends lua nginx openresty 
+fw_depends lua openresty
+
+sudo luarocks install --server=http://rocks.moonscript.org lua-resty-template

+ 11 - 2
frameworks/Lua/openresty/nginx.conf

@@ -9,7 +9,7 @@ http {
     resolver 127.0.0.1;
     access_log off;
     lua_package_path 'CWD/?.lua;;';
-    init_by_lua 'jit.opt.start("minstitch=10"); require "resty.core" encode = require("cjson").encode mysql = require("resty.mysql")';
+    init_by_lua 'jit.opt.start("minstitch=10"); require "resty.core" encode = require("cjson").encode mysql = require("resty.mysql") app = require("app")';
     server {
         listen       8080;
         location /plaintext {
@@ -21,8 +21,17 @@ http {
             default_type "application/json";
             content_by_lua 'ngx.print(encode({message = "Hello, World!"}))';
         }
+        location /fortunes {
+            default_type "text/html; charset=UTF-8";
+            content_by_lua 'app.fortunes(ngx)';
+        }
+        location /db {
+            default_type "application/json";
+            content_by_lua 'app.db(ngx)';
+        }
         location / {
-            content_by_lua 'require("app")(ngx)';
+            default_type "application/json";
+            content_by_lua 'app.queries(ngx)';
         }
     }
 }

+ 1 - 1
frameworks/PHP/codeigniter/install.sh

@@ -9,4 +9,4 @@ fw_depends php nginx composer
 
 ${PHP_HOME}/bin/php ${COMPOSER_HOME}/composer.phar install \
   --no-interaction --working-dir $TROOT \
-  --no-progress --optimize-autoloader 
+  --no-progress --optimize-autoloader

+ 63 - 0
frameworks/PHP/cygnite-php-framework/.gitignore

@@ -0,0 +1,63 @@
+
+
+#Build System
+**/builds/*
+
+#bower
+/bower_components
+
+#Binary files
+/bin/
+
+#Grunt
+/node_modules/*
+
+# Composer
+/vendor/
+composer.phar
+composer.lock
+
+# Code Coverage
+build/coverage/*
+
+# always-ignore extensionsalways-ignore extensions
+*.diff
+*.err
+*.orig
+*.log
+*.rej
+*.swo
+*.swp
+*.vi
+*~
+*.sass-cache
+
+# OS or Editor folders
+.DS_Store
+Thumbs.db
+.cache
+.project
+.settings
+.tmproj
+*.esproj
+nbproject
+
+# Dreamweaver added files
+_notes
+dwsync.xml
+
+# Komodo
+*.komodoproject
+.komodotools
+
+# Folders to ignore
+.hg
+.svn
+.CVS
+intermediate
+publish
+.idea
+
+
+#Arcanist
+.arcconfig

+ 28 - 0
frameworks/PHP/cygnite-php-framework/.htaccess

@@ -0,0 +1,28 @@
+# Apache configuration file
+# http://httpd.apache.org/docs/2.2/mod/quickreference.html
+
+# Note: ".htaccess" files are an overhead for each request. This logic should
+# be placed in your Apache config whenever possible.
+# http://httpd.apache.org/docs/2.2/howto/htaccess.html
+
+# Turning on the rewrite engine is necessary for the following rules and
+# features. "+FollowSymLinks" must be enabled for this to work symbolically.
+
+<IfModule mod_rewrite.c>
+	Options +FollowSymLinks
+	RewriteEngine On
+	php_value safe_mode off
+</IfModule>
+
+# For all files not found in the file system, reroute the request to the
+# "index.php" front controller, keeping the query string intact
+
+<IfModule mod_rewrite.c>
+	RewriteCond %{REQUEST_FILENAME} !-f
+	RewriteCond %{REQUEST_FILENAME} !-d
+	RewriteRule ^(.*)$ index.php/$1 [L]
+	
+</IfModule>
+
+Order allow,deny
+Allow from all

+ 8 - 0
frameworks/PHP/cygnite-php-framework/.travis.yml

@@ -0,0 +1,8 @@
+language: php
+
+php:
+  - 5.4
+  - 5.5
+
+before_script:
+  - "composer install"

+ 20 - 0
frameworks/PHP/cygnite-php-framework/LICENSE

@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013-2014 Cygnite Framework <Sanjoy Dey>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 54 - 0
frameworks/PHP/cygnite-php-framework/README.md

@@ -0,0 +1,54 @@
+Skeleton Application Using Cygnite PHP Framework
+------------------------------------------------------------------
+
+[![Latest Stable Version](https://poser.pugx.org/cygnite/cygnite-application/v/stable.svg)](https://packagist.org/packages/cygnite/cygnite-application) [![Total Downloads](https://poser.pugx.org/cygnite/cygnite-application/downloads.svg)](https://packagist.org/packages/cygnite/cygnite-application) [![Latest Unstable Version](https://poser.pugx.org/cygnite/cygnite-application/v/unstable.svg)](https://packagist.org/packages/cygnite/cygnite-application) [![License](https://poser.pugx.org/cygnite/cygnite-application/license.svg)](https://packagist.org/packages/cygnite/cygnite-application)
+
+Sample skeleton application using the Cygnite MVC layer - http://www.cygniteframework.com
+
+>  Note: This repository contains the skeleton application of the Cygnite Framework. If you would like to contribute
+on Cygnite Framework, please visit the core [repository](https://github.com/cygnite/framework).
+
+Installation
+--------------
+The best way to install Cygnite Framework is to download composer.phar from http://getcomposer.org/ to your local directory or to use globally on your system move it to
+usr/local/bin. For windows users please download and install composer setup.
+
+You may install Cygnite Framework either simply downloading skeleton application from github repository or install via composer. Composer installation is more convenient.
+
+
+Composer: Create Project
+--------------------------------
+Create your project from terminal by simply entering below command.
+
+    composer create-project cygnite/cygnite-application cygnite --prefer-dist
+                                        or
+    composer.phar create-project cygnite/cygnite-application cygnite --prefer-dist
+
+That's all you are ready to build your awesome application.
+
+
+##Contribute -
+------------------
+-> Getting bored with the same kind of development all time?
+
+-> Would you like to be well recognised by professionals ?
+
+-> Do you want to learn something interesting and showcase your skills to grab better position ?
+
+You are at right place. We welcome you to participate on Cygnite Framework development or its documentation.
+
+Contribute on Cygnite Framework development and grow with us. Join the team, learn, get help and help others, find, report bugs, send us your feedback,
+send your wishlist for new features, write and send us patches for Cygnite Framework.
+
+
+##Getting Started with Cygnite -
+-----------------------------------------
+i.  Make sure you have GitHub Account.
+
+ii. Clearly describe the issue you find to fix shortly.
+
+iii. Create a branch where you would like to place your changes and send the patches to us.
+
+iv.  Fork cygnite/framework repository on GitHub.
+
+v. Please follow the PSR coding standard as followed  while contributing or please request for coding standard to follow.

+ 1 - 0
frameworks/PHP/cygnite-php-framework/apps/.htaccess

@@ -0,0 +1 @@
+Deny from all

+ 0 - 0
frameworks/PHP/cygnite-php-framework/apps/components/authentication/.gitkeep


+ 0 - 0
frameworks/PHP/cygnite-php-framework/apps/components/form/.gitkeep


+ 235 - 0
frameworks/PHP/cygnite-php-framework/apps/configs/application.php

@@ -0,0 +1,235 @@
+<?php
+if (!defined('CF_SYSTEM')) {
+    exit('External script access not allowed');
+}
+/**
+ *  Cygnite Framework
+ *  Global Configuration Settings
+ *
+ *  An open source application development framework for PHP 5.3x or newer
+ *
+ *   License
+ *
+ *   This source file is subject to the MIT license that is bundled
+ *   with this package in the file LICENSE.txt.
+ *   http://www.cygniteframework.com/license.txt
+ *   If you did not receive a copy of the license and are unable to
+ *   obtain it through the world-wide-web, please send an email
+ *   to [email protected] so I can send you a copy immediately.
+ *
+ * @package            :  Apps
+ * @subpackages        :  Configs
+ * @filename           :  application
+ * @description        :  You can set your all your global configurations here.
+ * @author             :  Sanjoy Dey
+ * @copyright          :  Copyright (c) 2013 - 2014,
+ * @link               :  http://www.cygniteframework.com
+ * @since              :  Version 1.0
+ * @filesource
+ * @warning            :  If you don't protect this directory from direct web access,
+ *                     anybody will be able to see your configuration and settings.
+ *
+ *
+ */
+
+return array(
+    /**
+     *--------------------------------------------------------------------------
+     * Your Application Base URL
+     *--------------------------------------------------------------------------
+     * The base URL used to import your application assets in your web page.
+     * Based on base url we will perform page redirect and other internal
+     * functionality.
+     *
+     */
+    'base_path' => '',
+    /*
+    *--------------------------------------------------------------------------
+    * Your Application Default Controller
+    *--------------------------------------------------------------------------
+    * Set your application default controller here. Default controller
+    * will be called when you try to access cygnite application.
+    */
+    'default_controller' => 'Home',
+    /*
+    *--------------------------------------------------------------------------
+    * Your Application Default Method
+    *--------------------------------------------------------------------------
+    * You can set your application default method here. By default we
+    * we will call index method of your controller.
+    * You can also change the default method.
+    *
+    */
+    'default_method' => 'index',
+
+    /*
+    *---------------------------------------------------------------------------
+    * Set Application Environment
+    *---------------------------------------------------------------------------
+    * You can set your application environment in order to handle errors and exceptions.
+    * Development mode all errors are turned on. So that you can able to fix all issues easily.
+    * Errors will be turned off in production server mode.
+    *
+    * Example :
+    * environment => 'development/production'
+    */
+    'environment' => 'production', //Errors are turned on in development environment
+
+    /*
+    *--------------------------------------------------------------------------
+    * Your Application Character Encoding
+    *--------------------------------------------------------------------------
+    * Here you can set your application default character encoding . This encoding
+    * will be used by the Str, Text, Form, and any other classes that need
+    *  to know what type of encoding to use for your generous application.
+    *
+    */
+    'encoding' => 'UTF-8',
+    /*
+    *--------------------------------------------------------------------------
+    * Your Application Language
+    *--------------------------------------------------------------------------
+    * You can set your application default language here. Language library will
+    * will take care rest.
+    */
+    'language' => 'en',
+    /*
+    *--------------------------------------------------------------------------
+    * Application Timezone
+    *--------------------------------------------------------------------------
+    * You can set your application timezone here.This timezone will
+    * be used when cygnite need date time or any internal features.
+    *
+    */
+    'timezone' => 'UTC',
+    /*
+    *--------------------------------------------------------------------------
+    *  Application Encryption key
+    *--------------------------------------------------------------------------
+    * Set your encryption key here. You must set your encryption key here in order to
+    * use cygnite secure encryption and session library. We used php mcrypt extension
+    * library for encryption library. So please check whether you have else please activate
+    * to work with secure encryption and session library.
+    */
+    'cf_encryption_key' => 'cygnite-shaXatBNHQ4',
+    /*
+    *--------------------------------------------------------------------------
+    * Benchmark Your Application
+    *--------------------------------------------------------------------------
+    * Enable profiling as True if you wish to benchmark your application. You can
+    * make it FALSE to deactivate profiling. Cygnite will take care rest.
+    */
+    'enable_profiling' => false,
+    /*
+    *--------------------------------------------------------------------------
+    * ************Your Application Cache Config*************
+    *--------------------------------------------------------------------------
+    * You can enable cache here (example: TRUE/FALSE). Cygnite have
+    * three type of cache driver FileCache, Memcache, APC to boost your
+    * application performace. Follow user guide for usages.
+    */
+    'enable_cache' => false,
+    /*
+    *---------------------------------------------------------------------------
+    * Cache Name
+    *---------------------------------------------------------------------------
+    * Set your cache name here to generate cache file name if you are
+    * using cygnite file caching technique.
+    */
+    'cache_name' => 'file.cache',
+    /*
+    *---------------------------------------------------------------------------
+    * Cache Extension
+    *---------------------------------------------------------------------------
+    * Set your cache extension here. Cygnite will take care of rest. Cache will
+    * store with same extension which you will provide here.
+    *
+    */
+    'cache_extension' => '.cache',
+    /*
+    *---------------------------------------------------------------------------
+    * Cache Type
+    *---------------------------------------------------------------------------
+    * Set your cache type here. Cygnite will take care of rest.
+    *
+    */
+    'cache_type' => 'file',
+    /*
+    *---------------------------------------------------------------------------
+    * Cache Storage Location
+    *---------------------------------------------------------------------------
+    * Set your cache file storage location here. By default we are using
+    * temp/cache.
+    *
+    */
+    'cache_directory' => 'temp.cache', //Default value is none
+
+    /**
+     *---------------------------------------------------------------------------
+     * Cygnite Application Logs
+     *---------------------------------------------------------------------------
+     * If you enable debugger will generate error logs into apps/temp/logs/
+     *
+     */
+    'enable_logging' => false,
+    /*
+    *---------------------------------------------------------------------------
+    * Logs File Name
+    *---------------------------------------------------------------------------
+    * Set your log file name here. Your applications logs will generate
+    * by cygnite engine and store as filename you provide here.
+    *
+    */
+    //'log_file_name'                => 'application_logs' ,
+    /*
+    *---------------------------------------------------------------------------
+    * Logs Storage Location
+    *---------------------------------------------------------------------------
+    * Set your log storage location here. By default we are using
+    * temp/logs.
+    *
+    */
+    'log_path' => 'apps.temp.logs',
+
+    /**
+     * Enable error emailing. When any error occur in production
+     * Mode email will trigger. Set true or false
+     */
+    'enable_error_emailing' => false,
+
+    /*
+     * Email Configurations
+     */
+    'email_configurations' => array(
+
+        'protocol' => 'smtp',
+
+        'smtp' => array(
+            'host' => 'smtp.gmail.com',
+            'username' => 'your gmail id',
+            'password' => 'your password',
+            'port' => '465',
+            'encryption' => 'ssl',
+        ),
+        'sendmail' => array(
+            'path' => '/usr/sbin/exim -bs'
+        ),
+
+    ),
+    'params' => array(
+
+        /*
+        | You can define your params here.
+        | All your params defined here has access
+        | globally in your application.
+        */
+        'admin_email' => '[email protected]',
+
+        /*
+        | We will make use of email address to send error log
+        | when application is in production mode.
+        |
+        */
+        'log_email' => '[email protected]',
+    ),
+);

+ 35 - 0
frameworks/PHP/cygnite-php-framework/apps/configs/autoload.php

@@ -0,0 +1,35 @@
+<?php
+/**
+ * This file is part of the Cygnite package.
+ *
+ * (c) Sanjoy Dey <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Cygnite\Foundation;
+
+if (!defined('CF_SYSTEM')) {
+    exit('External script access not allowed');
+}
+
+return array(
+    /*---------------------------------------------------------------------------
+    * Register all your directories to auto load your files.
+    *---------------------------------------------------------------------------
+    * You can specify multiple numbers of directories here to register on
+    * Cygnite Engine during runtime. Don't worry about the application
+    * performance because all libraries are lazy loaded. But filename,
+    * class name and file should be same, StudlyCaps.
+    *
+    *  Specify your directory path here. That's all. Cygnite will
+    *  take care of rest.
+    */
+    Application::instance()->registerDirectories(
+        array(
+            'apps.controllers',
+            'apps.models',
+            'apps.configs.definitions'
+        )
+    )
+);

+ 55 - 0
frameworks/PHP/cygnite-php-framework/apps/configs/database.php

@@ -0,0 +1,55 @@
+<?php
+/*
+ * This file is part of the Cygnite package.
+ *
+ * (c) Sanjoy Dey <[email protected]>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+namespace Cygnite\Database;
+
+if (!defined('CF_SYSTEM')) {
+    exit('External script access not allowed');
+}
+
+/**
+ * Initialize your database configurations settings here.
+ * You can connect with multiple database on the fly.
+ * Don't worry about performance Cygnite will not
+ * connect with database until first time you need your
+ * connection to interact with database.
+ * Specify your database name and table name in model to
+ * do crude operations.
+ *
+ * Please protect this file to have maximum security.
+ */
+Configuration::initialize(
+    function ($config) {
+        $config->default = 'db';
+        $config->setConfig(
+            array(
+                'db' => array(
+                    'driver' => 'mysql',
+                    'host' => '127.0.0.1',
+                    'port' => '',
+                    'database' => 'hello_world',
+                    'username' => 'benchmarkdbuser',
+                    'password' => 'benchmarkdbpass',
+                    'charset' => 'utf8'
+                )
+                /*'db1' => array(
+                    'driver' => 'mysql',
+                    'host' => 'localhost',
+                    'port' => '',
+                    'database' => '',
+                    'username' => '',
+                    'password' => '',
+                    'charset' => 'utf8'
+                )*/
+            )
+        );
+    }
+);
+
+

+ 77 - 0
frameworks/PHP/cygnite-php-framework/apps/configs/definitions/DefinitionManager.php

@@ -0,0 +1,77 @@
+<?php
+namespace Apps\Configs\Definitions;
+
+if (!defined('CF_SYSTEM')) {
+    exit('External script access not allowed');
+}
+/**
+ *  Cygnite Framework
+ *  Database Configuration Settings
+ *
+ *  An open source application development framework for PHP 5.3x or newer
+ *
+ *   License
+ *
+ *   This source file is subject to the MIT license that is bundled
+ *   with this package in the file LICENSE.txt.
+ *   http://www.cygniteframework.com/license.txt
+ *   If you did not receive a copy of the license and are unable to
+ *   obtain it through the world-wide-web, please send an email
+ *   to [email protected] so I can send you a copy immediately.
+ *
+ *@package               : Apps
+ *@subpackages           : Configurations
+ *@filename              : DefinitionManager.php
+ *@description           : Define all your property dependencies. Cygnite will
+ *                         inject your dependency at run time.
+ *@author                : Sanjoy Dey
+ *@copyright             : Copyright (c) 2013 - 2014,
+ *@link	                 : http://www.cygniteframework.com
+ *@since	             : Version 1.2
+ *@filesource
+ *
+ */
+
+ class DefinitionManager
+ {
+
+   /**
+      * Set controller property dependencies here.
+      * Cygnite will inject all your dependencies at runtime
+      *
+      * @return array
+      *  <code>
+      *   return
+      *     array(
+      *          'HomeController' => array(
+      *              'service' => 'apps.extensions.general',
+      *              'api' => 'apps.extensions.api'
+      *           ),
+      *          'ProductsController' => array(
+      *             'social' => 'apps.extensions.social-share',
+      *          ),
+      *      );
+      *  </code>
+      *
+      */
+     public function getPropertyDependencies()
+     {
+        return array();
+     }
+
+     /**
+      *
+      * @return type
+       *  <code>
+      *   return
+      *     array(
+      *          'GeneralInterface' => '\\Apps\\Extensions\\General',
+      *          'ORM' => '\\Cygnite\\Database\\ActiveRecord',
+      *      );
+      *  </code>
+      */
+     public function registerAlias()
+     {
+         return array();
+     }
+ }

+ 69 - 0
frameworks/PHP/cygnite-php-framework/apps/configs/migration.php

@@ -0,0 +1,69 @@
+<?php
+namespace Cygnite\Database;
+
+/**
+ *  Cygnite Framework
+ *  Database Migration Configuration Settings
+ *
+ *  An open source application development framework for PHP 5.3x or newer
+ *
+ *   License
+ *
+ *   This source file is subject to the MIT license that is bundled
+ *   with this package in the file LICENSE.txt.
+ *   http://www.cygniteframework.com/license.txt
+ *   If you did not receive a copy of the license and are unable to
+ *   obtain it through the world-wide-web, please send an email
+ *   to [email protected] so I can send you a copy immediately.
+ *
+ *@package               : Apps
+ *@subpackages           : Database Migration Configurations
+ *@filename              : migration.php
+ *@description           : You can set your session configurations here.
+ *@author                : Sanjoy Dey
+ *@copyright             : Copyright (c) 2013 - 2014,
+ *@link	                 : http://www.cygniteframework.com
+ *@since	             : Version 1.2
+ *@filesource
+ *@warning               : If you don't protect this directory from direct web access,
+ * anybody will be able to see your database configuration and settings.
+ *
+ *
+ */
+
+if (!defined('CF_SYSTEM')) {
+    exit('External script access not allowed');
+}
+
+/**
+ * Initialize your database configurations settings here.
+ * You can connect with multiple database on the fly.
+ * Don't worry about performance Cygnite will not
+ * connect with database until first time you need your
+ * connection to interact with database.
+ * Specify your database name and table name in model to
+ * do crude operations.
+ *
+ * <code>
+ * 'connection'  => 'your-database',
+ * 'migration_path' => 'migration-directory',
+ * 'migration_table' => 'migration-table-name',
+ *
+ * </code>
+ *
+ * Example :
+ * cd console/bin
+ * php cygnite migrate:init create_products_table 
+ * php cygnite migrate
+ */
+
+
+return array(
+    'connection' => 'cygnite', //If you don't specify your connection name Cygnite will take default database 
+    //connection to generate your migrations
+
+    'migration_path' => 'apps.migrations',
+
+    'migration_table' => 'migrations',
+
+);

+ 27 - 0
frameworks/PHP/cygnite-php-framework/apps/configs/services.php

@@ -0,0 +1,27 @@
+<?php
+use Cygnite\Foundation\Application as App;
+
+if (!defined('CF_SYSTEM')) {
+    exit('External script access not allowed');
+}
+
+// Register all service provider
+App::service(function ($app)
+{
+    // Add multiple Service Provider into the array
+    /*
+     $app->registerServiceProvider(
+        array(
+            "Apps\\Services\\Payment\\ApiServiceProvider",
+        )
+    );
+	
+    // Use Controller as Service manual configuration
+    $app['user.controller'] = function () use($app)
+    {
+        return new \Apps\Controllers\HelloController(new \Cygnite\Mvc\Controller\ServiceController, $app);
+    }; 
+	// OR 
+	// Controller as Service automatic configuration
+    $app->setServiceController('hello.controller', '\Application\Controllers\HelloController');*/
+});

+ 105 - 0
frameworks/PHP/cygnite-php-framework/apps/configs/session.php

@@ -0,0 +1,105 @@
+<?php
+if (!defined('CF_SYSTEM')) {
+    exit('External script access not allowed');
+}
+/**
+ * Cygnite PHP Framework
+ *
+ * Session Configuration
+ *
+ * @author Sanjoy Dey <[email protected]>
+ */
+
+return array(
+
+    /**
+     *----------------------------------------------------------
+     * Session Driver
+     *----------------------------------------------------------
+     * Set session driver to use native session or database
+     * based session. Just provide the driver as "native" or
+     * "database". Cygnite will take care of next.
+     */
+    'driver' => 'native', // native, database
+
+    /**
+     *----------------------------------------------------------
+     * Session Name
+     *----------------------------------------------------------
+     * Set your session name, else cygnite will use default name
+     */
+    'session_name'  => 'cf_secure_session',
+
+    /**
+     *----------------------------------------------------------
+     * Session Storage Path
+     *----------------------------------------------------------
+     * Leave it as default as it will store into the default session
+     * directory.
+     */
+    'path' => 'default',
+
+    /**
+     *----------------------------------------------------------
+     * Database For Session Storage
+     *----------------------------------------------------------
+     * Set the database name if you are using database based session
+     * in order to store session.
+     *
+     * Change database name below to use session database driver
+     */
+    'database_name' => 'cygnite',
+
+    /**
+     *----------------------------------------------------------
+     * Setting Table Name For Session Storage
+     *----------------------------------------------------------
+     * Provide table name if you are using database based session.
+     * By default "cf_sessions" is the table to store all session
+     * into table.
+     */
+    'table' => 'cf_sessions',
+
+    /**
+     *----------------------------------------------------------
+     * Use Session Cookie
+     *----------------------------------------------------------
+     * Configure to use session cookie or not
+     */
+    'use_session_cookie' => false,
+
+    /**
+     *----------------------------------------------------------
+     * Session Cookie Name
+     *----------------------------------------------------------
+     * If you are using session cookie then provide the name here else
+     * leave it blank.
+     */
+    'session_cookie_name' => '',
+
+    /**
+     *----------------------------------------------------------
+     * HTTP Only
+     *----------------------------------------------------------
+     * Configure to set httponly for cookie params
+     */
+    'httponly' => true,
+
+    /**
+     * --------------------------------------------------------
+     *  Set Session Time out
+     * --------------------------------------------------------
+     * Currently not implemented, you can change the session
+     * timeout in php.ini configuration file
+     */
+    'timeout' => 1440,
+
+    /**
+     *----------------------------------------------------------
+     * Secure Session
+     *----------------------------------------------------------
+     * You may leave it as false or true to use secure session
+     * By default cygnite provides most security to the session.
+     */
+    'secure' => false,
+);

+ 94 - 0
frameworks/PHP/cygnite-php-framework/apps/controllers/BenchController.php

@@ -0,0 +1,94 @@
+<?php
+namespace Apps\Controllers;
+
+use Cygnite\Mvc\Controller\AbstractBaseController;
+use Apps\Models\Fortune;
+use Apps\Models\World;
+
+class BenchController extends AbstractBaseController
+{
+    protected $templateEngine = false;
+
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    public function indexAction()
+    {
+        echo 'Hello World!';
+    }
+
+    public function dbAction()
+    {
+        $worlds = $arr = array();
+        $world = null;
+        $queries = 1;
+
+        $worlds = $this->getWorldsInfo($queries);
+        $worlds = $worlds[0];
+
+        header('Content-type: application/json');
+        echo json_encode($worlds);
+    }
+
+    private function getWorldsInfo($queries)
+    {
+        $world = null;
+        $worlds = $arr = array();
+
+        for ($i = 0; $i < $queries; ++$i) {
+            $world = World::find(mt_rand(1, 10000));
+            $arr['id'] = (int) $world->id;
+            $arr['randomNumber'] = (int) $world->randomnumber;
+            $worlds[] = $arr;
+        }
+
+        return $worlds;
+    }
+
+    public function queriesAction($queries = 1)
+    {
+        $queries = intval($queries);
+        if ($queries < 1 ) {
+            $queries = 1;
+        } elseif ($queries > 500) {
+            $queries = 500;
+        }
+
+        $worlds = array();
+        $worlds = $this->getWorldsInfo($queries);
+
+        header('Content-type: application/json');
+        echo json_encode($worlds);
+    }
+
+    public function fortunesAction()
+    {
+        $fortuneCollection = array();
+        $fortuneCollection = Fortune::all();
+        $fortunes = $fortuneCollection->asArray();
+
+        $runtimeFortune = new Fortune();
+        $runtimeFortune->id = 0;
+        $runtimeFortune->message = 'Additional fortune added at request time.';
+
+        $fortunes[] = $runtimeFortune;
+
+        usort($fortunes, function($left, $right) {
+
+            if ($left->message === $right->message) {
+                return 0;
+            } else if ($left->message > $right->message) {
+                return 1;
+            } else {
+                return -1;
+            }
+
+        });
+
+        $this->render('fortunes', array(
+                'fortunes' => $fortunes
+        ));
+    }
+}

+ 80 - 0
frameworks/PHP/cygnite-php-framework/apps/controllers/HomeController.php

@@ -0,0 +1,80 @@
+<?php
+namespace Apps\Controllers;
+
+use Cygnite\Foundation\Application;
+use Cygnite\Mvc\Controller\AbstractBaseController;
+
+class HomeController extends AbstractBaseController
+{
+    /**
+    * --------------------------------------------------------------------------
+    * The Default Controller
+    *--------------------------------------------------------------------------
+    *  This controller respond to uri beginning with home and also
+    *  respond to root url like "home/index"
+    *
+    * Your GET request of "home/index" will respond like below -
+    *
+    *      public function indexAction()
+    *     {
+    *            echo "Cygnite : Hellow ! World ";
+    *     }
+    * Note: By default cygnite doesn't allow you to pass query string in url, which
+    * consider as bad url format.
+    *
+    * You can also pass parameters into the function as below-
+    * Your request to  "home/form/2134" will pass to
+    *
+    *      public function formAction($id = ")
+    *      {
+    *             echo "Cygnite : Your user Id is $id";
+    *      }
+    * In case if you are not able to access parameters passed into method
+    * directly as above, you can also get the uri segment
+    *  echo Url::segment(3);
+    *
+    * That's it you are ready to start your awesome application with Cygnite Framework.
+    *
+    */
+
+    protected $layout = 'layout.home';
+
+    protected $templateEngine = false;
+
+   // protected $templateExtension = '.html.twig';
+
+   //protected $autoReload = true;
+     /*
+     * Your constructor.
+     * @access public
+     *
+     */
+    public function __construct()
+    {
+        parent::__construct();
+
+    }
+
+    /**
+     * Default method for your controller. Render welcome page to user.
+     * @access public
+     *
+     */
+   public function indexAction()
+   {
+       $this->render('welcome', array('title' => 'Welcome to Cygnite Framework'));
+   }
+   
+   public function hmvcAction($id)
+   {
+        //We are calling HMVC widget and return response
+		$widgetResponse = $this->call('modules.admin.controllers.user@index', array('id' => $id));
+		
+		//You should enable layout in order to access variable into view page
+       $this->render('application', array(
+                'messege' => 'Welcome to Cygnite framework',
+                'userwidget' => $widgetResponse
+        ));  
+   }
+
+}//End of your home controller

+ 0 - 0
frameworks/PHP/cygnite-php-framework/apps/database/.gitkeep


+ 0 - 0
frameworks/PHP/cygnite-php-framework/apps/database/migrations/.gitkeep


+ 0 - 0
frameworks/PHP/cygnite-php-framework/apps/extensions/.gitkeep


Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini