appcelerator 2.0.1.1 → 2.0.2

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 (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