root/t2-web/trunk/bin/t2_webapp.rb @ 149

Revision 149, 7.4 KB (checked in by kostas.karasavvas@…, 3 years ago)

Removed our html_sanitise in favour of CGI::unescapeHTML

Line 
1#!/usr/bin/env ruby
2
3require 'rubygems' if RUBY_VERSION < '1.9'
4require 'sinatra'
5require 'haml'
6require 'rest-open-uri'
7require 'rest-client'
8require 't2-server'
9require 'myexperiment-rest'
10require 'cgi'
11#require "web-t2" TODO: move whole of WebT2App in lib
12
13
14class WebT2App < Sinatra::Base
15
16  WEB_APP_NAME = "t2web"
17  # TODO: const for TMP_UPLOAD_PATH ? - need to read from config file?
18
19  set :port, 9494
20  set :views, File.dirname(__FILE__) + '/../views'
21  set :public, File.dirname(__FILE__) + '/../public'
22
23  # can be used from routes and views (haml)
24  helpers do
25
26    # Used before we sent the workflow inputs to the taverna server. Just converts
27    # double quotations to single ones. That is because the t2-server library
28    # is confused with double quotes and apparently it is not easy to fix.
29    def t2_library_sanitize(string)
30      ex = string.gsub('"', "'")
31    end
32
33    #
34    # Deletes last new line of file if it exists! It is needed for t2 workflows that
35    # do not sanitize properly, i.e. via a user-provided beanshell script
36    #
37    def chomp_last_newline(file)
38
39      if File.file?(file) and File.size(file) > 1
40        f = open(file, "rb+")
41        f.seek(-1, File::SEEK_END)
42        f.truncate(File.size(file) - 1) if f.read(1) == "\n"
43        f.close
44      end
45
46    end
47   
48    # Construct the complete or partial URL as MyExperimentRest lib expects it
49    # TODO: Maybe update myExperimentRest lib to accept only wid and wkf_version
50    # Minor for now
51    def get_url_from_wid(wid, wkf_version)
52      if wkf_version == "default"
53        "/workflows/#{wid}"
54      else
55        "/workflows/#{wid}?version=#{wkf_version}"
56      end
57    end
58
59
60    # Generates the contents of the header frame
61    def generate_header_frame(my_exp_wkf)
62      "<html>" <<
63         "<head><link href='/css/results_header.css' rel='stylesheet'/></head>" <<
64         "<body><table class='header'>" <<
65           "<tr><td class='header'>Workflow: #{my_exp_wkf.title}</td></tr>" <<
66         "</table></body>" <<
67      "</html>"
68    end
69
70
71    # Generates the contents of the data-navigation frame
72    def generate_data_navigation_frame(my_exp_wkf, uuid, wid, wkf_version, t2_server, finished_execution)
73
74      data_navigation_frame = "<html><head><link href='/css/results_navigation.css' rel='stylesheet'/></head><body><table>"
75      if my_exp_wkf.outputs.size >=1
76        my_exp_wkf.outputs.each do |output|
77          data_navigation_frame << "<tr>"
78          if finished_execution
79            data_navigation_frame << "<td><a href='javascript:void(0);' onclick='parent.getSampleOutput(\\\"#{t2_server}\\\", \\\"#{uuid}\\\", " <<
80                                     "\\\"#{output.name}\\\", \\\"#{wid}\\\", \\\"#{wkf_version}\\\");'>#{output.name}</a></td><td></td>"
81          else
82            data_navigation_frame << "<td>#{output.name}</td><td><img src='/images/snake_transparent.gif' alt='Loading Content...'></td>"
83          end
84          data_navigation_frame << "</tr>"
85        end
86      end
87      data_navigation_frame << "</table></body></html>"
88    end
89
90
91    # Check type of data and generate appropriate html for that result!
92    def generate_html_result(data)
93      html = ""
94      #p data
95      if data.instance_of? Array
96        html = data.flatten.join('<br>')
97      elsif data.instance_of? String
98        html = data.gsub(/[\n]/, '<br>')
99      else
100        html = data
101      end
102      html
103    end
104
105  end
106
107
108
109  # Create the Web UI for that workflow
110  get "/#{WEB_APP_NAME}/workflow/:wid" do
111
112    # Get http request's parameters
113    # TODO: consider adding the following to a session
114    @wid = params[:wid]
115    @wkf_version = params[:wkf_version] || "default"
116    @t2_server = params[:server] || "http://test.mybiobank.org/taverna-server"
117
118    # Get myExperiment workflow object
119    @my_exp_wkf = MyExperimentREST::Workflows.new.read(get_url_from_wid(@wid, @wkf_version))
120
121    haml :form
122
123  end
124
125
126  # Enact the workflow with the submitted parameters and returns
127  # result display (involves checking run's status and getting results)
128  post "/#{WEB_APP_NAME}/enact" do
129    #p params
130
131    # Get http POST request's parameters
132    # TODO: consider adding the following to a session
133    @wid = params[:wid]
134    @wkf_version = params[:wkf_version]
135    @t2_server = params[:server]
136
137    # Get myExperiment workflow object (TODO: session!)
138    @my_exp_wkf = MyExperimentREST::Workflows.new.read(get_url_from_wid(@wid, @wkf_version))
139
140    # use the uri reference to download the workflow locally
141    wkf_file = URI.parse(@my_exp_wkf.xml_uri)
142    wkf = wkf_file.read
143
144    # create run
145    begin
146      run = T2Server::Run.create(@t2_server, wkf)
147    rescue T2Server::T2ServerError => e
148      return "404 Not Found: run could not be instantiated!"
149    end
150
151    # Get the run as instance member to make visible in views
152    @run_uuid = run.uuid
153
154    # Set workflow inputs
155    @my_exp_wkf.inputs.each do |input|
156      if params[:"upload-checkbox-#{input.name}"] == "yes"
157        filename = params[:"#{input.name}-file"]
158        tmp_filename = "/tmp/#{WEB_APP_NAME}/#{filename}"
159
160        # make sure that the file is uploaded completely, i.e. all it's
161        # connections are closed
162        #while `lsof -c cp | grep /tmp/#{WEB_APP_NAME}/#{filename}` != ""
163        #  sleep 1
164        #end
165       
166        chomp_last_newline(tmp_filename)
167        run.upload_input_file(input.name, tmp_filename)
168      else
169        run.set_input(input.name, t2_library_sanitize(params["#{input.name}-input".to_sym]) )
170      end
171    end
172
173    # start run and wait until it is finished
174    run.start
175
176    haml :results
177  end
178
179
180
181  # Proxy operation (to bypass cross-domain AJAX) to get T2 run's status
182  get '/runs/:uuid/status' do
183    uuid = params[:uuid]
184    t2_server = params[:server]
185
186    response = RestClient.get t2_server + "/rest/runs/" + uuid + "/status", :content_type => "text/plain"
187
188    response.to_str
189  end
190
191
192
193  # Get results for specified run and output - display it in data-display div
194  # Cross-domain AJAX to get result from T2
195  get "/#{WEB_APP_NAME}/run/:uuid/output/:out" do
196
197    # Get http request's parameters
198    # TODO: consider adding the following to a session
199    @wid = params[:wid]
200    @wkf_version = params[:wkf_version]
201
202    # Get myExperiment workflow object
203    # TODO: with sessions that would be remembered
204    @my_exp_wkf = MyExperimentREST::Workflows.new.read(get_url_from_wid(@wid, @wkf_version))
205
206    @run_uuid = params[:uuid]
207    @t2_server = params[:server]
208    t2_output = params[:out]
209
210    # Get t2 server and then the run using uuid
211    server = T2Server::Server.connect(@t2_server)
212    run = server.run(@run_uuid)
213
214    # Get output from t2 server
215    # TODO: that gets the whole output.. request client lib to support partial
216    # download! -- refs could then be used to download the full results!
217    begin
218      data_lists = run.get_output(t2_output, false)
219    rescue Exception => e
220      data_lists = run.get_output("#{t2_output}.error", false)
221    end
222   
223    # that should be a sample of the results -- not the complete results!
224    data = generate_html_result(data_lists)
225
226    data
227  end
228
229
230  # Used from input's upload-form to upload files without refresh (actually
231  # a hidden iframe is refreshed).
232  post "/#{WEB_APP_NAME}/upload" do
233    filename = params[:file][:filename]
234    tempfile = params[:file][:tempfile]
235    FileUtils.mkdir("/tmp/#{WEB_APP_NAME}") unless File.exist?("/tmp/#{WEB_APP_NAME}")
236    FileUtils.copy(tempfile.path, "/tmp/#{WEB_APP_NAME}/#{filename}")
237    "Successfully copied #{filename}!!"
238  end
239
240end
241
242
243# Start Web App
244WebT2App.run!
Note: See TracBrowser for help on using the browser.