appcelerator 2.0.1.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (147) hide show
  1. data/appcelerator/templates/appcelerator.xml +1 -0
  2. data/appcelerator/templates/application.rb +1 -2
  3. data/appcelerator/templates/index.html +1 -1
  4. data/appcelerator/templates/{js → javascripts}/appcelerator-debug.js +1110 -372
  5. data/appcelerator/templates/javascripts/appcelerator.js +20 -0
  6. data/appcelerator/templates/modules/app_box/app_box.js +1 -0
  7. data/appcelerator/templates/modules/app_button/app_button.js +1 -0
  8. data/appcelerator/templates/modules/app_button/css/button.css +1 -0
  9. data/appcelerator/templates/modules/app_button/images/dark_round_left.png +0 -0
  10. data/appcelerator/templates/modules/app_button/images/dark_round_left_disabled.png +0 -0
  11. data/appcelerator/templates/modules/app_button/images/dark_round_left_over.png +0 -0
  12. data/appcelerator/templates/modules/app_button/images/dark_round_left_press.png +0 -0
  13. data/appcelerator/templates/modules/app_button/images/dark_round_middle.png +0 -0
  14. data/appcelerator/templates/modules/app_button/images/dark_round_middle_disabled.png +0 -0
  15. data/appcelerator/templates/modules/app_button/images/dark_round_middle_over.png +0 -0
  16. data/appcelerator/templates/modules/app_button/images/dark_round_middle_press.png +0 -0
  17. data/appcelerator/templates/modules/app_button/images/dark_round_right.png +0 -0
  18. data/appcelerator/templates/modules/app_button/images/dark_round_right_disabled.png +0 -0
  19. data/appcelerator/templates/modules/app_button/images/dark_round_right_over.png +0 -0
  20. data/appcelerator/templates/modules/app_button/images/dark_round_right_press.png +0 -0
  21. data/appcelerator/templates/modules/app_button/images/dark_square_left.png +0 -0
  22. data/appcelerator/templates/modules/app_button/images/dark_square_left_disabled.png +0 -0
  23. data/appcelerator/templates/modules/app_button/images/dark_square_left_over.png +0 -0
  24. data/appcelerator/templates/modules/app_button/images/dark_square_left_press.png +0 -0
  25. data/appcelerator/templates/modules/app_button/images/dark_square_middle.png +0 -0
  26. data/appcelerator/templates/modules/app_button/images/dark_square_middle_disabled.png +0 -0
  27. data/appcelerator/templates/modules/app_button/images/dark_square_middle_over.png +0 -0
  28. data/appcelerator/templates/modules/app_button/images/dark_square_middle_press.png +0 -0
  29. data/appcelerator/templates/modules/app_button/images/dark_square_right.png +0 -0
  30. data/appcelerator/templates/modules/app_button/images/dark_square_right_disabled.png +0 -0
  31. data/appcelerator/templates/modules/app_button/images/dark_square_right_over.png +0 -0
  32. data/appcelerator/templates/modules/app_button/images/dark_square_right_press.png +0 -0
  33. data/appcelerator/templates/modules/app_button/images/icon_add_gray.png +0 -0
  34. data/appcelerator/templates/modules/app_button/images/icon_add_green.png +0 -0
  35. data/appcelerator/templates/modules/app_button/images/icon_delete_gray.png +0 -0
  36. data/appcelerator/templates/modules/app_button/images/icon_delete_red.png +0 -0
  37. data/appcelerator/templates/modules/app_button/images/icon_edit_gray.png +0 -0
  38. data/appcelerator/templates/modules/app_button/images/icon_edit_yellow.png +0 -0
  39. data/appcelerator/templates/modules/app_button/images/icon_save_blue.png +0 -0
  40. data/appcelerator/templates/modules/app_button/images/icon_save_gray.png +0 -0
  41. data/appcelerator/templates/modules/app_button/images/light_round_left.png +0 -0
  42. data/appcelerator/templates/modules/app_button/images/light_round_left_disabled.png +0 -0
  43. data/appcelerator/templates/modules/app_button/images/light_round_left_over.png +0 -0
  44. data/appcelerator/templates/modules/app_button/images/light_round_left_press.png +0 -0
  45. data/appcelerator/templates/modules/app_button/images/light_round_middle.png +0 -0
  46. data/appcelerator/templates/modules/app_button/images/light_round_middle_disabled.png +0 -0
  47. data/appcelerator/templates/modules/app_button/images/light_round_middle_over.png +0 -0
  48. data/appcelerator/templates/modules/app_button/images/light_round_middle_press.png +0 -0
  49. data/appcelerator/templates/modules/app_button/images/light_round_right.png +0 -0
  50. data/appcelerator/templates/modules/app_button/images/light_round_right_disabled.png +0 -0
  51. data/appcelerator/templates/modules/app_button/images/light_round_right_over.png +0 -0
  52. data/appcelerator/templates/modules/app_button/images/light_round_right_press.png +0 -0
  53. data/appcelerator/templates/modules/app_button/images/light_square_left.png +0 -0
  54. data/appcelerator/templates/modules/app_button/images/light_square_left_disabled.png +0 -0
  55. data/appcelerator/templates/modules/app_button/images/light_square_left_over.png +0 -0
  56. data/appcelerator/templates/modules/app_button/images/light_square_left_press.png +0 -0
  57. data/appcelerator/templates/modules/app_button/images/light_square_middle.png +0 -0
  58. data/appcelerator/templates/modules/app_button/images/light_square_middle_disabled.png +0 -0
  59. data/appcelerator/templates/modules/app_button/images/light_square_middle_over.png +0 -0
  60. data/appcelerator/templates/modules/app_button/images/light_square_middle_press.png +0 -0
  61. data/appcelerator/templates/modules/app_button/images/light_square_right.png +0 -0
  62. data/appcelerator/templates/modules/app_button/images/light_square_right_disabled.png +0 -0
  63. data/appcelerator/templates/modules/app_button/images/light_square_right_over.png +0 -0
  64. data/appcelerator/templates/modules/app_button/images/light_square_right_press.png +0 -0
  65. data/appcelerator/templates/modules/app_calendar/app_calendar.js +1 -1
  66. data/appcelerator/templates/modules/app_chart/app_chart.js +1 -1
  67. data/appcelerator/templates/modules/app_content/app_content.js +1 -1
  68. data/appcelerator/templates/modules/app_datatable/app_datatable.js +1 -1
  69. data/appcelerator/templates/modules/app_http/app_http.js +1 -0
  70. data/appcelerator/templates/modules/app_if/app_if.js +1 -0
  71. data/appcelerator/templates/modules/app_iterator/app_iterator.js +1 -1
  72. data/appcelerator/templates/modules/app_message/app_message.js +1 -1
  73. data/appcelerator/templates/modules/app_modaldialog/app_modaldialog.js +1 -1
  74. data/appcelerator/templates/modules/app_panel/app_panel.js +1 -0
  75. data/appcelerator/templates/modules/app_panel/app_panel_test.html +24 -0
  76. data/appcelerator/templates/modules/app_panel/css/panel.css +1 -0
  77. data/appcelerator/templates/modules/app_panel/css/panel_ie7.css +1 -0
  78. data/appcelerator/templates/modules/app_panel/images/close.png +0 -0
  79. data/appcelerator/templates/modules/app_panel/images/close_hover.png +0 -0
  80. data/appcelerator/templates/modules/app_panel/images/close_onclick.png +0 -0
  81. data/appcelerator/templates/modules/app_panel/images/collapsed_headers_12.png +0 -0
  82. data/appcelerator/templates/modules/app_panel/images/collapsed_headers_13.gif +0 -0
  83. data/appcelerator/templates/modules/app_panel/images/collapsed_headers_15.png +0 -0
  84. data/appcelerator/templates/modules/app_panel/images/collapsed_headers_17.png +0 -0
  85. data/appcelerator/templates/modules/app_panel/images/collapsed_headers_19.png +0 -0
  86. data/appcelerator/templates/modules/app_panel/images/collapsed_headers_62.png +0 -0
  87. data/appcelerator/templates/modules/app_panel/images/collapsed_headers_63.gif +0 -0
  88. data/appcelerator/templates/modules/app_panel/images/collapsed_headers_65.png +0 -0
  89. data/appcelerator/templates/modules/app_panel/images/collapsed_headers_67.png +0 -0
  90. data/appcelerator/templates/modules/app_panel/images/collapsed_headers_69.png +0 -0
  91. data/appcelerator/templates/modules/app_panel/images/down.png +0 -0
  92. data/appcelerator/templates/modules/app_panel/images/down_hover.png +0 -0
  93. data/appcelerator/templates/modules/app_panel/images/down_onclick.png +0 -0
  94. data/appcelerator/templates/modules/app_panel/images/expanded_headers_12.png +0 -0
  95. data/appcelerator/templates/modules/app_panel/images/expanded_headers_13.gif +0 -0
  96. data/appcelerator/templates/modules/app_panel/images/expanded_headers_15.png +0 -0
  97. data/appcelerator/templates/modules/app_panel/images/expanded_headers_17.png +0 -0
  98. data/appcelerator/templates/modules/app_panel/images/expanded_headers_19.png +0 -0
  99. data/appcelerator/templates/modules/app_panel/images/expanded_headers_52.png +0 -0
  100. data/appcelerator/templates/modules/app_panel/images/expanded_headers_53.gif +0 -0
  101. data/appcelerator/templates/modules/app_panel/images/expanded_headers_55.png +0 -0
  102. data/appcelerator/templates/modules/app_panel/images/expanded_headers_57.png +0 -0
  103. data/appcelerator/templates/modules/app_panel/images/expanded_headers_59.png +0 -0
  104. data/appcelerator/templates/modules/app_panel/images/footer_30.png +0 -0
  105. data/appcelerator/templates/modules/app_panel/images/footer_32.png +0 -0
  106. data/appcelerator/templates/modules/app_panel/images/footer_37.png +0 -0
  107. data/appcelerator/templates/modules/app_panel/images/footer_39.png +0 -0
  108. data/appcelerator/templates/modules/app_panel/images/footer_43.gif +0 -0
  109. data/appcelerator/templates/modules/app_panel/images/footer_72.png +0 -0
  110. data/appcelerator/templates/modules/app_panel/images/footer_75.png +0 -0
  111. data/appcelerator/templates/modules/app_panel/images/footer_77.png +0 -0
  112. data/appcelerator/templates/modules/app_panel/images/footer_79.png +0 -0
  113. data/appcelerator/templates/modules/app_panel/images/footer_93.gif +0 -0
  114. data/appcelerator/templates/modules/app_panel/images/gray_left_tail.png +0 -0
  115. data/appcelerator/templates/modules/app_panel/images/gray_right_tail.png +0 -0
  116. data/appcelerator/templates/modules/app_panel/images/up.png +0 -0
  117. data/appcelerator/templates/modules/app_panel/images/up_hover.png +0 -0
  118. data/appcelerator/templates/modules/app_panel/images/up_onclick.png +0 -0
  119. data/appcelerator/templates/modules/app_panel/images/white_left_tail.png +0 -0
  120. data/appcelerator/templates/modules/app_panel/images/white_right_tail.png +0 -0
  121. data/appcelerator/templates/modules/app_progressbar/app_progressbar.js +1 -0
  122. data/appcelerator/templates/modules/app_progressbar/css/progressbar.css +1 -0
  123. data/appcelerator/templates/modules/app_script/app_script.js +1 -1
  124. data/appcelerator/templates/modules/app_search/app_search.js +1 -0
  125. data/appcelerator/templates/modules/app_search/css/search.css +1 -0
  126. data/appcelerator/templates/modules/app_security/app_security.js +1 -1
  127. data/appcelerator/templates/modules/app_upload/app_upload.js +1 -1
  128. data/appcelerator/templates/proxy_controller.rb +25 -0
  129. data/appcelerator/templates/routes.rb +2 -0
  130. data/appcelerator/templates/{service_broker.rb → service_broker_controller.rb} +0 -0
  131. data/appcelerator/templates/servicetester.html +208 -0
  132. data/appcelerator/templates/test_service.rb +3 -3
  133. data/appcelerator/templates/upload_controller.rb +55 -0
  134. data/bin/appcelerator +51 -30
  135. data/lib/appcelerator.rb +11 -5
  136. data/lib/appcelerator/dispatcher.rb +62 -62
  137. data/lib/appcelerator/service.rb +220 -222
  138. data/lib/appcelerator/service_broker_controller.rb +3 -11
  139. data/lib/appcelerator/servicebroker/inmemory_service_broker.rb +43 -37
  140. data/service/USAGE +1 -0
  141. data/service/templates/service.rb +3 -3
  142. metadata +164 -49
  143. data/appcelerator/appcelerator_generator.rb +0 -195
  144. data/appcelerator/templates/environment.rb +0 -65
  145. data/appcelerator/templates/js/appcelerator.js +0 -20
  146. data/appcelerator/templates/server +0 -4
  147. data/lib/appcelerator/model.rb +0 -94
