openwferu 0.9.5 → 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/examples/mano_tracker.rb +11 -13
  2. data/lib/openwfe.rb +2 -4
  3. data/lib/openwfe/contextual.rb +8 -2
  4. data/lib/openwfe/engine/engine.rb +118 -2
  5. data/lib/openwfe/expool/expressionpool.rb +148 -53
  6. data/lib/openwfe/expool/expstorage.rb +36 -4
  7. data/lib/openwfe/expool/yamlexpstorage.rb +18 -0
  8. data/lib/openwfe/expressions/environment.rb +1 -1
  9. data/lib/openwfe/expressions/fe_misc.rb +14 -2
  10. data/lib/openwfe/expressions/fe_raw.rb +27 -11
  11. data/lib/openwfe/expressions/fe_subprocess.rb +45 -12
  12. data/lib/openwfe/expressions/fe_utils.rb +1 -1
  13. data/lib/openwfe/expressions/flowexpression.rb +5 -1
  14. data/lib/openwfe/expressions/raw_prog.rb +80 -32
  15. data/lib/openwfe/expressions/raw_xml.rb +10 -0
  16. data/lib/openwfe/flowexpressionid.rb +28 -7
  17. data/lib/openwfe/listeners/listener.rb +106 -0
  18. data/lib/openwfe/listeners/listeners.rb +140 -0
  19. data/lib/openwfe/listeners/socketlisteners.rb +239 -0
  20. data/lib/openwfe/listeners/sqslisteners.rb +145 -0
  21. data/lib/openwfe/participants/{csvparticipant.rb → csvparticipants.rb} +0 -0
  22. data/lib/openwfe/participants/{enoparticipant.rb → enoparticipants.rb} +1 -1
  23. data/lib/openwfe/participants/participantmap.rb +33 -1
  24. data/lib/openwfe/participants/participants.rb +99 -11
  25. data/lib/openwfe/participants/soapparticipants.rb +28 -8
  26. data/lib/openwfe/participants/socketparticipants.rb +172 -0
  27. data/lib/openwfe/participants/sqsparticipants.rb +121 -0
  28. data/lib/openwfe/rest/definitions.rb +1 -1
  29. data/lib/openwfe/{osocket.rb → rest/osocket.rb} +16 -8
  30. data/lib/openwfe/rest/xmlcodec.rb +41 -5
  31. data/lib/openwfe/storage/yamlfilestorage.rb +10 -13
  32. data/lib/openwfe/util/dollar.rb +23 -2
  33. data/lib/openwfe/util/otime.rb +1 -1
  34. data/lib/openwfe/util/safe.rb +149 -0
  35. data/lib/openwfe/util/scheduler.rb +47 -5
  36. data/lib/openwfe/util/sqs.rb +582 -0
  37. data/lib/openwfe/utils.rb +23 -0
  38. data/lib/openwfe/version.rb +1 -1
  39. data/lib/openwfe/workitem.rb +86 -3
  40. data/lib/openwfe/worklist/storeparticipant.rb +44 -4
  41. data/test/csv_test.rb +1 -1
  42. data/test/eno_test.rb +1 -1
  43. data/test/fei_test.rb +2 -15
  44. data/test/flowtestbase.rb +6 -2
  45. data/test/ft_11_ppd.rb +31 -0
  46. data/test/ft_13_eno.rb +1 -1
  47. data/test/ft_14b_subprocess.rb +74 -0
  48. data/test/ft_15_iterator.rb +0 -1
  49. data/test/ft_19_csv.rb +1 -1
  50. data/test/ft_20_cron.rb +1 -1
  51. data/test/ft_21_cron.rb +1 -1
  52. data/test/ft_27_getflowpos.rb +89 -0
  53. data/test/ft_28_fileparticipant.rb +65 -0
  54. data/test/ft_29_httprb.rb +95 -0
  55. data/test/ft_30_socketlistener.rb +197 -0
  56. data/test/ft_4_misc.rb +2 -1
  57. data/test/hash_test.rb +75 -0
  58. data/test/rake_qtest.rb +5 -4
  59. data/test/raw_prog_test.rb +205 -0
  60. data/test/rutest_utils.rb +16 -0
  61. data/test/safely_test.rb +89 -0
  62. data/test/scheduler_test.rb +71 -0
  63. data/test/sqs_test.rb +103 -0
  64. metadata +21 -6
  65. data/test/journal_persistence_test.rb +0 -147
@@ -123,6 +123,16 @@ module OpenWFE
123
123
 
124
124
  return c
125
125
  end
