eric-adhearsion 0.7.999 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (150) hide show
  1. data/CHANGELOG +8 -2
  2. data/EVENTS +11 -0
  3. data/Rakefile +96 -24
  4. data/adhearsion.gemspec +148 -0
  5. data/app_generators/ahn/ahn_generator.rb +24 -9
  6. data/app_generators/ahn/templates/.ahnrc +25 -3
  7. data/app_generators/ahn/templates/Rakefile +22 -2
  8. data/app_generators/ahn/templates/components/ami_remote/ami_remote.rb +15 -0
  9. data/app_generators/ahn/templates/components/disabled/HOW_TO_ENABLE +7 -0
  10. data/app_generators/ahn/templates/components/disabled/stomp_gateway/README.markdown +47 -0
  11. data/app_generators/ahn/templates/components/disabled/stomp_gateway/config.yml +12 -0
  12. data/app_generators/ahn/templates/components/disabled/stomp_gateway/stomp_gateway.rb +34 -0
  13. data/app_generators/ahn/templates/components/simon_game/{lib/simon_game.rb → simon_game.rb} +14 -19
  14. data/app_generators/ahn/templates/config/startup.rb +3 -6
  15. data/app_generators/ahn/templates/dialplan.rb +2 -3
  16. data/app_generators/ahn/templates/events.rb +32 -0
  17. data/bin/jahn +10 -0
  18. data/examples/asterisk_manager_interface/standalone.rb +51 -0
  19. data/lib/adhearsion.rb +17 -11
  20. data/lib/adhearsion/cli.rb +141 -24
  21. data/lib/adhearsion/component_manager.rb +169 -238
  22. data/lib/adhearsion/component_manager/component_tester.rb +55 -0
  23. data/lib/adhearsion/component_manager/spec_framework.rb +24 -0
  24. data/lib/adhearsion/events_support.rb +84 -0
  25. data/lib/adhearsion/{core_extensions → foundation}/all.rb +0 -0
  26. data/lib/adhearsion/{blank_slate.rb → foundation/blank_slate.rb} +0 -0
  27. data/lib/adhearsion/{core_extensions → foundation}/custom_daemonizer.rb +0 -0
  28. data/lib/adhearsion/foundation/event_socket.rb +203 -0
  29. data/lib/adhearsion/foundation/future_resource.rb +36 -0
  30. data/lib/adhearsion/{core_extensions → foundation}/global.rb +0 -0
  31. data/lib/adhearsion/{core_extensions → foundation}/metaprogramming.rb +0 -0
  32. data/lib/adhearsion/foundation/numeric.rb +13 -0
  33. data/lib/adhearsion/foundation/pseudo_guid.rb +10 -0
  34. data/lib/adhearsion/{core_extensions → foundation}/relationship_properties.rb +2 -0
  35. data/lib/adhearsion/foundation/string.rb +26 -0
  36. data/lib/adhearsion/foundation/synchronized_hash.rb +96 -0
  37. data/lib/adhearsion/{core_extensions → foundation}/thread_safety.rb +0 -0
  38. data/lib/adhearsion/host_definitions.rb +5 -1
  39. data/lib/adhearsion/initializer.rb +229 -73
  40. data/lib/adhearsion/initializer/asterisk.rb +33 -11
  41. data/lib/adhearsion/initializer/configuration.rb +58 -6
  42. data/lib/adhearsion/initializer/database.rb +3 -46
  43. data/lib/adhearsion/initializer/drb.rb +9 -3
  44. data/lib/adhearsion/initializer/freeswitch.rb +3 -3
  45. data/lib/adhearsion/initializer/rails.rb +1 -1
  46. data/lib/adhearsion/tasks.rb +2 -1
  47. data/lib/adhearsion/tasks/deprecations.rb +59 -0
  48. data/lib/adhearsion/version.rb +3 -3
  49. data/lib/adhearsion/voip/asterisk.rb +2 -2
  50. data/lib/adhearsion/voip/asterisk/agi_server.rb +9 -6
  51. data/lib/adhearsion/voip/asterisk/commands.rb +106 -4
  52. data/lib/adhearsion/voip/asterisk/manager_interface.rb +562 -0
  53. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +1754 -0
  54. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +286 -0
  55. data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +78 -0
  56. data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +87 -0
  57. data/lib/adhearsion/voip/asterisk/super_manager.rb +19 -0
  58. data/lib/adhearsion/voip/call.rb +51 -2
  59. data/lib/adhearsion/voip/dial_plan.rb +74 -61
  60. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +1 -1
  61. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +2 -6
  62. data/lib/adhearsion/voip/dsl/numerical_string.rb +2 -2
  63. data/lib/adhearsion/voip/freeswitch/oes_server.rb +2 -2
  64. data/lib/theatre.rb +151 -0
  65. data/lib/theatre/README.markdown +64 -0
  66. data/lib/theatre/callback_definition_loader.rb +84 -0
  67. data/lib/theatre/guid.rb +23 -0
  68. data/lib/theatre/invocation.rb +121 -0
  69. data/lib/theatre/namespace_manager.rb +153 -0
  70. data/lib/theatre/version.rb +2 -0
  71. metadata +63 -138
  72. data/Manifest.txt +0 -149
  73. data/README.txt +0 -6
  74. data/ahn_generators/component/USAGE +0 -5
  75. data/ahn_generators/component/component_generator.rb +0 -57
  76. data/ahn_generators/component/templates/configuration.rb +0 -0
  77. data/ahn_generators/component/templates/lib/lib.rb.erb +0 -3
  78. data/ahn_generators/component/templates/test/test.rb.erb +0 -12
  79. data/ahn_generators/component/templates/test/test_helper.rb +0 -14
  80. data/app_generators/ahn/templates/components/simon_game/configuration.rb +0 -0
  81. data/app_generators/ahn/templates/components/simon_game/test/test_helper.rb +0 -14
  82. data/app_generators/ahn/templates/components/simon_game/test/test_simon_game.rb +0 -31
  83. data/lib/adhearsion/core_extensions/array.rb +0 -0
  84. data/lib/adhearsion/core_extensions/guid.rb +0 -5
  85. data/lib/adhearsion/core_extensions/hash.rb +0 -0
  86. data/lib/adhearsion/core_extensions/numeric.rb +0 -4
  87. data/lib/adhearsion/core_extensions/proc.rb +0 -0
  88. data/lib/adhearsion/core_extensions/pseudo_uuid.rb +0 -11
  89. data/lib/adhearsion/core_extensions/publishable.rb +0 -73
  90. data/lib/adhearsion/core_extensions/string.rb +0 -26
  91. data/lib/adhearsion/core_extensions/thread.rb +0 -13
  92. data/lib/adhearsion/core_extensions/time.rb +0 -0
  93. data/lib/adhearsion/distributed/gateways/dbus_gateway.rb +0 -0
  94. data/lib/adhearsion/distributed/gateways/osa_gateway.rb +0 -0
  95. data/lib/adhearsion/distributed/gateways/rest_gateway.rb +0 -9
  96. data/lib/adhearsion/distributed/gateways/soap_gateway.rb +0 -9
  97. data/lib/adhearsion/distributed/gateways/xmlrpc_gateway.rb +0 -9
  98. data/lib/adhearsion/distributed/peer_finder.rb +0 -0
  99. data/lib/adhearsion/distributed/remote_cli.rb +0 -0
  100. data/lib/adhearsion/hooks.rb +0 -57
  101. data/lib/adhearsion/initializer/paths.rb +0 -55
  102. data/lib/adhearsion/services/scheduler.rb +0 -5
  103. data/lib/adhearsion/voip/asterisk/ami.rb +0 -147
  104. data/lib/adhearsion/voip/asterisk/ami/actions.rb +0 -238
  105. data/lib/adhearsion/voip/asterisk/ami/machine.rb +0 -871
  106. data/lib/adhearsion/voip/asterisk/ami/machine.rl +0 -109
  107. data/lib/adhearsion/voip/asterisk/ami/parser.rb +0 -262
  108. data/script/destroy +0 -14
  109. data/script/generate +0 -14
  110. data/spec/fixtures/dialplan.rb +0 -3
  111. data/spec/initializer/test_configuration.rb +0 -267
  112. data/spec/initializer/test_loading.rb +0 -162
  113. data/spec/initializer/test_paths.rb +0 -43
  114. data/spec/silence.rb +0 -10
  115. data/spec/test_ahn_command.rb +0 -149
  116. data/spec/test_code_quality.rb +0 -87
  117. data/spec/test_component_manager.rb +0 -97
  118. data/spec/test_constants.rb +0 -8
  119. data/spec/test_drb.rb +0 -104
  120. data/spec/test_helper.rb +0 -94
  121. data/spec/test_hooks.rb +0 -37
  122. data/spec/test_host_definitions.rb +0 -79
  123. data/spec/test_initialization.rb +0 -105
  124. data/spec/test_logging.rb +0 -80
  125. data/spec/test_relationship_properties.rb +0 -54
  126. data/spec/voip/asterisk/ami_response_definitions.rb +0 -23
  127. data/spec/voip/asterisk/config_file_generators/test_agents.rb +0 -253
  128. data/spec/voip/asterisk/config_file_generators/test_queues.rb +0 -325
  129. data/spec/voip/asterisk/config_file_generators/test_voicemail.rb +0 -306
  130. data/spec/voip/asterisk/menu_command/test_calculated_match.rb +0 -111
  131. data/spec/voip/asterisk/menu_command/test_matchers.rb +0 -98
  132. data/spec/voip/asterisk/mock_ami_server.rb +0 -176
  133. data/spec/voip/asterisk/test_agi_server.rb +0 -451
  134. data/spec/voip/asterisk/test_ami.rb +0 -227
  135. data/spec/voip/asterisk/test_commands.rb +0 -2006
  136. data/spec/voip/asterisk/test_config_manager.rb +0 -129
  137. data/spec/voip/dsl/dispatcher_spec_helper.rb +0 -45
  138. data/spec/voip/dsl/test_dialing_dsl.rb +0 -268
  139. data/spec/voip/dsl/test_dispatcher.rb +0 -82
  140. data/spec/voip/dsl/test_parser.rb +0 -87
  141. data/spec/voip/freeswitch/test_basic_connection_manager.rb +0 -39
  142. data/spec/voip/freeswitch/test_inbound_connection_manager.rb +0 -39
  143. data/spec/voip/freeswitch/test_oes_server.rb +0 -9
  144. data/spec/voip/test_call_routing.rb +0 -127
  145. data/spec/voip/test_dialplan_manager.rb +0 -372
  146. data/spec/voip/test_numerical_string.rb +0 -48
  147. data/spec/voip/test_phone_number.rb +0 -36
  148. data/test/test_ahn_generator.rb +0 -59
  149. data/test/test_component_generator.rb +0 -52
  150. data/test/test_generator_helper.rb +0 -20