@@ -3,9 +3,9 @@ class TestService < Appcelerator::Service
3
3
 
4
4
  Service 'app.test.message.request', :testMessage, 'app.test.message.response'
5
5
 
6
- def testMessage(request,message)
7
- p "received message: #{message.inspect}"
8
- msg = message["message"]
6
+ def testMessage
7
+ p "received message: #{params.inspect}"
8
+ msg = params["message"]
9
9
  {"message"=>"I received from you: #{msg}","success"=>true}
10
10
  end
11
11
 
@@ -0,0 +1,55 @@
1
+
2
+ class UploadController < ApplicationController
3
+
4
+ def get_extension(mimetype)
5
+ case mimetype
6
+ when 'image/png'
7
+ return 'png'
8
+ when 'image/gif'
9
+ return 'gif'
10
+ when 'image/jpeg'
11
+ return 'jpg'
12
+ end
13
+ end
14
+
15
+ def make_temp_file(value)
16
+ extension = get_extension value.content_type.strip || ''
17
+ uniquename = MD5.new(Time.now.to_s).hexdigest.slice(0,8).gsub(/[^\w\.\-]/,'_')
18
+ FileUtils.mkdir_p("#{FileUtils.pwd}/tmp/uploads")
19
+ f = File.new("#{FileUtils.pwd}/tmp/uploads/#{uniquename}.#{extension}", 'wb')
20
+ f.write value.read
21
+ f.close
22
+ f
23
+ end
24
+
25
+ def index
26
+ msg = {}
27
+ params.each do |key, value|
28
+ case value.class.to_s
29
+ when 'String'
30
+ msg[key] = value
31
+ when 'StringIO'
32
+ msg[key] = make_temp_file value
33
+ when 'Tempfile'
34
+ msg[key] = make_temp_file value
35
+ end
36
+ end
37
+
38
+ cb = params['callback']
39
+
40
+ if cb
41
+ if cb =~ /^(r:|remote:|l:|local:)/
42
+ @callback = "window.parent.$MQ('#{cb}');"
43
+ else
44
+ @callback = cb
45
+ end
46
+ else
47
+ @callback = ''
48
+ end
49
+
50
+ request_id = Time.now
51
+ message_type = params['type']
52
+ Appcelerator::Dispatcher.dispatch_message(request, response, session, message_type, msg, request_id)
53
+
54
+ end
55
+ end
@@ -1,36 +1,57 @@
1
- #!/usr/bin/env ruby
2
-
3
- freeze = ARGV.any? { |option| %w(--freeze -f).include?(option) }
4
- app_path = ARGV.first
5
-
6
- require 'rubygems'
7
- gem 'rails', '>= 1.2.3'
8
-
9
- # find the path to RAILS
10
- rails_gem = Gem.cache.search('rails').last
11
- RAILS = rails_gem.full_gem_path
12
-
13
- require RAILS + '/lib/ruby_version_check'
14
- Signal.trap("INT") { puts; exit }
15
-
16
- require RAILS + '/lib/rails/version'
17
- if %w(--version -v).include? ARGV.first
18
- puts "Rails #{Rails::VERSION::STRING}"
19
- exit(0)
1
+ require 'pathname'
2
+ require 'erb'
3
+ require 'md5'
4
+ require 'socket'
5
+ require 'fileutils'
6
+
7
+ args = ''
8
+ ARGV.each do |arg|
9
+ args = args + "#{arg} "
20
10
  end
