rbeai 0.0.1

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 (46) hide show
  1. data/lib/rbeai/GetLogic.rb +144 -0
  2. data/lib/rbeai/Main.rb +70 -0
  3. data/lib/rbeai/PipeTask.rb +216 -0
  4. data/lib/rbeai/PutLogic.rb +123 -0
  5. data/lib/rbeai/RouterLogic.rb +155 -0
  6. data/lib/rbeai/RouterPipeTask.rb +62 -0
  7. data/lib/rbeai/TasksLogic.rb +285 -0
  8. data/lib/rbeai/TransfLogic.rb +145 -0
  9. data/lib/rbeai/WorkerPool.rb +72 -0
  10. data/lib/rbeai/Workflow.rb +79 -0
  11. data/lib/rbeai/templates/csv2xml_nh.awk +14 -0
  12. data/lib/rbeai/templates/csv2xml_wh.awk +16 -0
  13. data/lib/rbeai.rb +13 -0
  14. data/rbeai-0.0.1.gem +0 -0
  15. data/rbeai.gemspec +20 -0
  16. data/test/config/conf.rb +2 -0
  17. data/test/test1.rb +4 -0
  18. data/test/test_files/empty_file.txt +0 -0
  19. data/test/test_files/empty_file.unused +0 -0
  20. data/test/test_files/test_router_1.txt +1 -0
  21. data/test/test_files/test_router_1.xml_91 +5 -0
  22. data/test/test_files/test_router_1.xml_92 +6 -0
  23. data/test/test_files/test_router_1.xml_fail +5 -0
  24. data/test/test_files/test_transf_1.xml +28 -0
  25. data/test/test_files/test_transf_2.txt +5 -0
  26. data/test/test_files/test_transf_3.xml +28 -0
  27. data/test/test_get_send_email.rb +11 -0
  28. data/test/test_get_send_file.rb +11 -0
  29. data/test/test_get_send_ftp.rb +11 -0
  30. data/test/test_router.rb +11 -0
  31. data/test/test_transf_1.rb +11 -0
  32. data/test/test_transf_2.awk +1 -0
  33. data/test/test_transf_2.rb +11 -0
  34. data/test/test_transf_3.rb +11 -0
  35. data/test/test_transf_3.xsl +10 -0
  36. data/test/tmp/test_get_send_file/1130328204.12500/getfile/empty_file.txt +0 -0
  37. data/test/tmp/test_get_send_ftp/1130328178.76500/getfile/empty_file.txt +0 -0
  38. data/test/workflows/test_get_send_email.wf +28 -0
  39. data/test/workflows/test_get_send_file.wf +21 -0
  40. data/test/workflows/test_get_send_ftp.wf +28 -0
  41. data/test/workflows/test_router_1.wf +35 -0
  42. data/test/workflows/test_start_end.wf +8 -0
  43. data/test/workflows/test_transf_1.wf +26 -0
  44. data/test/workflows/test_transf_2.wf +25 -0
  45. data/test/workflows/test_transf_3.wf +25 -0
  46. metadata +128 -0
