4 require "bundler/setup"
5 require 'active_support/all'
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'
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'],
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__)
38 logfile = File.open(logfilepath, File::WRONLY|File::APPEND|File::CREAT, 0600)
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]
44 @log.level = eval @config_soap_server['logger']['level']
46 # notifications database
47 if File.exist? DB_FILE
48 @db = SQLite3::Database.open DB_FILE
50 @db = SQLite3::Database.new DB_FILE
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)"
56 @log.info("Stopping server..")
60 self.serve :lsfPushData, %w(objectName objectId protocolId),
61 :objectName => :string,
63 :protocolId => :string,
65 self.serve :listNotifications
66 self.serve :fetchNotification
67 self.serve :deleteNotification
70 self.serve :getDataXML, %w(xmlParams), :xmlParams => :string, :return => :string
71 self.serve :getCourseUrl, %w(lectureId), :lectureId => :string, :return => :string
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__)
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
84 @log.info "LSF-SOAP-Server started (PID: #{Process.pid})"
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}"
94 def getCourseUrl(lectureId)
96 :url => "http://freeit.de/documents/ecsa/index.html",
97 :online_status => true
101 text= "There is no course available with the lecture-id: #{lectureId}"
103 raise NonExistentCourseError, text, []
105 text= "There is no course URL available representing lecture-id: #{lectureId}"
107 raise NoCourseUrlError, text, []
109 @log.info "#getCourseUrl: lectureId=#{lectureId} url=#{result[:url]} online_status=#{result[:online_status]}"
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']
129 def listNotifications
130 rows= @db.execute("select * from notifications order by id ASC")
135 puts row.values_at(1,2,3).join(",")
140 def fetchNotification
141 row= @db.execute("select * from notifications order by id ASC limit 1")[0]
146 @db.execute("delete from notifications where id = #{id}")
147 row.values_at(1,2,3).join(",")
151 def deleteNotification
152 row= @db.execute("select * from notifications order by id ASC limit 1")[0]
156 @db.execute("delete from notifications where id = #{row[0]}")
170 # Test if pathname represent an absolute path or not.
171 def absolute_path?(pathname)
172 (pathname.slice(0,1)== "/") ? true : false
175 # Raise exeption when directory is not accessable/available
176 def directory_check(pathname, context=nil, logging=true)
177 if not File.directory?(pathname)
179 err_text= "#{context}: Directory #{pathname} not accessable/available."
181 err_text= "Directory #{pathname} not accessable/available."
183 @log.fatal(err_text) if logging
184 raise Exception, err_text
189 def lsf_mock_lecture(lecture_id)
192 IO.read('test_lsf_xml_files/lectures_132742.xml')
194 IO.read('test_lsf_xml_files/lectures_132743.xml')
196 IO.read('test_lsf_xml_files/lectures_132634_multiple_dates_and_groups.xml')
198 IO.read('test_lsf_xml_files/lectures_132635_multiple_dates_no_groups.xml')
200 IO.read('test_lsf_xml_files/lectures_35246_hsz.xml')
202 IO.read('test_lsf_xml_files/lectures_26703_hsz.xml')
204 IO.read('test_lsf_xml_files/lectures_empty.xml')
210 def lsf_mock_enrollments(lecture_id)
213 IO.read('test_lsf_xml_files/enrollments_132742.xml')
215 IO.read('test_lsf_xml_files/enrollments_132743.xml')
217 IO.read('test_lsf_xml_files/enrollments_132634.xml')
219 IO.read('test_lsf_xml_files/enrollments_132634.xml')
225 def lsf_mock_course_catalog(term_id)
228 IO.read('test_lsf_xml_files/course_catalog_20131.xml')
230 IO.read('test_lsf_xml_files/course_catalog_20132.xml')
232 IO.read('test_lsf_xml_files/course_catalog_20131.xml')
234 IO.read('test_lsf_xml_files/course_catalog_empty.xml')
243 LsfProxySoapServer.new.start
244 rescue SQLite3::Exception => e
245 puts "Error in accessing database file @{NOTIFICATIONS_DB}"
247 rescue Exception => e