21
11
 
12
+ app_path = ARGV.last
13
+ system('rails ' + args + ' >> rails.log')
14
+ FileUtils.rm_r 'rails.log'
15
+ p = Pathname.new(app_path)
22
16
 
23
- require RAILS + '/lib/rails_generator'
24
- require 'rails_generator/scripts/generate'
17
+ secret_auth_key = Digest::MD5.hexdigest(Time.new.to_s + self.inspect + IPSocket.getaddress(Socket::gethostname).to_s)
25
18
 
26
- Rails::Generator::Base.use_application_sources!
19
+ #
20
+ # remove rails files
21
+ #
22
+ FileUtils.rm_r "#{p}/public/javascripts"
27
23
 
28
- path = File.dirname(__FILE__) + '/../'
29
-
30
- Rails::Generator::Base.sources << Rails::Generator::PathSource.new('', path)
31
-
32
- # execute the appcelerator generator
33
- Rails::Generator::Scripts::Generate.new.run(ARGV, {:generator => 'appcelerator', :source => path + 'appcelerator', :source_root => path + 'appcelerator', 'railspath'=>'../../rails-'+rails_gem.version.to_s})
34
-
35
- Dir.chdir(app_path) { `rake rails:freeze:gems`; puts "froze" } if freeze
24
+ #
25
+ # add appcelerator files
26
+ #
27
+ APP_GEM = Gem.cache.search('appcelerator').last.full_gem_path
28
+ FileUtils.mkdir "#{p}/public/javascripts"
29
+ FileUtils.mkdir "#{p}/app/services"
36
30
 