@@ -1,6 +1,10 @@
1
1
  require 'yaml'
2
2
 
3
3
  module Adhearsion
4
+
5
+ ##
6
+ # This class isn't yet tied into Adhearsion.
7
+ #
4
8
  class HostDefinition
5
9
 
6
10
  SUPPORTED_KEYS = [:host, :username, :password, :key, :name]
@@ -41,7 +45,7 @@ module Adhearsion
41
45
  attr_reader :name, :host, :username, :password, :key
42
46
  def initialize(hash)
43
47
  @host, @username, @password, @key, @name = hash.values_at(*SUPPORTED_KEYS)
44
- @name ||= uuid
48
+ @name ||= new_guid
45
49
 
46
50
  unrecognized_keys = hash.keys - SUPPORTED_KEYS
47
51
  raise HostDefinitionException, "Unrecognized key(s): #{unrecognized_keys.map(&:inspect).to_sentence}" if unrecognized_keys.any?
@@ -1,6 +1,45 @@
1
1
  module Adhearsion
2
2
 
3
+ class << self
4
+
5
+ ##
6
+ # Shuts down the framework.
7
+ #
8
+ def self.shutdown!
9
+ ahn_log "Shutting down gracefully at #{Time.now}."
10
+ Events.stop!
11
+ exit
12
+ end
13
+
14
+ end
3
15
  class PathString < String