126
+
127
+ def extract_text_children ()
128
+ raw_representation.children.collect do |elt|
129
+ next if elt.is_a? REXML::Element
130
+ next if elt.is_a? REXML::Comment
131
+ s = elt.to_s.strip
132
+ next if s.length < 1
133
+ s
134
+ end
135
+ end
126
136
  end
127
137
  end
128
138
 
@@ -48,16 +48,19 @@ module OpenWFE
48
48
  #
49
49
  class FlowExpressionId
50
50
 
51
- attr_accessor \
52
- :owfe_version,
53
- :engine_id,
51
+ FIELDS = [
52
+ :owfe_version,
53
+ :engine_id,
54
54
  :initial_engine_id,
55
- :workflow_definition_url,
55
+ :workflow_definition_url,
56
56
  :workflow_definition_name,
57
57
  :workflow_definition_revision,
58
58
  :workflow_instance_id,
59
59
  :expression_name,
60
60
  :expression_id
61
+ ]
62
+
63
+ FIELDS.each { |f| attr_accessor f }
61
64
 
62
65
  #
63
66
  # A shortcut for fei.workflow_instance_id.
@@ -66,14 +69,32 @@ module OpenWFE
66
69
  alias :wfid :workflow_instance_id
67
70
 
68
71
  #
69
- # overrides the classical to_s()
72
+ # Overrides the classical to_s()
70
73
  #
71
74
  def to_s ()
72
- return "(fei #{@owfe_version} #{@engine_id}/#{@initial_engine_id} #{@workflow_definition_url} #{@workflow_definition_name} #{@workflow_definition_revision} #{@workflow_instance_id} #{@expression_name} #{@expression_id})"
75
+ "(fei #{@owfe_version} #{@engine_id}/#{@initial_engine_id} #{@workflow_definition_url} #{@workflow_definition_name} #{@workflow_definition_revision} #{@workflow_instance_id} #{@expression_name} #{@expression_id})"
76
+ end
77
+
78
+ #
79
+ # Returns a hash version of this FlowExpressionId instance.
80
+ #
81
+ def to_h ()
82
+ h = {}
83
+ FIELDS.each { |f| h[f] = instance_eval("@#{f.to_s}") }
84
+ h
85
+ end
86
+
87
+ #
88
+ # Rebuilds a FlowExpressionId from its Hash representation.
89
+ #
90
+ def FlowExpressionId.from_h (h)
91
+ fei = FlowExpressionId.new
92
+ FIELDS.each { |f| fei.instance_variable_set("@#{f}", h[f]) }
93
+ fei
73
94
  end
74
95
 
75
96
  def hash ()
76
- return to_s().hash()
97
+ to_s().hash()
77
98
  end
78
99
 
79
100
  def == (other)