31
+ FileUtils.cp_r "#{APP_GEM}/appcelerator/templates/appcelerator.xml", "#{p}/public"
32
+ rails_gem = Gem.cache.search('rails').last
33
+ if rails_gem.version.to_s.to_f >= 2
34
+ FileUtils.cp_r "#{APP_GEM}/appcelerator/templates/application.rb", "#{p}/app/controllers"
35
+ end
36
+ f = File.open("#{p}/config/environment.rb", 'a')
37
+ f.write("\n\nrequire 'appcelerator'")
38
+ f.close
39
+ FileUtils.cp_r "#{APP_GEM}/appcelerator/templates/generate", "#{p}/script"
40
+ FileUtils.cp_r "#{APP_GEM}/appcelerator/templates/index.html", "#{p}/public"
41
+ FileUtils.cp_r "#{APP_GEM}/appcelerator/templates/images", "#{p}/public"
42
+ FileUtils.cp_r "#{APP_GEM}/appcelerator/templates/javascripts", "#{p}/public"
43
+ FileUtils.cp_r "#{APP_GEM}/appcelerator/templates/modules", "#{p}/public"
44
+ FileUtils.cp_r "#{APP_GEM}/appcelerator/templates/README", "#{p}"
45
+ FileUtils.cp_r "#{APP_GEM}/appcelerator/templates/routes.rb", "#{p}/config"
46
+ FileUtils.cp_r "#{APP_GEM}/appcelerator/templates/proxy_controller.rb", "#{p}/app/controllers"
47
+ FileUtils.cp_r "#{APP_GEM}/appcelerator/templates/service_broker_controller.rb", "#{p}/app/controllers"
48
+ FileUtils.cp_r "#{APP_GEM}/appcelerator/templates/upload_controller.rb", "#{p}/app/controllers"
49
+ result = ERB.new(File.read("#{p}/app/controllers/service_broker_controller.rb")).result(binding)
50
+ f = File.new("#{p}/app/controllers/service_broker_controller.rb",'w')
51
+ f.write(result)
52
+ f.close
53
+ FileUtils.cp_r "#{APP_GEM}/appcelerator/templates/service_broker_helper.rb", "#{p}/app/helpers"
54
+ FileUtils.cp_r "#{APP_GEM}/appcelerator/templates/servicetester.html", "#{p}/public"
55
+ FileUtils.cp_r "#{APP_GEM}/appcelerator/templates/test_service.rb", "#{p}/app/services"
56
+
57
+ puts "Successfully created new Appcelerator project in '#{app_path}'"
@@ -5,7 +5,7 @@ require 'md5'
5
5
 
6
6
  unless defined?(APP_VERSION)
7
7
 
8
- APP_VERSION = '2.0.1.1'
8
+ APP_VERSION = '2.0.2'
9
9
  APP_SERVICES = Array.new
10
10
 
11
11
  def model_name(name)
@@ -47,14 +47,20 @@ unless defined?(APP_VERSION)
47
47
  log_to STDOUT
48
48
  end
49
49
 
50
- Appcelerator::Service.load_services
51
-
50
+ # just do this once, make rails do the implicit loading for us
51
+ Dir[RAILS_ROOT + '/app/services/*_service.rb'].each do |file|
52
+ #Dependencies.load_file file
53
+ name = Inflector.camelize(File.basename(file).chomp('_service.rb')) + 'Service'
54
+ Object.const_get name
55
+ end
56
+ puts Appcelerator::ServiceBroker.diagnostics
57
+
52
58
  #
