IOWA 1.0.0

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 (502) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTORS +14 -0
  3. data/README.md +23 -0
  4. data/RELEASE_NOTES +77 -0
  5. data/ToDo +21 -0
  6. data/components/CRUDList/CRUDList.html +13 -0
  7. data/components/CRUDList/CRUDList.iwa +136 -0
  8. data/components/Content/Content.html +0 -0
  9. data/components/Content/Content.iwa +143 -0
  10. data/components/Content/example/README +9 -0
  11. data/components/Content/example/cgi/iowa.cgi +10 -0
  12. data/components/Content/example/demo.rb +30 -0
  13. data/components/Content/example/doc/index.html +7 -0
  14. data/components/Content/example/iowa/Content.html +1 -0
  15. data/components/Content/example/iowa/Content.iwa +1 -0
  16. data/components/Content/example/iowa/Main.html +6 -0
  17. data/components/Content/example/iowa/Main.iwa +3 -0
  18. data/components/Content/example/iowa/_content/body +7 -0
  19. data/components/Content/example/iowa/_content/body2 +3 -0
  20. data/components/Content/example/iowa/_content/title +2 -0
  21. data/components/Content/example/iowa/app.cnf +8 -0
  22. data/components/Content/example/iowa/app.rb +8 -0
  23. data/components/Content/example/webrick.rb +38 -0
  24. data/components/Include/Include.html +1 -0
  25. data/components/Include/Include.iwa +30 -0
  26. data/components/Include/readme +5 -0
  27. data/components/JumpTo/JumpTo.html +8 -0
  28. data/components/JumpTo/JumpTo.iwa +8 -0
  29. data/components/JumpTo/readme +6 -0
  30. data/doc/Architecture.txt +6 -0
  31. data/doc/History.txt +33 -0
  32. data/doc/StandardDispatcher.txt +19 -0
  33. data/examples/blog/README +1 -0
  34. data/examples/hello_world/README +17 -0
  35. data/examples/hello_world/htdocs/hello_world_html.html +24 -0
  36. data/examples/hello_world/htdocs/hello_world_ruby.html +41 -0
  37. data/examples/hello_world/iowa/HelloWorld.html +14 -0
  38. data/examples/hello_world/iowa/HelloWorld.iwa +31 -0
  39. data/examples/hello_world/iowa/Index.html +16 -0
  40. data/examples/hello_world/iowa/Index.iwa +5 -0
  41. data/examples/hello_world/iowa/iowa_hello_world.cnf +19 -0
  42. data/examples/hello_world/iowa/iowa_hello_world.rb +5 -0
  43. data/examples/hello_world/iowa/mapfile.cnf +6 -0
  44. data/examples/hw1/iowa/Main.html +1 -0
  45. data/examples/hw1/iowa/README +9 -0
  46. data/examples/hw1/iowa/hw.rb +4 -0
  47. data/examples/hw2/iowa/Main.html +10 -0
  48. data/examples/hw2/iowa/Main.iwa +7 -0
  49. data/examples/hw2/iowa/README +16 -0
  50. data/examples/hw2/iowa/hw.rb +4 -0
  51. data/examples/hw3/iowa/Main.html +11 -0
  52. data/examples/hw3/iowa/Main.iwa +7 -0
  53. data/examples/hw3/iowa/README +22 -0
  54. data/examples/hw3/iowa/hw.rb +4 -0
  55. data/examples/hw4/iowa/Greetings.html +10 -0
  56. data/examples/hw4/iowa/Greetings.iwa +9 -0
  57. data/examples/hw4/iowa/Main.html +12 -0
  58. data/examples/hw4/iowa/Main.iwa +10 -0
  59. data/examples/hw4/iowa/README +28 -0
  60. data/examples/hw4/iowa/hw.rb +4 -0
  61. data/examples/hw5/iowa/Footer.html +2 -0
  62. data/examples/hw5/iowa/Greetings.html +4 -0
  63. data/examples/hw5/iowa/Greetings.iwa +12 -0
  64. data/examples/hw5/iowa/Header.html +6 -0
  65. data/examples/hw5/iowa/Main.html +12 -0
  66. data/examples/hw5/iowa/Main.iwa +13 -0
  67. data/examples/hw5/iowa/README +16 -0
  68. data/examples/hw5/iowa/hw.rb +4 -0
  69. data/examples/template_server/iowa/Content.iwa +121 -0
  70. data/examples/template_server/iowa/Content.view +0 -0
  71. data/examples/template_server/iowa/DBContentDispatcher.rb +112 -0
  72. data/examples/template_server/iowa/DBContentPage.html +3 -0
  73. data/examples/template_server/iowa/DBContentPage.iwa +85 -0
  74. data/examples/template_server/iowa/app.cnf +13 -0
  75. data/examples/template_server/iowa/app.rb +5 -0
  76. data/ext/Classifier/classifier.c +256 -0
  77. data/ext/Classifier/ext_help.h +14 -0
  78. data/ext/Classifier/extconf.rb +5 -0
  79. data/ext/Classifier/tst.h +40 -0
  80. data/ext/Classifier/tst_cleanup.c +24 -0
  81. data/ext/Classifier/tst_delete.c +146 -0
  82. data/ext/Classifier/tst_grow_node_free_list.c +38 -0
  83. data/ext/Classifier/tst_init.c +41 -0
  84. data/ext/Classifier/tst_insert.c +192 -0
  85. data/ext/Classifier/tst_search.c +68 -0
  86. data/ext/http11/README +11 -0
  87. data/ext/http11/ext_help.h +15 -0
  88. data/ext/http11/extconf.rb +5 -0
  89. data/ext/http11/http11.c +534 -0
  90. data/ext/http11/http11.c.dif +422 -0
  91. data/ext/http11/http11_parser.c +1243 -0
  92. data/ext/http11/http11_parser.c.dif +193 -0
  93. data/ext/http11/http11_parser.h +49 -0
  94. data/ext/http11/http11_parser.h.dif +20 -0
  95. data/ext/http11/http11_parser.rl +192 -0
  96. data/ext/httpmachine/Makefile +149 -0
  97. data/ext/httpmachine/extconf.rb +33 -0
  98. data/ext/httpmachine/http.cpp +430 -0
  99. data/ext/httpmachine/http.h +156 -0
  100. data/ext/httpmachine/rubyhttp.cpp +165 -0
  101. data/external/mime-types/LICENCE +18 -0
  102. data/external/mime-types/README +46 -0
  103. data/external/mime-types/doc/classes/MIME.html +120 -0
  104. data/external/mime-types/doc/classes/MIME/InvalidContentType.html +119 -0
  105. data/external/mime-types/doc/classes/MIME/Type.html +866 -0
  106. data/external/mime-types/doc/classes/MIME/Type.src/M000010.html +22 -0
  107. data/external/mime-types/doc/classes/MIME/Type.src/M000011.html +18 -0
  108. data/external/mime-types/doc/classes/MIME/Type.src/M000012.html +19 -0
  109. data/external/mime-types/doc/classes/MIME/Type.src/M000013.html +18 -0
  110. data/external/mime-types/doc/classes/MIME/Type.src/M000014.html +26 -0
  111. data/external/mime-types/doc/classes/MIME/Type.src/M000015.html +33 -0
  112. data/external/mime-types/doc/classes/MIME/Type.src/M000016.html +27 -0
  113. data/external/mime-types/doc/classes/MIME/Type.src/M000017.html +35 -0
  114. data/external/mime-types/doc/classes/MIME/Type.src/M000018.html +34 -0
  115. data/external/mime-types/doc/classes/MIME/Type.src/M000019.html +24 -0
  116. data/external/mime-types/doc/classes/MIME/Type.src/M000020.html +38 -0
  117. data/external/mime-types/doc/classes/MIME/Type.src/M000021.html +22 -0
  118. data/external/mime-types/doc/classes/MIME/Type.src/M000022.html +18 -0
  119. data/external/mime-types/doc/classes/MIME/Type.src/M000023.html +18 -0
  120. data/external/mime-types/doc/classes/MIME/Type.src/M000024.html +18 -0
  121. data/external/mime-types/doc/classes/MIME/Type.src/M000025.html +18 -0
  122. data/external/mime-types/doc/classes/MIME/Type.src/M000026.html +18 -0
  123. data/external/mime-types/doc/classes/MIME/Type.src/M000027.html +18 -0
  124. data/external/mime-types/doc/classes/MIME/Type.src/M000028.html +18 -0
  125. data/external/mime-types/doc/classes/MIME/Type.src/M000029.html +18 -0
  126. data/external/mime-types/doc/classes/MIME/Type.src/M000030.html +19 -0
  127. data/external/mime-types/doc/classes/MIME/Type.src/M000031.html +26 -0
  128. data/external/mime-types/doc/classes/MIME/Types.html +459 -0
  129. data/external/mime-types/doc/classes/MIME/Types.src/M000001.html +19 -0
  130. data/external/mime-types/doc/classes/MIME/Types.src/M000002.html +32 -0
  131. data/external/mime-types/doc/classes/MIME/Types.src/M000003.html +21 -0
  132. data/external/mime-types/doc/classes/MIME/Types.src/M000004.html +18 -0
  133. data/external/mime-types/doc/classes/MIME/Types.src/M000005.html +26 -0
  134. data/external/mime-types/doc/classes/MIME/Types.src/M000006.html +18 -0
  135. data/external/mime-types/doc/classes/MIME/Types.src/M000007.html +18 -0
  136. data/external/mime-types/doc/classes/MIME/Types.src/M000008.html +18 -0
  137. data/external/mime-types/doc/classes/MIME/Types.src/M000009.html +18 -0
  138. data/external/mime-types/doc/created.rid +1 -0
  139. data/external/mime-types/doc/files/ChangeLog.html +320 -0
  140. data/external/mime-types/doc/files/README.html +145 -0
  141. data/external/mime-types/doc/files/lib/mime/types_rb.html +101 -0
  142. data/external/mime-types/doc/fr_class_index.html +30 -0
  143. data/external/mime-types/doc/fr_file_index.html +29 -0
  144. data/external/mime-types/doc/fr_method_index.html +57 -0
  145. data/external/mime-types/doc/index.html +24 -0
  146. data/external/mime-types/doc/rdoc-style.css +208 -0
  147. data/external/mime-types/lib/mime/types.rb +1558 -0
  148. data/external/package.rb +672 -0
  149. data/external/test_support.rb +95 -0
  150. data/external/tmail/README +7 -0
  151. data/external/tmail/tmail.rb +4 -0
  152. data/external/tmail/tmail/address.rb +222 -0
  153. data/external/tmail/tmail/base64.rb +52 -0
  154. data/external/tmail/tmail/compat.rb +39 -0
  155. data/external/tmail/tmail/config.rb +50 -0
  156. data/external/tmail/tmail/encode.rb +447 -0
  157. data/external/tmail/tmail/header.rb +895 -0
  158. data/external/tmail/tmail/info.rb +14 -0
  159. data/external/tmail/tmail/loader.rb +1 -0
  160. data/external/tmail/tmail/mail.rb +869 -0
  161. data/external/tmail/tmail/mailbox.rb +386 -0
  162. data/external/tmail/tmail/mbox.rb +1 -0
  163. data/external/tmail/tmail/net.rb +260 -0
  164. data/external/tmail/tmail/obsolete.rb +123 -0
  165. data/external/tmail/tmail/parser.rb +1475 -0
  166. data/external/tmail/tmail/parser.y +372 -0
  167. data/external/tmail/tmail/port.rb +356 -0
  168. data/external/tmail/tmail/scanner.rb +17 -0
  169. data/external/tmail/tmail/scanner_r.rb +243 -0
  170. data/external/tmail/tmail/stringio.rb +256 -0
  171. data/external/tmail/tmail/textutils.rb +197 -0
  172. data/external/tmail/tmail/tmail.rb +1 -0
  173. data/external/tmail/tmail/utils.rb +23 -0
  174. data/external/win32-process/README +133 -0
  175. data/external/win32-process/lib/win32/process.rb +561 -0
  176. data/external/windows-pr/README +145 -0
  177. data/external/windows-pr/doc/conversion_guide.txt +25 -0
  178. data/external/windows-pr/lib/windows/clipboard.rb +72 -0
  179. data/external/windows-pr/lib/windows/console.rb +323 -0
  180. data/external/windows-pr/lib/windows/device_io.rb +88 -0
  181. data/external/windows-pr/lib/windows/directory.rb +80 -0
  182. data/external/windows-pr/lib/windows/error.rb +313 -0
  183. data/external/windows-pr/lib/windows/eventlog.rb +120 -0
  184. data/external/windows-pr/lib/windows/file.rb +349 -0
  185. data/external/windows-pr/lib/windows/filesystem.rb +16 -0
  186. data/external/windows-pr/lib/windows/handle.rb +31 -0
  187. data/external/windows-pr/lib/windows/library.rb +76 -0
  188. data/external/windows-pr/lib/windows/limits.rb +13 -0
  189. data/external/windows-pr/lib/windows/memory.rb +117 -0
  190. data/external/windows-pr/lib/windows/msvcrt/buffer.rb +48 -0
  191. data/external/windows-pr/lib/windows/msvcrt/file.rb +18 -0
  192. data/external/windows-pr/lib/windows/msvcrt/string.rb +46 -0
  193. data/external/windows-pr/lib/windows/national.rb +557 -0
  194. data/external/windows-pr/lib/windows/path.rb +296 -0
  195. data/external/windows-pr/lib/windows/pipe.rb +77 -0
  196. data/external/windows-pr/lib/windows/process.rb +171 -0
  197. data/external/windows-pr/lib/windows/registry.rb +238 -0
  198. data/external/windows-pr/lib/windows/security.rb +89 -0
  199. data/external/windows-pr/lib/windows/service.rb +183 -0
  200. data/external/windows-pr/lib/windows/shell.rb +88 -0
  201. data/external/windows-pr/lib/windows/sound.rb +52 -0
  202. data/external/windows-pr/lib/windows/synchronize.rb +161 -0
  203. data/external/windows-pr/lib/windows/system_info.rb +70 -0
  204. data/external/windows-pr/lib/windows/unicode.rb +138 -0
  205. data/external/windows-pr/lib/windows/window.rb +22 -0
  206. data/iowa.gemspec +45 -0
  207. data/microprojects/DiskCache/LICENSE +28 -0
  208. data/microprojects/DiskCache/README +17 -0
  209. data/microprojects/DiskCache/external/package.rb +608 -0
  210. data/microprojects/DiskCache/external/test_support.rb +8 -0
  211. data/microprojects/DiskCache/setup.rb +22 -0
  212. data/microprojects/DiskCache/src/iowa/Association.rb +67 -0
  213. data/microprojects/DiskCache/src/iowa/Constants.rb +159 -0
  214. data/microprojects/DiskCache/src/iowa/DiskStore.rb +377 -0
  215. data/microprojects/DiskCache/src/iowa/Hash.rb +63 -0
  216. data/microprojects/DiskCache/src/iowa/Lockfile.rb +575 -0
  217. data/microprojects/DiskCache/src/iowa/Mutex.rb +142 -0
  218. data/microprojects/DiskCache/src/iowa/caches/DiskCache.rb +605 -0
  219. data/microprojects/DiskCache/src/iowa/caches/LRUCache.rb +287 -0
  220. data/microprojects/DiskCache/test/TC_DiskCache.rb +218 -0
  221. data/microprojects/LRUCache/LICENSE +28 -0
  222. data/microprojects/LRUCache/README +13 -0
  223. data/microprojects/LRUCache/external/package.rb +608 -0
  224. data/microprojects/LRUCache/external/test_support.rb +8 -0
  225. data/microprojects/LRUCache/setup.rb +22 -0
  226. data/microprojects/LRUCache/src/iowa/Association.rb +57 -0
  227. data/microprojects/LRUCache/src/iowa/Constants.rb +159 -0
  228. data/microprojects/LRUCache/src/iowa/Hash.rb +63 -0
  229. data/microprojects/LRUCache/src/iowa/Mutex.rb +129 -0
  230. data/microprojects/LRUCache/src/iowa/caches/LRUCache.rb +287 -0
  231. data/microprojects/LRUCache/test/TC_LRUCache.rb +65 -0
  232. data/microprojects/LinkedList/LICENSE +28 -0
  233. data/microprojects/LinkedList/README +13 -0
  234. data/microprojects/LinkedList/external/package.rb +608 -0
  235. data/microprojects/LinkedList/external/test_support.rb +8 -0
  236. data/microprojects/LinkedList/setup.rb +22 -0
  237. data/microprojects/LinkedList/src/iowa/LinkedList.rb +165 -0
  238. data/microprojects/LinkedList/test/TC_LinkedList.rb +42 -0
  239. data/microprojects/README +8 -0
  240. data/setup.rb +116 -0
  241. data/share/iowa/app_skeleton/Main.html +8 -0
  242. data/share/iowa/app_skeleton/Main.iwa +15 -0
  243. data/share/iowa/app_skeleton/app.cnf +48 -0
  244. data/share/iowa/app_skeleton/app.rb +58 -0
  245. data/share/iowa/app_skeleton/models/model.rb +49 -0
  246. data/src/ihc.rb +223 -0
  247. data/src/iowa.cgi +29 -0
  248. data/src/iowa.rb +637 -0
  249. data/src/iowa/AbstractCache.rb +96 -0
  250. data/src/iowa/AcceptLanguage.rb +76 -0
  251. data/src/iowa/Application.rb +928 -0
  252. data/src/iowa/ApplicationStats.rb +72 -0
  253. data/src/iowa/Association.rb +67 -0
  254. data/src/iowa/BindingsParser.rb +62 -0
  255. data/src/iowa/Breakpoint.rb +273 -0
  256. data/src/iowa/CSS.rb +564 -0
  257. data/src/iowa/Client.rb +192 -0
  258. data/src/iowa/Component.rb +405 -0
  259. data/src/iowa/ComponentProxy.rb +26 -0
  260. data/src/iowa/Config.rb +21 -0
  261. data/src/iowa/Constants.rb +226 -0
  262. data/src/iowa/Context.rb +218 -0
  263. data/src/iowa/ContextLogger.rb +16 -0
  264. data/src/iowa/DbPool.rb +222 -0
  265. data/src/iowa/DetachedComponent.rb +18 -0
  266. data/src/iowa/Dispatcher.rb +27 -0
  267. data/src/iowa/DynamicElements.rb +471 -0
  268. data/src/iowa/Element.rb +100 -0
  269. data/src/iowa/Email.rb +287 -0
  270. data/src/iowa/Extensions/AllExtensions.rb +4 -0
  271. data/src/iowa/Extensions/Class.rb +94 -0
  272. data/src/iowa/Extensions/Date.rb +88 -0
  273. data/src/iowa/Extensions/DateTime.rb +88 -0
  274. data/src/iowa/Extensions/Hash.rb +22 -0
  275. data/src/iowa/Extensions/Kernel.rb +6 -0
  276. data/src/iowa/Extensions/Numeric.rb +47 -0
  277. data/src/iowa/Extensions/Object.rb +11 -0
  278. data/src/iowa/Extensions/String.rb +60 -0
  279. data/src/iowa/Extensions/Time.rb +89 -0
  280. data/src/iowa/Extensions/TimeExtensions.rb +6 -0
  281. data/src/iowa/Form.rb +368 -0
  282. data/src/iowa/Hash.rb +85 -0
  283. data/src/iowa/ISAAC.rb +175 -0
  284. data/src/iowa/ImageSize.rb +279 -0
  285. data/src/iowa/IowaComponentMixins.rb +7 -0
  286. data/src/iowa/JSON-lexer.rb +296 -0
  287. data/src/iowa/JSON-objects.rb +201 -0
  288. data/src/iowa/KeyValueCoding.rb +91 -0
  289. data/src/iowa/LinkedList.rb +175 -0
  290. data/src/iowa/Loader.rb +22 -0
  291. data/src/iowa/Lockfile.rb +575 -0
  292. data/src/iowa/Logger.rb +74 -0
  293. data/src/iowa/Monkey.rb +20 -0
  294. data/src/iowa/Mutex.rb +142 -0
  295. data/src/iowa/Policy.rb +70 -0
  296. data/src/iowa/Pool.rb +243 -0
  297. data/src/iowa/PrettyException.rb +1091 -0
  298. data/src/iowa/Request.rb +244 -0
  299. data/src/iowa/Response.rb +133 -0
  300. data/src/iowa/Session.rb +354 -0
  301. data/src/iowa/SessionStats.rb +78 -0
  302. data/src/iowa/String.rb +65 -0
  303. data/src/iowa/Tag.rb +101 -0
  304. data/src/iowa/TemplateParser.rb +236 -0
  305. data/src/iowa/Util.rb +314 -0
  306. data/src/iowa/Webcache.rb +122 -0
  307. data/src/iowa/caches/BiLevelCache.rb +65 -0
  308. data/src/iowa/caches/ClassLimitedCache.rb +67 -0
  309. data/src/iowa/caches/DiskCache.rb +609 -0
  310. data/src/iowa/caches/DiskStore.rb +380 -0
  311. data/src/iowa/caches/LRUCache-alternative.rb +155 -0
  312. data/src/iowa/caches/LRUCache.rb +290 -0
  313. data/src/iowa/caches/SimpleLRUCache.rb +112 -0
  314. data/src/iowa/dispatchers/StandardDispatcher.rb +396 -0
  315. data/src/iowa/dispatchers/StandardDispatcherWithClassifier.rb +93 -0
  316. data/src/iowa/js/iowa_jsonrpc.js +381 -0
  317. data/src/iowa/js/jsonrpc.js +187 -0
  318. data/src/iowa/js/jsonrpc_async.js +261 -0
  319. data/src/iowa/loaders/DiskLoader.rb +50 -0
  320. data/src/iowa/loggers/Analogger.rb +54 -0
  321. data/src/iowa/loggers/AsyncLogger.rb +54 -0
  322. data/src/iowa/loggers/BitBucket.rb +38 -0
  323. data/src/iowa/loggers/Log4R.rb +13 -0
  324. data/src/iowa/loggers/Log4rLogger.rb +48 -0
  325. data/src/iowa/loggers/Logger.rb +29 -0
  326. data/src/iowa/loggers/RubyLogger.rb +9 -0
  327. data/src/iowa/pools/DBConnectionPool.rb +53 -0
  328. data/src/iowa/request/Apache.rb +90 -0
  329. data/src/iowa/request/EMHybrid.rb +59 -0
  330. data/src/iowa/request/ENV.rb +80 -0
  331. data/src/iowa/request/FCGI.rb +68 -0
  332. data/src/iowa/request/HTTPMachine.rb +75 -0
  333. data/src/iowa/request/Mongrel.rb +68 -0
  334. data/src/iowa/request/WEBrick.rb +48 -0
  335. data/src/iowa/version.rb +3 -0
  336. data/src/iowa/webrick/HTTPServer.rb +43 -0
  337. data/src/iowa/webrick/WEBrickServlet.rb +28 -0
  338. data/src/iowa_fcgi_handler.rb +101 -0
  339. data/src/iowa_httpmachine.rb +141 -0
  340. data/src/iowa_hybrid.rb +193 -0
  341. data/src/iowa_hybrid_cluster.rb +231 -0
  342. data/src/iowa_mongrel.rb +136 -0
  343. data/src/iowa_webrick.rb +194 -0
  344. data/src/iowa_webrick_legacy.rb +104 -0
  345. data/src/mod_iowa.rb +104 -0
  346. data/tcss.rb +61 -0
  347. data/test/README.windows +12 -0
  348. data/test/TC_AcceptLanguage.rb +61 -0
  349. data/test/TC_AppConfig.rb +43 -0
  350. data/test/TC_AppConfig/cgi/iowa.cgi +7 -0
  351. data/test/TC_AppConfig/doc/index.html +1 -0
  352. data/test/TC_AppConfig/iowa/Main.html +4 -0
  353. data/test/TC_AppConfig/iowa/Main.iwa +17 -0
  354. data/test/TC_AppConfig/iowa/README +1 -0
  355. data/test/TC_AppConfig/iowa/app.cnf +19 -0
  356. data/test/TC_AppConfig/iowa/app.rb +8 -0
  357. data/test/TC_AppConfig/webrick.rb +38 -0
  358. data/test/TC_Association.rb +29 -0
  359. data/test/TC_BiLevelCache.rb +71 -0
  360. data/test/TC_CGI_Adaptor.rb +55 -0
  361. data/test/TC_CGI_Adaptor/cgi/iowa.cgi +7 -0
  362. data/test/TC_CGI_Adaptor/doc/index.html +1 -0
  363. data/test/TC_CGI_Adaptor/iowa/Main.html +8 -0
  364. data/test/TC_CGI_Adaptor/iowa/Main.iwa +14 -0
  365. data/test/TC_CGI_Adaptor/iowa/README +1 -0
  366. data/test/TC_CGI_Adaptor/iowa/app.cnf +8 -0
  367. data/test/TC_CGI_Adaptor/iowa/app.rb +8 -0
  368. data/test/TC_CGI_Adaptor/webrick.rb +38 -0
  369. data/test/TC_CSS.rb +660 -0
  370. data/test/TC_ClassLimitedCache.rb +89 -0
  371. data/test/TC_Classifier.rb +80 -0
  372. data/test/TC_DbPool.rb +127 -0
  373. data/test/TC_DiskCache.rb +218 -0
  374. data/test/TC_Hybrid.rb +58 -0
  375. data/test/TC_Hybrid/doc/thing.txt +1 -0
  376. data/test/TC_Hybrid/iowa/Main.html +3 -0
  377. data/test/TC_Hybrid/iowa/Main.iwa +7 -0
  378. data/test/TC_Hybrid/iowa/NewPage.html +1 -0
  379. data/test/TC_Hybrid/iowa/NewPage.iwa +5 -0
  380. data/test/TC_Hybrid/iowa/app.cnf +10 -0
  381. data/test/TC_Hybrid/iowa/app.rb +5 -0
  382. data/test/TC_IOWAFunctions/doc/Ajax1.html +1 -0
  383. data/test/TC_IOWAFunctions/doc/Ajax1.iwa +1 -0
  384. data/test/TC_IOWAFunctions/doc/index.html +1 -0
  385. data/test/TC_IOWAFunctions/doc/js/dojo.js +9686 -0
  386. data/test/TC_IOWAFunctions/iowa/Ajax1.html +40 -0
  387. data/test/TC_IOWAFunctions/iowa/Ajax1.iwa +23 -0
  388. data/test/TC_IOWAFunctions/iowa/AjaxWidget.iwa +19 -0
  389. data/test/TC_IOWAFunctions/iowa/AjaxWidget.view +22 -0
  390. data/test/TC_IOWAFunctions/iowa/DanielTest.html +9 -0
  391. data/test/TC_IOWAFunctions/iowa/DanielTest.iwa +10 -0
  392. data/test/TC_IOWAFunctions/iowa/IntervalWidget.html +1 -0
  393. data/test/TC_IOWAFunctions/iowa/IntervalWidget.iwa +14 -0
  394. data/test/TC_IOWAFunctions/iowa/Main.html +1 -0
  395. data/test/TC_IOWAFunctions/iowa/NestedRepeat1.html +12 -0
  396. data/test/TC_IOWAFunctions/iowa/NestedRepeat1.iwa +24 -0
  397. data/test/TC_IOWAFunctions/iowa/RPCResponse.iwa +7 -0
  398. data/test/TC_IOWAFunctions/iowa/RPCResponse.view +1 -0
  399. data/test/TC_IOWAFunctions/iowa/Repeat1.iwa +31 -0
  400. data/test/TC_IOWAFunctions/iowa/Repeat1.view +9 -0
  401. data/test/TC_IOWAFunctions/iowa/Repeat2.iwa +32 -0
  402. data/test/TC_IOWAFunctions/iowa/Repeat2.view +11 -0
  403. data/test/TC_IOWAFunctions/iowa/Repeat3.iwa +44 -0
  404. data/test/TC_IOWAFunctions/iowa/Repeat3.view +18 -0
  405. data/test/TC_IOWAFunctions/iowa/TesCon.html +1 -0
  406. data/test/TC_IOWAFunctions/iowa/TesCon.iwa +5 -0
  407. data/test/TC_IOWAFunctions/iowa/app.cnf +19 -0
  408. data/test/TC_IOWAFunctions/iowa/app.rb +9 -0
  409. data/test/TC_IOWAFunctions/iowa/mapfile.cnf +8 -0
  410. data/test/TC_ISAAC.rb +52 -0
  411. data/test/TC_ImageSize.rb +84 -0
  412. data/test/TC_ImageSize/img.bmp +0 -0
  413. data/test/TC_ImageSize/img.gif +0 -0
  414. data/test/TC_ImageSize/img.jpg +0 -0
  415. data/test/TC_ImageSize/img.pcx +0 -0
  416. data/test/TC_ImageSize/img.pgm +7144 -0
  417. data/test/TC_ImageSize/img.png +0 -0
  418. data/test/TC_ImageSize/img.ppm +0 -0
  419. data/test/TC_ImageSize/img.psd +0 -0
  420. data/test/TC_ImageSize/img.tiff +0 -0
  421. data/test/TC_ImageSize/img.xbm +22 -0
  422. data/test/TC_KeyValueCoding.rb +35 -0
  423. data/test/TC_LRUCache.rb +296 -0
  424. data/test/TC_LinkedList.rb +46 -0
  425. data/test/TC_Lockfile.rb +106 -0
  426. data/test/TC_Minimal.rb +45 -0
  427. data/test/TC_Minimal/app.cnf +8 -0
  428. data/test/TC_Minimal/cgi-bin/iowa.cgi +11 -0
  429. data/test/TC_Minimal/doc/index.html +1 -0
  430. data/test/TC_Minimal/iowa/Main.html +1 -0
  431. data/test/TC_Minimal/iowa/README +1 -0
  432. data/test/TC_Minimal/iowa/app.rb +3 -0
  433. data/test/TC_Minimal/webrick.rb +38 -0
  434. data/test/TC_Mongrel.rb +58 -0
  435. data/test/TC_Mongrel/doc/thing.txt +1 -0
  436. data/test/TC_Mongrel/iowa/Main.html +3 -0
  437. data/test/TC_Mongrel/iowa/Main.iwa +7 -0
  438. data/test/TC_Mongrel/iowa/NewPage.html +1 -0
  439. data/test/TC_Mongrel/iowa/NewPage.iwa +5 -0
  440. data/test/TC_Mongrel/iowa/app.cnf +10 -0
  441. data/test/TC_Mongrel/iowa/app.rb +5 -0
  442. data/test/TC_NoSubclass.rb +56 -0
  443. data/test/TC_NoSubclass/cgi/iowa.cgi +7 -0
  444. data/test/TC_NoSubclass/doc/index.html +1 -0
  445. data/test/TC_NoSubclass/iowa/Main.html +8 -0
  446. data/test/TC_NoSubclass/iowa/Main.iwa +14 -0
  447. data/test/TC_NoSubclass/iowa/README +1 -0
  448. data/test/TC_NoSubclass/iowa/app.cnf +8 -0
  449. data/test/TC_NoSubclass/iowa/app.rb +5 -0
  450. data/test/TC_NoSubclass/webrick.rb +38 -0
  451. data/test/TC_Pool.rb +139 -0
  452. data/test/TC_RenderedCache/doc/thing.txt +1 -0
  453. data/test/TC_RenderedCache/iowa/BigPage.html +1 -0
  454. data/test/TC_RenderedCache/iowa/BigPage.iwa +12 -0
  455. data/test/TC_RenderedCache/iowa/Main.html +3 -0
  456. data/test/TC_RenderedCache/iowa/Main.iwa +7 -0
  457. data/test/TC_RenderedCache/iowa/NewPage.html +1 -0
  458. data/test/TC_RenderedCache/iowa/NewPage.iwa +11 -0
  459. data/test/TC_RenderedCache/iowa/app.cnf +13 -0
  460. data/test/TC_RenderedCache/iowa/app.rb +5 -0
  461. data/test/TC_RenderedCache/iowa/mapfile.map +4 -0
  462. data/test/TC_ResourceURL.rb +73 -0
  463. data/test/TC_ResourceURL/iowa/Main.html +2 -0
  464. data/test/TC_ResourceURL/iowa/Main.iwa +10 -0
  465. data/test/TC_ResourceURL/iowa/app.cnf +10 -0
  466. data/test/TC_ResourceURL/iowa/app.rb +5 -0
  467. data/test/TC_SimpleDetached.rb +41 -0
  468. data/test/TC_StandardDispatcher.rb +362 -0
  469. data/test/TC_StandardDispatcherWithClassifier.rb +358 -0
  470. data/test/TC_String.rb +24 -0
  471. data/test/TC_Tag.rb +41 -0
  472. data/test/TC_Webrick.rb +56 -0
  473. data/test/TC_Webrick/doc/thing.txt +1 -0
  474. data/test/TC_Webrick/iowa/Main.html +3 -0
  475. data/test/TC_Webrick/iowa/Main.iwa +7 -0
  476. data/test/TC_Webrick/iowa/NewPage.html +1 -0
  477. data/test/TC_Webrick/iowa/NewPage.iwa +5 -0
  478. data/test/TC_Webrick/iowa/app.cnf +10 -0
  479. data/test/TC_Webrick/iowa/app.rb +5 -0
  480. data/test/tc_template.rb +15 -0
  481. data/test/tests.conf +19 -0
  482. data/utils/CVS/Entries +3 -0
  483. data/utils/CVS/Repository +1 -0
  484. data/utils/CVS/Root +1 -0
  485. data/utils/QuickCert-1.0.2.tar.gz +0 -0
  486. data/utils/QuickCert-1.0.2/InstalledFiles +7 -0
  487. data/utils/QuickCert-1.0.2/MANIFEST +10 -0
  488. data/utils/QuickCert-1.0.2/Makefile +15 -0
  489. data/utils/QuickCert-1.0.2/README +56 -0
  490. data/utils/QuickCert-1.0.2/bin/QuickCert +355 -0
  491. data/utils/QuickCert-1.0.2/config.save +12 -0
  492. data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/README +60 -0
  493. data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/drbssl_c.rb +26 -0
  494. data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/drbssl_s.rb +35 -0
  495. data/utils/QuickCert-1.0.2/data/examples/ruby/QuickCert/qc_config +21 -0
  496. data/utils/QuickCert-1.0.2/lib/QuickCert/defaults.rb +28 -0
  497. data/utils/QuickCert-1.0.2/setup.rb +1312 -0
  498. data/utils/iowa_apps +422 -0
  499. data/utils/smtp_sink.rb +9 -0
  500. data/utils/startup_template.cnf +27 -0
  501. data/utils/startup_template.rb +73 -0
  502. metadata +551 -0
