taverna-player 0.1.0

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 (192) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +18 -0
  3. data/LICENCE.rdoc +29 -0
  4. data/README.rdoc +663 -0
  5. data/Rakefile +65 -0
  6. data/app/assets/javascripts/taverna_player/application.js +14 -0
  7. data/app/assets/javascripts/taverna_player/runs.js +42 -0
  8. data/app/assets/stylesheets/scaffold.css +56 -0
  9. data/app/assets/stylesheets/taverna_player/application.css +13 -0
  10. data/app/assets/stylesheets/taverna_player/coderay.css +120 -0
  11. data/app/controllers/taverna_player/application_controller.rb +16 -0
  12. data/app/controllers/taverna_player/runs_controller.rb +18 -0
  13. data/app/controllers/taverna_player/service_credentials_controller.rb +18 -0
  14. data/app/helpers/taverna_player/application_helper.rb +55 -0
  15. data/app/helpers/taverna_player/runs_helper.rb +84 -0
  16. data/app/models/taverna_player/interaction.rb +25 -0
  17. data/app/models/taverna_player/run.rb +117 -0
  18. data/app/models/taverna_player/run_port.rb +148 -0
  19. data/app/models/taverna_player/service_credential.rb +56 -0
  20. data/app/views/layouts/taverna_player/embedded.html.erb +27 -0
  21. data/app/views/taverna_player/runs/_button.html.erb +19 -0
  22. data/app/views/taverna_player/runs/_info.html.erb +56 -0
  23. data/app/views/taverna_player/runs/_info.json.jbuilder +2 -0
  24. data/app/views/taverna_player/runs/_inputs.html.erb +34 -0
  25. data/app/views/taverna_player/runs/_inputs.json.jbuilder +8 -0
  26. data/app/views/taverna_player/runs/_interaction.html.erb +68 -0
  27. data/app/views/taverna_player/runs/_outputs.html.erb +41 -0
  28. data/app/views/taverna_player/runs/_poll.html.erb +27 -0
  29. data/app/views/taverna_player/runs/create.json.jbuilder +3 -0
  30. data/app/views/taverna_player/runs/embedded/_button.html.erb +19 -0
  31. data/app/views/taverna_player/runs/embedded/_info.html.erb +25 -0
  32. data/app/views/taverna_player/runs/embedded/_inputs.html.erb +32 -0
  33. data/app/views/taverna_player/runs/embedded/_outputs.html.erb +32 -0
  34. data/app/views/taverna_player/runs/embedded/new.html.erb +58 -0
  35. data/app/views/taverna_player/runs/embedded/show.html.erb +39 -0
  36. data/app/views/taverna_player/runs/embedded/show.js.erb +35 -0
  37. data/app/views/taverna_player/runs/index.html.erb +40 -0
  38. data/app/views/taverna_player/runs/index.json.jbuilder +1 -0
  39. data/app/views/taverna_player/runs/new.html.erb +56 -0
  40. data/app/views/taverna_player/runs/new.json.jbuilder +1 -0
  41. data/app/views/taverna_player/runs/show.html.erb +29 -0
  42. data/app/views/taverna_player/runs/show.js.erb +25 -0
  43. data/app/views/taverna_player/runs/show.json.jbuilder +25 -0
  44. data/app/views/taverna_player/service_credentials/_form.html.erb +53 -0
  45. data/app/views/taverna_player/service_credentials/edit.html.erb +18 -0
  46. data/app/views/taverna_player/service_credentials/index.html.erb +41 -0
  47. data/app/views/taverna_player/service_credentials/new.html.erb +17 -0
  48. data/app/views/taverna_player/service_credentials/show.html.erb +36 -0
  49. data/config/routes.rb +34 -0
  50. data/db/migrate/20130313105546_create_taverna_player_runs.rb +16 -0
  51. data/db/migrate/20130315163019_create_taverna_player_run_ports.rb +15 -0
  52. data/db/migrate/20130318170744_add_attachment_file_to_taverna_player_run_ports.rb +6 -0
  53. data/db/migrate/20130319183634_create_delayed_jobs.rb +22 -0
  54. data/db/migrate/20130320102600_add_status_message_to_taverna_player_runs.rb +5 -0
  55. data/db/migrate/20130321100110_add_depth_and_metadata_to_taverna_player_run_ports.rb +6 -0
  56. data/db/migrate/20130704095504_add_attachment_results_to_taverna_player_runs.rb +5 -0
  57. data/db/migrate/20130705142704_add_embedded_to_taverna_player_runs.rb +5 -0
  58. data/db/migrate/20130714140911_create_taverna_player_interactions.rb +13 -0
  59. data/db/migrate/20130717083653_add_proxy_to_taverna_player_runs.rb +6 -0
  60. data/db/migrate/20130717155415_add_stop_to_taverna_player_runs.rb +5 -0
  61. data/db/migrate/20130811152840_add_attachment_log_to_taverna_player_runs.rb +5 -0
  62. data/db/migrate/20130811211725_change_taverna_player_runs_state_column.rb +5 -0
  63. data/db/migrate/20130812155839_add_name_to_taverna_player_runs.rb +5 -0
  64. data/db/migrate/20130918135348_create_taverna_player_service_credentials.rb +15 -0
  65. data/db/migrate/20130919154200_add_displayed_to_taverna_player_interactions.rb +5 -0
  66. data/db/migrate/20131007153209_add_job_ref_to_taverna_player_runs.rb +13 -0
  67. data/db/migrate/20131010094537_add_reply_caching_to_taverna_player_interactions.rb +19 -0
  68. data/db/migrate/20131017141514_add_failure_message_to_taverna_player_run.rb +5 -0
  69. data/db/migrate/20131018152940_add_serial_number_to_taverna_player_interactions.rb +5 -0
  70. data/db/migrate/20131018160715_add_parent_run_id_to_taverna_player_runs.rb +5 -0
  71. data/db/migrate/20131102113933_add_page_uri_to_taverna_player_interaction.rb +5 -0
  72. data/db/migrate/20131105115218_remove_proxy_from_taverna_player_runs.rb +11 -0
  73. data/db/migrate/20131105141934_change_taverna_player_interactions_output_value_column_name.rb +5 -0
  74. data/db/migrate/20131112165520_add_user_to_taverna_player_run.rb +5 -0
  75. data/lib/generators/taverna_player/callbacks_generator.rb +25 -0
  76. data/lib/generators/taverna_player/controllers_generator.rb +30 -0
  77. data/lib/generators/taverna_player/install_generator.rb +30 -0
  78. data/lib/generators/taverna_player/job_generator.rb +26 -0
  79. data/lib/generators/taverna_player/models_generator.rb +27 -0
  80. data/lib/generators/taverna_player/renderers_generator.rb +26 -0
  81. data/lib/generators/taverna_player/views_generator.rb +27 -0
  82. data/lib/generators/templates/ReadMe.txt +118 -0
  83. data/lib/generators/templates/callbacks/render_callbacks.rb +56 -0
  84. data/lib/generators/templates/callbacks/worker_callbacks.rb +31 -0
  85. data/lib/generators/templates/controllers/runs_controller.rb +20 -0
  86. data/lib/generators/templates/controllers/service_credentials_controller.rb +20 -0
  87. data/lib/generators/templates/initializer.rb +154 -0
  88. data/lib/generators/templates/models/run.rb +20 -0
  89. data/lib/tasks/delete-cancelled-runs.rake +26 -0
  90. data/lib/tasks/delete-old-embedded-runs.rake +26 -0
  91. data/lib/taverna-player.rb +139 -0
  92. data/lib/taverna_player/concerns/controllers/runs_controller.rb +281 -0
  93. data/lib/taverna_player/concerns/controllers/service_credentials_controller.rb +89 -0
  94. data/lib/taverna_player/concerns/models/run.rb +205 -0
  95. data/lib/taverna_player/engine.rb +23 -0
  96. data/lib/taverna_player/model_proxy.rb +51 -0
  97. data/lib/taverna_player/output_renderer.rb +96 -0
  98. data/lib/taverna_player/render_callbacks.rb +41 -0
  99. data/lib/taverna_player/version.rb +15 -0
  100. data/lib/taverna_player/worker.rb +325 -0
  101. data/script/delayed_job +5 -0
  102. data/script/rails +8 -0
  103. data/taverna_player.gemspec +46 -0
  104. data/test/dummy/Rakefile +7 -0
  105. data/test/dummy/app/assets/javascripts/application.js +16 -0
  106. data/test/dummy/app/assets/stylesheets/application.css +14 -0
  107. data/test/dummy/app/controllers/application_controller.rb +15 -0
  108. data/test/dummy/app/controllers/home_controller.rb +16 -0
  109. data/test/dummy/app/controllers/taverna_player/runs_controller.rb +25 -0
  110. data/test/dummy/app/controllers/taverna_player/service_credentials_controller.rb +25 -0
  111. data/test/dummy/app/controllers/workflows_controller.rb +17 -0
  112. data/test/dummy/app/models/user.rb +15 -0
  113. data/test/dummy/app/models/workflow.rb +32 -0
  114. data/test/dummy/app/views/home/index.html.erb +18 -0
  115. data/test/dummy/app/views/layouts/application.html.erb +43 -0
  116. data/test/dummy/app/views/workflows/index.html.erb +35 -0
  117. data/test/dummy/config.ru +4 -0
  118. data/test/dummy/config/application.rb +58 -0
  119. data/test/dummy/config/boot.rb +10 -0
  120. data/test/dummy/config/database.yml +25 -0
  121. data/test/dummy/config/environment.rb +5 -0
  122. data/test/dummy/config/environments/development.rb +37 -0
  123. data/test/dummy/config/environments/production.rb +67 -0
  124. data/test/dummy/config/environments/test.rb +37 -0
  125. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  126. data/test/dummy/config/initializers/inflections.rb +15 -0
  127. data/test/dummy/config/initializers/mime_types.rb +5 -0
  128. data/test/dummy/config/initializers/secret_token.rb +7 -0
  129. data/test/dummy/config/initializers/session_store.rb +8 -0
  130. data/test/dummy/config/initializers/taverna_player.example.rb +40 -0
  131. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  132. data/test/dummy/config/locales/en.yml +5 -0
  133. data/test/dummy/config/routes.rb +22 -0
  134. data/test/dummy/db/migrate/20130314103555_create_workflows.rb +12 -0
  135. data/test/dummy/db/migrate/20130318141557_create_taverna_player_runs.taverna_player.rb +17 -0
  136. data/test/dummy/db/migrate/20130318141558_create_taverna_player_run_ports.taverna_player.rb +16 -0
  137. data/test/dummy/db/migrate/20130318173013_add_attachment_file_to_taverna_player_run_ports.taverna_player.rb +7 -0
  138. data/test/dummy/db/migrate/20130319183816_create_delayed_jobs.taverna_player.rb +23 -0
  139. data/test/dummy/db/migrate/20130320102635_add_status_message_to_taverna_player_runs.taverna_player.rb +6 -0
  140. data/test/dummy/db/migrate/20130321161859_add_depth_and_metadata_to_taverna_player_run_ports.taverna_player.rb +7 -0
  141. data/test/dummy/db/migrate/20130704100146_add_attachment_results_to_taverna_player_runs.taverna_player.rb +6 -0
  142. data/test/dummy/db/migrate/20130705142816_add_embedded_to_taverna_player_runs.taverna_player.rb +6 -0
  143. data/test/dummy/db/migrate/20130714142144_create_taverna_player_interactions.taverna_player.rb +14 -0
  144. data/test/dummy/db/migrate/20130717084809_add_proxy_to_taverna_player_runs.taverna_player.rb +7 -0
  145. data/test/dummy/db/migrate/20130718102707_add_stop_to_taverna_player_runs.taverna_player.rb +6 -0
  146. data/test/dummy/db/migrate/20130811204449_add_attachment_log_to_taverna_player_runs.taverna_player.rb +6 -0
  147. data/test/dummy/db/migrate/20130811212709_change_taverna_player_runs_state_column.taverna_player.rb +6 -0
  148. data/test/dummy/db/migrate/20130812161152_add_name_to_taverna_player_runs.taverna_player.rb +6 -0
  149. data/test/dummy/db/migrate/20130918155525_create_taverna_player_service_credentials.taverna_player.rb +16 -0
  150. data/test/dummy/db/migrate/20130919155202_add_displayed_to_taverna_player_interactions.taverna_player.rb +6 -0
  151. data/test/dummy/db/migrate/20131007153659_add_job_ref_to_taverna_player_runs.taverna_player.rb +14 -0
  152. data/test/dummy/db/migrate/20131016123941_add_reply_caching_to_taverna_player_interactions.taverna_player.rb +20 -0
  153. data/test/dummy/db/migrate/20131017141614_add_failure_message_to_taverna_player_run.taverna_player.rb +6 -0
  154. data/test/dummy/db/migrate/20131018153316_add_serial_number_to_taverna_player_interactions.taverna_player.rb +6 -0
  155. data/test/dummy/db/migrate/20131018164614_add_parent_run_id_to_taverna_player_runs.taverna_player.rb +6 -0
  156. data/test/dummy/db/migrate/20131102114343_add_page_uri_to_taverna_player_interaction.taverna_player.rb +6 -0
  157. data/test/dummy/db/migrate/20131105115724_remove_proxy_from_taverna_player_runs.taverna_player.rb +12 -0
  158. data/test/dummy/db/migrate/20131105142417_change_taverna_player_interactions_output_value_column_name.taverna_player.rb +6 -0
  159. data/test/dummy/db/migrate/20131112165815_add_user_to_taverna_player_run.taverna_player.rb +6 -0
  160. data/test/dummy/db/migrate/20131114130937_create_users.rb +10 -0
  161. data/test/dummy/db/schema.rb +123 -0
  162. data/test/dummy/lib/callbacks.rb +35 -0
  163. data/test/dummy/log/.gitkeep +0 -0
  164. data/test/dummy/public/404.html +26 -0
  165. data/test/dummy/public/422.html +26 -0
  166. data/test/dummy/public/500.html +25 -0
  167. data/test/dummy/public/favicon.ico +0 -0
  168. data/test/dummy/script/delayed_job +5 -0
  169. data/test/dummy/script/rails +6 -0
  170. data/test/dummy/test/functional/home_controller_test.rb +28 -0
  171. data/test/dummy/test/functional/workflows_controller_test.rb +21 -0
  172. data/test/fixtures/files/crassostrea_gigas.csv +737 -0
  173. data/test/fixtures/taverna_player/interactions.yml +32 -0
  174. data/test/fixtures/taverna_player/run_ports.yml +54 -0
  175. data/test/fixtures/taverna_player/runs.yml +69 -0
  176. data/test/fixtures/taverna_player/service_credentials.yml +25 -0
  177. data/test/fixtures/users.yml +16 -0
  178. data/test/fixtures/workflows.yml +32 -0
  179. data/test/functional/taverna_player/runs_controller_test.rb +316 -0
  180. data/test/functional/taverna_player/service_credentials_controller_test.rb +99 -0
  181. data/test/taverna_player_test.rb +25 -0
  182. data/test/test_helper.rb +33 -0
  183. data/test/unit/helpers/taverna_player/application_helper_test.rb +70 -0
  184. data/test/unit/helpers/taverna_player/runs_helper_test.rb +45 -0
  185. data/test/unit/taverna_player/interaction_test.rb +47 -0
  186. data/test/unit/taverna_player/run_port_test.rb +309 -0
  187. data/test/unit/taverna_player/run_test.rb +196 -0
  188. data/test/unit/taverna_player/service_credential_test.rb +64 -0
  189. data/test/workflows/hello.t2flow +164 -0
  190. data/test/workflows/list_with_errors.t2flow +107 -0
  191. data/test/workflows/pass_through.t2flow +12 -0
  192. metadata +539 -0