53
59
  # register a service broker listener for admin appcelerator models
54
60
  #
55
- sam_proc = Proc.new do |req,type,obj|
61
+ sam_proc = Proc.new do |request,type,obj|
56
62
  resp = {'success'=>true, 'models'=> APP_SERVICES}
57
- Appcelerator::Dispatcher.instance.outgoing(req,'app.admin.models.response',resp)
63
+ Appcelerator::Dispatcher.instance.outgoing(request,'app.admin.models.response',resp)
58
64
  end
59
65
  Appcelerator::ServiceBroker.register_listener('app.admin.models.request',sam_proc)
60
66
 
@@ -1,68 +1,68 @@
1
1
  module Appcelerator
2
- class Dispatcher
3
- include Singleton
2
+ module Dispatcher
3
+
4
+ # dispatch a standard request, called by the service_broker_controller
5
+ #
6
+ def self.dispatch_request(request, response, session)
7
+ message_queue = []
8
+ extract_messages(request, session) do |in_message|
9
+ out_messages = ServiceBroker.send(in_message)
10
+ message_queue.concat(out_messages)
11
+ end
12
+ serialize(message_queue, session.session_id, response.body)
13
+ end
4
14
 
5
- def serialize(session,body)
6
- queue = session['_app_mq']
7
- body << '<?xml version="1.0"?>'
8
- body << "<messages version='1.0' sessionid='#{session.session_id}'>"
9
- if queue
10
- queue.each do |msg|
11
- body << msg
12
- end
13
- session['_app_mq']=[]
14
- end
15
- body << '</messages>'
16
- end
17
-
18
- def outgoing(obj,type,message)
19
- queue = obj['session']['_app_mq']
20
- if !queue
21
- queue = [];
22
- obj['session']['_app_mq'] = queue
23
- end
24
- #TODO requestid
25
- queue << "<message requestid='' direction='OUTGOING' datatype='JSON' type='#{type}'><![CDATA["
26
- queue << message.to_json
27
- queue << ']]></message>'
28
- end
29
-
30
- def incoming(session,request,response)
31
- body = request.env['RAW_POST_DATA']
32
- if body and body != ''
33
- node = REXML::Document.new(body)
34
- node.root.each_element('//message') do |message|
35
- requestid = message.attributes['requestid']
36
- type = message.attributes['type']
37
- text = message.text
38
- msg = JSON.parse(text)
39
- req = {'requestid'=>requestid, 'session'=>session, 'orig_request'=>request}
40
- ServiceBroker.send(req,type,msg)
41
- end
42
- end
43
- end
44
- end
45
- end
46
-
47
-
48
-
49
- # this is the rails dispatcher
50
- require 'dispatcher'
51
-
52
- module ClassMethods
53
- def reset_application_and_services!
54
- Appcelerator::Service.load_services
55
- reset_application_but_not_services!
56
- end
57
- end
58
-
59
- Dispatcher.extend(ClassMethods)
60
- Dispatcher.class_eval do
61
- class << self
62
- unless method_defined? :reset_application_but_not_services!
63
- alias_method :reset_application_but_not_services!, :reset_application!
15
+ # dispatch a message that was generated in some other way, like the upload_controller
16
+ #
17
+ def self.dispatch_message(request, response, session, message_type, params, request_id)
18
+ msg = Message.new(request, session, message_type, params, request_id)
19
+
20
+ message_queue = ServiceBroker.send(msg)
21
+
22
+ serialize(message_queue, session.session_id, response.body)
23
+ end
24
+
25
+ def self.extract_messages(request, session)
26
+ body = request.env['RAW_POST_DATA']
27
+ if body and body != ''
28
+ node = REXML::Document.new(body)
29
+ node.root.each_element('//message') do |message|
30
+
31
+ request_id = message.attributes['requestid']
32
+ message_type = message.attributes['type']
33
+ params = JSON.parse(message.text)
34
+
35
+ yield Message.new(request, session, message_type, params, request_id)
36
+ end
37
+ end
38
+ end
39
+
40
+ def self.serialize(message_queue, session_id, output)
41
+ output << '<?xml version="1.0"?>'
42
+ output << "<messages version='1.0' sessionid='#{session_id}'>"
43
+
44
+ message_queue.compact!
45
+ message_queue.each do |msg|
46
+ if msg.response_type
47
+ output << "<message requestid='#{msg.request_id}' direction='OUTGOING' datatype='JSON' type='#{msg.response_type}'><![CDATA["
48
+ output << msg.response.to_json
49
+ output << ']]></message>'
50
+ end
51
+ end
52
+
53
+ output << '</messages>'
54
+ end
55
+
56
+ class Message
57
+ attr_accessor :request, :session, :message_type, :params, :request_id, :response_type, :response
58
+ def initialize(request, session, message_type, params, request_id)
59
+ @request = request
60
+ @session = session
61
+ @message_type = message_type
62
+ @params = params
63
+ @request_id = request_id
64
+ end
64
65
  end
65
- alias_method :reset_application!, :reset_application_and_services!
66
66
  end
67
67
  end
68
68
 
@@ -1,195 +1,44 @@
1
1
 
2
2
 