@@ -0,0 +1,49 @@
1
+ require 'iowa/pools/DBConnectionPool'
2
+ require 'kansas'
3
+
4
+ $public_dbconf = Iowa.config[Iowa::Capplication]['public_database']
5
+ $private_dbconf = Iowa.config[Iowa::Capplication]['private_database']
6
+ KSDatabase.new("dbi:#{$public_dbconf['vendor']}:#{$public_dbconf['database']}:#{$public_dbconf['host']}",$public_dbconf['user'],$public_dbconf['password']).map_all_tables
7
+
8
+ class KSDatabase
9
+
10
+ class ProductUrls
11
+ to_one(:product, :product_idx, :Products)
12
+ to_one(:product_preview, :product_idx, :ProductsPreview)
13
+ end
14
+
15
+ class Products
16
+ to_many(:product_url, :ProductUrls, :product_idx)
17
+ end
18
+
19
+ class ProductsPreview
20
+ to_many(:product_url, :ProductUrls, :product_idx)
21
+ end
22
+
23
+ end
24
+
25
+ class PubDrxDBPool < Iowa::Pool::DBConnectionPool
26
+ StartSize $public_dbconf['startsize']
27
+ MaxSize $public_dbconf['maxsize']
28
+ MaxAge $public_dbconf['maxage']
29
+ MonitorInterval $public_dbconf['monitorinterval']
30
+ DBClass KSDatabase
31
+ ConnectArgs ["dbi:#{$public_dbconf['vendor']}:#{$public_dbconf['database']}:#{$public_dbconf['host']}",$public_dbconf['user'],$public_dbconf['password']]
32
+
33
+ def getConnection(&b)
34
+ obtain {|h| b.call(h)}
35
+ end
36
+ end
37
+
38
+ class PrivDrxDBPool < Iowa::Pool::DBConnectionPool
39
+ StartSize $private_dbconf['startsize']
40
+ MaxSize $private_dbconf['maxsize']
41
+ MaxAge $private_dbconf['maxage']
42
+ MonitorInterval $private_dbconf['monitorinterval']
43
+ DBClass KSDatabase
44
+ ConnectArgs ["dbi:#{$private_dbconf['vendor']}:#{$private_dbconf['database']}:#{$private_dbconf['host']}",$private_dbconf['user'],$private_dbconf['password']]
45
+
46
+ def getConnection(&b)
47
+ obtain {|h| b.call(h)}
48
+ end
49
+ end
@@ -0,0 +1,223 @@
1
+ Iowa.runmode = :emhybridcluster
2
+ require 'eventmachine'
3
+ require 'iowa/http11'
4
+ require 'iowa/Client'
5
+ require 'iowa/request/EMHybrid'
6
+
7
+
8
+ module Iowa
9
+ class EMHybridClusterServer < EventMachine::Connection
10
+
11
+ MAX_HEADER = MAX_BODY = 114688
12
+ CEMHYBRIDCLUSTERSERVER = 'EMHybridClusterServer'.freeze
13
+
14
+ class MaxHeaderExceeded < Exception; end
15
+
16
+ def self.connect(hostname = nil,port = nil)
17
+ @hostname ||= hostname
18
+ @port ||= port
19
+ ::EventMachine.connect(@hostname, @port, self) do |conn|
20
+ conn.set_comm_inactivity_timeout 60
21
+ end
22
+ end
23
+
24
+ def self.hostname
25
+ @hostname
26
+ end
27
+
28
+ def self.port
29
+ @port
30
+ end
31
+
32
+ def initialize *args
33
+ super
34
+ @filecache = Iowa::Caches::LRUCache.new({:maxsize => 10})
35
+ @iowa_client = Iowa::InlineClient.new(nil,nil)
36
+ end
37
+
38
+ def connection_completed
39
+ @completed = true
40
+ send_data "swiftclient#{Iowa.app.location}"
41
+ end
42
+
43
+ def deliver_file(filename, suffix, params, headers)
44
+ if @filecache.include?(filename)
45
+ d,e,m = @filecache[filename]
46
+ else
47
+ d = File.read(filename)
48
+ e = Digest::SHA256.hexdigest(d)
49
+ m = File.mtime(filename)
50
+ @filecache[filename] = [d,e,m] if d.length < 130000
51
+ end
52
+ if headers.has_key?(CIF_MODIFIED_SINCE) and Time.parse(headers[CIF_MODIFIED_SINCE]) >= m
53
+ send_data "HTTP/1.1 304 Not Modified\r\n\r\n"
54
+ Iowa::Log.info("static #{filename}: 304")
55
+ else
56
+ ct = MIME::Types.type_for("foo.#{suffix}").first
57
+ h = "Connection: close\r\nDate: #{Time.now.httpdate}\r\nLast-Modified: #{m.httpdate}\r\nETag: #{e}\r\nCache-Control: max-age=3600\r\nContent-Type: #{ct ? ct.content_type : 'application/octet-stream'}\r\nContent-Length: #{d.length}\r\n\r\n"
58
+ send_data "HTTP/1.1 200 OK\r\n"
59
+ send_data h
60
+ send_data d
61
+ Iowa::Log.info("static #{filename}: 200")
62
+ end
63
+ end
64
+
65
+ def handle_file(params,headers)
66
+ path_info = params[CREQUEST_URI]
67
+ qs = params[CQUERY_STRING]
68
+ if path_info == C_slash or path_info == C_empty
69
+ path_info = C_slashindex_html
70
+ elsif path_info =~ /^([^.]+)$/
71
+ path_info = "#{$1}/index.html"
72
+ end
73
+
74
+ qsfilename = "#{Iowa.config[Iowa::Capplication][Iowa::Cdoc_root]}#{path_info}__#{qs}"
75
+ filename = "#{Iowa.config[Iowa::Capplication][Iowa::Cdoc_root]}#{path_info}"
76
+ if (FileTest.exist?(filename) and File.expand_path(filename).index(Iowa.config[Iowa::Capplication][Iowa::Cdoc_root]) == 0)
77
+ suffix = path_info.sub(/[_\s]*$/,C_empty)
78
+ deliver_file(filename, File.extname(suffix)[1..-1],params,headers)
79
+ true
80
+ elsif qs and (FileTest.exist?(qsfilename) and File.expand_path(qsfilename).index(Iowa.config[Iowa::Capplication][Iowa::Cdoc_root]) == 0)
81
+ suffix = path_info.sub(/[_\s]*$/,C_empty)
82
+ deliver_file(qsfilename, File.extname(suffix)[1..-1],params,headers)
83
+ true
84
+ else
85
+ false
86
+ end
87
+ end
88
+
89
+ def post_init
90
+ @parser = Iowa::HttpParser.new
91
+ @params = {}
92
+ @headers = {}
93
+ @nparsed = 0
94
+ @request = nil
95
+ @request_len = nil
96
+ @linebuffer = ''
97
+ end
98
+
99
+ def unbind
100
+ if @completed
101
+ self.class.connect
102
+ else
103
+ Logger['iowa_log'].error "FAILED to connect to cluster server #{self.class.hostname}:#{self.class.port}"
104
+ ::EventMachine.add_timer(rand(4)) {self.class.connect}
105
+ end
106
+ end
107
+
108
+ def process_http_request(headers,params,buffer)
109
+ unless handle_file(params,headers)
110
+ clen = buffer.length - headers[CCONTENT_LENGTH].to_i
111
+ body = buffer[clen,headers[CCONTENT_LENGTH].to_i]
112
+ request = Iowa::Request::EMHybrid.new(headers,params,body)
113
+ response = Iowa.handleConnection request
114
+
115
+ @iowa_client.reset(request,response)
116
+ send_data "HTTP/1.1 #{response.status_line}\r\n"
117
+ @iowa_client.print(self)
118
+ end
119
+ post_init
120
+ end
121
+
122
+ def print(data)
123
+ send_data data
124
+ end
125
+
126
+ def receive_data data
127
+ @linebuffer << data
128
+ @nparsed = @parser.execute(@headers, @params, @linebuffer, @nparsed) unless @parser.finished?
129
+ if @parser.finished?
130
+ if @request_len.nil?
131
+ @request_len = @nparsed + @params[CCONTENT_LENGTH].to_i
132
+ if @request_len > MAX_BODY
133
+ new_buffer = Tempfile.new(CEMHYBRIDCLUSTERSERVER)
134
+ new_buffer.binmode
135
+ new_buffer << @linebuffer
136
+ @linebuffer = new_buffer
137
+ end
138
+ end
139
+
140
+ if @linebuffer.length >= @request_len
141
+ process_http_request(@headers,@params,@linebuffer)
142
+ end
143
+ elsif @linebuffer.length > MAX_HEADER
144
+ raise MaxHeaderExceeded
145
+ end
146
+ rescue => e
147
+ Logger['iowa_log'].error "Error while reading request: #{e}"
148
+ close_connection
149
+ end
150
+ end
151
+ end
152
+
153
+ module Iowa
154
+
155
+ # Handle the communications coming in on the monitored socket,
156
+ # create a context object from the data received, and then pass
157
+ # the context information into the Application object for final
158
+ # handling. Exception handling is simply via capturing the Exception
159
+ # and outputting a stack backtrace (this could be improved).
160
+
161
+ class << self
162
+ remove_method(:handleConnection)
163
+ remove_method(:eventLoop)
164
+ remove_method(:run)
165
+ end
166
+
167
+ def self.handleConnection(request)
168
+ start_time = read_time = Time.now
169
+ mylog = Logger[Ciowa_log]
170
+
171
+ status = []
172
+ response = handleRequest(request)
173
+ begin
174
+ response.status_line = request.status_line if request.status_line
175
+ response.content_type = request.content_type if request.content_type
176
+ status[0] = response.status_line
177
+ if request.headers_out.respond_to?(:length) and request.headers_out.length > 0
178
+ request.headers_out.each {|k,v| response.headers.set(k,v)}
179
+ end
180
+ rescue Exception => e
181
+ mylog.info e.to_s, e.backtrace.inspect
182
+ end
183
+
184
+ end_time = Time.now
185
+ logline = "#{start_time} (#{read_time - start_time}/#{end_time - start_time}) :: #{request.uri} \"#{status[0]}\" #{response.body.length}B"
186
+ mylog.info logline
187
+ response
188
+ end
189
+
190
+ # Outputs the location of the socket being monitored, then enters the
191
+ # event loop to wait for and handle connections.
192
+
193
+ def self.eventLoop
194
+ Logger[Ciowa_log].info 'Entering the EMHybrid event loop...'
195
+
196
+ ::EventMachine.run do
197
+ #::EventMachine.start_server @config[Csocket][Chostname], @config[Csocket][Cport], EMHybridClusterServer
198
+
199
+ EMHybridClusterServer.connect(@config[Csocket][Chostname], @config[Csocket][Cport])
200
+ end
201
+ end
202
+
203
+ def self.run(*args)
204
+ run_check_started(*args)
205
+ mylog = Logger[Ciowa_log]
206
+ my_ip = @config[Csocket][Chostname]
207
+ my_ip_hex = my_ip.split('.',4).collect {|x| to_hex(x)}.join
208
+
209
+ Iowa.app.location = "#{my_ip_hex}#{sprintf('%04s',$$.to_s(16)).gsub(' ','0')}"
210
+
211
+ app.initialLoad()
212
+ @server = nil
213
+ setup_signal_handlers
214
+
215
+ begin
216
+ eventLoop
217
+ rescue Exception => exception
218
+ mylog.fatal "Catastrophic failure in main event loop: #{exception} :: " + exception.backtrace.join(".....").to_s
219
+ ensure
220
+ File.delete(@config[Csocket][Cpath]) if @config[Csocket].has_key? Cpath
221
+ end
222
+ end
223
+ end
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ =begin
4
+
5
+ This is a simple CGI adaptor that will allow one to use Iowa with any CGI
6
+ capable web server without requiring any special permissions with regard
7
+ to web server configuration.
8
+
9
+ To install the Iowa CGI adaptor:
10
+ - Copy this file into your cgi-bin directory.
11
+ - Set up a url that invokes this script.
12
+ In Apache, this involves adding something like this to your httpd.conf file:
13
+
14
+ Action iowaGuestbook /cgi-bin/iowa_guestbook_adaptor.cgi
15
+ <Location /guestbook>
16
+ SetHandler iowaGuestbook
17
+ </Location>
18
+
19
+ Configuration of the script is simple. Simply replace the text below that
20
+ reads, "[REPLACE_WITH_SOCKET_DEF]" with a valid socket definition
21
+ that points to where your Iowa application is listening.
22
+
23
+ =end
24
+
25
+ require 'iowa/Client'
26
+
27
+ iowa_socket = '[REPLACE_WITH_SOCKET_DEF]'
28
+ client = Iowa::Client.new(iowa_socket)
29
+ client.handle_request
@@ -0,0 +1,637 @@
1
+ begin
2
+ require 'rubygems'
3
+ rescue Exception
4
+ end
5
+
6
+ require 'yaml'
7
+ #require 'log4r'
8
+ #include Log4r
9
+
10
+ require 'iowa/Constants'
11
+ require 'iowa/Config'
12
+ require 'iowa/Util'
13
+ require 'iowa/String'
14
+ require 'iowa/TemplateParser'
15
+ require 'iowa/Hash'
16
+ require 'iowa/Association'
17
+ require 'iowa/Context'
18
+ require 'iowa/Element'
19
+ require 'iowa/Tag'
20
+ require 'iowa/DynamicElements'
21
+ require 'iowa/Form'
22
+ require 'iowa/Component'
23
+ require 'iowa/DetachedComponent'
24
+ require 'iowa/ComponentProxy'
25
+ require 'iowa/BindingsParser'
26
+ require 'iowa/KeyValueCoding'
27
+ require 'iowa/Session'
28
+ require 'iowa/Application'
29
+ require 'iowa/Request'
30
+ require 'iowa/Response'
31
+ require 'iowa/Email'
32
+ require 'iowa/PrettyException'
33
+ #require 'iowa/request/Apache'
34
+ #require 'iowa/request/FCGI'
35
+ #require 'iowa/request/WEBrick'
36
+ #require 'iowa/request/Mongrel'
37
+ require 'iowa/request/ENV'
38
+
39
+ require 'socket'
40
+ require 'resolv'
41
+ require 'optparse'
42
+ require 'fileutils'
43
+
44
+ module Iowa
45
+ @app = nil
46
+
47
+ def self.started?
48
+ @started ||= nil
49
+ end
50
+
51
+ def self.started=(val)
52
+ @started = val
53
+ end
54
+
55
+ # Forks the process. The parent outputs the PID of the child (so that
56
+ # an external invocation process can capture this information) and then
57
+ # exits. The child sets inself as it's session leader and returns.
58
+
59
+ def self.startDaemon(configuration_file,daemonize = nil)
60
+ self.started = true
61
+ Iowa::Application.applicationClass.Config = configuration_file if configuration_file and FileTest.exist?(configuration_file)
62
+ app
63
+
64
+ mylog = Logger[Ciowa_log]
65
+
66
+ daemonize = @config[Capplication][Cdaemonize] if daemonize.nil? and @config[Capplication].has_key?(Cdaemonize)
67
+ daemonize = true if daemonize.nil?
68
+
69
+ if daemonize
70
+ begin
71
+ if (child_pid = fork)
72
+ puts "PID #{child_pid}"
73
+ exit!
74
+ end
75
+ Process.setsid
76
+
77
+ mylog.info "Application started in #{Iowa.runmode} mode; process forked and daemonized as PID #{Process.pid}."
78
+ rescue Exception
79
+ mylog.info "Platform (#{RUBY_PLATFORM}) does not appear to support fork/setsid; skipping"
80
+ end
81
+ else
82
+ mylog.info "Application started; process not forked."
83
+ end
84
+ end
85
+
86
+ def self.configureExceptionScreens
87
+ @exception_screens = []
88
+ @exception_hosts = []
89
+ if @config.has_key?(Cexceptions)
90
+ if @config[Cexceptions].has_key?(Cscreens)
91
+ @config[Cexceptions][Cscreens].each do |item|
92
+ new_item = {}
93
+ next unless item.is_a?(::Hash)
94
+ item.each do |k,v|
95
+ k.sub!(/^\s+/,'')
96
+ v.sub!(/^\s+/,'')
97
+ c,m = v.split('.',2)
98
+ dd = Iowa::DispatchDestination.new(c,m)
99
+ if m = /^\/(.*)\//.match(k)
100
+ new_item[Regexp.new(m[1]),true] = dd
101
+ else
102
+ new_item[k] = dd
103
+ end
104
+ end
105
+ @exception_screens.push(new_item)
106
+ end
107
+ end
108
+ if @config[Cexceptions].has_key?(Chosts)
109
+ @config[Cexceptions][Chosts].each do |item|
110
+ new_item = {}
111
+ next unless item.is_a?(::Hash)
112
+ item.each do |k,v|
113
+ k.sub!(/^\s+/,'')
114
+ if v.is_a?(Array)
115
+ list = []
116
+ v.each {|x| list.push(Regexp.new(x.sub(/^\s+/,''),true))}
117
+ new_item[k] = list
118
+ end
119
+ end
120
+ @exception_hosts.push(new_item)
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ # configuration, and set the defaults for information that was
127
+ # omitted. Exceptions will be raised if socket information is
128
+ # missing, or if either socket or logging information seems to
129
+ # have errors.
130
+
131
+ def self.checkConfiguration
132
+ cc_setup
133
+ cc_socket
134
+ cc_logging
135
+ cc_misc
136
+
137
+ configureExceptionScreens
138
+ end
139
+
140
+ private
141
+ def self.cc_setup
142
+ # Make sure socket info was provided
143
+ @config[Csocket][Cport] = 2001 if (!@config[Csocket].has_key?(Cport) and !@config[Csocket].has_key?(Cpath))
144
+ @config[Csocket][Chostname] = '127.0.0.1' if (!@config[Csocket].has_key?(Chostname) and !@config[Csocket].has_key?(Cpath))
145
+ end
146
+
147
+ def self.cc_misc
148
+ @config[Capplication][Cdaemonize] = false unless @config[Capplication].has_key?(Cdaemonize)
149
+ @config[Capplication][Cdoc_root] = File.expand_path(@config[Capplication][Cdoc_root]) if @config[Capplication].has_key?(Cdoc_root)
150
+ @config[Capplication][Ccgi_root] = File.expand_path(@config[Capplication][Ccgi_root]) if @config[Capplication].has_key?(Ccgi_root)
151
+ end
152
+
153
+ def self.cc_logging
154
+ unless @config.has_key?(Clogger)
155
+ if @config.has_key?(Clogging)
156
+ @config[Clogger] = @config[Clogging]
157
+ @config[Clogger][Cclass] = 'Log4rLogger' unless @config[Clogger].has_key?(Cclass)
158
+ else
159
+ @config[Clogger][Cclass] = 'Logger'
160
+ end
161
+ end
162
+ @config[Clogger][Cbasedir] = @config[Capplication][Clog_root] || '.' unless @config[Clogger].has_key?(Cbasedir)
163
+ @config[Clogger][Cfilename] = 'iowa_log' unless @config[Clogger].has_key?(Cfilename)
164
+ @config[Clogger][Cmaxage] = :daily unless @config[Clogger].has_key?(Cmaxage)
165
+ end
166
+
167
+ def self.cc_socket_errors
168
+ raise "Please define only one of a TCP or a Unix domain socket in the configuration file." if @config[Csocket].has_key?(Cpath) and @config[Csocket].has_key?(Cport)
169
+ raise "The socket hostname contains illegal characters." unless @config[Csocket].has_key?(Chostname) and @config[Csocket][Chostname] =~ /^[a-zA-Z0-9\.\-]*$/
170
+ end
171
+
172
+ def self.cc_socket_resolveable
173
+ if @config[Csocket].has_key?(Chostname) and @config[Csocket][Chostname] !~ /^\s*\d+\.\d+\.\d+\.\d+\s*$/
174
+ begin
175
+ @config[Csocket][Chostname] = Resolv::getaddress(@config[Csocket][Chostname])
176
+ rescue Resolv::ResolvError
177
+ raise "The socket hostname must be resolveable to an IP address."
178
+ end
179
+ end
180
+ end
181
+
182
+ def self.cc_socket_valid_path
183
+ if @config[Csocket].has_key? Cpath
184
+ begin
185
+ File.unlink @config[Csocket][Cpath] if FileTest.exist? @config[Csocket][Cpath]
186
+ sf = File.open(@config[Csocket][Cpath],'w')
187
+ @config[Csocket][Cbasename] = File.basename(@config[Csocket][Cpath])
188
+ sf.close
189
+ File.unlink @config[Csocket][Cpath]
190
+ rescue Exception => exception
191
+ puts "The path for a Unix socket must be writeable."
192
+ raise
193
+ end
194
+ end
195
+ end
196
+
197
+ def self.cc_socket
198
+ cc_socket_errors
199
+ cc_socket_resolveable
200
+ cc_socket_valid_path
201
+ end
202
+ public
203
+ # Initialize logging mechanisms
204
+
205
+ def self.startLogging
206
+ lcfg = @config[Clogging]
207
+ mylog = Logger.new Ciowa_log
208
+ myformat = PatternFormatter.new :pattern => '[%l] %C @ %d :: %M'
209
+ mybaselog = RollingFileOutputter.new Cbaselog, :maxsize => lcfg[Cmaxsize], :maxtime => lcfg[Cmaxage], :level => lcfg[Cminlevel], :filename => lcfg[Cfilename], :trunc => false, :formatter => myformat
210
+ mylog.outputters = mybaselog
211
+
212
+ mylog.info 'Logging subsystem initialized.'
213
+ end
214
+
215
+ def self.maybe_kind_of(obj,classname)
216
+ r = false
217
+ obj.class.ancestors.each {|a| r ||= a.to_s == classname}
218
+ r
219
+ end
220
+
221
+ # Check the exception against the list of exception screens, if any. Return as
222
+ # soon as a match is found.
223
+
224
+ def self.checkScreen(exception)
225
+ klass = exception.class.to_s
226
+ @exception_screens.each do |item|
227
+ item.each do |k,v|
228
+ if k.is_a?(Regexp)
229
+ if k.match(klass)
230
+ return v
231
+ end
232
+ elsif maybe_kind_of(exception,k)
233
+ return v
234
+ end
235
+ end
236
+ end
237
+ nil
238
+ end
239
+
240
+ def self.internal_host?(request)
241
+ addr = false
242
+ browser = false
243
+ @exception_hosts.each do |host|
244
+ if host.has_key?(Caddresses)
245
+ host[Caddresses].each do |a|
246
+ if a.match(request.remote_host)
247
+ addr = true
248
+ break
249
+ end
250
+ end
251
+ elsif host.has_key?(Cips)
252
+ host[Cips].each do |i|
253
+ if i.match(request.remote_addr)
254
+ addr = true
255
+ break
256
+ end
257
+ end
258
+ else
259
+ addr = true
260
+ end
261
+ if host.has_key?(Cbrowsers)
262
+ host[Cbrowsers].each do |b|
263
+ if b.match(request.headers_in[CUserAgent])
264
+ browser = true
265
+ break
266
+ end
267
+ end
268
+ else
269
+ browser = true
270
+ end
271
+ end
272
+ (addr and browser)
273
+ end
274
+
275
+ def self.handleRequest(request)
276
+ mylog = Logger[Ciowa_log]
277
+ deployed_screen = false
278
+ dispatch_destination = nil
279
+ response = Iowa::Response.new(200)
280
+ original_exception = nil
281
+ context = nil
282
+ loop do
283
+ begin
284
+ response.content_type = Ctext_html
285
+ exception = nil
286
+ exception = catch(:session_error) do
287
+ begin
288
+ context = Iowa::Context.new(request, response)
289
+ context.prior_exception = original_exception if original_exception
290
+ app.handleRequest(context,dispatch_destination)
291
+ rescue Exception => exception
292
+ end
293
+ end
294
+ if exception.to_s != C_empty and exception.kind_of?(Exception)
295
+ mylog = Logger[Ciowa_log]
296
+ mylog.warn "Execution Error: #{exception} :: " + exception.backtrace.join(".....").to_s unless original_exception
297
+ if internal_host?(request)
298
+ mylog.info "Showing PrettyException"
299
+ response << Iowa::PrettyException.new(exception).to_s
300
+ else
301
+ if deployed_screen == false and dispatch_destination = checkScreen(exception)
302
+ dd = dispatch_destination.method ? "#{dispatch_destination.component}.#{dispatch_destination.method}" :
303
+ dispatch_destination.component
304
+ mylog.info "Deploying exception screen #{dd}"
305
+ response.status = Iowa::Response::InternalServerError
306
+ original_exception = exception
307
+ deployed_screen = true
308
+ raise "retry"
309
+ else
310
+ response.status = Iowa::Response::InternalServerError unless response.status >= 400
311
+ mylog.info "Showing ugly exception"
312
+ exception = original_exception if original_exception
313
+ response << "<p> An unhandled error has occured. Please inform your system or site's administrator of the error.</p>" if response.status == Iowa::Response::InternalServerError
314
+ response << "<p>#{exception.to_s.gsub("<","&lt;")}<br/>"
315
+ response << "</p>"
316
+ status = 'EOUT'
317
+ end
318
+ end
319
+ end
320
+ rescue
321
+ retry
322
+ end
323
+ break
324
+ end
325
+
326
+ # Unless the app forbids it or this is a page that went into the page cache,
327
+ # at this point we will write a cache of the generated page to the filesystem.
328
+ # This will allow pages that only need to be generated occasionally to be
329
+ # served as static content most of the time. Whether this is turned on or not
330
+ # is controlled by an application level config option, docroot_caching. It is
331
+ # turned off by default.
332
+ if context[:skip_pagecache] and context[:allow_docroot_caching]
333
+ if Iowa.config[Capplication][Cdocroot_caching]
334
+ if context.request.params['QUERY_STRING'].to_s != ''
335
+ path = "#{File.expand_path(File.join(Iowa.config[Capplication][Cdoc_root],context.request.uri))}__#{context.request.params['QUERY_STRING']}"
336
+ else
337
+ path = "#{File.expand_path(File.join(Iowa.config[Capplication][Cdoc_root],context.request.uri))}"
338
+ end
339
+ # Make sure that the path is inside the docroot!
340
+ if (path.index(Iowa.config[Capplication][Cdoc_root]) == 0)
341
+ begin
342
+ mylog.info "Writing cache entry: #{path}"
343
+ FileUtils.mkdir_p(File.dirname(path))
344
+ File.open(path,'w+') {|fh| fh.write response.body}
345
+ rescue Exception => e
346
+ # Well, that's too bad. Report the error and go on.
347
+ mylog.error "Error while writing filesystem cached page: #{e}"
348
+ end
349
+ end
350
+ end
351
+ end
352
+ if context.session
353
+ context.session.context = nil
354
+ context.session = nil
355
+ end
356
+
357
+ response
358
+ end
359
+
360
+ # Handle the communications coming in on the monitored socket,
361
+ # create a context object from the data received, and then pass
362
+ # the context information into the Application object for final
363
+ # handling. Exception handling is simply via capturing the Exception
364
+ # and outputting a stack backtrace (this could be improved).
365
+
366
+ def self.handleConnection(socket)
367
+ begin
368
+ Thread.current.priority = 2
369
+ start_time = Time.now
370
+ mylog = Logger[Ciowa_log]
371
+ message = ''
372
+ while (recv = socket.recv(8192)) != C_empty
373
+ message << recv
374
+ end
375
+ socket.shutdown(0)
376
+ read_time = Time.now
377
+ status = [COK]
378
+ rescue Exception => exception
379
+ mylog.error "Failure While Reading Inbound Data: #{exception}"
380
+ # TODO: When this happens, we need to either create a Request and return a useful response, or close the socket.
381
+ status = [CEIN, "Failure While Reading Inbound Data: #{exception}"]
382
+ end
383
+
384
+ begin
385
+ request = Marshal.load(message)
386
+ unless request.headers and request.headers.length > 0
387
+ request.headers = request.headers_in if request.headers_in.respond_to?(:length) and request.headers_in.length > 0
388
+ end
389
+ # Backward compatible yuckiness.
390
+ #request.content_type = nil
391
+ #request.status_line = nil
392
+ #request.headers_out = {}
393
+ rescue Exception => exception
394
+ mylog.error "Inbound Data Corruption: #{exception}"
395
+ status = [CEIN,"Inbound Data Corruption: #{exception}"]
396
+ end
397
+
398
+ unless status[0] == CEIN
399
+ response = handleRequest(request)
400
+ # Backward compatible yuckiness, continued.
401
+ response.status_line = request.status_line if request.status_line
402
+ response.content_type = request.content_type if request.content_type
403
+ status[0] = response.status_line
404
+ if request.headers_out.respond_to?(:length) and request.headers_out.length > 0
405
+ request.headers_out.each {|k,v| response.headers.set(k,v)}
406
+ end
407
+
408
+ begin
409
+ message = Marshal.dump(response)
410
+ socket.write(message)
411
+ socket.flush
412
+ socket.shutdown(1)
413
+ end_time = Time.now
414
+ rescue Exception => exception
415
+ mylog.error "Failure While Writing Outbound Data: #{exception}"
416
+ end
417
+
418
+ logline = "#{start_time} (#{read_time.to_f - start_time.to_f}/#{end_time.to_f - start_time.to_f}) :: #{request.uri} \"#{status[0]}\" #{response.body.length}B"
419
+ #mylog.info logline
420
+ else
421
+ response = Iowa::Response.new(500)
422
+ response.body = "BOOM: #{status[1]}"
423
+ message = Marshal.dump(response)
424
+ socket.write(message)
425
+ socket.flush
426
+ socket.shutdown(1)
427
+ logline = "#{start_time} (#{read_time.to_f - start_time.to_f}/#{end_time.to_f - start_time.to_f}) :: #{request.uri} ERROR #{response.body.length}B"
428
+ mylog.info logline
429
+ end
430
+ end
431
+
432
+ # Outputs the location of the socket being monitored, then enters the
433
+ # event loop to wait for and handle connections.
434
+
435
+ def self.eventLoop(server)
436
+ Logger[Ciowa_log].info 'Entering the main event loop...'
437
+ loop do
438
+ socket = server.accept
439
+ Thread.start do
440
+ Thread.current[:worker] = true
441
+ handleConnection socket
442
+ end
443
+ end
444
+ end
445
+
446
+ # Outputs the location of the socket being monitored, then enters the
447
+ # event loop to wait for and handle connections.
448
+
449
+ def self.to_hex(n)
450
+ sprintf('%02s',n.to_i.to_s(16)).sub(' ','0')
451
+ end
452
+
453
+ def self.run_check_started(*args)
454
+ unless started?
455
+ # Not started yet; call startDaemon()
456
+ if args[0].is_a?(::Hash)
457
+ # Pretty argument passing
458
+ ah = args.shift
459
+ daemonize = ah[:daemonize] ? true : false
460
+ path = ah[:config] ? ah[:config] : args[0] ? args.shift.to_s : nil
461
+ path = File.join( Iowa::Application.root_directory,
462
+ File.basename($0).sub( /\.\w+$/, '.cnf' ) ) unless path
463
+ else
464
+ daemonize = (args[0].is_a?(TrueClass) or args[0].is_a?(FalseClass)) ? args.shift : nil
465
+ path = args[0] ? args.shift.to_s : nil
466
+ path = File.join( Iowa::Application.root_directory,
467
+ File.basename($0).sub( /\.\w+$/, '.cnf' ) ) unless path
468
+ end
469
+
470
+ startDaemon(path,daemonize)
471
+ end
472
+ end
473
+
474
+ def self.run(*args)
475
+ run_check_started(*args)
476
+ mylog = Logger[Ciowa_log]
477
+ my_ip = @config[Csocket][Chostname]
478
+ my_ip_hex = my_ip.split('.',4).collect {|x| to_hex(x)}.join
479
+
480
+ if @config[Csocket].has_key? Cport
481
+ socket_host = @config[Csocket][Chostname]
482
+ socket_port = @config[Csocket][Cport]
483
+ my_port_hex = sprintf('%04s',socket_port.to_i.to_s(16)).gsub(' ','0')
484
+ begin
485
+ # This should be configurable and runtime toggleable.
486
+ TCPServer.do_not_reverse_lookup = true
487
+ if socket_host.to_s == ''
488
+ @server = TCPServer.new(socket_port)
489
+ mylog.info "Listening at localhost:#{socket_port}."
490
+ else
491
+ @server = TCPServer.new(socket_host,socket_port)
492
+ mylog.info "Listening at #{socket_host}:#{socket_port}."
493
+ end
494
+ app.location = "#{my_ip_hex}#{my_port_hex}"
495
+ rescue Exception => exception
496
+ mylog.fatal "Failure while attempting to establish a TCP socket at #{socket_host}:#{socket_port} : #{exception}"
497
+ raise
498
+ end
499
+ else
500
+ begin
501
+ @server = UNIXServer.new(@config[Csocket][Cpath])
502
+ File.chmod(0666, @config[Csocket][Cpath])
503
+ mylog.info "Listening on #{@config[Csocket][Cpath]}."
504
+ rescue Exception => exception
505
+ mylog.fatal "Failure while attemting to establish a Unix socket at #{@config[Csocket][Cpath]} : #{exception}"
506
+ raise
507
+ end
508
+ if app.serial_number.to_s != ''
509
+ app.location = "00000000#{sprintf('%04s',Iowa.app.serial_number.to_i.to_s(16)).gsub(' ','0')}"
510
+ else
511
+ app.location = ''
512
+ end
513
+ end
514
+
515
+ app.initialLoad()
516
+ setup_signal_handlers
517
+
518
+ begin
519
+ eventLoop(@server)
520
+ rescue Exception => exception
521
+ mylog.fatal "Catastrophic failure in main event loop: #{exception} :: " + exception.backtrace.join(".....").to_s
522
+ ensure
523
+ @server.close if @server
524
+ File.delete(@config[Csocket][Cpath]) if @config[Csocket].has_key? Cpath
525
+ end
526
+ end
527
+
528
+ def Iowa.app
529
+ if @app
530
+ @app
531
+ else
532
+ @app = Application.newApplication(Application.root_directory)
533
+ end
534
+ end
535
+
536
+ def Iowa.config
537
+ @config
538
+ end
539
+
540
+ def self.setup_signal_handlers
541
+ # A clean shutdown will wait up to a minute for any existing worker threads
542
+ # to finish before shutting down.
543
+ Logger['iowa_log'].info "Setting up signal handlers."
544
+
545
+ trap("INT") {Iowa.clean_shutdown}
546
+ trap("TERM") {Iowa.clean_shutdown}
547
+ end
548
+
549
+ def self.clean_shutdown
550
+ # If, for whatever reason, this is taking too long, a second signal will
551
+ # cause it to shut down immediately.
552
+
553
+ # A dirty shutdown doesn't wait for anything to finish.
554
+
555
+ trap("INT") { Iowa.dirty_shutdown }
556
+ trap("TERM") { Iowa.dirty_shutdown }
557
+ Logger['iowa_log'].info "Shutting down."
558
+
559
+ @server.close if @server and @server.respond_to?(:close)
560
+ threads_running = true
561
+ count = 0
562
+ while threads_running
563
+ # Don't wait forever....
564
+ count += 1
565
+ break if count > 30
566
+ threads_running = false
567
+ Thread.list.each {|t| threads_running = true if t[:worker] and t.alive?}
568
+ Logger['iowa_log'].info " ...still waiting for #{thread_count} threads." if threads_running
569
+ sleep 2 if threads_running
570
+ end
571
+ File.delete(@config[Csocket][Cpath]) if @config[Csocket].has_key? Cpath
572
+ ensure
573
+ Logger['iowa_log'].info "Clean shutdown."
574
+ Iowa::Log.close
575
+ ::Process.exit!
576
+ end
577
+
578
+ def self.thread_count
579
+ r = 0
580
+ Thread.list.each {|t| r += 1 if t[:worker] and t.alive?}
581
+ r
582
+ end
583
+
584
+ def self.dirty_shutdown
585
+ @server.close unless !@server or !server.respond_to(:close) or (@server and @server.closed?)
586
+ File.delete(@config[Csocket][Cpath]) if @config[Csocket].has_key? Cpath
587
+ ensure
588
+ Logger['iowa_log'].info "Dirty shutdown."
589
+ Iowa::Log.close
590
+ ::Process.exit!
591
+ end
592
+
593
+ def self.runmode
594
+ @runmode
595
+ end
596
+
597
+ def self.runmode=(mode)
598
+ @runmode = mode
599
+ end
600
+
601
+ end
602
+
603
+ OptionParser.new do |opts|
604
+ opts.banner = 'Usage: scriptname.rb [options]'
605
+ opts.separator ''
606
+ opts.on('-r','--run [MODE]', [:marshal, :webrick, :mongrel, :httpmachine, :hybrid, :hybridcluster],
607
+ "Select run mode (marshal, webrick, mongrel, httpmachine, hybrid); defaults to standalone") do |m|
608
+ case m
609
+ when :webrick
610
+ require 'iowa_webrick'
611
+ when :mongrel
612
+ require 'iowa_mongrel'
613
+ when :httpmachine
614
+ require 'iowa_httpmachine'
615
+ when :hybrid
616
+ require 'iowa_hybrid'
617
+ when :hybridcluster
618
+ require 'iowa_hybrid_cluster'
619
+ when :marshal
620
+ Iowa.runmode = :marshal
621
+ else
622
+ require 'webrick'
623
+ Iowa.runmode = :webrick
624
+ end
625
+ end
626
+ opts.on('-p','--port [NUMBER]',Integer,"Port to run IOWA process on") do |m|
627
+ Iowa.config[::Iowa::Csocket][::Iowa::Cport] = m
628
+ end
629
+ opts.on('-h','--host [HOST]',String,"Hostname or IP address to bind to") do |m|
630
+ Iowa.config[::Iowa::Csocket][::Iowa::Chost] = m
631
+ end
632
+
633
+ end.parse!
634
+
635
+ unless Iowa.runmode
636
+ require 'iowa_webrick'
637
+ end