rsence 2.0.0.0.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. data/INSTALL.rdoc +295 -0
  2. data/LICENSE +622 -0
  3. data/README.rdoc +24 -0
  4. data/VERSION +1 -0
  5. data/bin/build_client.rb +254 -0
  6. data/bin/help +6 -0
  7. data/bin/launch.rb +120 -0
  8. data/bin/rdoc.sh +2 -0
  9. data/bin/restart +6 -0
  10. data/bin/rsence +120 -0
  11. data/bin/run +6 -0
  12. data/bin/run.rb +6 -0
  13. data/bin/save +6 -0
  14. data/bin/start +6 -0
  15. data/bin/status +6 -0
  16. data/bin/stop +6 -0
  17. data/conf/config.ru +5 -0
  18. data/conf/default_conf.yaml +337 -0
  19. data/conf/default_strings.yaml +77 -0
  20. data/conf/local_conf.yaml +14 -0
  21. data/conf/unicorn.conf +78 -0
  22. data/js/comm/comm/autosync/autosync.js +18 -0
  23. data/js/comm/comm/autosync/js.inc +0 -0
  24. data/js/comm/comm/comm.js +195 -0
  25. data/js/comm/comm/js.inc +0 -0
  26. data/js/comm/comm/queue/js.inc +0 -0
  27. data/js/comm/comm/queue/queue.js +183 -0
  28. data/js/comm/comm/session/js.inc +0 -0
  29. data/js/comm/comm/session/session.js +51 -0
  30. data/js/comm/comm/sessionwatcher/js.inc +0 -0
  31. data/js/comm/comm/sessionwatcher/sessionwatcher.js +43 -0
  32. data/js/comm/comm/transporter/js.inc +0 -0
  33. data/js/comm/comm/transporter/transporter.js +257 -0
  34. data/js/comm/comm/urlresponder/js.inc +0 -0
  35. data/js/comm/comm/urlresponder/urlresponder.js +148 -0
  36. data/js/comm/comm/values/js.inc +0 -0
  37. data/js/comm/comm/values/values.js +432 -0
  38. data/js/comm/jsloader/js.inc +0 -0
  39. data/js/comm/jsloader/jsloader.js +114 -0
  40. data/js/comm/reloadapp/js.inc +0 -0
  41. data/js/comm/reloadapp/reloadapp.js +150 -0
  42. data/js/comm/reloadapp/themes/default/reloadapp_warning-ie6.gif +0 -0
  43. data/js/comm/reloadapp/themes/default/reloadapp_warning.png +0 -0
  44. data/js/comm/sha/js.inc +0 -0
  45. data/js/comm/sha/sha.js +432 -0
  46. data/js/comm/values/value/js.inc +0 -0
  47. data/js/comm/values/value/value.js +182 -0
  48. data/js/comm/values/valuematrix/js.inc +0 -0
  49. data/js/comm/values/valuematrix/valuematrix.js +138 -0
  50. data/js/controls/button/button.js +57 -0
  51. data/js/controls/button/js.inc +0 -0
  52. data/js/controls/button/themes/bright/button.css +89 -0
  53. data/js/controls/button/themes/bright/button.html +7 -0
  54. data/js/controls/button/themes/bright/button_parts1-ie6.gif +0 -0
  55. data/js/controls/button/themes/bright/button_parts1.png +0 -0
  56. data/js/controls/button/themes/default/button.css +89 -0
  57. data/js/controls/button/themes/default/button.html +7 -0
  58. data/js/controls/button/themes/default/button_parts1-ie6.gif +0 -0
  59. data/js/controls/button/themes/default/button_parts1.png +0 -0
  60. data/js/controls/checkbox/checkbox.js +47 -0
  61. data/js/controls/checkbox/js.inc +0 -0
  62. data/js/controls/checkbox/themes/default/checkbox.css +69 -0
  63. data/js/controls/checkbox/themes/default/checkbox.html +5 -0
  64. data/js/controls/checkbox/themes/default/checkbox_parts1-ie6.gif +0 -0
  65. data/js/controls/checkbox/themes/default/checkbox_parts1.png +0 -0
  66. data/js/controls/datetime/calendar/calendar.js +197 -0
  67. data/js/controls/datetime/calendar/js.inc +0 -0
  68. data/js/controls/datetime/calendar/themes/default/calendar.css +108 -0
  69. data/js/controls/datetime/calendar/themes/default/calendar.html +9 -0
  70. data/js/controls/datetime/calendar/themes/default/calendar_arrows-ie6.gif +0 -0
  71. data/js/controls/datetime/calendar/themes/default/calendar_arrows.png +0 -0
  72. data/js/controls/datetime/datetimevalue/datetimevalue.js +246 -0
  73. data/js/controls/datetime/datetimevalue/js.inc +0 -0
  74. data/js/controls/datetime/timesheet/js.inc +0 -0
  75. data/js/controls/datetime/timesheet/themes/default/timesheet.css +30 -0
  76. data/js/controls/datetime/timesheet/themes/default/timesheet.html +2 -0
  77. data/js/controls/datetime/timesheet/timesheet.js +182 -0
  78. data/js/controls/datetime/timesheet_item/js.inc +0 -0
  79. data/js/controls/datetime/timesheet_item/themes/default/timesheet_item.css +42 -0
  80. data/js/controls/datetime/timesheet_item/themes/default/timesheet_item.html +8 -0
  81. data/js/controls/datetime/timesheet_item/timesheet_item.js +247 -0
  82. data/js/controls/datetime/timesheet_item_edit/js.inc +0 -0
  83. data/js/controls/datetime/timesheet_item_edit/timesheet_item_edit.js +274 -0
  84. data/js/controls/dialogs/alert_sheet/alert_sheet.js +62 -0
  85. data/js/controls/dialogs/alert_sheet/js.inc +0 -0
  86. data/js/controls/dialogs/confirm_sheet/confirm_sheet.js +36 -0
  87. data/js/controls/dialogs/confirm_sheet/js.inc +0 -0
  88. data/js/controls/dialogs/sheet/js.inc +0 -0
  89. data/js/controls/dialogs/sheet/sheet.js +83 -0
  90. data/js/controls/dialogs/sheet/themes/default/sheet.css +64 -0
  91. data/js/controls/dialogs/sheet/themes/default/sheet.html +14 -0
  92. data/js/controls/dialogs/sheet/themes/default/sheet_bg-ie6.gif +0 -0
  93. data/js/controls/dialogs/sheet/themes/default/sheet_bg.png +0 -0
  94. data/js/controls/dialogs/sheet/themes/default/sheet_dim-ie6.gif +0 -0
  95. data/js/controls/dialogs/sheet/themes/default/sheet_dim.png +0 -0
  96. data/js/controls/dialogs/sheet/themes/default/sheet_parts1-ie6.gif +0 -0
  97. data/js/controls/dialogs/sheet/themes/default/sheet_parts1.png +0 -0
  98. data/js/controls/dialogs/sheet/themes/default/sheet_parts2-ie6.gif +0 -0
  99. data/js/controls/dialogs/sheet/themes/default/sheet_parts2.png +0 -0
  100. data/js/controls/dialogs/sheet/themes/default/sheet_warning-ie6.gif +0 -0
  101. data/js/controls/dialogs/sheet/themes/default/sheet_warning.png +0 -0
  102. data/js/controls/imageview/imageview.js +108 -0
  103. data/js/controls/imageview/js.inc +0 -0
  104. data/js/controls/imageview/themes/default/blank.gif +0 -0
  105. data/js/controls/lists/checkboxlist/checkboxlist.js +170 -0
  106. data/js/controls/lists/checkboxlist/js.inc +0 -0
  107. data/js/controls/lists/listitems/js.inc +0 -0
  108. data/js/controls/lists/listitems/listitems.js +65 -0
  109. data/js/controls/lists/radiobuttonlist/js.inc +0 -0
  110. data/js/controls/lists/radiobuttonlist/radiobuttonlist.js +126 -0
  111. data/js/controls/passwordcontrol/js.inc +0 -0
  112. data/js/controls/passwordcontrol/passwordcontrol.js +22 -0
  113. data/js/controls/passwordcontrol/themes/default/passwordcontrol.css +0 -0
  114. data/js/controls/passwordcontrol/themes/default/passwordcontrol.html +18 -0
  115. data/js/controls/progress/progressbar/js.inc +0 -0
  116. data/js/controls/progress/progressbar/progressbar.js +36 -0
  117. data/js/controls/progress/progressbar/themes/default/progressbar.css +16 -0
  118. data/js/controls/progress/progressbar/themes/default/progressbar.html +2 -0
  119. data/js/controls/progress/progressindicator/js.inc +0 -0
  120. data/js/controls/progress/progressindicator/progressindicator.js +43 -0
  121. data/js/controls/radiobutton/js.inc +0 -0
  122. data/js/controls/radiobutton/radiobutton.js +41 -0
  123. data/js/controls/radiobutton/themes/default/radiobutton.css +69 -0
  124. data/js/controls/radiobutton/themes/default/radiobutton.html +5 -0
  125. data/js/controls/radiobutton/themes/default/radiobutton_parts1-ie6.gif +0 -0
  126. data/js/controls/radiobutton/themes/default/radiobutton_parts1.png +0 -0
  127. data/js/controls/sliders/slider/js.inc +0 -0
  128. data/js/controls/sliders/slider/slider.js +356 -0
  129. data/js/controls/sliders/slider/themes/default/hslider_tracks-ie6.gif +0 -0
  130. data/js/controls/sliders/slider/themes/default/hslider_tracks.png +0 -0
  131. data/js/controls/sliders/slider/themes/default/slider.css +108 -0
  132. data/js/controls/sliders/slider/themes/default/slider.html +5 -0
  133. data/js/controls/sliders/slider/themes/default/slider_thumbs-ie6.gif +0 -0
  134. data/js/controls/sliders/slider/themes/default/slider_thumbs.png +0 -0
  135. data/js/controls/sliders/vslider/js.inc +0 -0
  136. data/js/controls/sliders/vslider/themes/default/vslider.css +52 -0
  137. data/js/controls/sliders/vslider/themes/default/vslider.html +5 -0
  138. data/js/controls/sliders/vslider/themes/default/vslider_tracks-ie6.gif +0 -0
  139. data/js/controls/sliders/vslider/themes/default/vslider_tracks.png +0 -0
  140. data/js/controls/sliders/vslider/vslider.js +40 -0
  141. data/js/controls/stepper/js.inc +0 -0
  142. data/js/controls/stepper/stepper.js +212 -0
  143. data/js/controls/stepper/themes/default/stepper-ie6.gif +0 -0
  144. data/js/controls/stepper/themes/default/stepper.css +14 -0
  145. data/js/controls/stepper/themes/default/stepper.html +2 -0
  146. data/js/controls/stepper/themes/default/stepper.png +0 -0
  147. data/js/controls/stringview/js.inc +0 -0
  148. data/js/controls/stringview/stringview.js +49 -0
  149. data/js/controls/stringview/themes/default/stringview.css +8 -0
  150. data/js/controls/stringview/themes/default/stringview.html +1 -0
  151. data/js/controls/tab/js.inc +0 -0
  152. data/js/controls/tab/tab.js +276 -0
  153. data/js/controls/tab/themes/bright/tab.css +76 -0
  154. data/js/controls/tab/themes/bright/tab.html +6 -0
  155. data/js/controls/tab/themes/bright/tab_bg_color-ie6.gif +0 -0
  156. data/js/controls/tab/themes/bright/tab_bg_color.png +0 -0
  157. data/js/controls/tab/themes/bright/tab_border_pattern-ie6.gif +0 -0
  158. data/js/controls/tab/themes/bright/tab_border_pattern.png +0 -0
  159. data/js/controls/tab/themes/bright/tab_parts1-ie6.gif +0 -0
  160. data/js/controls/tab/themes/bright/tab_parts1.png +0 -0
  161. data/js/controls/tab/themes/default/tab.css +77 -0
  162. data/js/controls/tab/themes/default/tab.html +6 -0
  163. data/js/controls/tab/themes/default/tab_bg_color-ie6.gif +0 -0
  164. data/js/controls/tab/themes/default/tab_bg_color.png +0 -0
  165. data/js/controls/tab/themes/default/tab_border_pattern-ie6.gif +0 -0
  166. data/js/controls/tab/themes/default/tab_border_pattern.png +0 -0
  167. data/js/controls/tab/themes/default/tab_parts1-ie6.gif +0 -0
  168. data/js/controls/tab/themes/default/tab_parts1.png +0 -0
  169. data/js/controls/textarea/js.inc +0 -0
  170. data/js/controls/textarea/textarea.js +23 -0
  171. data/js/controls/textarea/themes/default/textarea.css +21 -0
  172. data/js/controls/textarea/themes/default/textarea.html +18 -0
  173. data/js/controls/textcontrol/js.inc +0 -0
  174. data/js/controls/textcontrol/textcontrol.js +372 -0
  175. data/js/controls/textcontrol/themes/default/textcontrol.css +107 -0
  176. data/js/controls/textcontrol/themes/default/textcontrol.html +18 -0
  177. data/js/controls/textcontrol/themes/default/textcontrol_parts1-ie6.gif +0 -0
  178. data/js/controls/textcontrol/themes/default/textcontrol_parts1.png +0 -0
  179. data/js/controls/textcontrol/themes/default/textcontrol_parts2-ie6.gif +0 -0
  180. data/js/controls/textcontrol/themes/default/textcontrol_parts2.png +0 -0
  181. data/js/controls/textcontrol/themes/default/textcontrol_parts3-ie6.gif +0 -0
  182. data/js/controls/textcontrol/themes/default/textcontrol_parts3.png +0 -0
  183. data/js/controls/uploader/js.inc +0 -0
  184. data/js/controls/uploader/themes/default/upload_progress.gif +0 -0
  185. data/js/controls/uploader/themes/default/uploader.css +108 -0
  186. data/js/controls/uploader/themes/default/uploader.html +27 -0
  187. data/js/controls/uploader/uploader.js +153 -0
  188. data/js/controls/validatorview/js.inc +0 -0
  189. data/js/controls/validatorview/themes/default/validator-ie6.gif +0 -0
  190. data/js/controls/validatorview/themes/default/validator.png +0 -0
  191. data/js/controls/validatorview/themes/default/validatorview.css +0 -0
  192. data/js/controls/validatorview/themes/default/validatorview.html +0 -0
  193. data/js/controls/validatorview/validatorview.js +55 -0
  194. data/js/controls/window/js.inc +0 -0
  195. data/js/controls/window/themes/default/window.css +219 -0
  196. data/js/controls/window/themes/default/window.html +17 -0
  197. data/js/controls/window/themes/default/window_bg_active-ie6.gif +0 -0
  198. data/js/controls/window/themes/default/window_bg_active.png +0 -0
  199. data/js/controls/window/themes/default/window_bg_inactive-ie6.gif +0 -0
  200. data/js/controls/window/themes/default/window_bg_inactive.png +0 -0
  201. data/js/controls/window/themes/default/window_buttons-ie6.gif +0 -0
  202. data/js/controls/window/themes/default/window_buttons.png +0 -0
  203. data/js/controls/window/themes/default/window_parts1-ie6.gif +0 -0
  204. data/js/controls/window/themes/default/window_parts1.png +0 -0
  205. data/js/controls/window/themes/default/window_parts2-ie6.gif +0 -0
  206. data/js/controls/window/themes/default/window_parts2.png +0 -0
  207. data/js/controls/window/window.js +284 -0
  208. data/js/core/class/class.js +317 -0
  209. data/js/core/class/js.inc +0 -0
  210. data/js/core/elem/elem.js +1376 -0
  211. data/js/core/elem/js.inc +0 -0
  212. data/js/core/event/event.js +1021 -0
  213. data/js/core/event/js.inc +0 -0
  214. data/js/core/iefix/ie_css_element.htc +5 -0
  215. data/js/core/iefix/ie_css_style.htc +5 -0
  216. data/js/core/iefix/iefix.js +359 -0
  217. data/js/core/iefix/js.inc +0 -0
  218. data/js/debugg/debugg.js +43 -0
  219. data/js/debugg/js.inc +0 -0
  220. data/js/foundation/application/application.js +209 -0
  221. data/js/foundation/application/js.inc +0 -0
  222. data/js/foundation/control/control.js +342 -0
  223. data/js/foundation/control/controldefaults/controldefaults.js +59 -0
  224. data/js/foundation/control/controldefaults/js.inc +0 -0
  225. data/js/foundation/control/dummyvalue/dummyvalue.js +50 -0
  226. data/js/foundation/control/dummyvalue/js.inc +0 -0
  227. data/js/foundation/control/dyncontrol/dyncontrol.js +494 -0
  228. data/js/foundation/control/dyncontrol/js.inc +0 -0
  229. data/js/foundation/control/dyncontrol/themes/default/dyncontrol.css +0 -0
  230. data/js/foundation/control/dyncontrol/themes/default/dyncontrol.html +0 -0
  231. data/js/foundation/control/eventresponder/eventresponder.js +713 -0
  232. data/js/foundation/control/eventresponder/js.inc +0 -0
  233. data/js/foundation/control/js.inc +0 -0
  234. data/js/foundation/control/valueresponder/js.inc +0 -0
  235. data/js/foundation/control/valueresponder/valueresponder.js +77 -0
  236. data/js/foundation/geom/point/js.inc +0 -0
  237. data/js/foundation/geom/point/point.js +202 -0
  238. data/js/foundation/geom/rect/js.inc +0 -0
  239. data/js/foundation/geom/rect/rect.js +610 -0
  240. data/js/foundation/json_renderer/js.inc +0 -0
  241. data/js/foundation/json_renderer/json_renderer.js +231 -0
  242. data/js/foundation/system/js.inc +0 -0
  243. data/js/foundation/system/system.js +369 -0
  244. data/js/foundation/thememanager/js.inc +0 -0
  245. data/js/foundation/thememanager/thememanager.js +387 -0
  246. data/js/foundation/view/js.inc +0 -0
  247. data/js/foundation/view/markupview/js.inc +0 -0
  248. data/js/foundation/view/markupview/markupview.js +113 -0
  249. data/js/foundation/view/morphanimation/js.inc +0 -0
  250. data/js/foundation/view/morphanimation/morphanimation.js +236 -0
  251. data/js/foundation/view/view.js +1804 -0
  252. data/js/foundation/view/viewdefaults/js.inc +0 -0
  253. data/js/foundation/view/viewdefaults/viewdefaults.js +25 -0
  254. data/js/views/centerview/centerview.js +45 -0
  255. data/js/views/centerview/js.inc +0 -0
  256. data/js/views/inlineview/inlineview.js +14 -0
  257. data/js/views/inlineview/js.inc +0 -0
  258. data/js/views/scrollview/js.inc +0 -0
  259. data/js/views/scrollview/scrollview.js +39 -0
  260. data/lib/conf/default.rb +220 -0
  261. data/lib/conf/wizard.rb +303 -0
  262. data/lib/daemon/daemon.rb +293 -0
  263. data/lib/http/broker.rb +102 -0
  264. data/lib/http/rackup.rb +88 -0
  265. data/lib/http/request.rb +69 -0
  266. data/lib/http/response.rb +63 -0
  267. data/lib/plugins/gui_plugin.rb +129 -0
  268. data/lib/plugins/guiparser.rb +114 -0
  269. data/lib/plugins/plugin.rb +652 -0
  270. data/lib/plugins/plugin_plugins.rb +47 -0
  271. data/lib/plugins/plugin_sqlite_db.rb +72 -0
  272. data/lib/plugins/plugin_util.rb +96 -0
  273. data/lib/plugins/pluginmanager.rb +517 -0
  274. data/lib/plugins/servlet.rb +69 -0
  275. data/lib/session/msg.rb +291 -0
  276. data/lib/session/sessionmanager.rb +491 -0
  277. data/lib/session/sessionstorage.rb +314 -0
  278. data/lib/transporter/transporter.rb +254 -0
  279. data/lib/util/gzstring.rb +5 -0
  280. data/lib/values/hvalue.rb +323 -0
  281. data/lib/values/valuemanager.rb +152 -0
  282. data/plugins/client_pkg/client_pkg.rb +186 -0
  283. data/plugins/client_pkg/info.yaml +25 -0
  284. data/plugins/client_pkg/lib/client_pkg_build.rb +569 -0
  285. data/plugins/client_pkg/lib/client_pkg_cache.rb +50 -0
  286. data/plugins/client_pkg/lib/client_pkg_serve.rb +210 -0
  287. data/plugins/client_pkg/log/build_log +0 -0
  288. data/plugins/index_html/img/loading.gif +0 -0
  289. data/plugins/index_html/img/riassence.gif +0 -0
  290. data/plugins/index_html/index_html.rb +150 -0
  291. data/plugins/index_html/tmpl/index.html +22 -0
  292. data/plugins/index_html/tmpl/startup_index.html +29 -0
  293. data/plugins/legacy/disabled +0 -0
  294. data/plugins/legacy/disabled- +0 -0
  295. data/plugins/legacy/info.yaml +22 -0
  296. data/plugins/legacy/legacy.rb +15 -0
  297. data/plugins/main/js/riassence_ns.js +87 -0
  298. data/plugins/main/main.rb +234 -0
  299. data/plugins/main/values.yaml +8 -0
  300. data/plugins/ticketservices/lib/common.rb +300 -0
  301. data/plugins/ticketservices/lib/favicon.rb +38 -0
  302. data/plugins/ticketservices/lib/file.rb +58 -0
  303. data/plugins/ticketservices/lib/img.rb +50 -0
  304. data/plugins/ticketservices/lib/objblob.rb +66 -0
  305. data/plugins/ticketservices/lib/rsrc.rb +34 -0
  306. data/plugins/ticketservices/lib/upload.rb +206 -0
  307. data/plugins/ticketservices/ticketservices.rb +268 -0
  308. data/var/db/.git_include +0 -0
  309. data/var/log/.git_include +0 -0
  310. data/var/run/.git_include +0 -0
  311. metadata +390 -0