@@ -0,0 +1,281 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2013 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Taverna Player was developed in the BioVeL project, funded by the European
7
+ # Commission 7th Framework Programme (FP7), through grant agreement
8
+ # number 283359.
9
+ #
10
+ # Author: Robert Haines
11
+ #------------------------------------------------------------------------------
12
+
13
+ module TavernaPlayer
14
+ module Concerns
15
+ module Controllers
16
+ module RunsController
17
+
18
+ extend ActiveSupport::Concern
19
+
20
+ included do
21
+ respond_to :html, :json, :js
22
+
23
+ before_filter :find_runs, :only => [ :index ]
24
+ before_filter :find_run, :except => [ :index, :new, :create ]
25
+ before_filter :find_workflow, :only => [ :new ]
26
+ before_filter :setup_new_run, :only => :new
27
+ before_filter :set_run_user, :only => :create
28
+ before_filter :filter_update_parameters, :only => :update
29
+ before_filter :find_interaction, :only => [ :read_interaction, :write_interaction ]
30
+
31
+ layout :choose_layout
32
+
33
+ private
34
+
35
+ def find_runs
36
+ select = { :embedded => false }
37
+ select[:workflow_id] = params[:workflow_id] if params[:workflow_id]
38
+ @runs = Run.where(select).all
39
+ end
40
+
41
+ def find_run
42
+ @run = Run.find(params[:id])
43
+ end
44
+
45
+ def find_workflow
46
+ @workflow = TavernaPlayer.workflow_proxy.class_name.find(params[:workflow_id])
47
+ end
48
+
49
+ def setup_new_run
50
+ @run = Run.new(:workflow_id => @workflow.id)
51
+ @run.embedded = true if params[:embedded] == "true"
52
+ end
53
+
54
+ def set_run_user
55
+ return if params[:run][:embedded] == "true" || TavernaPlayer.user_proxy.nil?
56
+
57
+ unless TavernaPlayer.current_user_callback.blank?
58
+ user = method(TavernaPlayer.current_user_callback).call
59
+ params[:run][:user_id] = user.id unless user.nil?
60
+ end
61
+ end
62
+
63
+ def filter_update_parameters
64
+ name = params[:run][:name]
65
+ @update_parameters = { :name => name } unless name.blank?
66
+ end
67
+
68
+ def find_interaction
69
+ @interaction = Interaction.find_by_unique_id(params[:int_id])
70
+ end
71
+
72
+ # Read the data from the results zip file.
73
+ def read_from_zip(file)
74
+ Zip::ZipFile.open(@run.results.path) do |zip|
75
+ zip.read(file)
76
+ end
77
+ end
78
+
79
+ # This is here because of Taverna's infinitely deep output ports :-(
80
+ def recurse_into_lists(list, indexes)
81
+ return list if indexes.empty? || !list.is_a?(Array)
82
+ i = indexes.shift
83
+ return recurse_into_lists(list[i], indexes)
84
+ end
85
+
86
+ # Choose a layout for the page depending on action and embedded status.
87
+ def choose_layout
88
+ if (action_name == "new" || action_name == "show") && @run.embedded?
89
+ "taverna_player/embedded"
90
+ else
91
+ ApplicationController.new.send(:_layout).virtual_path
92
+ end
93
+ end
94
+
95
+ end # included
96
+
97
+ # GET /runs
98
+ def index
99
+
100
+ end
101
+
102
+ # GET /runs/1
103
+ def show
104
+ if @run.running?
105
+ @interaction = Interaction.find_by_run_id_and_replied(@run.id, false)
106
+ unless @interaction.nil?
107
+ unless @interaction.displayed
108
+ @new_interaction = true
109
+ @interaction.displayed = true
110
+ @interaction.save
111
+ end
112
+ end
113
+ end
114
+
115
+ respond_with(@run) do |format|
116
+ # Render show.{html|js}.erb unless the run is embedded.
117
+ format.any(:html, :js) do
118
+ render "taverna_player/runs/embedded/show" if @run.embedded
119
+ end
120
+ end
121
+ end
122
+
123
+ # GET /runs/new
124
+ def new
125
+ respond_with(@run) do |format|
126
+ # Render new.html.erb unless the run is embedded.
127
+ format.html do
128
+ render "taverna_player/runs/embedded/new" if @run.embedded
129
+ end
130
+ end
131
+ end
132
+
133
+ # POST /runs
134
+ def create
135
+ @run = Run.new(params[:run])
136
+ if @run.save
137
+ flash[:notice] = "Run was successfully created."
138
+ end
139
+
140
+ respond_with(@run, :status => :created, :location => @run)
141
+ end
142
+
143
+ # PUT /runs/1
144
+ def update
145
+ @run.update_attributes(@update_parameters)
146
+
147
+ respond_with(@run)
148
+ end
149
+
150
+ # DELETE /runs/1
151
+ def destroy
152
+ if @run.destroy
153
+ flash[:notice] = "Run was deleted."
154
+ respond_with(@run)
155
+ else
156
+ flash[:error] = "Run must be cancelled before deletion."
157
+ respond_with(@run, :nothing => true, :status => :forbidden) do |format|
158
+ format.html { redirect_to :back }
159
+ end
160
+ end
161
+ end
162
+
163
+ # PUT /runs/1/cancel
164
+ def cancel
165
+ @run.cancel unless @run.complete?
166
+
167
+ respond_with(@run, :action => :show) do |format|
168
+ format.html do
169
+ if @run.embedded?
170
+ redirect_to view_context.new_embedded_run_path(@run)
171
+ else
172
+ redirect_to :back
173
+ end
174
+ end
175
+ end
176
+ end
177
+
178
+ # GET /runs/1/download/log
179
+ def download_log
180
+ send_file @run.log.path, :type => "text/plain",
181
+ :filename => "#{@run.name}-log.txt"
182
+ end
183
+
184
+ # GET /runs/1/download/results
185
+ def download_results
186
+ send_file @run.results.path, :type => "application/zip",
187
+ :filename => "#{@run.name}-all-results.zip"
188
+ end
189
+
190
+ # GET /runs/1/download/output/:port
191
+ def download_output
192
+ output = RunPort::Output.find_by_run_id_and_name(@run.id, params[:port])
193
+
194
+ # If there is no such output port then return a 404.
195
+ raise ActionController::RoutingError.new('Not Found') if output.nil?
196
+
197
+ if output.file.blank?
198
+ send_data output.value, :type => "text/plain",
199
+ :filename => "#{@run.name}-#{output.name}.txt"
200
+ else
201
+ send_file output.file.path, :type => output.file.content_type,
202
+ :filename => "#{@run.name}-#{output.file_file_name}"
203
+ end
204
+ end
205
+
206
+ # GET /runs/1/input/*
207
+ def input
208
+ input = RunPort::Input.find_by_run_id_and_name(@run.id, params[:port])
209
+
210
+ # If there is no such input port then return a 404.
211
+ raise ActionController::RoutingError.new('Not Found') if input.nil?
212
+
213
+ if input.file.blank?
214
+ send_data input.value, :disposition => "inline"
215
+ else
216
+ send_file input.file.path, :disposition => "inline"
217
+ end
218
+ end
219
+
220
+ # GET /runs/1/output/*
221
+ def output
222
+ # We need to parse out the path into a list of numbers here so we have
223
+ # a list of indices into the file structure.
224
+ path = []
225
+ unless params[:path].nil?
226
+ path = params[:path].split("/").map { |p| p.to_i }
227
+ end
228
+
229
+ output = RunPort::Output.find_by_run_id_and_name(@run.id, params[:port])
230
+
231
+ # If there is no such output port or the path is the wrong depth then
232
+ # return a 404.
233
+ if output.nil? || path.length != output.depth
234
+ raise ActionController::RoutingError.new('Not Found')
235
+ end
236
+
237
+ # A singleton should just return the value (if it's small enough) or the
238
+ # file if it's bigger. If it's a value in the database then it'll always
239
+ # be a text value, although not necessarily "plain".
240
+ if output.depth == 0 && !output.value.blank?
241
+ send_data output.value, :disposition => "inline",
242
+ :type => output.metadata[:type]
243
+ else
244
+ # We need to rebuild the path indices into a string here (and can't
245
+ # re-use the params[:path] variable directly) because files are
246
+ # indexed from one in the zip we get back from Server, not zero.
247
+ path_s = path.map { |p| p += 1 }.join("/")
248
+ file = path_s.blank? ? "#{output.name}" : "#{output.name}/#{path_s}"
249
+ type = recurse_into_lists(output.metadata[:type], path)
250
+
251
+ # If it's an error, then we need to further hack the file path and
252
+ # content type.
253
+ if type == "application/x-error"
254
+ file += ".error"
255
+ type = "text/plain"
256
+ end
257
+
258
+ send_data read_from_zip(file), :type => type,
259
+ :disposition => "inline"
260
+ end
261
+ end
262
+
263
+ # GET /runs/1/interaction/:int_id
264
+ def read_interaction
265
+ send_data @interaction.page, :type => "text/html",
266
+ :disposition => "inline"
267
+ end
268
+
269
+ # POST /runs/1/interaction/:int_id
270
+ def write_interaction
271
+ @interaction.data = request.body.read
272
+ @interaction.feed_reply = request.headers["X-Taverna-Interaction-Reply"]
273
+ @interaction.save
274
+
275
+ render :nothing => true, :status => 201
276
+ end
277
+
278
+ end
279
+ end
280
+ end
281
+ end
@@ -0,0 +1,89 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2013 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Taverna Player was developed in the BioVeL project, funded by the European
7
+ # Commission 7th Framework Programme (FP7), through grant agreement
8
+ # number 283359.
9
+ #
10
+ # Author: Robert Haines
11
+ #------------------------------------------------------------------------------
12
+
13
+ module TavernaPlayer
14
+ module Concerns
15
+ module Controllers
16
+ module ServiceCredentialsController
17
+
18
+ extend ActiveSupport::Concern
19
+
20
+ included do
21
+ respond_to :html
22
+
23
+ before_filter :find_creds, :only => [ :index ]
24
+ before_filter :find_cred, :except => [ :index, :new, :create ]
25
+
26
+ private
27
+
28
+ def find_creds
29
+ @service_credentials = ServiceCredential.all
30
+ end
31
+
32
+ def find_cred
33
+ @service_credential = ServiceCredential.find(params[:id])
34
+ end
35
+ end
36
+
37
+ # GET /service_credentials
38
+ def index
39
+
40
+ end
41
+
42
+ # GET /service_credentials/1
43
+ def show
44
+
45
+ end
46
+
47
+ # GET /service_credentials/new
48
+ def new
49
+ @service_credential = ServiceCredential.new
50
+ end
51
+
52
+ # GET /service_credentials/1/edit
53
+ def edit
54
+
55
+ end
56
+
57
+ # POST /service_credentials
58
+ def create
59
+ @service_credential = ServiceCredential.new(params[:service_credential])
60
+
61
+ if @service_credential.save
62
+ flash[:notice] = "Service credential was successfully created."
63
+ end
64
+
65
+ respond_with(@service_credential)
66
+ end
67
+
68
+ # PUT /service_credentials/1
69
+ def update
70
+ if @service_credential.update_attributes(params[:service_credential])
71
+ flash[:notice] = "Service credential was successfully updated."
72
+ end
73
+
74
+ respond_with(@service_credential)
75
+ end
76
+
77
+ # DELETE /service_credentials/1
78
+ def destroy
79
+ if @service_credential.destroy
80
+ flash[:notice] = "Service credential was deleted."
81
+ end
82
+
83
+ respond_with(@service_credential)
84
+ end
85
+
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,205 @@
1
+ #------------------------------------------------------------------------------
2
+ # Copyright (c) 2013 The University of Manchester, UK.
3
+ #
4
+ # BSD Licenced. See LICENCE.rdoc for details.
5
+ #
6
+ # Taverna Player was developed in the BioVeL project, funded by the European
7
+ # Commission 7th Framework Programme (FP7), through grant agreement
8
+ # number 283359.
9
+ #
10
+ # Author: Robert Haines
11
+ #------------------------------------------------------------------------------
12
+
13
+ module TavernaPlayer
14
+ module Concerns
15
+ module Models
16
+ module Run
17
+
18
+ extend ActiveSupport::Concern
19
+
20
+ included do
21
+ attr_accessible :create_time, :delayed_job, :embedded, :finish_time,
22
+ :inputs_attributes, :log, :name, :parent_id, :results, :run_id,
23
+ :start_time, :status_message, :user_id, :workflow_id
24
+
25
+ # Each run is spawned from a workflow. This provides the link to the
26
+ # workflow model in the parent app, whatever it calls its model.
27
+ belongs_to :workflow, :class_name => TavernaPlayer.workflow_proxy.class_name.to_s
28
+
29
+ unless TavernaPlayer.user_proxy.nil?
30
+ belongs_to :user, :class_name => TavernaPlayer.user_proxy.class_name.to_s
31
+ end
32
+
33
+ has_many :inputs, :class_name => "TavernaPlayer::RunPort::Input",
34
+ :dependent => :destroy
35
+ has_many :outputs, :class_name => "TavernaPlayer::RunPort::Output",
36
+ :dependent => :destroy
37
+ has_many :interactions, :class_name => "TavernaPlayer::Interaction",
38
+ :dependent => :destroy
39
+ belongs_to :delayed_job, :class_name => "::Delayed::Job"
40
+
41
+ # A run can have children, which are runs.
42
+ # A run can have a parent, which is another run.
43
+ has_many :children, :class_name => "TavernaPlayer::Run",
44
+ :foreign_key => "parent_id", :dependent => :nullify
45
+ belongs_to :parent, :class_name => "TavernaPlayer::Run"
46
+
47
+ accepts_nested_attributes_for :inputs
48
+
49
+ STATES = ["pending", "initialized", "running", "finished", "cancelled", "failed"]
50
+
51
+ validates :workflow_id, :presence => true
52
+ validates :name, :presence => true
53
+
54
+ # There is a :cancelled state but it can only be set if the run has
55
+ # previously had its stop flag set. This is to avoid race conditions.
56
+ # If we used a state to tell the delayed job worker to cancel a run
57
+ # it could be overwritten when the worker itself moves the run
58
+ # between states, thus losing the cancel request from the user.
59
+ validates :saved_state, :inclusion => { :in => STATES }
60
+ validates :stop, :presence => true, :if => :cancelled?
61
+
62
+ # A parent must have an "older" run id than its children. This only
63
+ # needs to be checked on update because on create we don't have an
64
+ # id for ourself.
65
+ validates :parent_id, :numericality => { :less_than => :id,
66
+ :message => "Parents must have lower ids than children" },
67
+ :allow_nil => true, :on => :update
68
+
69
+ has_attached_file :log,
70
+ :path => File.join(TavernaPlayer.file_store, ":class/:attachment/:id/:filename"),
71
+ :url => "/runs/:id/download/log",
72
+ :default_url => ""
73
+
74
+ has_attached_file :results,
75
+ :path => File.join(TavernaPlayer.file_store, ":class/:attachment/:id/:filename"),
76
+ :url => "/runs/:id/download/results",
77
+ :default_url => ""
78
+
79
+ after_initialize :initialize_child_run, :if => "new_record? && has_parent?"
80
+ after_create :populate_child_inputs, :if => :has_parent?
81
+ after_create :enqueue
82
+ before_destroy :complete?
83
+
84
+ private
85
+
86
+ # A child run MUST have the same workflow as its parent.
87
+ def initialize_child_run
88
+ self.workflow = parent.workflow
89
+ end
90
+
91
+ # For each input on the parent run, make sure we have an equivalent
92
+ # on the child. Copy the values/files of inputs that are missing.
93
+ def populate_child_inputs
94
+ parent.inputs.each do |i|
95
+ input = TavernaPlayer::RunPort::Input.find_or_initialize_by_run_id_and_name(id, i.name)
96
+ if input.new_record?
97
+ input.value = i.value
98
+ input.file = i.file
99
+ input.depth = i.depth
100
+ input.save
101
+ end
102
+ end
103
+ end
104
+
105
+ def enqueue
106
+ worker = TavernaPlayer::Worker.new(self)
107
+ job = Delayed::Job.enqueue worker, :queue => "player"
108
+ update_attributes(:delayed_job => job, :status_message => "Queued")
109
+ end
110
+
111
+ end # included
112
+
113
+ # Get the original ancestor of this run. In practice this is the first
114
+ # run in the chain without a parent.
115
+ def root_ancestor
116
+ has_parent? ? parent.root_ancestor : self
117
+ end
118
+
119
+ # There are two courses of action here:
120
+ #
121
+ # * If the run is already running then cancel this run by setting the
122
+ # stop flag. This is done to allow the delayed job that is
123
+ # monitoring the run to delete it and clean up Taverna Server
124
+ # gracefully.
125
+ # * If the run is still in the queue, destroy the queue object. This
126
+ # is checked in a transaction so that we don't get hit with a race
127
+ # condition between checking the queued status of the run and
128
+ # actually removing it from the queue.
129
+ #
130
+ # In both cases the stop flag is set to mark the run as cancelled
131
+ # internally.
132
+ #
133
+ # See the note above about the :cancelled state.
134
+ def cancel
135
+ return if complete?
136
+
137
+ # If the run has a delayed job (still) and it hasn't been locked yet
138
+ # then we just remove it from the queue directly and mark the run as
139
+ # cancelled.
140
+ unless delayed_job.nil?
141
+ delayed_job.with_lock do
142
+ if delayed_job.locked_by.nil?
143
+ delayed_job.destroy
144
+ update_attribute(:saved_state, "cancelled")
145
+ update_attribute(:status_message, "Cancelled")
146
+ end
147
+ end
148
+ end
149
+
150
+ update_attribute(:stop, true)
151
+ end
152
+
153
+ # Return state as a symbol. If a run is running, but has been asked to
154
+ # stop, then it is :cancelling. This is a pseudo-state to avoid race
155
+ # conditions when cancelling a run so is specifically NOT in the list
156
+ # of allowed states above.
157
+ def state
158
+ s = self[:saved_state].to_sym
159
+ if s == :running
160
+ stop ? :cancelling : :running
161
+ else
162
+ s
163
+ end
164
+ end
165
+
166
+ # Save state as a downcased string. See the note above about why a
167
+ # state cannot be used to actually cancel a run.
168
+ def state=(state)
169
+ s = state.to_s.downcase
170
+ return if s == "cancelled" && !stop
171
+ self[:saved_state] = s
172
+ end
173
+
174
+ def running?
175
+ state == :running
176
+ end
177
+
178
+ def finished?
179
+ state == :finished
180
+ end
181
+
182
+ def cancelled?
183
+ state == :cancelled
184
+ end
185
+
186
+ def cancelling?
187
+ state == :cancelling
188
+ end
189
+
190
+ def failed?
191
+ state == :failed
192
+ end
193
+
194
+ # This is used as a catch-all for finished, cancelled and failed
195
+ def complete?
196
+ finished? || cancelled? || failed?
197
+ end
198
+
199
+ def has_parent?
200
+ !parent_id.nil?
201
+ end
202
+ end
203
+ end
204
+ end
205
+ end