16
+
17
+ class << self
18
+
19
+ ##
20
+ # Will return a PathString for the application root folder to which the specified arbitrarily nested subfolder belongs.
21
+ # It works by traversing parent directories looking for the .ahnrc file. If no .ahnrc is found, nil is returned.
22
+ #
23
+ # @param [String] folder The path to the directory which should be a
24
+ # @return [nil] if the subdirectory does not belong to a parent Adhearsion app directory
25
+ # @return [PathString] if a directory is found
26
+ #
27
+ def from_application_subdirectory(folder)
28
+ folder = File.expand_path folder
29
+ ahn_rc = nil
30
+
31
+ until ahn_rc || folder == "/"
32
+ possible_ahn_rc = File.join(folder, ".ahnrc")
33
+ if File.exists?(possible_ahn_rc)
34
+ ahn_rc = possible_ahn_rc
35
+ else
36
+ folder = File.expand_path(folder + "/..")
37
+ end
38
+ end
39
+ ahn_rc ? new(folder) : nil
40
+ end
41
+ end
42
+
4
43
  attr_accessor :component_path, :dialplan_path, :log_path
5
44
 
6
45
  def initialize(path)
@@ -27,10 +66,6 @@ module Adhearsion
27
66
  self.base_path = original_path
28
67
  end
