Further mockups.
[ecp_lsfp_soaps.git] / server.rb
blob83bd9635d5741b432f5f44d88990a7ad47d5d5d7
1 #!/usr/bin/env ruby
3 require 'rubygems'
4 require "bundler/setup"
5 require 'active_support/all'
6 require 'sqlite3'
8 require 'yaml'
9 require 'simplews'
10 require 'pp'
11 require 'uri'
12 require 'json'
14 require 'nokogiri'
16 class LsfProxySoapServer < SimpleWS
18   class NonExistentCourseError < ::SOAP::Error; end 
19   class NoCourseUrlError < ::SOAP::Error; end 
21   DB_FILE = 'notifications.db'
22   DB_TABLE_NAME = 'notifications'
24   def initialize
25     doc = YAML::load_stream(File.open(File.expand_path("../config.yml", __FILE__)))
26     @config_soap_server = doc[0] 
27     url= URI::parse(@config_soap_server['soap']['url'])
28     super(@config_soap_server['soap']['name'],
29           @config_soap_server['soap']['info'],
30           url.host, url.port)
32     # initializing logger
33     logfilepath= @config_soap_server['logger']['filename']
34     directory_check(File.dirname(logfilepath),"Logfile", false)
35     if not absolute_path?(logfilepath)
36       logfilepath= File.expand_path("../"+logfilepath, __FILE__)
37     end
38     logfile = File.open(logfilepath, File::WRONLY|File::APPEND|File::CREAT, 0600)
39     logfile.sync= true
40     @log = Logger.new(logfile,5,100.kilobytes)
41     @log.formatter = proc do |severity, datetime, progname, msg|
42       "[%s%6s] %s\n" % [datetime.to_s(:db), severity, msg.dump]
43     end
44     @log.level = eval @config_soap_server['logger']['level']
45     
46     # notifications database
47     if File.exist? DB_FILE
48       @db = SQLite3::Database.open DB_FILE
49     else
50       @db = SQLite3::Database.new DB_FILE
51     end
52     @db.execute "CREATE TABLE IF NOT EXISTS #{DB_TABLE_NAME}(Id INTEGER PRIMARY KEY, 
53                 obj_name TEXT, obj_id TEXT, proto_id TEXT)"
55     trap('INT'){
56       @log.info("Stopping server..")
57       self.shutdown
58     }
59   
60     self.serve :lsfPushData, %w(objectName objectId protocolId), 
61           :objectName => :string,
62           :objectId => :string,
63           :protocolId => :string,
64           :return => :string
65     self.serve :listNotifications
66     self.serve :fetchNotification
67     self.serve :deleteNotification
68     self.serve :getTime
69     self.serve :ping
70     self.serve :getDataXML, %w(xmlParams), :xmlParams => :string, :return => :string
71     self.serve :getCourseUrl, %w(lectureId), :lectureId => :string, :return => :string
72   
73     wsdl_filename_path= @config_soap_server['soap']['wsdl_filename']
74     directory_check(File.dirname(wsdl_filename_path),"WSDL-File")
75     if not absolute_path?(wsdl_filename_path)
76       wsdl_filename_path= File.expand_path("../" + wsdl_filename_path, __FILE__)
77     end
78     @log.info "WSDL path: " + wsdl_filename_path
79     self.wsdl wsdl_filename_path
81     File.open("server.pid", "w") do |f|
82       f.puts Process.pid.to_s
83     end
84     @log.info "LSF-SOAP-Server started (PID: #{Process.pid})"
85   end
87   def lsfPushData(obj_name, obj_id, proto_id)
88       puts "#{obj_name}, #{obj_id}. #{proto_id}"
89       @db.execute "INSERT INTO #{DB_TABLE_NAME}(obj_name,obj_id,proto_id) VALUES ('#{obj_name}', '#{obj_id}', '#{proto_id}')"
90       @log.info "new notification: object_name:#{obj_name}, object_id:#{obj_id}, protocol_id:#{proto_id}"
91   end
93   # Course URL
94   def getCourseUrl(lectureId)
95     result= {
96             :url => "http://freeit.de/documents/ecsa/index.html",
97             :online_status => true
98          }
99     case lectureId
100       when "123456788"
101         text= "There is no course available with the lecture-id: #{lectureId}"
102         @log.error text
103         raise NonExistentCourseError, text, []
104       when "123456789"
105         text= "There is no course URL available representing lecture-id: #{lectureId}"
106         @log.error text
107         raise NoCourseUrlError, text, []
108       else
109         @log.info "#getCourseUrl: lectureId=#{lectureId}  url=#{result[:url]}  online_status=#{result[:online_status]}"
110         result.to_json
111     end
112   end
114   # LSF Mockup
115   def getDataXML(xml_params)
116     xml_doc= Nokogiri::XML(xml_params)
117     case xml_doc.css('SOAPDataService > general > object').text
118       when @config_soap_server['lsf']['db_interface']['lecture']
119         lsf_mock_lecture(xml_doc.css('SOAPDataService > condition > LectureID').text)
120       when @config_soap_server['lsf']['db_interface']['enrollments']
121         lsf_mock_enrollments(xml_doc.css('SOAPDataService > condition > LectureID').text)
122       when @config_soap_server['lsf']['db_interface']['course_catalog']
123         lsf_mock_course_catalog(xml_doc.css('SOAPDataService > condition > TermID').text)
124       #when @config_soap_server['lsf']['db_interface']['institutions']
125     end
126   end 
129   def listNotifications
130     rows= @db.execute("select * from notifications order by id ASC")
131     if rows.blank?
132       nil
133     else
134       rows.each do |row|
135         puts row.values_at(1,2,3).join(",")
136       end
137     end
138   end
140   def fetchNotification
141     row= @db.execute("select * from notifications order by id ASC limit 1")[0]
142     if row.blank?
143       nil
144     else
145       id= row[0]
146       @db.execute("delete from notifications where id = #{id}")
147       row.values_at(1,2,3).join(",")
148     end
149   end
151   def deleteNotification
152     row= @db.execute("select * from notifications order by id ASC limit 1")[0]
153     if row.blank?
154       nil
155     else
156       @db.execute("delete from notifications where id = #{row[0]}")
157     end
158   end
160   def getTime
161     Time.now
162   end
164   def ping
165     return true
166   end
168 private
170   # Test if pathname represent an absolute path or not.
171   def absolute_path?(pathname)
172     (pathname.slice(0,1)== "/") ? true : false
173   end
175   # Raise exeption when directory is not accessable/available
176   def directory_check(pathname, context=nil, logging=true)
177     if not File.directory?(pathname)
178       if context
179         err_text= "#{context}: Directory #{pathname} not accessable/available."
180       else
181         err_text= "Directory #{pathname} not accessable/available."
182       end
183       @log.fatal(err_text) if logging
184       raise Exception, err_text
185     end
186     true
187   end
189   def lsf_mock_lecture(lecture_id)
190     case lecture_id
191       when "132742"
192         IO.read('test_lsf_xml_files/lectures_132742.xml')
193       when "132743"
194         IO.read('test_lsf_xml_files/lectures_132743.xml')
195       when "132634"
196         IO.read('test_lsf_xml_files/lectures_132634_multiple_dates_and_groups.xml')
197       when "132635"
198         IO.read('test_lsf_xml_files/lectures_132635_multiple_dates_no_groups.xml')
199       when "35246"
200         IO.read('test_lsf_xml_files/lectures_35246_hsz.xml')
201       when "26703"
202         IO.read('test_lsf_xml_files/lectures_26703_hsz.xml')
203       when "empty"
204         IO.read('test_lsf_xml_files/lectures_empty.xml')
205       else
206         "not available"
207     end
208   end
210   def lsf_mock_enrollments(lecture_id)
211     case lecture_id
212       when "132742"
213         IO.read('test_lsf_xml_files/enrollments_132742.xml')
214       when "132743"
215         IO.read('test_lsf_xml_files/enrollments_132743.xml')
216       when "132634"
217         IO.read('test_lsf_xml_files/enrollments_132634.xml')
218       when "132635"
219         IO.read('test_lsf_xml_files/enrollments_132634.xml')
220       else
221         "not available"
222     end
223   end
225   def lsf_mock_course_catalog(term_id)
226     case term_id
227       when "20131"
228         IO.read('test_lsf_xml_files/course_catalog_20131.xml')
229       when "20132"
230         IO.read('test_lsf_xml_files/course_catalog_20132.xml')
231       when "-1"
232         IO.read('test_lsf_xml_files/course_catalog_20131.xml')
233       when "empty"
234         IO.read('test_lsf_xml_files/course_catalog_empty.xml')
235       else
236         "not available"
237     end
238   end
242 begin
243   LsfProxySoapServer.new.start
244 rescue SQLite3::Exception => e 
245   puts "Error in accessing database file @{NOTIFICATIONS_DB}"
246   puts e
247 rescue Exception => e
248   puts e
249   puts e.backtrace
250 ensure
251   db.close if $db