ruote 0.9.18

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 (291) hide show
  1. data/README.txt +24 -0
  2. data/bin/validate-workflow.rb +89 -0
  3. data/examples/about_state.rb +81 -0
  4. data/examples/bigflow.rb +19 -0
  5. data/examples/csv_weather.rb +23 -0
  6. data/examples/engine_template.rb +247 -0
  7. data/examples/flowtracing.rb +24 -0
  8. data/examples/homeworkreview.rb +68 -0
  9. data/examples/kotoba.rb +22 -0
  10. data/examples/mano_tracker.rb +172 -0
  11. data/examples/openwferu.rb +58 -0
  12. data/examples/quotereporter.rb +157 -0
  13. data/examples/scheduler_cron_usage.rb +48 -0
  14. data/examples/scheduler_usage.rb +56 -0
  15. data/lib/openwfe.rb +41 -0
  16. data/lib/openwfe/contextual.rb +111 -0
  17. data/lib/openwfe/def.rb +46 -0
  18. data/lib/openwfe/engine.rb +37 -0
  19. data/lib/openwfe/engine/engine.rb +756 -0
  20. data/lib/openwfe/engine/expool_methods.rb +172 -0
  21. data/lib/openwfe/engine/file_persisted_engine.rb +105 -0
  22. data/lib/openwfe/engine/participant_methods.rb +133 -0
  23. data/lib/openwfe/engine/status_methods.rb +353 -0
  24. data/lib/openwfe/engine/update_exp_methods.rb +112 -0
  25. data/lib/openwfe/exceptions.rb +51 -0
  26. data/lib/openwfe/expool/errorjournal.rb +476 -0
  27. data/lib/openwfe/expool/expressionpool.rb +1144 -0
  28. data/lib/openwfe/expool/expstorage.rb +403 -0
  29. data/lib/openwfe/expool/history.rb +174 -0
  30. data/lib/openwfe/expool/journal.rb +224 -0
  31. data/lib/openwfe/expool/journal_replay.rb +321 -0
  32. data/lib/openwfe/expool/parser.rb +242 -0
  33. data/lib/openwfe/expool/representation.rb +121 -0
  34. data/lib/openwfe/expool/threadedexpstorage.rb +188 -0
  35. data/lib/openwfe/expool/wfidgen.rb +388 -0
  36. data/lib/openwfe/expool/yamlexpstorage.rb +224 -0
  37. data/lib/openwfe/expressions/condition.rb +244 -0
  38. data/lib/openwfe/expressions/environment.rb +246 -0
  39. data/lib/openwfe/expressions/expressionmap.rb +258 -0
  40. data/lib/openwfe/expressions/fe_cancel.rb +109 -0
  41. data/lib/openwfe/expressions/fe_command.rb +241 -0
  42. data/lib/openwfe/expressions/fe_concurrence.rb +662 -0
  43. data/lib/openwfe/expressions/fe_cron.rb +259 -0
  44. data/lib/openwfe/expressions/fe_cursor.rb +259 -0
  45. data/lib/openwfe/expressions/fe_define.rb +192 -0
  46. data/lib/openwfe/expressions/fe_do.rb +168 -0
  47. data/lib/openwfe/expressions/fe_equals.rb +291 -0
  48. data/lib/openwfe/expressions/fe_filter.rb +129 -0
  49. data/lib/openwfe/expressions/fe_filter_definition.rb +168 -0
  50. data/lib/openwfe/expressions/fe_fqv.rb +250 -0
  51. data/lib/openwfe/expressions/fe_if.rb +303 -0
  52. data/lib/openwfe/expressions/fe_iterator.rb +145 -0
  53. data/lib/openwfe/expressions/fe_listen.rb +371 -0
  54. data/lib/openwfe/expressions/fe_losfor.rb +111 -0
  55. data/lib/openwfe/expressions/fe_misc.rb +421 -0
  56. data/lib/openwfe/expressions/fe_participant.rb +269 -0
  57. data/lib/openwfe/expressions/fe_reserve.rb +212 -0
  58. data/lib/openwfe/expressions/fe_save.rb +274 -0
  59. data/lib/openwfe/expressions/fe_sequence.rb +117 -0
  60. data/lib/openwfe/expressions/fe_set.rb +139 -0
  61. data/lib/openwfe/expressions/fe_sleep.rb +166 -0
  62. data/lib/openwfe/expressions/fe_step.rb +159 -0
  63. data/lib/openwfe/expressions/fe_subprocess.rb +168 -0
  64. data/lib/openwfe/expressions/fe_timeout.rb +127 -0
  65. data/lib/openwfe/expressions/fe_wait.rb +78 -0
  66. data/lib/openwfe/expressions/fe_when.rb +142 -0
  67. data/lib/openwfe/expressions/filter.rb +104 -0
  68. data/lib/openwfe/expressions/flowexpression.rb +847 -0
  69. data/lib/openwfe/expressions/iterator.rb +221 -0
  70. data/lib/openwfe/expressions/merge.rb +84 -0
  71. data/lib/openwfe/expressions/raw.rb +547 -0
  72. data/lib/openwfe/expressions/rprocdef.rb +375 -0
  73. data/lib/openwfe/expressions/time.rb +333 -0
  74. data/lib/openwfe/expressions/timeout.rb +178 -0
  75. data/lib/openwfe/expressions/value.rb +126 -0
  76. data/lib/openwfe/filterdef.rb +259 -0
  77. data/lib/openwfe/flowexpressionid.rb +357 -0
  78. data/lib/openwfe/listeners/listener.rb +97 -0
  79. data/lib/openwfe/listeners/listeners.rb +139 -0
  80. data/lib/openwfe/listeners/socketlisteners.rb +272 -0
  81. data/lib/openwfe/logging.rb +122 -0
  82. data/lib/openwfe/omixins.rb +95 -0
  83. data/lib/openwfe/orest/controlclient.rb +119 -0
  84. data/lib/openwfe/orest/definitions.rb +113 -0
  85. data/lib/openwfe/orest/exception.rb +60 -0
  86. data/lib/openwfe/orest/oldrestservlet.rb +279 -0
  87. data/lib/openwfe/orest/osocket.rb +148 -0
  88. data/lib/openwfe/orest/restclient.rb +176 -0
  89. data/lib/openwfe/orest/workitem.rb +206 -0
  90. data/lib/openwfe/orest/worklistclient.rb +272 -0
  91. data/lib/openwfe/orest/xmlcodec.rb +670 -0
  92. data/lib/openwfe/participants.rb +38 -0
  93. data/lib/openwfe/participants/enoparticipants.rb +230 -0
  94. data/lib/openwfe/participants/participant.rb +141 -0
  95. data/lib/openwfe/participants/participantmap.rb +249 -0
  96. data/lib/openwfe/participants/participants.rb +407 -0
  97. data/lib/openwfe/participants/soapparticipants.rb +135 -0
  98. data/lib/openwfe/participants/socketparticipants.rb +202 -0
  99. data/lib/openwfe/participants/storeparticipants.rb +254 -0
  100. data/lib/openwfe/rudefinitions.rb +130 -0
  101. data/lib/openwfe/service.rb +103 -0
  102. data/lib/openwfe/storage/yamlcustom.rb +106 -0
  103. data/lib/openwfe/storage/yamlfilestorage.rb +245 -0
  104. data/lib/openwfe/tools/flowtracer.rb +81 -0
  105. data/lib/openwfe/util/dollar.rb +217 -0
  106. data/lib/openwfe/util/irb.rb +86 -0
  107. data/lib/openwfe/util/observable.rb +144 -0
  108. data/lib/openwfe/util/ometa.rb +62 -0
  109. data/lib/openwfe/util/workqueue.rb +124 -0
  110. data/lib/openwfe/util/xml.rb +418 -0
  111. data/lib/openwfe/utils.rb +554 -0
  112. data/lib/openwfe/version.rb +37 -0
  113. data/lib/openwfe/workitem.rb +499 -0
  114. data/lib/openwfe/worklist/oldrest.rb +244 -0
  115. data/lib/openwfe/worklist/storelocks.rb +293 -0
  116. data/lib/openwfe/worklist/storeparticipant.rb +44 -0
  117. data/lib/openwfe/worklist/worklist.rb +297 -0
  118. data/test/README.txt +27 -0
  119. data/test/back_0916_test.rb +111 -0
  120. data/test/bm/bm_1_xml_vs_prog.rb +56 -0
  121. data/test/bm/bm_2_step.rb +109 -0
  122. data/test/bm/ft_0f_5ms.rb +35 -0
  123. data/test/bm/ft_26_load.rb +210 -0
  124. data/test/bm/ft_26b_load.rb +86 -0
  125. data/test/bm/ft_26c_load.rb +97 -0
  126. data/test/bm/ft_26d_load.rb +97 -0
  127. data/test/bm/ft_recu.rb +71 -0
  128. data/test/clone_test.rb +122 -0
  129. data/test/concurrence_test.rb +77 -0
  130. data/test/condition_test.rb +155 -0
  131. data/test/console_test.rb +12 -0
  132. data/test/cron_ltest.rb +15 -0
  133. data/test/description_test.rb +87 -0
  134. data/test/eno_test.rb +76 -0
  135. data/test/expmap_test.rb +54 -0
  136. data/test/expool_20031219_0916.tgz +0 -0
  137. data/test/fe_lookup_att_test.rb +62 -0
  138. data/test/fei_test.rb +181 -0
  139. data/test/file_persisted_engine_test.rb +64 -0
  140. data/test/file_persistence_test.rb +134 -0
  141. data/test/filep_cancel_test.rb +123 -0
  142. data/test/filter_test.rb +109 -0
  143. data/test/flowtestbase.rb +351 -0
  144. data/test/ft_0.rb +68 -0
  145. data/test/ft_0b_sequence.rb +36 -0
  146. data/test/ft_0c_testname.rb +33 -0
  147. data/test/ft_0d_participant.rb +30 -0
  148. data/test/ft_0e_multibody.rb +34 -0
  149. data/test/ft_10_loop.rb +134 -0
  150. data/test/ft_11_ppd.rb +415 -0
  151. data/test/ft_11b_ppd.rb +54 -0
  152. data/test/ft_12_blockparticipant.rb +97 -0
  153. data/test/ft_13_eno.rb +52 -0
  154. data/test/ft_14_subprocess.rb +88 -0
  155. data/test/ft_14b_subprocess.rb +192 -0
  156. data/test/ft_14c_subprocess.rb +68 -0
  157. data/test/ft_15_iterator.rb +216 -0
  158. data/test/ft_15b_iterator.rb +74 -0
  159. data/test/ft_16_fqv.rb +73 -0
  160. data/test/ft_17_condition.rb +84 -0
  161. data/test/ft_18_pname.rb +56 -0
  162. data/test/ft_1_unset.rb +175 -0
  163. data/test/ft_1b_unset.rb +39 -0
  164. data/test/ft_20_cron.rb +53 -0
  165. data/test/ft_21_cron.rb +87 -0
  166. data/test/ft_21b_cron_pause.rb +82 -0
  167. data/test/ft_22_history.rb +74 -0
  168. data/test/ft_23_when.rb +77 -0
  169. data/test/ft_23b_when.rb +70 -0
  170. data/test/ft_23c_wait.rb +80 -0
  171. data/test/ft_23d_cww.rb +58 -0
  172. data/test/ft_24_def.rb +44 -0
  173. data/test/ft_25_cancel.rb +89 -0
  174. data/test/ft_27_getflowpos.rb +147 -0
  175. data/test/ft_28_fileparticipant.rb +63 -0
  176. data/test/ft_29_httprb.rb +106 -0
  177. data/test/ft_2_concurrence.rb +135 -0
  178. data/test/ft_2b_concurrence.rb +188 -0
  179. data/test/ft_2c_concurrence.rb +64 -0
  180. data/test/ft_30_socketlistener.rb +203 -0
  181. data/test/ft_31_flowname.rb +40 -0
  182. data/test/ft_32_journal.rb +91 -0
  183. data/test/ft_32c_journal.rb +102 -0
  184. data/test/ft_32d_journal.rb +84 -0
  185. data/test/ft_33_description.rb +107 -0
  186. data/test/ft_34_cancelwfid.rb +80 -0
  187. data/test/ft_35_localdefs.rb +75 -0
  188. data/test/ft_36_subprocids.rb +97 -0
  189. data/test/ft_37_pnames.rb +70 -0
  190. data/test/ft_38_tag.rb +127 -0
  191. data/test/ft_38b_tag.rb +161 -0
  192. data/test/ft_38c_tag.rb +100 -0
  193. data/test/ft_39_reserve.rb +63 -0
  194. data/test/ft_39b_reserve.rb +84 -0
  195. data/test/ft_3_equals.rb +170 -0
  196. data/test/ft_3b_lookup_vf.rb +83 -0
  197. data/test/ft_40_defined.rb +61 -0
  198. data/test/ft_41_case.rb +110 -0
  199. data/test/ft_42_environments.rb +75 -0
  200. data/test/ft_43_pat10.rb +85 -0
  201. data/test/ft_44_save.rb +70 -0
  202. data/test/ft_44b_restore.rb +212 -0
  203. data/test/ft_45_citerator.rb +214 -0
  204. data/test/ft_46_pparams.rb +62 -0
  205. data/test/ft_47_filter.rb +160 -0
  206. data/test/ft_48_fe_filter.rb +88 -0
  207. data/test/ft_49_condition.rb +126 -0
  208. data/test/ft_4_misc.rb +237 -0
  209. data/test/ft_50_xml_attribute.rb +155 -0
  210. data/test/ft_51_stack.rb +55 -0
  211. data/test/ft_52_obs_participant.rb +123 -0
  212. data/test/ft_53_null_noop_participant.rb +62 -0
  213. data/test/ft_54_listen.rb +288 -0
  214. data/test/ft_54b_listen.rb +66 -0
  215. data/test/ft_54c_listen.rb +99 -0
  216. data/test/ft_55_ptimeout.rb +59 -0
  217. data/test/ft_56_timeout.rb +59 -0
  218. data/test/ft_57_a.rb +145 -0
  219. data/test/ft_58_ejournal.rb +151 -0
  220. data/test/ft_59_ps.rb +150 -0
  221. data/test/ft_59b_ps_for_pat.rb +58 -0
  222. data/test/ft_5_time.rb +118 -0
  223. data/test/ft_60_ecancel.rb +161 -0
  224. data/test/ft_61_elsub.rb +51 -0
  225. data/test/ft_62_procparticipant.rb +71 -0
  226. data/test/ft_63_pause.rb +124 -0
  227. data/test/ft_64_alias.rb +102 -0
  228. data/test/ft_64_clone.rb +69 -0
  229. data/test/ft_65_stringlaunch.rb +59 -0
  230. data/test/ft_66_subforget.rb +70 -0
  231. data/test/ft_67_schedlaunch.rb +116 -0
  232. data/test/ft_68_ifparticipant.rb +70 -0
  233. data/test/ft_69_cancelmissing.rb +51 -0
  234. data/test/ft_6_lambda.rb +64 -0
  235. data/test/ft_70_lookupvar.rb +55 -0
  236. data/test/ft_71_log.rb +60 -0
  237. data/test/ft_72_lookup_processes.rb +76 -0
  238. data/test/ft_73_cancel_sub.rb +139 -0
  239. data/test/ft_74_block_and_workitem_dup.rb +63 -0
  240. data/test/ft_75_ruby_attributes.rb +87 -0
  241. data/test/ft_76_merge_isolate.rb +88 -0
  242. data/test/ft_77_segments.rb +35 -0
  243. data/test/ft_78_eval.rb +150 -0
  244. data/test/ft_79_tticket.rb +187 -0
  245. data/test/ft_79b_tticket.rb +172 -0
  246. data/test/ft_79c_outcome.rb +56 -0
  247. data/test/ft_7_lose.rb +104 -0
  248. data/test/ft_7b_lose.rb +78 -0
  249. data/test/ft_80_spname.rb +91 -0
  250. data/test/ft_81_exp.rb +60 -0
  251. data/test/ft_82_trecu.rb +46 -0
  252. data/test/ft_83_badpause.rb +58 -0
  253. data/test/ft_84_updateexp.rb +198 -0
  254. data/test/ft_85_dolhash.rb +43 -0
  255. data/test/ft_86_dollar_fv.rb +68 -0
  256. data/test/ft_87_define.rb +74 -0
  257. data/test/ft_8_forget.rb +44 -0
  258. data/test/ft_9_cursor.rb +145 -0
  259. data/test/ft_9b_cursor.rb +105 -0
  260. data/test/ft_tests.rb +124 -0
  261. data/test/hash_test.rb +75 -0
  262. data/test/hparticipant_test.rb +164 -0
  263. data/test/lookup_att_test.rb +90 -0
  264. data/test/lookup_vf_test.rb +94 -0
  265. data/test/misc_test.rb +90 -0
  266. data/test/nut_0_irb.rb +20 -0
  267. data/test/obs_test.rb +142 -0
  268. data/test/orest_test.rb +251 -0
  269. data/test/param_test.rb +290 -0
  270. data/test/participant_test.rb +101 -0
  271. data/test/pending.rb +23 -0
  272. data/test/ps_representation.rb +133 -0
  273. data/test/rake_ltest.rb +38 -0
  274. data/test/rake_qtest.rb +68 -0
  275. data/test/raw_prog_test.rb +412 -0
  276. data/test/restart_cron_test.rb +136 -0
  277. data/test/restart_paused_test.rb +98 -0
  278. data/test/restart_sleep_test.rb +140 -0
  279. data/test/restart_tests.rb +18 -0
  280. data/test/restart_when_test.rb +112 -0
  281. data/test/ruby_procdef_test.rb +132 -0
  282. data/test/rutest_utils.rb +63 -0
  283. data/test/sec_test.rb +205 -0
  284. data/test/slock_test.rb +80 -0
  285. data/test/storage_test.rb +44 -0
  286. data/test/test.rb +3 -0
  287. data/test/timeout_test.rb +105 -0
  288. data/test/util_xml_test.rb +112 -0
  289. data/test/wfid_test.rb +175 -0
  290. data/test/wi_test.rb +75 -0
  291. metadata +433 -0