29
68
 
30
- def dial_plan_named(name)
31
- File.join(dialplan_path, name)
32
- end
33
-
34
69
  private
35
70
  def build_path_for(path)
36
71
  File.join(to_s, path)
@@ -41,9 +76,7 @@ module Adhearsion
41
76
 
42
77
  class << self
43
78
  def get_rules_from(location)
44
- if File.directory? location
45
- location = File.join location, ".ahnrc"
46
- end
79
+ location = File.join location, ".ahnrc" if File.directory? location
47
80
  File.exists?(location) ? YAML.load_file(location) : nil
48
81
  end
49
82
 
@@ -55,18 +88,19 @@ module Adhearsion
55
88
  end
56
89
  end
57
90
 
91
+ def start(*args, &block)
92
+ new(*args, &block).start
93
+ end
94
+
58
95
  def start_from_init_file(file, ahn_app_path)
59
96
  return if defined?(@@started) && @@started
60
- new(ahn_app_path, :loaded_init_files => file)
97
+ start ahn_app_path, :loaded_init_files => file
61
98
  end
62
99
 
63
100
  end
64
101
 
65
102
  attr_reader :path, :daemon, :pid_file, :log_file, :ahn_app_log_directory
66
103
 
67
- DEFAULT_RULES = { :pattern => "*.rb",
68
- :directory => "helpers"}
69
-
70
104
  # Creation of pid_files
71
105
  #
72
106
  # - You may want to have Adhearsion create a process identification
@@ -80,39 +114,49 @@ module Adhearsion
80
114
  # even in daemon mode by supplying "false".
81
115
  def initialize(path=nil, options={})
82
116
  @@started = true
83
- @path = path
84
- @daemon = options[:daemon]
85
- @pid_file = options[:pid_file].nil? ? ENV['PID_FILE'] : options[:pid_file]
86
- @loaded_init_files = options[:loaded_init_files]
117
+ @path = path
118
+ @daemon = options[:daemon]
119
+ @pid_file = options[:pid_file].nil? ? ENV['PID_FILE'] : options[:pid_file]
120
+ @loaded_init_files = options[:loaded_init_files]
121
+ end
122
+
123
+ def start
87
124
  self.class.ahn_root = path
125
+
88
126
  resolve_pid_file_path
89
127
  resolve_log_file_path
90
128
  switch_to_root_directory
91
129
  catch_termination_signal
92
130
  bootstrap_rc
93
- load_all_init_files
94
- init_modules
95
131
  daemonize! if should_daemonize?
96
132
  initialize_log_file
133
+ load_all_init_files
134
+ init_components_subsystem
135
+ init_modules
136
+ init_events_subsystem
97
137
  create_pid_file if pid_file
98
138
  load_components
139
+ init_events_file
99
140
 
100
141
  ahn_log "Adhearsion initialized!"
101
142
 
102
143
  trigger_after_initialized_hooks
103
- join_framework_threads
144
+ join_important_threads
145
+
146
+ self
104
147
  end
105
148
 
106
- def initialize_log_file
107
- Dir.mkdir(ahn_app_log_directory) unless File.directory? ahn_app_log_directory
108
- file_logger = Log4r::FileOutputter.new("Main Adhearsion log file", :filename => log_file, :trunc => false)
109
-
110
- if should_daemonize?
111
- Adhearsion::Logging::AdhearsionLogger.outputters = file_logger
112
- else
113
- Adhearsion::Logging::AdhearsionLogger.outputters << file_logger
149
+ def default_pid_path
150
+ File.join AHN_ROOT, 'adhearsion.pid'
151
+ end
152
+
153
+ def resolve_pid_file_path
154
+ @pid_file = if pid_file.equal?(true) then default_pid_path
155
+ elsif pid_file then pid_file
156
+ elsif pid_file.equal?(false) then nil
157
+ # FIXME @pid_file = @daemon? Assignment or equality? I'm assuming equality.
158
+ else @pid_file = @daemon ? default_pid_path : nil
114
159
  end