3
- module Appcelerator
4
- class Service
5
- include Singleton
6
-
7
- def Service.Service(messagetype,handler,responsetype)
8
- self.instance.preregister(messagetype,handler,responsetype)
9
- end
3
+ module Appcelerator
4
+ class Service
5
+ include Singleton
10
6
 
11
- def Service.service_scaffold(model)
12
- servicename = model_name(model)
13
- self.instance.model_class = eval(model.to_s.camelize)
14
- %w(create retrieve update delete list assembly search).each do |operation|
15
- messagetype = "app."+ servicename +"."+ operation
16
- request = messagetype + ".request"
17
- response = messagetype + ".response"
18
- self.instance.preregister(request,operation,response)
19
- APP_SERVICES << {'name'=>name, 'model'=>servicename}
20
- end
7
+ # registration point of standard services
8
+ def Service.Service(messagetype,handler,responsetype = nil)
9
+ self.instance.register(messagetype,handler,responsetype)
10
+ end
11
+
12
+ # registration point for service handler filters for authentication, etc
13
+ def Service.before_filter(filter)
14
+ self.instance.before_filters << filter
21
15
  end
22
16
 
23
- #
24
- # The following methods are usable by services that call the "service_scaffold" method
25
- # to provide CRUD (and more) operations on a single model object.
26
- #
27
- def assembly(request,message)
28
- if self.respond_to?(:before_assembly)
29
- request,message = send(:before_assembly,request,message)
30
- end
31
- data = Array.new
32
- @model_class.columns.each do |column|
33
- data << {'name'=>column.name,'type'=>column.type, 'limit'=>column.limit,
34
- 'nullable'=>column.null, 'primary'=>column.primary,
35
- 'default'=>column.default}
36
- end
37
- response = {'success'=>true,'columns'=>data}
38
- if self.respond_to?(:after_assembly)
39
- response = send(:after_assembly,response)
40
- end
41
- response
42
- end
43
-
44
- def create(request,message)
45
- if self.respond_to?(:before_create)
46
- request,message = send(:before_create,request,message)
47
- end
48
- o = @model_class.new(message)
49
- o.save
50
- response = {'success'=>true,'id'=>o.id}
51
- if self.respond_to?(:after_create)
52
- response = send(:after_create,response)
53
- end
54
- response
55
- end
56
-
57
- def retrieve(request,message)
58
- if self.respond_to?(:before_retrieve)
59
- request,message = send(:before_retrieve,request,message)
60
- end
61
- o = @model_class.find(message['id'])
62
- response = {'success'=>true}
63
- o.attributes.each do |key,val|
64
- response[key]=val
65
- end
66
- response
67
- if self.respond_to?(:after_retrieve)
68
- response = send(:after_retrieve,response)
69
- end
70
- response
71
- end
72
-
73
- def update(request,message)
74
- if self.respond_to?(:before_update)
75
- request,message = send(:before_update,request,message)
76
- end
77
- o = @model_class.find(message['id'])
78
- return {'success'=>false,'message'=>'record does not exist'} unless o
79
- message.each do |key,value|
80
- if o.attributes.has_key?(key)
81
- o[key]=true if value=='true'
82
- o[key]=false if value=='false'
83
- o[key]=value if o[key]!=true && o[key]!=false
84
- end
85
- end
86
- o.save!
87
- response = {'success'=>true,'id'=>o.id}
88
- if self.respond_to?(:after_update)
89
- response = send(:after_update,response)
90
- end
91
- response
92
- end
93
-
94
- def delete(request,message)
95
- if self.respond_to?(:before_delete)
96
- request,message = send(:before_delete,request,message)
97
- end
98
- @model_class.delete(message['id'])
99
- response = {'success'=>true,'id'=>message['id']}
100
- if self.respond_to?(:after_delete)
101
- response = send(:after_delete,response)
102
- end
103
- response
104
- end
105
-
106
- def search(request,message)
107
- if self.respond_to?(:before_search)
108
- request,message = send(:before_search,request,message)
109
- end
110
- query = '%%' + message['query'] + '%%'
111
- conditions_str = Array.new
112
- @model_class.content_columns.each do |col|
113
- name = col.name + ' like ?'
114
- conditions_str << name if col.type == :string
115
- end
116
-
117
- conditions = Array.new
118
- conditions << conditions_str.join(' OR ')
119
- conditions_str.length.times {|e| conditions<<query}
120
-
121
- results = @model_class.find(:all,:conditions=>conditions)
122
- response = {'success'=>true, 'rows'=>results, 'total'=>@model_class.count, 'count'=>results.length}
123
-
124
- if self.respond_to?(:after_search)
125
- response = send(:after_search,response)
126
- end
127
- response
128
- end
129
-
130
- def list(request,message)
131
- pk = message['id']
132
- limit = message['limit'] || 100
133
- if pk
134
- objs = [@model_class.find_by_id(pk)]
135
- else
136
- objs = @model_class.find(:all,:limit=>limit)
137
- end
138
- response = {'success'=>true,'rows'=>objs, 'total'=>@model_class.count}
139
- if self.respond_to?(:after_list)
140
- response = send(:after_list,response)
141
- end
142
- response
143
- end
144
-
17
+ # registration point for post-service-handling filters
18
+ def Service.after_filter(filter)
19
+ self.instance.after_filters << filter
20
+ end
145
21
 