@@ -0,0 +1,69 @@
1
+ #--
2
+ ## Riassence Framework
3
+ # Copyright 2008 Riassence Inc.
4
+ # http://riassence.com/
5
+ #
6
+ # You should have received a copy of the GNU General Public License along
7
+ # with this software package. If not, contact licensing@riassence.com
8
+ ##
9
+ #++
10
+
11
+
12
+ require 'rubygems'
13
+ require 'rack'
14
+
15
+ module RSence
16
+
17
+ class Request < Rack::Request
18
+ attr_reader :header, :path, :query
19
+ def initialize(env)
20
+ @header = {
21
+
22
+ }
23
+ super
24
+ env2header()
25
+ @path = path_info()
26
+ @query = params()
27
+ end
28
+ def unparsed_uri
29
+ return @header['request-uri']
30
+ end
31
+ def env2header
32
+ [ ['SERVER_NAME', 'server-name'],
33
+ ['HTTP_USER_AGENT', 'user-agent'],
34
+ ['HTTP_ACCEPT_ENCODING', 'accept-encoding'],
35
+ ['PATH_INFO', 'path-info'],
36
+ ['HTTP_HOST', 'host'],
37
+ ['HTTP_ACCEPT_LANGUAGE', 'accept-language'],
38
+ ['SERVER_PROTOCOL', 'server-protocol'],
39
+ ['REQUEST_PATH', 'request-path'],
40
+ ['HTTP_KEEP_ALIVE', 'keep-alive'],
41
+ ['SERVER_SOFTWARE', 'server-software'],
42
+ ['REMOTE_ADDR', 'remote-addr'],
43
+ ['HTTP_REFERER', 'referer'],
44
+ ['HTTP_VERSION', 'version'],
45
+ ['HTTP_ACCEPT_CHARSET', 'accept-charset'],
46
+ ['REQUEST_URI', 'request-uri'],
47
+ ['SERVER_PORT', 'server-port'],
48
+ ['QUERY_STRING', 'query-string'],
49
+ ['HTTP_ACCEPT', 'accept'],
50
+ ['REQUEST_METHOD', 'request-method'],
51
+ ['HTTP_CONNECTION', 'connection'],
52
+ ['HTTP_SOAPACTION', 'soapaction'],
53
+ ['HTTP_FORWARDED_HOST', 'forwarded-host']
54
+ ].each do |env_key,header_key|
55
+ if @env.has_key?(env_key)
56
+ @header[header_key] = @env[env_key]
57
+ end
58
+ if env_key.start_with?( 'HTTP_' )
59
+ x_env_key = "HTTP_X#{env_key[4..-1]}"
60
+ if @env.has_key?( x_env_key )
61
+ @header["x-#{header_key}"] = @env[ x_env_key ]
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+
69
+ end
@@ -0,0 +1,63 @@
1
+ #--
2
+ ## Riassence Framework
3
+ # Copyright 2008 Riassence Inc.
4
+ # http://riassence.com/
5
+ #
6
+ # You should have received a copy of the GNU General Public License along
7
+ # with this software package. If not, contact licensing@riassence.com
8
+ ##
9
+ #++
10
+
11
+
12
+ module RSence
13
+
14
+ class ResponseBody < Array
15
+ def +(body_data)
16
+ self.push(body_data)
17
+ end
18
+ end
19
+
20
+ ## Minimally WEBrick -compatible Response object.
21
+ ## Implements only the methods used by the framework.
22
+ class Response
23
+ def initialize
24
+ @body = ResponseBody.new(1)
25
+ @body[0] = ''
26
+ @status = 200
27
+ @header = {
28
+ 'Content-Type' => 'text/plain',
29
+ 'Server' => 'Riassence Framework'
30
+ }
31
+ end
32
+ def body=(body_data)
33
+ @body = ResponseBody.new(1)
34
+ @body[0] = body_data
35
+ end
36
+ def body
37
+ @body.join
38
+ end
39
+ def content_type=(new_content_type)
40
+ @header['Content-Type'] = new_content_type
41
+ end
42
+ def content_type
43
+ @header['Content-Type']
44
+ end
45
+ def camelize( header_key )
46
+ header_key.capitalize.gsub(/\-([a-z])/) { '-'+$1.upcase }
47
+ end
48
+ def []=(header_key,header_val)
49
+ @header[camelize( header_key )] = header_val.to_s
50
+ end
51
+ def status=(new_val)
52
+ @status = new_val.to_i
53
+ end
54
+ def status
55
+ @status
56
+ end
57
+ def header
58
+ @header
59
+ end
60
+ end
61
+
62
+ end
63
+
@@ -0,0 +1,129 @@
1
+ ## Riassence Framework
2
+ # Copyright 2009 Riassence Inc.
3
+ # http://riassence.com/
4
+ #
5
+ # You should have received a copy of the GNU General Public License along
6
+ # with this software package. If not, contact licensing@riassence.com
7
+ ##
8
+
9
+ ## The GUIPlugin extends Plugin by automatically initializing an GUIParser
10
+ ## instance as @gui
11
+ ## It makes the include_js method public to enable automatic dependency
12
+ ## loading based on the dependencies item in the YAML gui declaration.
13
+ ## It also makes the @path public.
14
+ ## It inits the gui automatically.
15
+ ## Extend the gui_params method to define your own params for the gui data.
16
+ ##
17
+ ## HValues can be defined inside values.yaml at the root directory of
18
+ ## plugin. The HValues may be linked directly with methods on the values.yaml
19
+ ## as well.
20
+ ##
21
+ ## == Values.yaml
22
+ ## :valuename: # name of the HValue
23
+ ## :value: 2.56 # defined value
24
+ ## :responders: # methods responding to the value on ruby code upon change
25
+ ## - :method: validate_convert_factor
26
+ ##
27
+ ##
28
+ ##
29
+ class GUIPlugin < Plugin
30
+
31
+ @@default_yaml_src = %{
32
+ type: GUITree
33
+ version: 0.5
34
+
35
+ class: HApplication
36
+ options:
37
+ label: "Dummy Application"
38
+ }
39
+
40
+ # Automatically initializes an GUIParser instance as @gui
41
+ def init
42
+ super
43
+ yaml_src = file_read( "gui/#{@name}.yaml" )
44
+ yaml_src = file_read( "gui/main.yaml" ) unless yaml_src
45
+ yaml_src = @@default_yaml_src unless yaml_src
46
+ @gui = GUIParser.new( self, yaml_src )
47
+ @client_pkgs = false
48
+ end
49
+
50
+ # Extend this method to return custom params to GUIParser#init.
51
+ # Called from init_ui.
52
+ # By default assigns the session values as :values to use for
53
+ # valueObjId: ":values.my_value_name" in the YAML GUI file.
54
+ def gui_params( msg )
55
+ return {
56
+ :values => @gui.values( get_ses( msg ) )
57
+ }
58
+ end
59
+
60
+ def install_client_pkgs
61
+ if @client_pkgs
62
+ warn "install_client_pkgs: called with @client_pkgs defined; returning"
63
+ return
64
+ end
65
+ @client_pkgs = yaml_read( 'client_pkgs.yaml' )
66
+ if @client_pkgs
67
+ if @client_pkgs.has_key?(:src_dirs)
68
+ @client_pkgs[:src_dirs].each do |src_dir|
69
+ src_dir = bundle_path( src_dir[2..-1] ) if src_dir.start_with?('./')
70
+ @plugins.client_pkg.add_src_dir( src_dir )
71
+ end
72
+ end
73
+ @plugins.client_pkg.add_packages( @client_pkgs[:packages ] ) if @client_pkgs.has_key?(:packages )
74
+ @plugins.client_pkg.add_themes( @client_pkgs[:theme_names ] ) if @client_pkgs.has_key?(:theme_names )
75
+ @plugins.client_pkg.add_gfx_formats( @client_pkgs[:gfx_formats ] ) if @client_pkgs.has_key?(:gfx_formats )
76
+ @plugins.client_pkg.add_reserved_names( @client_pkgs[:reserved_names] ) if @client_pkgs.has_key?(:reserved_names)
77
+ @plugins.client_pkg.rebuild_client
78
+ end
79
+ end
80
+
81
+ def uninstall_client_pkgs
82
+ if not @client_pkgs
83
+ warn "uninstall_client_pkgs: called without @client_pkgs defined"
84
+ else
85
+ if @client_pkgs.has_key?(:src_dirs)
86
+ @client_pkgs[:src_dirs].each do |src_dir|
87
+ src_dir = bundle_path( src_dir[2..-1] ) if src_dir.start_with?('./')
88
+ @plugins.client_pkg.del_src_dir( src_dir )
89
+ end
90
+ end
91
+ @plugins.client_pkg.del_reserved_names( @client_pkgs[:reserved_names] ) if @client_pkgs.has_key?(:reserved_names)
92
+ @plugins.client_pkg.del_gfx_formats( @client_pkgs[:gfx_formats ] ) if @client_pkgs.has_key?(:gfx_formats )
93
+ @plugins.client_pkg.del_themes( @client_pkgs[:theme_names ] ) if @client_pkgs.has_key?(:theme_names )
94
+ @plugins.client_pkg.del_packages( @client_pkgs[:packages].keys ) if @client_pkgs.has_key?(:packages )
95
+ @plugins.client_pkg.rebuild_client
96
+ end
97
+ @client_pkgs = false
98
+ end
99
+
100
+ def open
101
+ super
102
+ install_client_pkgs if File.exist? bundle_path( 'client_pkgs.yaml' )
103
+ end
104
+
105
+ def close
106
+ super
107
+ uninstall_client_pkgs if @client_pkgs
108
+ end
109
+
110
+ # Sends gui specification to the main plugin
111
+ def spec_ui( msg )
112
+ # TODO
113
+ end
114
+
115
+ # Automatically inits the UI using GUIParser#init.
116
+ # Passes on the return value of gui_params.
117
+ def init_ui( msg ); @gui.init( msg, gui_params( msg ) ); end
118
+
119
+ # Automatically kills the UI using GUIParser#kill
120
+ def kill_ui( msg ); @gui.kill( msg ); end
121
+
122
+ # Makes include_js public to enable calls to it from GUIParser
123
+ public :include_js, :read_js_once
124
+
125
+ attr_reader :plugins
126
+
127
+ end
128
+
129
+
@@ -0,0 +1,114 @@
1
+ ## Riassence Framework
2
+ # Copyright 2009 Riassence Inc.
3
+ # http://riassence.com/
4
+ #
5
+ # You should have received a copy of the GNU General Public License along
6
+ # with this software package. If not, contact licensing@riassence.com
7
+ ##
8
+
9
+ # This class automatically loads a YAML file from "gui" subdirectory of a plugin.
10
+ # Extend your plugin from the GUIPlugin class instead of the Plugin class to make
11
+ # this work automatically.
12
+ # = Usage:
13
+ # Initialize like this from inside a plugin method. This will load the "gui/my_gui.yaml" file.
14
+ # @gui = GUIParser.new( self, 'my_gui' )
15
+ # To make the client render the contents of the yaml do this:
16
+ # ses = get_ses( msg )
17
+ # params = { :values => @gui.values( ses ) }
18
+ # @gui.init( msg, params )
19
+ class GUIParser
20
+
21
+ include ::RSence
22
+
23
+ # Use this method to send the client all commands required to construct the GUI Tree using JSONRenderer.
24
+ # = Parameters
25
+ # +msg+:: The +Message+ instance +msg+ used all over the place.
26
+ # +params+:: An hash containing all parameters referred from the YAML file.
27
+ def init( msg, params )
28
+ gui_data = YAML.load( @yaml_src )
29
+ parse_gui( gui_data, params )
30
+ if gui_data.has_key?('dependencies')
31
+ @parent.include_js( msg, gui_data['dependencies'] )
32
+ gui_data.delete('dependencies')
33
+ end
34
+ if gui_data.has_key?('include')
35
+ gui_data['include'].each do | js_file |
36
+ js_src = @parent.read_js_once( msg, js_file )
37
+ msg.reply( js_src )
38
+ end
39
+ end
40
+ gui_name = @parent.name
41
+ msg.reply( "JSONRenderer.nu(#{gui_data.to_json});", true )
42
+ end
43
+
44
+ # Use this method to extract all the value id's of the +ses+ hash.
45
+ def values( ses )
46
+ ids = {}
47
+ ses.each do | key, value |
48
+ if value.class == HValue
49
+ ids[ key ] = value.val_id
50
+ end
51
+ end
52
+ return ids
53
+ end
54
+
55
+ private
56
+
57
+ def json_fun( value )
58
+ JSON.parse( "[#{value}]" ).first
59
+ end
60
+
61
+ # Parses the gui data using params. Called from +init+.
62
+ def parse_gui( gui_data, params )
63
+ data_class = gui_data.class
64
+ if data_class == Array
65
+ gui_data.each_with_index do | item, i |
66
+ gui_data[i] = parse_gui( item, params )
67
+ end
68
+ elsif data_class == Hash
69
+ gui_data.each do | key, value |
70
+ gui_data[key] = parse_gui( value, params )
71
+ end
72
+ elsif data_class == Symbol
73
+ sym_str = gui_data.to_s
74
+ if sym_str.include? '.'
75
+ sym_arr = sym_str.split('.')
76
+ else
77
+ sym_arr = [ sym_str ]
78
+ end
79
+ return get_params( sym_arr, params )
80
+ elsif data_class == String and gui_data.strip.start_with?('function(')
81
+ return @parent.plugins[:client_pkg].squeeze( "a="+json_fun( gui_data.to_json ) )[2..-1]
82
+ end
83
+ return gui_data
84
+ end
85
+
86
+ # Searches the params hash for parameters whenever encountered a Symbol in the YAML.
87
+ def get_params( params_path, params )
88
+ item = params_path.shift
89
+ if params.class == Hash
90
+ has_str = params.has_key?( item )
91
+ has_sym = params.has_key?( item.to_sym )
92
+ item = item.to_sym if has_sym
93
+ if has_str or has_sym
94
+ if params_path.size == 0
95
+ return params[item]
96
+ else
97
+ return get_params( params_path, params[ item ] )
98
+ end
99
+ end
100
+ end
101
+ return ''
102
+ end
103
+
104
+ # Loads the YAML file.
105
+ # = Parameters
106
+ # +parent+:: The Plugin instance called from, use +self+ when constructing in a Plugin method.
107
+ # +yaml_src+:: The YAML source template for the GUI
108
+ def initialize( parent, yaml_src )
109
+ @parent = parent
110
+ @yaml_src = yaml_src
111
+ end
112
+
113
+ end
114
+
@@ -0,0 +1,652 @@
1
+ ## Riassence Framework
2
+ # Copyright 2006 Riassence Inc.
3
+ # http://riassence.com/
4
+ #
5
+ # You should have received a copy of the GNU General Public License along
6
+ # with this software package. If not, contact licensing@riassence.com
7
+ ##
8
+
9
+ ## = Abstract
10
+ ## The Plugin class is the base class for extending server logic.
11
+ ## A single Plugin instance serves the requests of all sessions,
12
+ ## which makes them very cpu and memory efficient compared to systems,
13
+ ## where the server classes are constructed and destructed for each
14
+ ## request.
15
+ ##
16
+ ## Plugins are designed to be contained in a plugin directory bundle and
17
+ ## to be loaded by the +PluginManager+, which is also responsible for
18
+ ## delegating the events and other calls throughout the system.
19
+ ##
20
+ ## == Anatomy of a plugin bundle
21
+ ## The plugin bundle contains all data needed to run the plugin. Design
22
+ ## your plugin without any hard-coded paths, remember that it's intended
23
+ ## to be deployed by "dropping" the whole plugin into one of the server's
24
+ ## plugins directories.
25
+ ##
26
+ ## The +PluginManager+ looks for such bundles and evaluates them into an
27
+ ## anonymous +Module+ namespace. The content of the ruby source file
28
+ ## is then responsible for including its libraries, constructing an
29
+ ## instance of itself and registering itself as a part of the system.
30
+ ##
31
+ ## It's advised to use the +GUIPlugin+ class for plugins that handle
32
+ ## user interfaces. Usage of the +Plugin+ bundle is advised to use
33
+ ## for plugins that provide extra functionality, value responders
34
+ ## and other utilities that supplement the user interface.
35
+ ##
36
+ ## You must call the +#register+ method after the class is constructed.
37
+ ## Otherwise, the class is not connected to the system and just discarded
38
+ ## and then garbage collected.
39
+ ##
40
+ ## == Messages
41
+ ## As a side effect of having single instances of plugins serve the requests
42
+ ## of all sessions, the request/response/session messaging is implemented
43
+ ## as messaging objects. These objects contain or delegate all the necessary
44
+ ## hooks required by the complete request/response cycle.
45
+ ##
46
+ ## The naming convention of the +Message+ instance is +msg+ and it's
47
+ ## given as the first parameter of methods needing it.
48
+ ##
49
+ ## Use +msg.ses_id+ to identify the session's serial number and +msg.user_id+
50
+ ## to identify the user's identity.
51
+ ##
52
+ ## Use the +msg.session+ +Hash+ to store any persistent data
53
+ ## associated with the user's session, preferably using the name of the
54
+ ## plugin or its registered name as the primary key entry in the Hash.
55
+ ## The session data is persistent; it's stored in the session database
56
+ ## by +SessionStorage+ automatically.
57
+ ##
58
+ ## The +msg+ instance also provides access to the +Request+ and +Response+
59
+ ## objects as +msg.request+ and +msg.response+, respectively.
60
+ ##
61
+ ## Use the +msg.run+ method to call other plugins.
62
+ ##
63
+ ## To append js source code to be evaluated in the client, use the +msg.reply+
64
+ ## call. The +msg.console+ call appends messages to the browser's js console.
65
+ ##
66
+ ##
67
+ ## == Session -related event methods
68
+ ## The +#get_ses+ method returns (or creates and returns) the entry in
69
+ ## the session based on the name your plugin is registered as. It's advised
70
+ ## to use this call instead of manually managing +msg.session+ in most cases.
71
+ ##
72
+ ## The +#idle+ method is called each time a client performs a data
73
+ ## synchronization or "idle poll" request.
74
+ ##
75
+ ## The +#init_ses+ method is called once in the same request a new session
76
+ ## is created. A new session is created, when a user enters accesses the
77
+ ## server the first time, or the first time after the previous session is
78
+ ## expired.
79
+ ##
80
+ ## The +#init_ui+ method is called by the "main" plugin after the client has
81
+ ## booted successfully. The +GUIPlugin+ class extends this method to
82
+ ## automatically load and initialize the user interface from a data structure.
83
+ ##
84
+ ## The +#restore_ses+ method is called once in the same request an old
85
+ ## session is restored. A session is restored, when the user returns to
86
+ ## the page or reloads the page before the session is expired.
87
+ ##
88
+ ## === When the server is configured to restore previous sessions (default):
89
+ ## If the user accesses the same page using the same browser (in different
90
+ ## tabs or windows), only the most recently restored one is valid, while
91
+ ## the previous ones are immediately invalidated.
92
+ ## If your application is intended to support several sessions per browser,
93
+ ## enable session cloning in the configuration file.
94
+ ##
95
+ ## === When the server is configured to restore and clone previous sessions:
96
+ ## When sessions are cloned, the previous session is not invalidated and
97
+ ## exists until timing out as a result of the web browser window being closed
98
+ ## or client computer losing network connectivity for a certain (configurable)
99
+ ## time frame.
100
+ ##
101
+ ## The +#cloned_target+ method is like +#restore_ses+, but called when
102
+ ## the session is a clone of a previous session.
103
+ ##
104
+ ## The +#cloned_source+ method is called on the next request of the previous
105
+ ## session after it has been cloned.
106
+ ##
107
+ ## == Server event methods
108
+ ## Extend the +#init+ method to invoke constructor functionality that
109
+ ## depends on the plugin to be constructed and registered as a part of
110
+ ## the system.
111
+ ##
112
+ ## Extend the +#open+, +#flush+ and +#close+ methods to open, flush and close
113
+ ## streams or other similar functionality.
114
+ ##
115
+ ## == Data handling
116
+ ## The data exchange system exists to support bi-directional
117
+ ## data synchronization between the browser and the plugin. The values
118
+ ## are stored in the session as +HValue+ instances.
119
+ ##
120
+ ## Values support Hashes, Arrays, Strings, Numbers, Booleans and
121
+ ## combinations of them. The data is automatically converted between
122
+ ## ruby objects (server) and json objects (client).
123
+ ##
124
+ ## Each instance may be bound to plugin methods that are used as
125
+ ## value change notification responders.
126
+ ##
127
+ ## When a method is bound to the value, the method is called as an
128
+ ## event notification whenever the client has changed the value and
129
+ ## synchronizes it to the server. The responders act as validators
130
+ ## by default.
131
+ ##
132
+ ## Values are also bound in the client to classes implementing the
133
+ ## HValueResponder interface, like any derivate of HControl. See the
134
+ ## client documentation for instructions about using them.
135
+ ##
136
+ ## To define a value responder method, it needs to respond to exactly
137
+ ## two parameters: the +Message+ instance +msg+ and the HValue object
138
+ ## (in that order). The method's return value must be either +true+
139
+ ## or +false+. When the method returns +false+, the change is discarded
140
+ ## and the previously server-set value is sent back to the client.
141
+ ##
142
+ ## A minimal value responder method is defined like this:
143
+ ##
144
+ ## def my_value_responder( msg, my_value )
145
+ ## return true
146
+ ## end
147
+ ##
148
+ ## To access the content of the value, use the +HValue#data+ attribute.
149
+ ##
150
+ ## def int_between_100_and_200( msg, value )
151
+ ## data = value.data.to_i
152
+ ## return ( data >= 100 and data <= 200 )
153
+ ## end
154
+ ##
155
+ ## To change the content of the value, use the +HValue#set+ method.
156
+ ##
157
+ ## def int_between_100_and_200( msg, value )
158
+ ## data = value.data.to_i
159
+ ## value.set( msg, 100 ) if data < 100
160
+ ## value.set( msg, 200 ) if data > 200
161
+ ## return true
162
+ ## end
163
+ ##
164
+ ## == Defining values
165
+ ## The simplest and recommended way of defining the values is to define
166
+ ## the value configuration file +values.yaml+. Its configuration is then
167
+ ## applied to sessions automatically.
168
+ ##
169
+ ##
170
+ ## === Syntax reference of the contents of a +values.yaml+ file:
171
+ ##
172
+ ## # The name of the value (:value_name).
173
+ ## # A hash key in the yaml syntax
174
+ ## :value_name:
175
+ ##
176
+ ## # All of these keys are optional!
177
+ ##
178
+ ## # Default value, a string "Foo" here.
179
+ ## # Defaults to 0
180
+ ## :value: Foo
181
+ ##
182
+ ## # A plugin method to call to define the default value
183
+ ## # instead of the one defined in :value
184
+ ## :value_call:
185
+ ## :plugin: plugin_name # defaults to the plugin where defined
186
+ ##
187
+ ## # Mandatory; name of the method to call
188
+ ## :method: method_name
189
+ ##
190
+ ## # Optional, list of parameter values for the :method
191
+ ## :args:
192
+ ## # three parameters: 1, 'foo', 3
193
+ ## - 1
194
+ ## - foo
195
+ ## - 3
196
+ ##
197
+ ## # When false, doesn't pass the msg as the first parameter.
198
+ ## # Defaults to true
199
+ ## :uses_msg: true
200
+ ##
201
+ ## # Restore the default, when the session is restored; defaults to false
202
+ ## :restore_default: false
203
+ ##
204
+ ## # List of value responder methods to bind.
205
+ ## :responders:
206
+ ## -
207
+ ## # name of plugin to call, defaults to the plugin where defined:
208
+ ## :plugin: plugin_name
209
+ ##
210
+ ## # mandatory, name of the method to call
211
+ ## :method: method_name
212
+ ##
213
+ ## # Another responder, this one using the same plugin where defined:
214
+ ## - :method: another_method
215
+ ##
216
+ ## # Another value, this one just defining the defaults
217
+ ## # by supplying an empty Hash:
218
+ ## # (value: 0, default restored, no responders or calls)
219
+ ## :value_with_defaults: {}
220
+ ##
221
+ ## # This value defines a Number (123) and doesn't restore
222
+ ## # the default, when restoring the session.
223
+ ## :one_two_three:
224
+ ## :value: 123
225
+ ## :restore_default: false
226
+ ##
227
+ ## # This value gets a random string and specifies a responder,
228
+ ## # that ensures it's unique, if changed in the client.
229
+ ## :random_unique_string:
230
+ ## :value_call:
231
+ ## :method: get_unique_random_string
232
+ ## :uses_msg: false
233
+ ## :responders:
234
+ ## - :method: ensure_unique_random_string
235
+ ##
236
+ ## = Examples
237
+ ## More examples are available in the repository;
238
+ ## http://svn.rsence.org/contrib/plugins
239
+ ## ..as well as the standard "main" plugin in the "plugins" directory.
240
+ ##
241
+ ##
242
+ ## == A minimal Plugin bundle
243
+ ## The minimal active plugin bundle (named "name_of_plugin")
244
+ ## is defined like this:
245
+ ##
246
+ ## [dir] name_of_plugin
247
+ ## |
248
+ ## +---[file] name_of_plugin.rb
249
+ ##
250
+ ## This sample Plugin doesn't do anything except construct itself and
251
+ ## respond as 'name_of_plugin'.
252
+ ##
253
+ ## Plugin.new.register('name_of_plugin')
254
+ ##
255
+ ## However, this is not very useful in itself, so you'll need to extend
256
+ ## its functionality to do anything useful.
257
+ ##
258
+ ## == A simple Plugin extension
259
+ ## This plugin logs session events to the logs/session_log file.
260
+ ##
261
+ ## [dir] ses_logger
262
+ ## |
263
+ ## +---[file] ses_logger.rb
264
+ ## |
265
+ ## +---[dir] logs
266
+ ## |
267
+ ## +---[file] session_log
268
+ ##
269
+ ## == Contents of "ses_logger.rb"
270
+ ##
271
+ ## class SessionLogger < Plugin
272
+ ## def init
273
+ ## super
274
+ ## @logfile = false
275
+ ## end
276
+ ## def open
277
+ ## log_path = compose_plugin_path( 'session_log', 'logs' )
278
+ ## @logfile = File.open( log_path, 'a' )
279
+ ## end
280
+ ## def close
281
+ ## @logfile.close if @logfile
282
+ ## @logfile = false
283
+ ## end
284
+ ## def flush
285
+ ## @logfile.flush if @logfile
286
+ ## end
287
+ ## def init_ses( msg )
288
+ ## super
289
+ ## @logfile.write( "#{Time.new} -- Session id #{msg.ses_id} was created.\n" )
290
+ ## end
291
+ ## def restore_ses( msg )
292
+ ## super
293
+ ## @logfile.write( "#{Time.new} -- Session id #{msg.ses_id} was restored.\n" )
294
+ ## end
295
+ ## def idle( msg )
296
+ ## @logfile.write( "#{Time.new} -- Client of session id #{msg.ses_id} connected.\n" )
297
+ ## end
298
+ ## end
299
+ ## SessionLogger.new.register( 'ses_logger' )
300
+ ##
301
+ class Plugin
302
+
303
+ include PluginUtil
304
+
305
+ # The +names+ is a list of (usually just one) names the plugin is registered under.
306
+ attr_reader :name, :path, :info, :inited
307
+
308
+ # The constructor should not take any parameters. In most cases, it's better
309
+ # to extend the +#init+ method, because it's called after the plugin is set up.
310
+ def initialize
311
+ @inited = false
312
+ @info = @@bundle_info
313
+ @name = @@bundle_name
314
+ @path = @@bundle_path
315
+ @plugins = @@plugin_manager
316
+ register unless @info[:inits_self]
317
+ end
318
+
319
+ # Extend this method to do any initial tasks before other methods are called.
320
+ # By default init_values is called to load the +values.yaml+ configuration file.
321
+ def init
322
+ @values = init_values
323
+ end
324
+
325
+ # Extend this method to do any tasks every time the client makes a request.
326
+ def idle( msg )
327
+ end
328
+
329
+ # Extend this method to invoke actions, when a new session is created.
330
+ # By default +#init_ses_values+ is called to initialize values defined in the
331
+ # +values.yaml+ configuration file.
332
+ def init_ses( msg )
333
+ init_ses_values( msg )
334
+ end
335
+
336
+ # Extend this method to invoke actions, when a previous session is restored.
337
+ # By default +#restore_ses_values+ is called to perform actions on values as
338
+ # defined in the +values.yaml+ configuration file.
339
+ def restore_ses( msg )
340
+ restore_ses_values( msg )
341
+ end
342
+
343
+ # Extend this method to invoke actions, when the session
344
+ # is a clone of another session. It's called once, just
345
+ # before +#restore_ses+ is called.
346
+ #
347
+ # A session is cloned, when a user opens a another browser
348
+ # window or tab, while the previous session is still active.
349
+ #
350
+ # The +source_ses+ is the actual previous session object, which
351
+ # was used as the source of the clone.
352
+ def cloned_target( msg, source_session )
353
+ end
354
+
355
+ # Extend this method to invoke actions, when the session
356
+ # has been cloned to another session. It's called once, just
357
+ # before +#restore_ses+ is called on the first request after
358
+ # the cloning happened.
359
+ #
360
+ # A session is cloned, when a user opens a another browser
361
+ # window or tab, while the previous session is still active.
362
+ #
363
+ # The +target_ses+ is the actual cloned session object, which
364
+ # is a copy of the current session.
365
+ def cloned_source( msg, target_sessions )
366
+ end
367
+
368
+ # This method must be called to register the plugin instance
369
+ # into the system. Otherwise, it's subject to destruction
370
+ # and garbage collection. Use the +name+ parameter to
371
+ # give the (unique) name of your plugin.
372
+ def register( name=false )
373
+ if @inited
374
+ @plugins.register_alias( @name, name )
375
+ else
376
+ if name
377
+ name = name.to_s
378
+ else
379
+ name = @name
380
+ end
381
+ @plugins.register_bundle( self, name )
382
+ @inited = true
383
+ end
384
+ end
385
+
386
+ private
387
+
388
+ # This method looks looks for a file called "values.yaml"
389
+ # in the plugin's bundle directory
390
+ #.
391
+ # If this file is found, it loads it for initial value definitions.
392
+ #
393
+ # These definitions are accessible as the +@values+ attribute.
394
+ def init_values
395
+ values_path = compose_plugin_path( 'values.yaml' )
396
+ return yaml_read( values_path )
397
+ end
398
+
399
+ # Returns all the names your plugin respond to.
400
+ # def name
401
+ # return @names.first
402
+ # end
403
+
404
+
405
+ # Returns or creates a new session hash for the plugin.
406
+ #
407
+ # Uses the first name registered for the plugin and converts it to a symbol.
408
+ def get_ses( msg )
409
+ name_sym = name.to_sym
410
+ unless msg.session.has_key?( name_sym )
411
+ msg.session[ name_sym ] = {}
412
+ end
413
+ return msg.session[ name_sym ]
414
+ end
415
+
416
+ # Returns the source code of the javascript file +name+ in the 'js'
417
+ # subdirectory of the plugin bundle.
418
+ def read_js( js_name )
419
+ file_read( compose_plugin_path( js_name, 'js', '.js' ) )
420
+ end
421
+
422
+ # Deprecated name of +#read_js+
423
+ alias require_js read_js
424
+
425
+ # Like +#read_js+, but reads the file only once per session.
426
+ #
427
+ # Returns the contents of the file on the first call,
428
+ # an empty string on the subsequent calls.
429
+ #
430
+ # Returns false otherwise.
431
+ def read_js_once( msg, js_name )
432
+ ses = msg.session
433
+ if not ses.has_key?(:deps)
434
+ ses[:deps] = []
435
+ end
436
+ path = compose_plugin_path( js_name, 'js', '.js' )
437
+ unless ses[:deps].include?( path )
438
+ ses[:deps].push( path )
439
+ return file_read( path )
440
+ else
441
+ return ''
442
+ end
443
+ end
444
+
445
+ # Deprecated name of +#read_js_once+
446
+ alias require_js_once read_js_once
447
+
448
+ # Creates a new instance of HValue, assigns it as +value_name+ into the
449
+ # session and uses the +value_properties+ Hash to define the default
450
+ # value and value responders.
451
+ #
452
+ # This method is invoked automatically, when handling the properties
453
+ # of the +values.yaml+ configuration file of a new session.
454
+ #
455
+ # It's invoked by +#init_ses+ via +#init_ses_values+.
456
+ #
457
+ # Structure of +value_properties+, all top-level items are optional:
458
+ #
459
+ # {
460
+ # # Default value; defaults to 0
461
+ # :value => 'foo',
462
+ #
463
+ # # A plugin method to call to define the default value instead of the one defined in :value
464
+ # :value_call => {
465
+ # :plugin => 'plugin_name', # defaults to the plugin where defined
466
+ # :method => 'method_name', # mandatory; name of the method to call
467
+ # :args => [ 1, 'foo', 3 ], # optional, list of parameter values for the :method
468
+ # :uses_msg => true # defaults to true; when false, doesn't pass the msg as the first parameter
469
+ # },
470
+ #
471
+ # # Restore the default, when the session is restored; defaults to false
472
+ # :restore_default => false,
473
+ #
474
+ # # List of value responder methods to bind.
475
+ # :responders => [
476
+ # {
477
+ # :plugin => 'plugin_name', # defaults to the plugin where defined
478
+ # :method => 'method_name' # mandatory, name of the method to call
479
+ # },
480
+ # # You can supply as many responders as you like:
481
+ # { :plugin => 'another_plugin', :method => 'another_method' }
482
+ # ]
483
+ # }
484
+ #
485
+ def init_ses_value( msg, value_name, value_properties )
486
+ ses = get_ses( msg )
487
+ if value_properties.has_key?(:value_call)
488
+ default_value = init_value_call( msg, value_properties[:value_call] )
489
+ elsif value_properties.has_key?(:value)
490
+ default_value = value_properties[:value]
491
+ else
492
+ default_value = 0
493
+ end
494
+ ses[value_name] = HValue.new( msg, default_value )
495
+ if value_properties.has_key?(:responders)
496
+ value_properties[:responders].each do |responder|
497
+ if responder.has_key?(:plugin)
498
+ responder_plugin = responder[:plugin]
499
+ else
500
+ responder_plugin = @name
501
+ end
502
+ if responder.has_key?(:method)
503
+ ses[value_name].bind( responder_plugin, responder[:method] )
504
+ end
505
+ end
506
+ end
507
+ end
508
+
509
+ # Initializes session values, if the contents of the +values.yaml+
510
+ # file is defined in the bundle directory and loaded in +#init_values+.
511
+ def init_ses_values( msg )
512
+ return unless @values
513
+ @values.each do | value_name, value_properties |
514
+ init_ses_value( msg, value_name, value_properties )
515
+ end
516
+ end
517
+
518
+ # Returns a value based on the :method and :plugin members of the
519
+ # +value_call+ hash.
520
+ #
521
+ # The call is made via msg.run if the method is not defined in
522
+ # the local plugin bundle.
523
+ #
524
+ # This method is called from +#init_ses_value+.
525
+ #
526
+ # Structure of the +value_call+ Hash:
527
+ # { :plugin => 'plugin_name', # defaults to the plugin where defined
528
+ # :method => 'method_name', # mandatory; name of the method to call
529
+ # :args => [ 1, 'foo', 3 ], # optional, list of parameter values for the :method
530
+ # :uses_msg => true # defaults to true; when false, doesn't pass the msg as the first parameter
531
+ # }
532
+ def init_value_call( msg, value_call )
533
+ value_call_method = value_call[:method]
534
+ if value_call.has_key?(:plugin)
535
+ value_call_plugin = value_call[:plugin]
536
+ else
537
+ value_call_plugin = false
538
+ end
539
+ if value_call.has_key?(:args)
540
+ if value_call.has_key?(:uses_msg) and value_call[:uses_msg] != false
541
+ if value_call_plugin
542
+ return msg.run( value_call_plugin, value_call_method, msg, *value_call[:args] )
543
+ else
544
+ return self.method( value_call_method ).call( msg, *value_call[:args] )
545
+ end
546
+ else
547
+ if value_call_plugin
548
+ return msg.run( value_call_plugin, value_call_method, *value_call[:args] )
549
+ else
550
+ return self.method( value_call_method ).call( *value_call[:args] )
551
+ end
552
+ end
553
+ else
554
+ if value_call.has_key?(:uses_msg) and value_call[:uses_msg] != false
555
+ if value_call_plugin
556
+ return msg.run( value_call_plugin, value_call_method, msg )
557
+ else
558
+ return self.method( value_call_method ).call( msg )
559
+ end
560
+ else
561
+ if value_call_plugin
562
+ return msg.run( value_call_plugin, value_call_method )
563
+ else
564
+ return self.method( value_call_method ).call( )
565
+ end
566
+ end
567
+ end
568
+ end
569
+
570
+ # Restores session values to default, unless specified otherwise.
571
+ #
572
+ # Called from +#restore_ses+
573
+ def restore_ses_values( msg )
574
+ return unless @values
575
+ ses = get_ses( msg )
576
+ @values.each do | value_name, value_properties |
577
+ if ses.has_key?( value_name ) and ses[ value_name ].class == HValue
578
+ unless value_properties[:restore_default] == false
579
+ if value_properties.has_key?(:value_call)
580
+ default_value = init_value_call( msg, value_properties[:value_call] )
581
+ elsif value_properties.has_key?(:value)
582
+ default_value = value_properties[:value]
583
+ else
584
+ default_value = 0
585
+ end
586
+ ses[value_name].set( msg, default_value )
587
+ end
588
+ else
589
+ init_ses_value( msg, value_name, value_properties )
590
+ end
591
+ end
592
+ end
593
+
594
+ # Extracts +HValue+ references as javascript from the session Hash.
595
+ # The +ses+ parameter is used for supplying a hash with the +HValue+
596
+ # instances. It's optional and defaults to the current plugin node in
597
+ # the active session.
598
+ #
599
+ # The return value is a string representing a js object similar to
600
+ # the ruby Hash +ses+.
601
+ #
602
+ # Sample usage:
603
+ #
604
+ # values_js( msg, msg.session[:main] )
605
+ #
606
+ def values_js( msg, ses=false )
607
+ # backwards-compatible with pre-1.3 behaviour
608
+ ses = msg if msg.class == Hash
609
+ # gets the session automatically, if false
610
+ ses = get_ses( msg ) unless ses
611
+ js_references = []
612
+ ses.each_key do |key_name|
613
+ if ses[key_name].class == HValue
614
+ js_references.push( "#{key_name.to_s}:HVM.values['#{ses[key_name].val_id}']" )
615
+ end
616
+ end
617
+ return "{#{js_references.join(',')}}"
618
+ end
619
+
620
+ # Deprecated name of +#values_js+
621
+ alias extract_hvalues_from_hash values_js
622
+
623
+ # Tells the js client framework to load a list of dependency packages.
624
+ # It keeps track of what's loaded, so nothing library loaded twice.
625
+ #
626
+ # The +dependencies+ parameter is an Array of dependencies.
627
+ #
628
+ # Sample usage:
629
+ #
630
+ # include_js( msg, [ 'default_theme', 'controls', 'lists', 'datetime' ] )
631
+ #
632
+ def include_js( msg, dependencies=[] )
633
+ ses = msg.session
634
+ # check, if the session has a dependency array
635
+ if not ses.has_key?( :deps )
636
+ # make an array of dependencies for this session, if not already done
637
+ ses[:deps] = []
638
+ end
639
+ dependencies = [dependencies] if dependencies.class == String
640
+ # Check the required dependencies until everything is loaded.
641
+ dependencies.each do |dependency|
642
+ unless ses[:deps].include?( dependency )
643
+ ses[:deps].push( dependency )
644
+ msg.reply(%{jsLoader.load("#{dependency}");})
645
+ end
646
+ end
647
+ end
648
+
649
+
650
+ end
651
+
652
+