115
- Adhearsion::Logging::DefaultAdhearsionLogger.redefine_outputters
116
160
  end
117
161
 
118
162
  def resolve_log_file_path
@@ -120,16 +164,99 @@ module Adhearsion
120
164
  @log_file = File.expand_path(ahn_app_log_directory + "/adhearsion.log")
121
165
  end
122
166
 
123
- def create_pid_file(file = pid_file)
124
- if file
125
- File.open pid_file, 'w' do |file|
126
- file.puts Process.pid
167
+ def switch_to_root_directory
168
+ Dir.chdir AHN_ROOT
169
+ end
170
+
171
+ def catch_termination_signal
172
+ %w'INT TERM'.each do |process_signal|
173
+ trap process_signal do
174
+ ahn_log "Shutting down gracefully at #{Time.now}."
175
+ Events.trigger :shutdown
176
+ exit
127
177
  end
128
-
129
- Hooks::TearDown.create_hook do
130
- File.delete(pid_file) if File.exists?(pid_file)
178
+ end
179
+ end
180
+
181
+ ##
182
+ # This step in the initialization process loads the .ahnrc in the given app folder. With the information in .ahnrc, we
183
+ # can continue the initialization knowing where certain files are specifically.
184
+ #
185
+ def bootstrap_rc
186
+ rules = self.class.get_rules_from AHN_ROOT
187
+
188
+ AHN_CONFIG.ahnrc = rules
189
+
190
+ # DEPRECATION: Check if the old paths format is being used. If so, abort and notify.
191
+ if rules.has_key?("paths") && rules["paths"].kind_of?(Hash)
192
+ paths = rules["paths"].each_pair do |key,value|
193
+ if value.kind_of?(Hash)
194
+ if value.has_key?("directory") || value.has_key?("pattern")
195
+ puts
196
+ puts *caller
197
+ puts
198
+
199
+ abort <<-WARNING
200
+ Deprecation Warning
201
+ -------------------
202
+ The (hidden) .ahnrc file in this app is of an older format and needs to be fixed.
203
+
204
+ There is a rake task to automatically fix it or you can do it manually. Note: it's
205
+ best if you do it manually so you can retain the YAML comments in your .ahnrc file.
206
+
207
+ The rake task is called "deprecations:fix_ahnrc_path_format".
208
+
209
+ To do it manually, find all entries in the "paths" section of your ".ahnrc" file
210
+ which look like the following:
211
+
212
+ paths:
213
+ key_name_could_be_anything:
214
+ directory: some_folder
215
+ pattern: *.rb
216
+
217
+ Note: the "models" section had this syntax before:
218
+
219
+ models:
220
+ directory: models
221
+ pattern: "*.rb"
222
+
223
+ The NEW syntax is as follows (using models as an example):
224
+
225
+ models: models/*.rb
226
+
227
+ This new format is much cleaner.
228
+
229
+ Adhearsion will abort until you fix this. Sorry for the incovenience.
230
+ WARNING
231
+ end
232
+ end
131
233
  end
132
234
  end
235
+
236
+ gems = rules['gems']
237
+ if gems.kind_of?(Hash) && gems.any? && respond_to?(:gem)
238
+ gems.each_pair do |gem_name,properties_hash|
239
+ if properties_hash && properties_hash["version"]
240
+ gem gem_name, properties_hash["version"]
241
+ else
242
+ gem gem_name
243
+ end
244
+ if properties_hash
245
+ case properties_hash["require"]
246
+ when Array
247
+ properties_hash["require"].each { |lib| require lib }
248
+ when String
249
+ require properties_hash["require"]
250
+ end
251
+ end
252
+ end
253
+ end
254
+ end
255
+
256
+ def load_all_init_files
257
+ init_files_from_rc = AHN_CONFIG.files_from_setting("paths", "init").map { |file| File.expand_path(file) }
258
+ already_loaded_init_files = Array(@loaded_init_files).map { |file| File.expand_path(file) }
259
+ (init_files_from_rc - already_loaded_init_files).each { |init| load init }
133
260
  end
134
261
 
135
262
  def init_modules
@@ -146,28 +273,23 @@ module Adhearsion
146
273
  # FreeswitchInitializer.start if AHN_CONFIG.freeswitch_enabled?
147
274
  end
148
275
 
149
- def resolve_pid_file_path
150
- @pid_file = if pid_file.equal?(true) then default_pid_path
151
- elsif pid_file then pid_file
152
- elsif pid_file.equal?(false) then nil
153
- # FIXME @pid_file = @daemon? Assignment or equality? I'm assuming equality.
154
- else @pid_file = @daemon ? default_pid_path : nil
276
+ def init_events_subsystem
277
+ application_events_files = AHN_CONFIG.files_from_setting("paths", "events")
278
+ if application_events_files.any?
279
+ Events.register_callback(:shutdown) do
280
+ ahn_log.events "Performing a graceful stop of events subsystem"
281
+ Events.framework_theatre.graceful_stop!
282
+ end
283
+ Events.framework_theatre.start!
284
+ else
285
+ ahn_log.events.warn 'No entries in the "events" section of .ahnrc. Skipping its initialization.'
155
286
  end
156
287
  end
157
288
 
158
- def switch_to_root_directory
159
- Dir.chdir AHN_ROOT
160
- end
161
-
162
- def catch_termination_signal
163
- Hooks::TearDown.catch_termination_signals
164
- end
165
-
166
- def load_all_init_files
167
- if Paths.manager_for? "init"
168
- init_files_from_rc = all_inits.map { |file| File.expand_path(file) }
169
- already_loaded_init_files = Array(@loaded_init_files).map { |file| File.expand_path(file) }
170
- (init_files_from_rc - already_loaded_init_files).each { |init| load init }
289
+ def init_events_file
290
+ application_events_files = AHN_CONFIG.files_from_setting("paths", "events")
291
+ application_events_files.each do |file|
292
+ Events.framework_theatre.load_events_file file
171
293
  end
172
294
  end
173
295
 
@@ -181,35 +303,69 @@ module Adhearsion
181
303
  daemonize log_file
182
304
  end
183
305
 
184
- def load_components
185
- ComponentManager.load
186
- ComponentManager.start
306
+ def initialize_log_file
307
+ Dir.mkdir(ahn_app_log_directory) unless File.directory? ahn_app_log_directory
308
+ file_logger = Log4r::FileOutputter.new("Main Adhearsion log file", :filename => log_file, :trunc => false)
309
+
310
+ if should_daemonize?
311
+ Logging::AdhearsionLogger.outputters = file_logger
312
+ else
313
+ Logging::AdhearsionLogger.outputters << file_logger
314
+ end
315
+ Logging::DefaultAdhearsionLogger.redefine_outputters
187
316
  end
188
317
 
189
- def trigger_after_initialized_hooks
190
- Hooks::AfterInitialized.trigger_hooks
318
+ def create_pid_file(file = pid_file)
319
+ if file
320
+ File.open pid_file, 'w' do |file|
321
+ file.puts Process.pid
322
+ end
323
+
324
+ Events.register_callback :shutdown do
325
+ File.delete(pid_file) if File.exists?(pid_file)
326
+ end
327
+ end
191
328
  end
192
329
 
193
- def join_framework_threads
194
- Hooks::ThreadsJoinedAfterInitialized.trigger_hooks
330
+ def init_components_subsystem
331
+ @components_directory = File.expand_path "components"
332
+ if File.directory? @components_directory
333
+ Components.component_manager = Components::ComponentManager.new @components_directory
334
+ Kernel.send(:const_set, :COMPONENTS, Components.component_manager.lazy_config_loader)
335
+ Components.component_manager.globalize_global_scope!
336
+ Components.component_manager.extend_object_with(Theatre::CallbackDefinitionLoader, :events)
337
+ else
338
+ ahn_log.warn "No components directory found. Not initializing any components."
339
+ end
195
340
  end
196
341
 
197
- def bootstrap_rc
198
- rules = Initializer.get_rules_from(AHN_ROOT) || DEFAULT_RULES
199
- paths = rules['paths'] || DEFAULT_RULES
200
- paths.each_pair do |k,v|
201
- if v.kind_of? Hash
202
- directory, pattern = v['directory'] || '.', v['pattern'] || '*'
203
- Paths.manager_for k, :pattern => File.join(directory, pattern)
204
- else
205
- directory, pattern = '.', v
206
- Paths.manager_for k, :pattern => File.join(directory,pattern)
207
- end
342
+ def load_components
343
+ if Components.component_manager
344
+ Components.component_manager.load_components
208
345
  end
209
346
  end
210
347
 
211
- def default_pid_path
212
- File.join AHN_ROOT, 'adhearsion.pid'
348
+ def trigger_after_initialized_hooks
349
+ Events.trigger_immediately :after_initialized
350
+ end
351
+
352
+ ##
353
+ # This method will block Thread.main() until calling join() has returned for all Threads in IMPORTANT_THREADS.
354
+ # Note: IMPORTANT_THREADS won't always contain Thread instances. It simply requires the objects respond to join().
355
+ #
356
+ def join_important_threads
357
+ # Note: we're using this ugly accumulator to ensure that all threads have ended since IMPORTANT_THREADS will almost
358
+ # certainly change sizes after this method is called.
359
+ index = 0
360
+ until index == IMPORTANT_THREADS.size
361
+ begin
362
+ IMPORTANT_THREADS[index].join
363
+ rescue => e
364
+ ahn_log.error "Error after join()ing Thread #{thread.inspect}. #{e.message}"
365
+ ensure
366
+ index = index + 1
367
+ end
368
+ end
213
369
  end
214
370
 
215
371
  class InitializationFailedError < Exception; end
@@ -8,9 +8,9 @@ module Adhearsion
8
8
  class << self
9
9
 
10
10
  def start
11
- self.config = Adhearsion::AHN_CONFIG.asterisk
11
+ self.config = AHN_CONFIG.asterisk
12
12
  self.agi_server = initialize_agi
13
- self.ami_client = initialize_ami if config.ami_enabled?
13
+ self.ami_client = VoIP::Asterisk.manager_interface = initialize_ami if config.ami_enabled?
14
14
  join_server_thread_after_initialized
15
15
  end
16
16
 
@@ -22,16 +22,25 @@ module Adhearsion
22
22
  private
23
23
 
24
24
  def initialize_agi
25
- Adhearsion::VoIP::Asterisk::AGI::Server.new :host => config.listening_host,
26
- :port => config.listening_port
25
+ VoIP::Asterisk::AGI::Server.new :host => config.listening_host,
26
+ :port => config.listening_port
27
27
  end
28
28
 
29
29
  def initialize_ami
30
30
  options = ami_options
31
31
  start_ami_after_initialized
32
- Adhearsion::VoIP::Asterisk::AMI.new options[:username], options[:password],
33
- options[:host], :port => options[:port],
34
- :events => options[:events]
32
+ returning VoIP::Asterisk::Manager::ManagerInterface.new(options) do
33
+ class << VoIP::Asterisk
34
+ if respond_to?(:manager_interface)
35
+ ahn_log.warn "Asterisk.manager_interface already initialized?"
36
+ else
37
+ def manager_interface
38
+ # ahn_log.ami.warn "Warning! This Asterisk.manager_interface() notation is for Adhearsion version 0.8.0 only. Subsequent versions of Adhearsion will use a feature called SuperManager. Migrating to use SuperManager will be very simple. See http://docs.adhearsion.com/AMI for more information."
39
+ Adhearsion::Initializer::AsteriskInitializer.ami_client
40
+ end
41
+ end
42
+ end
43
+ end
35
44
  end
36
45
 
37
46
  def ami_options
@@ -42,13 +51,26 @@ module Adhearsion
42
51
  end
43
52
 
44
53
  def join_server_thread_after_initialized
45
- Adhearsion::Hooks::AfterInitialized.create_hook { agi_server.start }
46
- Adhearsion::Hooks::ThreadsJoinedAfterInitialized.create_hook { agi_server.join }
54
+ Events.register_callback(:after_initialized) do
55
+ begin
56
+ agi_server.start
57
+ rescue => e
58
+ ahn_log.fatal "Failed to start AGI server! #{e.inspect}"
59
+ abort
60
+ end
61
+ end
62
+ IMPORTANT_THREADS << agi_server
47
63
  end
48
64
 
49
65
  def start_ami_after_initialized
50
- Adhearsion::Hooks::AfterInitialized.create_hook do
51
- ami_client.connect!
66
+ Events.register_callback(:after_initialized) do
67
+ begin
68
+ self.ami_client.connect!
69
+ rescue Errno::ECONNREFUSED
70
+ ahn_log.ami.error "Connection refused when connecting to AMI! Please check your configuration."
71
+ rescue => e
72
+ ahn_log.ami.error "Error connecting to AMI! #{e.inspect}"
73
+ end
52
74
  end
53
75
  end
54
76