146
- def self.load_services
147
- APP_SERVICES.clear
148
- # TODO: remove this and solve the multiple singleton issue
149
- Appcelerator::ServiceBroker.clear_listeners
150
- Dir[RAILS_ROOT + '/app/services/*_service.rb'].each do |file|
151
-
152
- name = Inflector.camelize(File.basename(file).chomp('_service.rb')) + 'Service'
153
-
154
- if Dependencies.load?
155
- if defined?(name)
156
- klass = eval(name)
157
- # clear the service class's existing listeners, if possible
158
- klass.instance.clear_listeners
159
- end
160
- load file
161
- else
162
- require file[0..-4]
163
- end
164
-
165
- begin
166
- klass = eval(name)
167
- klass.instance.register_listeners
168
- rescue
169
- puts 'Unable to find class "'+ name +'" in file "'+ file +'"'
170
- puts $!
171
- end
22
+ # for use by message handlers
23
+ attr_accessor :request,:params,:session,:message_type,:response,:response_type
24
+
25
+ # call this method from a before filter to prevent the remain handlers from running
26
+ def respond_with(response,response_type=nil)
27
+ @response = response
28
+ if response_type
29
+ @response_type = response_type
172
30
  end
173
- puts 'done loading services'
174
- puts Appcelerator::ServiceBroker.diagnostics
175
31
  end
176
32
 
177
- def initialize
178
- @listeners = []
179
- @preregistrations = []
180
- end
181
33
 
182
- def preregister(*args)
183
- @preregistrations << args
184
- end
34
+
35
+ # internal
36
+ attr_accessor :before_filters, :after_filters
185
37
 
186
- def register_listeners
187
- # call after class-load when all methods are defined
188
- @listeners = @preregistrations.map do |reg|
189
- register(*reg)
190
- end
191
- @preregistrations.clear
192
- @listeners.length
38
+ def initialize
39
+ @listeners = []
40
+ @before_filters = []
41
+ @after_filters = []
193
42
  end
194
43
 
195
44
  def clear_listeners
@@ -201,56 +50,204 @@ module Appcelerator
201
50
  num_cleared
202
51
  end
203
52
 
204
- def register(msgtype,methodname,responsetype = nil)
205
- service = self.class # add to the ServiceProc binding
206
- handler = self.method(methodname)
207
- args = handler.arity
208
- proc = ServiceProc.new do |req,msgtype,obj|
209
-
210
- #
211
- # try and be smart about sending in the request to the
212
- # service based on the arguments he supports
213
- #
214
- case args
215
- when 2
216
- resp = handler.call(req,obj)
217
- when 3
218
- resp = handler.call(req,obj,req['session'])
219
- when 4
220
- resp = handler.call(req,obj,req['session'],req['session']['username'])
221
- end
222
-
223
- if responsetype
224
- Dispatcher.instance.outgoing(req,responsetype,resp||{})
225
- end
53
+ def do_before_filters
54
+ @before_filters.each do |filter|
55
+ method(filter).call()
56
+ break if @response
57
+ end
58
+ end
59
+
60
+ def do_after_filters
61
+ @after_filters.each do |filter|
62
+ method(filter).call()
63
+ end
64
+ end
65
+
66
+ # handle a message
67
+ def handle(msg, method_name, response_type)
68
+ @request = msg.request
69
+ @session = msg.session
70
+ @message_type = msg.message_type
71
+ @params = msg.params
72
+ @response = nil # this is the handler's response, not the request/response pair
73
+ @response_type = response_type
74
+
75
+ do_before_filters()
76
+
77
+ # any response added by the before_filters prevents the handler from running
78
+ if not @response
79
+ @response = method(method_name).call()
80
+
81
+ do_after_filters()
226
82
  end
227
- ServiceBroker.register_listener(msgtype,proc)
83
+
84
+ if @response_type
85
+ msg.response_type = @response_type
86
+ msg.response = @response || {}
87
+ end
88
+ msg
89
+ end
90
+
91
+ def register(message_type, method_name, response_type = nil)
92
+ # adding to the ServiceProc binding, for preventing dups # this need may have been removed by properly reloading
93
+ service_name = self.class.name
94
+
95
+ proc = ServiceProc.new do |msg|
96
+ # is this const_get stuff important?
97
+ instance = Object.const_get(service_name).instance
98
+ instance.handle(msg,method_name,response_type)
99
+ end
100
+
101
+ ServiceBroker.register_listener(message_type, proc)
228
102
  proc
229
103
  end
230
-
231
- def send_message(req,type,message)
232
- ServiceBroker.send(req,type,message)
233
- end
234
104
 
235
- def secure_password_matches?(request,message,password_field,password)
236
-
237
- password_obj = message[password_field]
238
-
239
- if password_obj
240
- return Digest::MD5.hexdigest(password + request['authtoken']) == password_obj['auth']
241
- end
242
-
243
- false
244
- end
245
105
  end
246
106
 