@@ -0,0 +1,144 @@
1
+ require 'rio'
2
+ require 'rmail/parser'
3
+ require 'net/pop'
4
+ require 'rexml/document'
5
+
6
+ include REXML
7
+
8
+ module RbEAI
9
+
10
+ class GetLogic
11
+
12
+
13
+ def initialize(xmlDoc, task)
14
+ @task = task
15
+ protNode = XPath.first(xmlDoc, "./protocol")
16
+ protocol = protNode.attributes["def"]
17
+ @logic = case protocol
18
+ when "file" then GetFileLogic.new(protNode, task)
19
+ when "ftp" then GetFileLogic.new(protNode, task)
20
+ when "email" then GetEmailLogic.new(protNode, task)
21
+ end
22
+ end
23
+
24
+ def getFiles()
25
+ return @logic.getFiles()
26
+ end
27
+
28
+ end
29
+
30
+ class GetFileLogic
31
+
32
+ def initialize(protNode, task)
33
+ @task = task
34
+ @location = task.location
35
+ @pattern = task.pattern
36
+ end
37
+
38
+ def getFiles()
39
+ files = []
40
+ filesaux = []
41
+ files = rio("#{@location}")["#{@pattern}"]
42
+ files.each do |file|
43
+ filesaux << @task.persist(file)
44
+ end
45
+ return filesaux
46
+ end
47
+
48
+ end
49
+
50
+ class GetFtpLogic
51
+
52
+ def initialize(protNode, task)
53
+ @task = task
54
+ @location = task.location
55
+ @pattern = task.pattern
56
+ end
57
+
58
+ def getFiles()
59
+ files = []
60
+ filesaux = []
61
+ files = rio("#{@location}")
62
+ regexp = Regexp.new("#{@pattern}")
63
+ files.each do |file|
64
+ puts "file = #{file}"
65
+ filesaux << @task.persistFtp(file) if regexp.match("#{file}")
66
+ end
67
+ return filesaux
68
+ end
69
+
70
+ end
71
+
72
+ # <protocol def="email">
73
+ # <location address="" port=""/>
74
+ # <account name="" pwd=""/>
75
+ # <pattern>out.xml</pattern>
76
+ # </protocol>
77
+
78
+ class GetEmailLogic
79
+
80
+ def initialize(protNode, task)
81
+ @task = task
82
+ location = XPath.first(protNode, "./location")
83
+ account = XPath.first(protNode, "./account")
84
+ @address = location.attributes["address"]
85
+ @port = location.attributes["port"]
86
+ @name = account.attributes["name"]
87
+ @pwd = account.attributes["pwd"]
88
+ @pattern = task.pattern
89
+ end
90
+
91
+ def getFiles()
92
+ files = []
93
+ pop = Net::POP3.new(@address)
94
+ pop.start(@name, @pwd)
95
+ if pop.mails.empty?
96
+ puts 'No mail.'
97
+ else
98
+ i = 1
99
+ pop.each_mail do |m|
100
+ str = m.pop
101
+ i = i + 1
102
+ begin
103
+ email = RMail::Parser.read(str)
104
+ aux = true
105
+ _parseMail(email, @pattern, "mail_#{i}").each do |file|
106
+ _persistAndDelete(m, str, "mail_#{i}.txt") if aux
107
+ aux = false
108
+ files << file
109
+ end
110
+ rescue Exception
111
+ puts $!
112
+ end
113
+ end
114
+ puts "#{pop.mails.size} mails popped."
115
+ end
116
+ pop.finish
117
+ return files
118
+ end
119
+
120
+ private
121
+
122
+ def _persistAndDelete(mail, str, basename)
123
+ @task.persistStr(str, "#{basename}.txt")
124
+ #mail.delete
125
+ end
126
+
127
+ def _parseMail(email, fnameExpr, basename)
128
+ result = []
129
+ if email.multipart?
130
+ i = 0
131
+ email.each_part do |part|
132
+ fname = part.header.param('Content-Disposition','filename')
133
+ re = Regexp.new(fnameExpr.to_s)
134
+ if re.match(fname)
135
+ result << @task.persistStr(part.decode, "#{basename}_att_#{i}.txt")
136
+ end
137
+ end
138
+ end
139
+ return result
140
+ end
141
+
142
+ end
143
+
144
+ end #module
data/lib/rbeai/Main.rb ADDED
@@ -0,0 +1,70 @@
1
+ require 'rio'
2
+ require 'gserver'
3
+ require 'rbeai/Workflow'
4
+
5
+ include REXML
6
+
7
+ module RbEAI
8
+
9
+
10
+ class MAIN < GServer
11
+
12
+ load 'config/conf.rb'
13
+
14
+ def initialize()
15
+ #server_port = 8888
16
+ #server_log = true
17
+ @wflowlist = []
18
+ super(port = @@server_port, host = "localhost", maxConnections = 1, audit = @@server_log)
19
+ end
20
+
21
+ def serve(io)
22
+ command = io.gets.strip
23
+ if command == "stop"
24
+ io.puts "Exiting ..."
25
+ stop()
26
+ end
27
+ end
28
+
29
+ def start()
30
+ files = []
31
+ files = rio("workflows")["*.wf"]
32
+ files.each do |file|
33
+ puts file
34
+ awflow = Workflow.new(File.new(file))
35
+ awflow.run
36
+ @wflowlist << awflow
37
+ end
38
+ super()
39
+ end
40
+
41
+ def shutdown()
42
+ _endWflows()
43
+ super()
44
+ end
45
+
46
+ def stop()
47
+ _endWflows()
48
+ super()
49
+ end
50
+
51
+ private
52
+
53
+ def _endWflows()
54
+ @wflowlist.each do |wflow|
55
+ wflow.finish
56
+ end
57
+ end
58
+
59
+ end #class
60
+
61
+
62
+ end #module
63
+
64
+ #wf = Workflow.new(wfstr)
65
+ #wf.run()
66
+ #sleep(10)
67
+ #wf.finish()
68
+ #eai = MAIN.new()
69
+ #eai.start
70
+ #eai.join
@@ -0,0 +1,216 @@
1
+ require 'thread'
2
+ require 'thwait'
3
+
4
+ module RbEAI
5
+
6
+ class Control
7
+
8
+ attr_accessor :controlQueue, :control
9
+
10
+ def initialize(controlQueue, dataQueue)
11
+ @controlQueue = controlQueue
12
+ @dataQueue = dataQueue
13
+ end
14
+
15
+ def start(threadPool)
16
+ @control = Thread.new() do
17
+ #print "Running control thread \n"
18
+ begin
19
+ obj = @controlQueue.deq
20
+ end until obj == :FINISH_THREADS
21
+ threadPool.size.times { @dataQueue.enq(:FINISH_WORK) }
22
+ threadPool.waitJoinAll()
23
+ #print "Finished control thread \n"
24
+ end
25
+ end
26
+
27
+ def waitJoin()
28
+ @control.join()
29
+ end
30
+
31
+ def finish()
32
+ @controlQueue.enq(:FINISH_THREADS)
33
+ end
34
+
35
+ end
36
+
37
+ class ThreadPool
38
+
39
+ attr_accessor :size
40
+
41
+ def initialize(size, task, method, inputQueue, resultQueue, bufferQueue, controlQueue)
42
+ @size = size
43
+ @task = task
44
+ @method = method
45
+ @inputQueue = inputQueue
46
+ @resultQueue = resultQueue
47
+ @bufferQueue = bufferQueue
48
+ @controlQueue = controlQueue
49
+ @threadgroup = ThreadsWait.new
50
+ end
51
+
52
+ def start(name)
53
+ @size.times do
54
+ th = Thread.new(@method) do |method|
55
+ #print "Running #{name} th \n"
56
+ begin
57
+ obj = @inputQueue.deq
58
+ #print "#{name} -> #{obj}\n"
59
+ if obj != :FINISH_WORK && obj != :FINISH_THREADS
60
+ if @bufferQueue != nil
61
+ method.call(@bufferQueue, obj)
62
+ @resultQueue.enq(obj)
63
+ else
64
+ method.call(@resultQueue, obj)
65
+ end
66
+ elsif obj == :FINISH_THREADS
67
+ @controlQueue.enq(:FINISH_THREADS)
68
+ end
69
+ end until obj == :FINISH_WORK
70
+ #print "Finished th \n"
71
+ end
72
+ @threadgroup.join_nowait(th)
73
+ end
74
+ end
75
+
76
+ def waitJoinAll()
77
+ @threadgroup.all_waits
78
+ @task.doBuffered(@bufferQueue) if @bufferQueue != nil
79
+ end
80
+
81
+ end
82
+
83
+ class PipeTask
84
+
85
+ def initialize(inputQueue, task, control)
86
+ @inputQueue = inputQueue
87
+ @task = task
88
+ @control = control
89
+ @resultQueue = Queue.new
90
+ @bufferQueue = task.respond_to?(:doBuffered) ? Queue.new : nil
91
+ @nextPipe = if @task.respond_to?(:nextTask) and @task.nextTask != nil
92
+ getNextPipe(@resultQueue, @task.nextTask, Control.new(Queue.new, @resultQueue))
93
+ else nil
94
+ end
95
+ @size = task.size
96
+ @threadPool = ThreadPool.new(@size, @task, @task.method(:doJob), @inputQueue, @resultQueue, @bufferQueue, control.controlQueue)
97
+ end
98
+
99
+ def run()
100
+ @nextPipe.run() if @nextPipe != nil
101
+ @threadPool.start(@task.name)
102
+ @control.start(@threadPool)
103
+ end
104
+
105
+ def waitToEnd()
106
+ #print "JOIN-#{@task.name}\n"
107
+ @control.waitJoin()
108
+ print "END-#{@task.name}\n"
109
+ @nextPipe.finish() if @nextPipe != nil
110
+ @nextPipe.waitToEnd() if @nextPipe != nil
111
+ end
112
+
113
+ def finish()
114
+ @control.finish()
115
+ #@inputQueue.enq(:FINISH_THREADS)
116
+ end
117
+
118
+ protected
119
+
120
+ def getNextPipe(inputQueue, task, control)
121
+ nextPipe = nil
122
+ if task.class == RouterTask
123
+ then nextPipe = RouterPipeTask.new(inputQueue, task, control)
124
+ else nextPipe = PipeTask.new(inputQueue, task, control)
125
+ end
126
+ #nextPipe = PipeTask.new(@resultQueue, @task.nextTask, Control.new(Queue.new, @resultQueue))
127
+ return nextPipe
128
+ end
129
+
130
+ end
131
+
132
+
133
+ class RouterPipeTask < PipeTask
134
+
135
+ def initialize(inputQueue, task, control)
136
+ @inputQueue = inputQueue
137
+ @task = task
138
+ @control = control
139
+ @resultQueue = task.initQueues()
140
+ @bufferQueue = nil
141
+ @nextPipe = _getNextPipes()
142
+ @size = task.size
143
+ @threadPool = ThreadPool.new(@size, @task, @task.method(:doJob), inputQueue, @resultQueue, @bufferQueue, control.controlQueue)
144
+ end
145
+
146
+ def run()
147
+ _RunNextPipes()
148
+ @threadPool.start(@task.name)
149
+ @control.start(@threadPool)
150
+ end
151
+
152
+ def waitToEnd()
153
+ #print "JOIN-#{@task.name}\n"
154
+ @control.waitJoin
155
+ print "END-#{@task.name}\n"
156
+ _WaitToEndNextPipes()
157
+ end
158
+
159
+ private
160
+
161
+ def _getNextPipes()
162
+ nextPipeList = Hash.new(0)
163
+ @task.nextTask.each do | key, task |
164
+ inputQueue = @resultQueue[key]
165
+ controlQueue = Queue.new
166
+ control = Control.new(controlQueue, inputQueue)
167
+ nextPipeList[key] = getNextPipe(inputQueue, task, control)
168
+ end
169
+ return nextPipeList
170
+ end
171
+
172
+ def _RunNextPipes()
173
+ @nextPipe.each do | key, pipe |
174
+ pipe.run() if pipe != nil
175
+ end
176
+ end
177
+
178
+ def _WaitToEndNextPipes()
179
+ @nextPipe.each do | key, pipe |
180
+ pipe.finish() if pipe != nil
181
+ end
182
+ @nextPipe.each do | key, pipe |
183
+ pipe.waitToEnd() if pipe != nil
184
+ end
185
+ end
186
+
187
+ end
188
+
189
+ class Hello
190
+
191
+ attr_accessor :size
192
+
193
+ def initialize
194
+ @size = 20
195
+ end
196
+
197
+ def doJob(aQueue, obj)
198
+ print "#{Thread.current.to_s}-#{obj}\n"
199
+ aQueue.enq("true")
200
+ end
201
+
202
+
203
+ def getItemsNext(numItems)
204
+ return 200
205
+ end
206
+ end
207
+
208
+ #h = Hello.new
209
+ #inputQ = Queue.new
210
+ #wp = PipeTask.new(inputQ, Queue.new, h)
211
+ #wp.run(1000)
212
+ #1000.times { |i| inputQ.enq(i) }
213
+ #wp.waitToEnd()
214
+
215
+ end #module
216
+
@@ -0,0 +1,123 @@
1
+ require 'rio'
2
+ require 'rmail/parser'
3
+ require 'net/smtp'
4
+ require "base64"
5
+ require 'rexml/document'
6
+
7
+ include REXML
8
+
9
+ module RbEAI
10
+
11
+ class PutLogic
12
+
13
+
14
+ def initialize(xmlDoc, task)
15
+ @task = task
16
+ protNode = XPath.first(xmlDoc, "./protocol")
17
+ protocol = protNode.attributes["def"]
18
+ @logic = case protocol
19
+ when "file", "ftp" then PutFileLogic.new(task)
20
+ when "email" then PutEmailLogic.new(protNode, task)
21
+ end
22
+ end
23
+
24
+ def putFile(obj)
25
+ return @logic.putFile(obj)
26
+ end
27
+
28
+ end
29
+
30
+ class PutFileLogic
31
+
32
+ def initialize(task)
33
+ @task = task
34
+ @location = task.location
35
+ end
36
+
37
+ def putFile(obj)
38
+ rio("#{obj}") > rio("#{@location}")
39
+ end
40
+
41
+ end
42
+
43
+
44
+
45
+ # <task name="sendfile" type="Put" rate="0s" pool="1">
46
+ # <next>final</next>
47
+ # <protocol def="mail">
48
+ # <location address="" port=""/>
49
+ # <account name="" pwd=""/>
50
+ # <from></from>
51
+ # <to></to>
52
+ # <cc></cc>
53
+ # <bcc></bcc>
54
+ # <subject></subject>
55
+ # </protocol>
56
+ # </task>
57
+
58
+ class PutEmailLogic
59
+
60
+ def initialize(protNode, task)
61
+ @task = task
62
+ location = XPath.first(protNode, "./location")
63
+ account = XPath.first(protNode, "./account")
64
+ @address = location.attributes["address"]
65
+ @domain = location.attributes["domain"]
66
+ @port = location.attributes["port"]
67
+ @name = account.attributes["name"]
68
+ @pwd = account.attributes["pwd"]
69
+ @from = XPath.first(protNode, "./from/text()")
70
+ @to = XPath.first(protNode, "./to/text()")
71
+ @subject = XPath.first(protNode, "./subject/text()")
72
+ @bodymsg = XPath.first(protNode, "./body/text()")
73
+ @attachment = XPath.first(protNode, "./attachment/text()")
74
+ end
75
+
76
+ def putFile(obj)
77
+ begin
78
+ smtp = if @name != nil
79
+ Net::SMTP.start(@address, @port, @domain, @name, @pwd, :login)
80
+ elsif @domain != nil
81
+ Net::SMTP.start(@address, @port, @domain)
82
+ else
83
+ Net::SMTP.start(@address, @port)
84
+ end
85
+ message = _buildMessage(obj)
86
+ smtp.send_message message, "#{@from}", "#{@to}".split(",").each { |to| to.strip! }
87
+ smtp.finish
88
+ rescue Exception
89
+ puts $!
90
+ end
91
+ end
92
+
93
+ private
94
+
95
+ def _buildMessage(obj)
96
+ message = RMail::Message.new
97
+ header = message.header
98
+ # HEADER ###############################
99
+ header.from= "#{@from}"
100
+ header.to = "#{@to}"
101
+ header.subject= "#{@subject}"
102
+ header.add('Content-Type', 'multipart/mixed')
103
+ # BODY #################################
104
+ abody = RMail::Message.new
105
+ abody.body = "#{@bodymsg}"
106
+ message.add_part(abody)
107
+ # ATTACHMENT ###########################
108
+ part= RMail::Message.new
109
+ headerpart = part.header
110
+ headerpart.add('Content-Type', 'text/plain', nil, 'name' => "#{@attachment}" )
111
+ headerpart.add('Content-Transfer-Encoding', 'base64')
112
+ headerpart.add('Content-Description', "#{@attachment}" )
113
+ headerpart.add('Content-Disposition', 'attachment', nil, 'filename' => "#{@attachment}" )
114
+ aux = ""
115
+ rio("#{obj}") > aux
116
+ part.body = Base64.encode64(aux)
117
+ message.add_part(part)
118
+ return message
119
+ end
120
+
121
+ end
122
+
123
+ end #module
@@ -0,0 +1,155 @@
1
+ require 'rio'
2
+ require 'rexml/document'
3
+ require 'rexml/sax2listener'
4
+ require 'rexml/parsers/sax2parser'
5
+
6
+ include REXML
7
+
8
+ module RbEAI
9
+
10
+ class RouterLogic
11
+
12
+ attr_accessor :destinations, :default
13
+
14
+ def initialize(xmlDoc)
15
+ @destinations = []
16
+ XPath.each(xmlDoc, "./next/goto[count(when) > 0]") do |el|
17
+ taskname = el.attributes["task"]
18
+ @destinations << [taskname, LogicFilter.new(el)]
19
+ end
20
+ XPath.each(xmlDoc, "./next/goto[count(when) = 0]") do |el|
21
+ taskname = el.attributes["task"]
22
+ @destinations << [taskname, LogicFilter.new(el)]
23
+ end
24
+ end
25
+
26
+ def enroute(file)
27
+ targettask = nil
28
+
29
+ @destinations.each do | item |
30
+ taskname = item[0]
31
+ filter = item[1]
32
+ if filter.match(file)
33
+ targettask = taskname
34
+ break
35
+ end
36
+ end
37
+
38
+ return targettask
39
+ end
40
+
41
+ end
42
+
43
+ class LogicFilter
44
+
45
+ def initialize(xmlDoc)
46
+ @parsers = []
47
+ XPath.each(xmlDoc, "./when") do |el|
48
+ @parsers << _getParser(el)
49
+ end
50
+ end
51
+
52
+ def match(file)
53
+ result = true
54
+ @parsers.each do | parser |
55
+ begin
56
+ if parser.match(file)
57
+ result = true
58
+ break
59
+ else
60
+ result = false
61
+ end
62
+ rescue Exception
63
+ result = false
64
+ end
65
+ end
66
+ return result
67
+ end
68
+
69
+ private
70
+
71
+ def _getParser(node)
72
+ filter = node.attributes["filter"]
73
+ re = Regexp.new('(re|xpath|sax|name):(.+)')
74
+ mr = re.match(filter)
75
+ case mr[1]
76
+ when 're' then RexParser.new(node, mr[2])
77
+ when 'xpath' then XPazParser.new(node, mr[2])
78
+ when 'sax' then SazParser.new(node, mr[2])
79
+ when 'name' then NameParser.new(node, mr[2])
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ class RexParser
86
+
87
+ def initialize(node, expression)
88
+ @resultList = node.elements["."].text
89
+ @regexp = Regexp.new(expression)
90
+ end
91
+
92
+ def match(file)
93
+ ario = rio(file)
94
+ ario > aString
95
+ mr = @regexp.match(aString)
96
+ return @resultList.include?(mr[0])
97
+ end
98
+
99
+ end
100
+
101
+ class NameParser
102
+
103
+ def initialize(node, expression)
104
+ @regexp = Regexp.new(expression)
105
+ end
106
+
107
+ def match(file)
108
+ filename = File.basename(file)
109
+ return @regexp.match(filename)
110
+ end
111
+
112
+ end
113
+
114
+ class XPazParser
115
+
116
+ def initialize(node, expression)
117
+ @resultList = node.elements["."].text
118
+ @xpath = expression
119
+ end
120
+
121
+ def match(file)
122
+ ario = rio("#{file}")
123
+ xmlString = ario.contents
124
+ xmldoc = REXML::Document.new(xmlString)
125
+ result = false
126
+ XPath.each(xmldoc, "#{@xpath}") do |el|
127
+ result = @resultList.include?(el.text)
128
+ break if result
129
+ end
130
+ return result
131
+ end
132
+
133
+ end
134
+
135
+ class SazParser
136
+
137
+ def initialize(node, expression)
138
+ @resultList = node.elements["."].text
139
+ @node = expression
140
+ end
141
+
142
+ def match(file)
143
+ result = "nil"
144
+ f = File.new(file)
145
+ parser = Parsers::SAX2Parser.new( f )
146
+ parser.listen( :characters , @node) do |text|
147
+ result = text if @resultList.include?(text)
148
+ end
149
+ parser.parse
150
+ return @resultList.include?(result)
151
+ end
152
+
153
+ end
154
+
155
+ end #module