@@ -0,0 +1,244 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2007, John Mettraux, OpenWFE.org
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # . Redistributions of source code must retain the above copyright notice, this
10
+ # list of conditions and the following disclaimer.
11
+ #
12
+ # . Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ #
16
+ # . Neither the name of the "OpenWFE" nor the names of its contributors may be
17
+ # used to endorse or promote products derived from this software without
18
+ # specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ # POSSIBILITY OF SUCH DAMAGE.
31
+ #++
32
+ #
33
+
34
+ #
35
+ # "made in Japan"
36
+ #
37
+ # John Mettraux at openwfe.org
38
+ #
39
+
40
+ require 'rexml/element'
41
+ require 'openwfe/orest/xmlcodec'
42
+ require 'openwfe/orest/oldrestservlet'
43
+
44
+
45
+ module OpenWFE
46
+
47
+ #
48
+ # This webrick servlet provides a REST interface for an old style
49
+ # OpenWFE worklist.
50
+ #
51
+ class OldRestWorklistServlet < OldRestServlet
52
+
53
+ def initialize (server, params)
54
+ super
55
+ @worklist = params[:Worklist]
56
+ end
57
+
58
+ #
59
+ # The realm for HTTP authentication.
60
+ #
61
+ def get_realm_name
62
+ "worklist"
63
+ end
64
+
65
+ #
66
+ # Lists the stores in the worklist
67
+ #
68
+ def do__getstorenames (req, res)
69
+
70
+ e = REXML::Element.new 'stores'
71
+
72
+ @worklist.each_store do |regex, store_name, store|
73
+
74
+ perms = @worklist.get_permissions(
75
+ req.attributes['username'], store_name)
76
+
77
+ es = REXML::Element.new 'store'
78
+ es.add_attribute 'name', store_name
79
+ es.add_attribute 'workitem-count', store.size
80
+ es.add_attribute 'permissions', perms
81
+ e << es
82
+ end
83
+
84
+ reply_with_xml res, 200, e
85
+ end
86
+
87
+ alias :do__liststores :do__getstorenames
88
+
89
+ #
90
+ # This implementation simply encodes the workitem, no transformation
91
+ # into headers at all.
92
+ #
93
+ def do__getheaders (req, res)
94
+
95
+ limit = req.query['limit']
96
+ limit = limit.to_s.to_i if limit
97
+ limit = nil if limit and limit < 1
98
+
99
+ hs = @worklist.get_headers(
100
+ req.attributes['username'],
101
+ get_store_name(req),
102
+ limit)
103
+
104
+ # TODO raise "404 no store named '#{store_name}'" unless store
105
+ # TODO raise "403 forbidden"
106
+
107
+ e = REXML::Element.new 'headers'
108
+
109
+ hs.each do |h|
110
+
111
+ workitem, locked = h
112
+
113
+ e << OpenWFE::XmlCodec::encode_workitem_as_header(
114
+ workitem, locked)
115
+ end
116
+
117
+ reply_with_xml res, 200, e
118
+ end
119
+
120
+ #
121
+ # Launches a new process instance.
122
+ #
123
+ def do__launchflow (req, res)
124
+
125
+ engine_name = req.query['engineid']
126
+ engine_name = "__nil__" unless engine_name
127
+
128
+ launch_item = OpenWFE::XmlCodec::decode req.body
129
+
130
+ r = @worklist.launch_flow engine_name, launch_item
131
+
132
+ e = REXML::Element.new 'ok'
133
+
134
+ e.add_attribute 'flow-id', r.to_s
135
+
136
+ reply_with_xml res, 200, e
137
+ end
138
+
139
+ #
140
+ # Retrieves a workitem from the worklist
141
+ #
142
+ def do__getworkitem (req, res)
143
+
144
+ execute_wi_get :get, req, res
145
+ end
146
+
147
+ #
148
+ # Retrieves a workitem from the worklist, locks it and returns it
149
+ #
150
+ def do__getandlockworkitem (req, res)
151
+
152
+ execute_wi_get :get_and_lock, req, res
153
+ end
154
+
155
+ #
156
+ # Returns the flow expression ids of the workitems with a given
157
+ # workflow instance id in a store.
158
+ #
159
+ def do__findflowinstance (req, res)
160
+
161
+ store_name = get_store_name req
162
+
163
+ wfid = req.query['id']
164
+ raise "404 'id' not specified" unless wfid
165
+
166
+ wis = @worklist.list_workitems(
167
+ req.attributes['username'], store_name, wfid)
168
+
169
+ e = REXML::Element.new 'stores'
170
+
171
+ wis.each do |wi|
172
+ e << OpenWFE::XmlCodec::encode(wi.fei)
173
+ end
174
+
175
+ reply_with_xml res, 200, e
176
+ end
177
+
178
+ #
179
+ # Releases a workitem (unlocks it).
180
+ #
181
+ def do__releaseworkitem (req, res)
182
+
183
+ execute_wi_post :release, req, res
184
+ end
185
+
186
+ #
187
+ # Simply saves the workitem and the modifications done to it.
188
+ #
189
+ def do__saveworkitem (req, res)
190
+
191
+ execute_wi_post :save, req, res
192
+ end
193
+
194
+ #
195
+ # Forwards the workitem (makes the worklist reply to the engine
196
+ # with the modified workitem)
197
+ #
198
+ def do__forwardworkitem (req, res)
199
+
200
+ execute_wi_post :forward, req, res
201
+ end
202
+
203
+ protected
204
+
205
+ def execute_wi_post (method, req, res)
206
+
207
+ store_name = get_store_name req
208
+
209
+ wi = OpenWFE::XmlCodec::decode req.body
210
+
211
+ @worklist.send(
212
+ method,
213
+ req.attributes['username'],
214
+ store_name,
215
+ wi)
216
+ end
217
+
218
+ def execute_wi_get (method, req, res)
219
+
220
+ store_name = get_store_name req
221
+ fei = OpenWFE::XmlCodec::decode req.body
222
+
223
+ wi = @worklist.send(
224
+ method, req.attributes['username'], store_name, fei)
225
+
226
+ raise "404 no workitem found for #{fei.to_s}" unless wi
227
+
228
+ reply_with_wi res, wi
229
+ end
230
+
231
+ def reply_with_wi (res, wi)
232
+
233
+ reply_with_xml res, 200, OpenWFE::XmlCodec::encode(wi)
234
+ end
235
+
236
+ def get_store_name (req)
237
+
238
+ ss = req.path.split("/")
239
+ raise "404 'store' not specified" if ss.length != 3
240
+ ss[-1]
241
+ end
242
+ end
243
+ end
244
+
@@ -0,0 +1,293 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2007-2008, John Mettraux, OpenWFE.org
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # . Redistributions of source code must retain the above copyright notice, this
10
+ # list of conditions and the following disclaimer.
11
+ #
12
+ # . Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ #
16
+ # . Neither the name of the "OpenWFE" nor the names of its contributors may be
17
+ # used to endorse or promote products derived from this software without
18
+ # specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ # POSSIBILITY OF SUCH DAMAGE.
31
+ #++
32
+ #
33
+ #
34
+
35
+ #
36
+ # "made in Japan"
37
+ #
38
+ # John Mettraux at openwfe.org
39
+ #
40
+
41
+ require 'thread'
42
+ require 'rufus/otime'
43
+ require 'openwfe/contextual'
44
+
45
+
46
+ module OpenWFE
47
+
48
+ #
49
+ # TODO #11162 : turn this class into a mixin
50
+ #
51
+
52
+
53
+ #
54
+ # A wrapper for a Store[Participant] that includes a lock system.
55
+ #
56
+ class StoreWithLocks
57
+ include Contextual
58
+
59
+ DEFAULT_LOCK_MAX_AGE = "1h"
60
+
61
+ attr_accessor :lock_max_age
62
+ attr_reader :store
63
+
64
+ #
65
+ # Builds a new store with a lock system wrapping a 'real_store'.
66
+ #
67
+ # This parameter 'real_store' may be a Class, like in
68
+ #
69
+ # store = StoreWithLocks.new(HashParticipant)
70
+ #
71
+ # You can retrieve the 'real store' with
72
+ #
73
+ # real_store = store.store
74
+ #
75
+ # By default, a lock is kept for one hour. You can change that
76
+ # value with, for example :
77
+ #
78
+ # store = StoreWithLocks.new(HashParticipant, :lock_max_age => "30m10s"
79
+ #
80
+ # (setting the lock maximum age to thirty minutes and 10 seconds).
81
+ #
82
+ def initialize (real_store, application_context=nil, params={})
83
+
84
+ @store = real_store
85
+ @store = @store.new if @store.kind_of?(Class)
86
+
87
+ self.application_context = application_context
88
+
89
+ @lock_max_age = params[:lock_max_age] || DEFAULT_LOCK_MAX_AGE
90
+ @lock_max_age = Rufus::parse_time_string @lock_max_age
91
+
92
+ @locks = {}
93
+ @lock_mutex = Mutex.new
94
+ end
95
+
96
+ #
97
+ # Sets the application context of this store lock and of the
98
+ # real store behind.
99
+ #
100
+ def application_context= (ac)
101
+
102
+ @application_context = ac
103
+
104
+ if @store.respond_to?(:application_context=) and \
105
+ not store.application_context
106
+
107
+ @store.application_context = @application_context
108
+ end
109
+ end
110
+
111
+ #
112
+ # Get a workitem, lock it and then return it. Ensures that no other
113
+ # 'locker' can lock it meanwhile.
114
+ #
115
+ def get_and_lock (locker, key)
116
+
117
+ @lock_mutex.synchronize do
118
+
119
+ object = @store[key]
120
+
121
+ return nil unless object
122
+
123
+ not_locked?(key)
124
+
125
+ @locks[key] = [ locker, Time.now.to_i ]
126
+ object
127
+ end
128
+ end
129
+
130
+ alias :lock :get_and_lock
131
+
132
+ #
133
+ # Gets a workitem without locking it.
134
+ #
135
+ def get (key)
136
+
137
+ @store[key]
138
+ end
139
+
140
+ #
141
+ # Removes a lock set on an item.
142
+ # If the item was locked by some other locker, will raise an exception.
143
+ # If the item was not locked, will simply exit silently.
144
+ #
145
+ def release (locker, key)
146
+
147
+ @lock_mutex.synchronize do
148
+ holding_lock? locker, key
149
+ @locks.delete key
150
+ end
151
+ end
152
+
153
+ #
154
+ # Returns the locker currently holding a given object
155
+ # (known by its key).
156
+ # Will return nil if the object is not locked (or doesn't exist).
157
+ #
158
+ def get_locker (key)
159
+
160
+ lock = get_lock key
161
+ return nil unless lock
162
+ lock[0]
163
+ end
164
+
165
+ #
166
+ # Saves the workitem and releases the lock on it.
167
+ #
168
+ def save (locker, workitem)
169
+
170
+ save_or_forward :save, locker, workitem
171
+ end
172
+
173
+ #
174
+ # Forwards the workitem (to the engine) and releases the lock on
175
+ # it (of course, it's not in the store anymore).
176
+ #
177
+ def forward (locker, workitem)
178
+
179
+ save_or_forward :forward, locker, workitem
180
+ end
181
+
182
+ alias :proceed :forward
183
+
184
+ #
185
+ # Directly forwards the list_workitems() call to the wrapped store.
186
+ #
187
+ def list_workitems (workflow_instance_id=nil)
188
+
189
+ @store.list_workitems(workflow_instance_id)
190
+ end
191
+
192
+ #
193
+ # Returns the count of workitems in the store.
194
+ #
195
+ def size
196
+
197
+ @store.size
198
+ end
199
+
200
+ #
201
+ # Just calls the consume method of the underlying store.
202
+ #
203
+ def consume (workitem)
204
+
205
+ @store.consume workitem
206
+ end
207
+
208
+ #
209
+ # Iterates over the workitems in the store.
210
+ #
211
+ # Doesn't care about any order for now.
212
+ #
213
+ def each (&block) # :yields: workitem, locked
214
+
215
+ @store.each do |fei, workitem|
216
+ block.call workitem, locked?(fei)
217
+ end
218
+ end
219
+
220
+ protected
221
+
222
+ def save_or_forward (method, locker, workitem)
223
+
224
+ @lock_mutex.synchronize do
225
+ holding_lock? locker, workitem.fei
226
+ @locks.delete workitem.fei
227
+ @store.send method, workitem
228
+ end
229
+ end
230
+
231
+ #
232
+ # Returns the lock info (else nil) for the given key.
233
+ #
234
+ def get_lock (key)
235
+
236
+ lock = @locks[key]
237
+
238
+ return nil unless lock
239
+
240
+ l, lt = lock
241
+
242
+ if (Time.now.to_i - lt) > @lock_max_age
243
+ @locks.delete key
244
+ return nil
245
+ end
246
+
247
+ [ l, lt ]
248
+ end
249
+
250
+ #
251
+ # Returns true if the object is locked
252
+ #
253
+ def locked? (key)
254
+
255
+ @locks[key] != nil
256
+ end
257
+
258
+ #
259
+ # Will raise an exception if the object (designated via its key)
260
+ # is already locked.
261
+ #
262
+ def not_locked? (key)
263
+
264
+ raise "already locked" if get_lock key
265
+ end
266
+
267
+ #
268
+ # Will raise an exception if the locker is not holding a lock
269
+ # for the given key.
270
+ #
271
+ def holding_lock? (locker, key)
272
+
273
+ lock = get_lock key
274
+ raise "not locked" unless lock
275
+ l, lt = lock
276
+ raise "locked by someone else" if (l != locker)
277
+ # else, simply end
278
+ end
279
+
280
+ #--
281
+ # Sets the lock on a given key to 'now'.
282
+ #
283
+ #def touch_lock (key)
284
+ # lock = @locks[key]
285
+ # return false unless lock
286
+ # locker, lock_time = lock
287
+ # @locks[key] = [ locker, Time.now.to_i ]
288
+ # true
289
+ #end
290
+ #++
291
+ end
292
+ end
293
+