107
+ # TODO: spin this into another file when we can resolve dependecy issues
108
+ class CrudService < Service
109
+
110
+ # registration point for crud services
111
+ def Service.service_scaffold(model)
112
+ servicename = model_name(model)
113
+ self.instance.model_class = eval(model.to_s.camelize)
114
+ %w(create retrieve update delete list assembly search).each do |operation|
115
+ messagetype = "app."+ servicename +"."+ operation
116
+ request = messagetype + ".request"
117
+ response = messagetype + ".response"
118
+ self.instance.register(request,operation,response)
119
+ APP_SERVICES << {'name'=>name, 'model'=>servicename}
120
+ end
121
+ end
122
+
123
+ attr_accessor :model_class
124
+
125
+ def assembly(request,message)
126
+ if self.respond_to?(:before_assembly)
127
+ request,message = send(:before_assembly,request,message)
128
+ end
129
+ data = Array.new
130
+ @model_class.columns.each do |column|
131
+ data << {'name'=>column.name,'type'=>column.type, 'limit'=>column.limit,
132
+ 'nullable'=>column.null, 'primary'=>column.primary,
133
+ 'default'=>column.default}
134
+ end
135
+ response = {'success'=>true,'columns'=>data}
136
+ if self.respond_to?(:after_assembly)
137
+ response = send(:after_assembly,response)
138
+ end
139
+ response
140
+ end
141
+
142
+ def create(request,message)
143
+ if self.respond_to?(:before_create)
144
+ request,message = send(:before_create,request,message)
145
+ end
146
+ o = @model_class.new(message)
147
+ o.save
148
+ response = {'success'=>true,'id'=>o.id}
149
+ if self.respond_to?(:after_create)
150
+ response = send(:after_create,response)
151
+ end
152
+ response
153
+ end
154
+
155
+ def retrieve(request,message)
156
+ if self.respond_to?(:before_retrieve)
157
+ request,message = send(:before_retrieve,request,message)
158
+ end
159
+ o = @model_class.find(message['id'])
160
+ response = {'success'=>true}
161
+ o.attributes.each do |key,val|
162
+ response[key]=val
163
+ end
164
+ response
165
+ if self.respond_to?(:after_retrieve)
166
+ response = send(:after_retrieve,response)
167
+ end
168
+ response
169
+ end
170
+
171
+ def update(request,message)
172
+ if self.respond_to?(:before_update)
173
+ request,message = send(:before_update,request,message)
174
+ end
175
+ o = @model_class.find(message['id'])
176
+ return {'success'=>false,'message'=>'record does not exist'} unless o
177
+ message.each do |key,value|
178
+ if o.attributes.has_key?(key)
179
+ o[key]=true if value=='true'
180
+ o[key]=false if value=='false'
181
+ o[key]=value if o[key]!=true && o[key]!=false
182
+ end
183
+ end
184
+ o.save!
185
+ response = {'success'=>true,'id'=>o.id}
186
+ if self.respond_to?(:after_update)
187
+ response = send(:after_update,response)
188
+ end
189
+ response
190
+ end
191
+
192
+ def delete(request,message)
193
+ if self.respond_to?(:before_delete)
194
+ request,message = send(:before_delete,request,message)
195
+ end
196
+ @model_class.delete(message['id'])
197
+ response = {'success'=>true,'id'=>message['id']}
198
+ if self.respond_to?(:after_delete)
199
+ response = send(:after_delete,response)
200
+ end
201
+ response
202
+ end
203
+
204
+ def search(request,message)
205
+ if self.respond_to?(:before_search)
206
+ request,message = send(:before_search,request,message)
207
+ end
208
+ query = '%%' + message['query'] + '%%'
209
+ conditions_str = Array.new
210
+ @model_class.content_columns.each do |col|
211
+ name = col.name + ' like ?'
212
+ conditions_str << name if col.type == :string
213
+ end
214
+
215
+ conditions = Array.new
216
+ conditions << conditions_str.join(' OR ')
217
+ conditions_str.length.times {|e| conditions<<query}
218
+
219
+ results = @model_class.find(:all,:conditions=>conditions)
220
+ response = {'success'=>true, 'rows'=>results, 'total'=>@model_class.count, 'count'=>results.length}
221
+
222
+ if self.respond_to?(:after_search)
223
+ response = send(:after_search,response)
224
+ end
225
+ response
226
+ end
227
+
228
+ def list(request,message)
229
+ pk = message['id']
230
+ limit = message['limit'] || 100
231
+ if pk
232
+ objs = [@model_class.find_by_id(pk)]
233
+ else
234
+ objs = @model_class.find(:all,:limit=>limit)
235
+ end
236
+ response = {'success'=>true,'rows'=>objs, 'total'=>@model_class.count}
237
+ if self.respond_to?(:after_list)
238
+ response = send(:after_list,response)
239
+ end
240
+ response
241
+ end
242
+ end
243
+
247
244
  #
248
245
  # Class to allow inspection and equality checking (for adding to sets)
249
246
  # TODO: remove the to_s in eql? and hash when the singleton issue is resolved
250
247
  #
251
248
  class ServiceProc < Proc
252
249
  def self.vars
253
- [:msgtype, :service, :methodname, :responsetype]
250
+ [:message_type, :service_name, :method_name, :response_type]
254
251
  end
255
252
 
256
253
  def method_missing name
@@ -258,7 +255,8 @@ module Appcelerator
258
255
  end
259
256
 
260
257
  def to_s
261
- "#{msgtype} -> #{service}.#{methodname} -> #{responsetype}"
258
+ service = Object.const_get(service_name).instance
259
+ "#{message_type} -> #{service.before_filters} #{service_name}.#{method_name} #{service.after_filters} -> #{response_type}"
262
260
  end
263
261
 
264
262
  def eql?(other)
@@ -288,5 +286,5 @@ module Appcelerator
288
286
  end
289
287
  return true
290
288
  end
291
- end
292
- end
289
+ end
290
+ end