@@ -0,0 +1,106 @@
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
+ # $Id: definitions.rb 2725 2006-06-02 13:26:32Z jmettraux $
34
+ #
35
+
36
+ #
37
+ # "made in Japan"
38
+ #
39
+ # John Mettraux at openwfe.org
40
+ #
41
+
42
+ require 'openwfe/logging'
43
+ require 'openwfe/workitem'
44
+ require 'openwfe/contextual'
45
+
46
+
47
+ #
48
+ # some base listener implementation
49
+ #
50
+ module OpenWFE
51
+
52
+ #
53
+ # The only thing this mixin module provides is a #reply_to_engine method.
54
+ # The details on how the workitems arrive are left to the implementations.
55
+ #
56
+ module WorkItemListener
57
+ include Contextual, Logging, OwfeServiceLocator
58
+
59
+ @accept_launchitems = true
60
+
61
+ #
62
+ # Determines if the listener should accept or not incoming
63
+ # launchitems.
64
+ #
65
+ def accept_launchitems= (b)
66
+ raise ArgumentError.new("boolean value expected") \
67
+ if b != true and b != false
68
+ @accept_launchitems = b
69
+ end
70
+
71
+ #
72
+ # Returns true if the listener accepts workitems.
73
+ # If launchitems are not accepted, the listener will simply
74
+ # discard them (with a log info message).
75
+ #
76
+ def accept_launchitems?
77
+ @accept_launchitems
78
+ end
79
+
80
+ protected
81
+
82
+ #
83
+ # Simply considers the object as a workitem and feeds it to the
84
+ # engine.
85
+ #
86
+ def handle_object (object)
87
+
88
+ return nil if filter_out_launchitems(object)
89
+
90
+ get_engine.reply(object)
91
+ end
92
+
93
+ #
94
+ # Returns true if the listener doesn't accept LaunchItem instances
95
+ # and the item is one of them.
96
+ #
97
+ def filter_out_launchitems (item)
98
+
99
+ return false unless item.is_a? OpenWFE::LaunchItem
100
+
101
+ return (not accept_launchitems?)
102
+ end
103
+ end
104
+
105
+ end
106
+
@@ -0,0 +1,140 @@
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
+ # $Id: definitions.rb 2725 2006-06-02 13:26:32Z jmettraux $
34
+ #
35
+
36
+ #
37
+ # "made in Japan"
38
+ #
39
+ # John Mettraux at openwfe.org
40
+ #
41
+
42
+ require 'find'
43
+ require 'yaml'
44
+ require 'fileutils'
45
+
46
+ require 'openwfe/service'
47
+ require 'openwfe/rudefinitions'
48
+ require 'openwfe/util/scheduler'
49
+ require 'openwfe/listeners/listener'
50
+
51
+
52
+ #
53
+ # some base listener implementations
54
+ #
55
+ module OpenWFE
56
+
57
+ #
58
+ # Polls a directory for incoming workitems (as files).
59
+ #
60
+ # Workitems can be instances of InFlowWorkItem or LaunchItem.
61
+ #
62
+ # require 'openwfe/listeners/listeners'
63
+ #
64
+ # engine.add_workitem_listener(OpenWFE::FileListener, "500")
65
+ #
66
+ # In this example, the directory ./work/in/ will be polled every 500
67
+ # milliseconds for incoming workitems (or launchitems).
68
+ #
69
+ # You can override the load_object(path) method to manage other formats
70
+ # then YAML.
71
+ #
72
+ class FileListener < Service
73
+ include WorkItemListener, Schedulable
74
+
75
+ attr_reader :workdir
76
+
77
+ def initialize (service_name, application_context)
78
+ super
79
+
80
+ @workdir = application_context[:work_directory]
81
+ @workdir = OpenWFE::DEFAULT_WORK_DIRECTORY unless @workdir
82
+ @workdir += "/in/"
83
+
84
+ linfo { "new() workdir is '#{@workdir}'" }
85
+ end
86
+
87
+ #
88
+ # Will 'find' files in the work directory (by default ./work/in/),
89
+ # extract the workitem in them and feed it back to the engine.
90
+ #
91
+ def trigger (params)
92
+ # no synchronization for now
93
+
94
+ ldebug { "trigger()" }
95
+
96
+ FileUtils.makedirs(@workdir) unless File.exist?(@workdir)
97
+
98
+ Find.find(@workdir) do |path|
99
+
100
+ next if File.stat(path).directory?
101
+
102
+ ldebug { "trigger() considering file '#{path}'" }
103
+
104
+ begin
105
+
106
+ object = load_object(path)
107
+
108
+ handle_object(object) if object
109
+
110
+ rescue Exception => e
111
+
112
+ linfo do
113
+ "trigger() failure while loading from '#{path}'. " +
114
+ "Resuming... \n" +
115
+ OpenWFE::exception_to_s(e)
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ protected
122
+
123
+ #
124
+ # Turns a file into a Ruby instance.
125
+ # This base implementation does it via YAML.
126
+ #
127
+ def load_object (path)
128
+
129
+ return nil unless path.match ".*\.yaml$"
130
+
131
+ object = YAML.load_file(path)
132
+
133
+ File.delete(path)
134
+
135
+ return object
136
+ end
137
+ end
138
+
139
+ end
140
+
@@ -0,0 +1,239 @@
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
+ # $Id: definitions.rb 2725 2006-06-02 13:26:32Z jmettraux $
34
+ #
35
+
36
+ #
37
+ # "made in Japan"
38
+ #
39
+ # John Mettraux at openwfe.org
40
+ #
41
+
42
+ require 'yaml'
43
+ require 'socket'
44
+
45
+ require 'openwfe/utils'
46
+ require 'openwfe/service'
47
+ require 'openwfe/workitem'
48
+ require 'openwfe/rudefinitions'
49
+ require 'openwfe/rest/xmlcodec'
50
+ require 'openwfe/listeners/listener'
51
+
52
+
53
+ #
54
+ # some base listener implementations
55
+ #
56
+ module OpenWFE
57
+
58
+ #
59
+ # Listens for workitems on a socket.
60
+ #
61
+ # Workitems can be instances of InFlowWorkItem or LaunchItem.
62
+ #
63
+ # By default, listens on port 7007.
64
+ #
65
+ # require 'openwfe/listeners/socketlisteners'
66
+ #
67
+ # engine.add_workitem_listener(OpenWFE::SocketListener)
68
+ #
69
+ # But you can be more specific :
70
+ #
71
+ # engine.add_workitem_listener(
72
+ # OpenWFE::SocketListener.new(
73
+ # "sl_whatever_name",
74
+ # engine.application_context,
75
+ # "target.host.xx",
76
+ # 7707)
77
+ #
78
+ class SocketListener < Service
79
+ include WorkItemListener
80
+
81
+ attr_reader :server, :thread
82
+
83
+ def initialize (service_name, application_context, port=nil, iface=nil)
84
+
85
+ super(service_name, application_context)
86
+
87
+ port ||= 7007
88
+
89
+ @server = TCPServer.new(iface, port)
90
+
91
+ @thread = OpenWFE.call_in_thread(@service_name, self) do
92
+ listen()
93
+ end
94
+ end
95
+
96
+ #
97
+ # Stops this socket listener (shuts down its socket)
98
+ #
99
+ def stop
100
+
101
+ @server.shutdown
102
+
103
+ linfo { "stop() shut socket down" }
104
+ end
105
+
106
+ #
107
+ # This base implementation is capable of decoding XML workitems
108
+ # and YAML workitems.
109
+ #
110
+ def decode_workitem (data)
111
+
112
+ return nil if not data or data.length < 4
113
+
114
+ if data[0, 1] == "<"
115
+ #
116
+ # seems like XML
117
+
118
+ OpenWFE.xml_decode(data)
119
+
120
+ elsif data[0, 3] == "---"
121
+ #
122
+ # must be YAML
123
+
124
+ YAML.load(data)
125
+
126
+ else
127
+ #
128
+ # perhaps OpenWFEja style header + workitem
129
+
130
+ data = pop_line(data)
131
+ data = pop_line(data)
132
+
133
+ decode_workitem(data)
134
+ end
135
+ end
136
+
137
+ #
138
+ # Simply pipes back the result of get_engine.reply(wi) on the
139
+ # socket.
140
+ #
141
+ def reply_to_socket (socket, result)
142
+
143
+ socket.puts result.to_s
144
+ socket.close_write
145
+
146
+ ldebug { "reply_to_socket() result is >>>#{result}<<<" }
147
+ end
148
+
149
+ #
150
+ # The base implementation allows returns true.
151
+ #
152
+ # An override of this method might check the origin of the socket
153
+ # and maybe only allow a certain range of hosts...
154
+ #
155
+ def is_allowed? (socket)
156
+ true
157
+ end
158
+
159
+ protected
160
+
161
+ #
162
+ # Where the socket waiting loop is...
163
+ #
164
+ def listen
165
+
166
+ linfo { "listen() listening on #{@server.addr.join(' ')}" }
167
+
168
+ while socket = @server.accept
169
+ OpenWFE.call_in_thread(@service_name, self) do
170
+ handle_socket(socket) if is_allowed? socket
171
+ end
172
+ end
173
+ end
174
+
175
+ #
176
+ # The bulk work of handling a connection is done here. The
177
+ # incoming workitem is piped to the engine, then the result
178
+ # it written back a string on the socket which then gets closed.
179
+ #
180
+ def handle_socket (socket)
181
+
182
+ ldebug do
183
+ "handle_socket() "+
184
+ "connection from #{socket.peeraddr.join(' ')}"
185
+ end
186
+
187
+ data = ""
188
+ while true
189
+ s = socket.gets
190
+ break unless s
191
+ data += s
192
+ end
193
+
194
+ wi = decode_workitem(data)
195
+
196
+ if not wi
197
+
198
+ ldebug do
199
+ "handle_socket() "+
200
+ ">>>#{data}<<< doesn't contain a workitem"
201
+ end
202
+ socket.close
203
+ return
204
+
205
+ elsif wi.kind_of? InFlowWorkItem
206
+
207
+ ldebug do
208
+ "handle_socket() received wi for #{wi.fei.to_debug_s}"
209
+ end
210
+
211
+ elsif wi.kind_of? LaunchItem
212
+
213
+ ldebug do
214
+ "handle_socket() received li for #{wi.wfdurl}"
215
+ end
216
+ else
217
+
218
+ ldebug do
219
+ "handle_socket() "+
220
+ "received something of class #{wi.class}"
221
+ end
222
+ end
223
+
224
+ result = get_engine.reply(wi)
225
+
226
+ reply_to_socket(socket, result)
227
+
228
+ socket.close
229
+ end
230
+
231
+ def pop_line (s)
232
+ i = s.index("\n")
233
+ return s unless i
234
+ return s[i+1..-1]
235
+ end
236
+ end
237
+
238
+ end
239
+