adhearsion-cw 1.0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/CHANGELOG +109 -0
  2. data/EVENTS +11 -0
  3. data/Gemfile +3 -0
  4. data/LICENSE +456 -0
  5. data/Rakefile +134 -0
  6. data/adhearsion.gemspec +174 -0
  7. data/app_generators/ahn/USAGE +5 -0
  8. data/app_generators/ahn/ahn_generator.rb +97 -0
  9. data/app_generators/ahn/templates/.ahnrc +34 -0
  10. data/app_generators/ahn/templates/Gemfile +7 -0
  11. data/app_generators/ahn/templates/README +8 -0
  12. data/app_generators/ahn/templates/Rakefile +27 -0
  13. data/app_generators/ahn/templates/components/ami_remote/ami_remote.rb +15 -0
  14. data/app_generators/ahn/templates/components/disabled/HOW_TO_ENABLE +7 -0
  15. data/app_generators/ahn/templates/components/disabled/restful_rpc/README.markdown +11 -0
  16. data/app_generators/ahn/templates/components/disabled/restful_rpc/example-client.rb +48 -0
  17. data/app_generators/ahn/templates/components/disabled/restful_rpc/restful_rpc.rb +91 -0
  18. data/app_generators/ahn/templates/components/disabled/restful_rpc/restful_rpc.yml +34 -0
  19. data/app_generators/ahn/templates/components/disabled/restful_rpc/spec/restful_rpc_spec.rb +251 -0
  20. data/app_generators/ahn/templates/components/disabled/sandbox/sandbox.rb +104 -0
  21. data/app_generators/ahn/templates/components/disabled/sandbox/sandbox.yml +2 -0
  22. data/app_generators/ahn/templates/components/disabled/stomp_gateway/README.markdown +47 -0
  23. data/app_generators/ahn/templates/components/disabled/stomp_gateway/stomp_gateway.rb +34 -0
  24. data/app_generators/ahn/templates/components/disabled/stomp_gateway/stomp_gateway.yml +12 -0
  25. data/app_generators/ahn/templates/components/disabled/xmpp_gateway/README.markdown +3 -0
  26. data/app_generators/ahn/templates/components/disabled/xmpp_gateway/xmpp_gateway.rb +11 -0
  27. data/app_generators/ahn/templates/components/disabled/xmpp_gateway/xmpp_gateway.yml +0 -0
  28. data/app_generators/ahn/templates/components/simon_game/simon_game.rb +56 -0
  29. data/app_generators/ahn/templates/config/startup.rb +74 -0
  30. data/app_generators/ahn/templates/dialplan.rb +3 -0
  31. data/app_generators/ahn/templates/events.rb +32 -0
  32. data/bin/ahn +29 -0
  33. data/bin/ahnctl +68 -0
  34. data/bin/jahn +43 -0
  35. data/examples/asterisk_manager_interface/standalone.rb +51 -0
  36. data/lib/adhearsion/cli.rb +296 -0
  37. data/lib/adhearsion/component_manager/component_tester.rb +53 -0
  38. data/lib/adhearsion/component_manager/spec_framework.rb +18 -0
  39. data/lib/adhearsion/component_manager.rb +272 -0
  40. data/lib/adhearsion/events_support.rb +84 -0
  41. data/lib/adhearsion/foundation/all.rb +15 -0
  42. data/lib/adhearsion/foundation/blank_slate.rb +3 -0
  43. data/lib/adhearsion/foundation/custom_daemonizer.rb +45 -0
  44. data/lib/adhearsion/foundation/event_socket.rb +205 -0
  45. data/lib/adhearsion/foundation/future_resource.rb +36 -0
  46. data/lib/adhearsion/foundation/metaprogramming.rb +17 -0
  47. data/lib/adhearsion/foundation/numeric.rb +13 -0
  48. data/lib/adhearsion/foundation/pseudo_guid.rb +10 -0
  49. data/lib/adhearsion/foundation/relationship_properties.rb +42 -0
  50. data/lib/adhearsion/foundation/string.rb +26 -0
  51. data/lib/adhearsion/foundation/synchronized_hash.rb +96 -0
  52. data/lib/adhearsion/foundation/thread_safety.rb +7 -0
  53. data/lib/adhearsion/host_definitions.rb +67 -0
  54. data/lib/adhearsion/initializer/asterisk.rb +87 -0
  55. data/lib/adhearsion/initializer/configuration.rb +321 -0
  56. data/lib/adhearsion/initializer/database.rb +60 -0
  57. data/lib/adhearsion/initializer/drb.rb +31 -0
  58. data/lib/adhearsion/initializer/freeswitch.rb +22 -0
  59. data/lib/adhearsion/initializer/ldap.rb +57 -0
  60. data/lib/adhearsion/initializer/rails.rb +41 -0
  61. data/lib/adhearsion/initializer/xmpp.rb +42 -0
  62. data/lib/adhearsion/initializer.rb +394 -0
  63. data/lib/adhearsion/logging.rb +92 -0
  64. data/lib/adhearsion/tasks/components.rb +32 -0
  65. data/lib/adhearsion/tasks/database.rb +5 -0
  66. data/lib/adhearsion/tasks/deprecations.rb +59 -0
  67. data/lib/adhearsion/tasks/generating.rb +20 -0
  68. data/lib/adhearsion/tasks/lint.rb +4 -0
  69. data/lib/adhearsion/tasks/testing.rb +37 -0
  70. data/lib/adhearsion/tasks.rb +17 -0
  71. data/lib/adhearsion/version.rb +35 -0
  72. data/lib/adhearsion/voip/asterisk/agi_server.rb +115 -0
  73. data/lib/adhearsion/voip/asterisk/commands.rb +1581 -0
  74. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +140 -0
  75. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +102 -0
  76. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +250 -0
  77. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +240 -0
  78. data/lib/adhearsion/voip/asterisk/config_manager.rb +71 -0
  79. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +1681 -0
  80. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +341 -0
  81. data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +78 -0
  82. data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +87 -0
  83. data/lib/adhearsion/voip/asterisk/manager_interface.rb +705 -0
  84. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +80 -0
  85. data/lib/adhearsion/voip/asterisk/super_manager.rb +19 -0
  86. data/lib/adhearsion/voip/asterisk.rb +4 -0
  87. data/lib/adhearsion/voip/call.rb +498 -0
  88. data/lib/adhearsion/voip/call_routing.rb +64 -0
  89. data/lib/adhearsion/voip/commands.rb +9 -0
  90. data/lib/adhearsion/voip/constants.rb +39 -0
  91. data/lib/adhearsion/voip/conveniences.rb +18 -0
  92. data/lib/adhearsion/voip/dial_plan.rb +250 -0
  93. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +37 -0
  94. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +151 -0
  95. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +27 -0
  96. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +124 -0
  97. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +69 -0
  98. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +16 -0
  99. data/lib/adhearsion/voip/dsl/numerical_string.rb +128 -0
  100. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +48 -0
  101. data/lib/adhearsion/voip/freeswitch/event_handler.rb +58 -0
  102. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +129 -0
  103. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +38 -0
  104. data/lib/adhearsion/voip/freeswitch/oes_server.rb +195 -0
  105. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +80 -0
  106. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +123 -0
  107. data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +57 -0
  108. data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +149 -0
  109. data/lib/adhearsion/xmpp/connection.rb +61 -0
  110. data/lib/adhearsion.rb +46 -0
  111. data/lib/theatre/README.markdown +64 -0
  112. data/lib/theatre/callback_definition_loader.rb +84 -0
  113. data/lib/theatre/guid.rb +23 -0
  114. data/lib/theatre/invocation.rb +121 -0
  115. data/lib/theatre/namespace_manager.rb +153 -0
  116. data/lib/theatre/version.rb +2 -0
  117. data/lib/theatre.rb +151 -0
  118. metadata +323 -0
@@ -0,0 +1,60 @@
1
+ # TODO: Have all of the initializer modules required and then traverse the subclasses, asking them if they're enabled. If they are enabled, then they should do their initialization stuff. Is this really necessary to develop this entirely new system when the components system exists?
2
+
3
+ module Adhearsion
4
+ class Initializer
5
+
6
+ class DatabaseInitializer
7
+
8
+ class << self
9
+
10
+ def start
11
+ require_dependencies
12
+ require_models
13
+ @@config = Adhearsion::AHN_CONFIG.database
14
+ # You may need to uncomment the following line for older versions of ActiveRecord
15
+ # ActiveRecord::Base.allow_concurrency = true
16
+ establish_connection
17
+ ActiveRecord::Base.logger =
18
+ @@config.connection_options.has_key?(:logger) ?
19
+ @@config.connection_options[:logger] :
20
+ ahn_log.db
21
+ create_call_hook_for_connection_cleanup
22
+ end
23
+
24
+ def stop
25
+ ActiveRecord::Base.remove_connection
26
+ end
27
+
28
+ private
29
+
30
+ def create_call_hook_for_connection_cleanup
31
+ Events.register_callback([:asterisk, :before_call]) do
32
+ ActiveRecord::Base.verify_active_connections!
33
+ end
34
+ end
35
+
36
+ def require_dependencies
37
+ begin
38
+ require 'active_record'
39
+ rescue LoadError
40
+ ahn_log.fatal "Database support requires the \"activerecord\" gem."
41
+ # Silence the abort so we don't get an ugly backtrace
42
+ abort ""
43
+ end
44
+ end
45
+
46
+ def require_models
47
+ AHN_CONFIG.files_from_setting("paths", "models").each do |model|
48
+ load model
49
+ end
50
+ end
51
+
52
+ def establish_connection
53
+ ActiveRecord::Base.establish_connection @@config.connection_options
54
+ end
55
+
56
+ end
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,31 @@
1
+ require 'drb'
2
+ require 'drb/acl'
3
+ require 'thread'
4
+
5
+ module Adhearsion
6
+ class Initializer
7
+
8
+ class DrbInitializer
9
+
10
+ class << self
11
+
12
+ def start
13
+ config = Adhearsion::AHN_CONFIG.drb
14
+ DRb.install_acl ACL.new(config.acl) if config.acl
15
+
16
+ drb_door = Object.new
17
+ Components.component_manager.extend_object_with(drb_door, :rpc)
18
+
19
+ DRb.start_service "druby://#{config.host}:#{config.port}", drb_door
20
+
21
+ ahn_log "Starting DRb on #{config.host}:#{config.port}"
22
+ end
23
+
24
+ def stop
25
+ DRb.stop_service
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,22 @@
1
+ # THIS FREESWITCH LIBRARY HASN'T BEEN INTEGRATED INTO THE REFACTORED 0.8.0 YET.
2
+ # WHAT EXISTS HERE IS OLD, MUST BE CHANGED, AND DOES NOT EVEN GET LOADED AT THE MOMENT.
3
+ require "adhearsion/voip/freeswitch/oes_server"
4
+ require "adhearsion/voip/freeswitch/event_handler"
5
+ require "adhearsion/voip/freeswitch/inbound_connection_manager"
6
+ require "adhearsion/voip/dsl/dialplan/control_passing_exception"
7
+
8
+ oes_enabled = Adhearsion::Configuration.core.voip.freeswitch.oes && Adhearsion::Configuration.core.voip.freeswitch.oes.port
9
+
10
+
11
+ if oes_enabled
12
+
13
+ port = Adhearsion::Configuration.core.voip.freeswitch.oes.port
14
+ host = Adhearsion::Configuration.core.voip.freeswitch.oes.host
15
+
16
+ server = Adhearsion::VoIP::FreeSwitch::OesServer.new port, host
17
+
18
+ Events.register_callback(:after_initialized) { server.start }
19
+ Events.register_callback(:shutdown) { server.stop }
20
+ IMPORTANT_THREADS << server
21
+
22
+ end
@@ -0,0 +1,57 @@
1
+ # TODO: Have all of the initializer modules required and then traverse the subclasses, asking them if they're enabled. If they are enabled, then they should do their initialization stuff. Is this really necessary to develop this entirely new system when the components system exists?
2
+
3
+ module Adhearsion
4
+ class Initializer
5
+
6
+ class LdapInitializer
7
+
8
+ class << self
9
+
10
+ def start
11
+ require_dependencies
12
+ require_models
13
+ @@config = Adhearsion::AHN_CONFIG.ldap
14
+ # You may need to uncomment the following line for older versions of ActiveRecord
15
+ # ActiveRecord::Base.allow_concurrency = true
16
+ establish_connection
17
+ end
18
+
19
+ def stop
20
+ ActiveLdap::Base.remove_connection
21
+ end
22
+
23
+ private
24
+
25
+ # TODO: It appears that ActiveLdap does not have a connection validation
26
+ # or reconnection routine.
27
+ #def create_call_hook_for_connection_cleanup
28
+ # Events.register_callback([:asterisk, :before_call]) do
29
+ # ActiveLdap::Base.verify_active_connections!
30
+ # end
31
+ #end
32
+
33
+ def require_dependencies
34
+ begin
35
+ require 'active_ldap'
36
+ rescue LoadError
37
+ ahn_log.fatal "LDAP support requires the \"activeldap\" gem."
38
+ # Silence the abort so we don't get an ugly backtrace
39
+ abort ""
40
+ end
41
+ end
42
+
43
+ def require_models
44
+ AHN_CONFIG.files_from_setting("paths", "models").each do |model|
45
+ load model
46
+ end
47
+ end
48
+
49
+ def establish_connection
50
+ ActiveLdap::Base.setup_connection @@config.connection_options
51
+ end
52
+
53
+ end
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,41 @@
1
+ require 'adhearsion/voip/asterisk'
2
+
3
+ module Adhearsion
4
+ class Initializer
5
+ class RailsInitializer
6
+
7
+ cattr_accessor :rails_root, :config, :environment
8
+ class << self
9
+
10
+ def start
11
+ ahn_config = Adhearsion::AHN_CONFIG
12
+ self.config = ahn_config.rails
13
+ self.rails_root = config.rails_root
14
+ self.environment = config.environment
15
+ raise "You cannot enable the database and Rails at the same time!" if ahn_config.database_enabled?
16
+ raise "Error loading Rails environment in #{rails_root.inspect}. " +
17
+ "It's not a directory!" unless File.directory?(rails_root)
18
+ load_rails
19
+ if defined? ActiveRecord
20
+ # You may need to uncomment the following line for older versions of ActiveRecord
21
+ # ActiveRecord::Base.allow_concurrency = true
22
+ Events.register_callback([:asterisk, :before_call]) do
23
+ ActiveRecord::Base.verify_active_connections!
24
+ end
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def load_rails
31
+ environment_file = File.expand_path(rails_root + "/config/environment.rb")
32
+ raise "There is no config/environment.rb file!" unless File.exists?(environment_file)
33
+ ENV['RAILS_ENV'] = environment.to_s
34
+ require environment_file
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,42 @@
1
+ require 'adhearsion/xmpp/connection.rb'
2
+
3
+ module Adhearsion
4
+ class Initializer
5
+ class XMPPInitializer
6
+
7
+ cattr_accessor :config, :jid, :password, :server, :port
8
+ class << self
9
+
10
+ def start
11
+ require_dependencies
12
+ XMPP::Connection.extend Blather::DSL
13
+ ahn_config = Adhearsion::AHN_CONFIG
14
+ self.config = ahn_config.xmpp
15
+ self.jid = config.jid
16
+ self.password = config.password
17
+ self.server = config.server
18
+ self.port = config.port
19
+
20
+ XMPP::Connection.start(jid, password, server, port)
21
+ end
22
+
23
+ def stop
24
+ XMPP::Connection.stop
25
+ end
26
+
27
+ private
28
+
29
+ def require_dependencies
30
+ begin
31
+ require 'blather/client/client'
32
+ require 'blather/client/dsl'
33
+ rescue LoadError
34
+ ahn_log.fatal "XMPP support requires the \"blather\" gem."
35
+ # Silence the abort so we don't get an ugly backtrace
36
+ abort ""
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,394 @@
1
+ module Adhearsion
2
+
3
+ mattr_accessor :status
4
+
5
+ class << self
6
+
7
+ ##
8
+ # Shuts down the framework.
9
+ #
10
+ def shutdown!
11
+ if self.status == :stopping
12
+ # This is the second shutdown request we've received while attempting
13
+ # to shut down gracefully. At this point, let's pull the plug...
14
+ ahn_log.warning "Shutting down immediately at #{Time.now}"
15
+ exit
16
+ end
17
+ ahn_log "Shutting down gracefully at #{Time.now}."
18
+ self.status = :stopping
19
+ Events.trigger_immediately :shutdown
20
+ Events.stop!
21
+ exit
22
+ end
23
+
24
+ end
25
+ class PathString < String
26
+
27
+ class << self
28
+
29
+ ##
30
+ # Will return a PathString for the application root folder to which the specified arbitrarily nested subfolder belongs.
31
+ # It works by traversing parent directories looking for the .ahnrc file. If no .ahnrc is found, nil is returned.
32
+ #
33
+ # @param [String] folder The path to the directory which should be a
34
+ # @return [nil] if the subdirectory does not belong to a parent Adhearsion app directory
35
+ # @return [PathString] if a directory is found
36
+ #
37
+ def from_application_subdirectory(folder)
38
+ folder = File.expand_path folder
39
+ ahn_rc = nil
40
+
41
+ until ahn_rc || folder == "/"
42
+ possible_ahn_rc = File.join(folder, ".ahnrc")
43
+ if File.exists?(possible_ahn_rc)
44
+ ahn_rc = possible_ahn_rc
45
+ else
46
+ folder = File.expand_path(folder + "/..")
47
+ end
48
+ end
49
+ ahn_rc ? new(folder) : nil
50
+ end
51
+ end
52
+
53
+ attr_accessor :component_path, :dialplan_path, :log_path
54
+
55
+ def initialize(path)
56
+ super
57
+ defaults
58
+ end
59
+
60
+ def defaults
61
+ @component_path = build_path_for "components"
62
+ @dialplan_path = dup
63
+ @log_path = build_path_for "logs"
64
+ end
65
+
66
+ def base_path=(value)
67
+ replace(value)
68
+ defaults
69
+ end
70
+
71
+ def using_base_path(temporary_base_path, &block)
72
+ original_path = dup
73
+ self.base_path = temporary_base_path
74
+ block.call
75
+ ensure
76
+ self.base_path = original_path
77
+ end
78
+
79
+ private
80
+ def build_path_for(path)
81
+ File.join(to_s, path)
82
+ end
83
+ end
84
+
85
+ class Initializer
86
+
87
+ class << self
88
+ def get_rules_from(location)
89
+ location = File.join location, ".ahnrc" if File.directory? location
90
+ File.exists?(location) ? YAML.load_file(location) : nil
91
+ end
92
+
93
+ def ahn_root=(path)
94
+ if Object.constants.include?("AHN_ROOT")
95
+ Object.const_get(:AHN_ROOT).base_path = File.expand_path(path)
96
+ else
97
+ Object.const_set(:AHN_ROOT, PathString.new(File.expand_path(path)))
98
+ end
99
+ end
100
+
101
+ def start(*args, &block)
102
+ new(*args, &block).start
103
+ end
104
+
105
+ def start_from_init_file(file, ahn_app_path)
106
+ return if defined?(@@started) && @@started
107
+ start ahn_app_path, :loaded_init_files => file
108
+ end
109
+
110
+ end
111
+
112
+ attr_reader :path, :daemon, :pid_file, :log_file, :ahn_app_log_directory
113
+
114
+ # Creation of pid_files
115
+ #
116
+ # - You may want to have Adhearsion create a process identification
117
+ # file when it boots so that a crash monitoring program such as
118
+ # Monit can reboot if necessary or so the init script can kill it
119
+ # for system shutdowns.
120
+ # - To have Adhearsion create a pid file in the default location (i.e.
121
+ # AHN_INSTALL_DIR/adhearsion.pid), supply :pid_file with 'true'. Otherwise
122
+ # one is not created UNLESS it is running in daemon mode, in which
123
+ # case one is created. You can force Adhearsion to not create one
124
+ # even in daemon mode by supplying "false".
125
+ def initialize(path=nil, options={})
126
+ @@started = true
127
+ @path = path
128
+ @daemon = options[:daemon] || ENV['DAEMON']
129
+ @pid_file = options[:pid_file].nil? ? ENV['PID_FILE'] : options[:pid_file]
130
+ @loaded_init_files = options[:loaded_init_files]
131
+ self.class.ahn_root = path
132
+ end
133
+
134
+ def start
135
+ Adhearsion.status = :starting
136
+
137
+ resolve_pid_file_path
138
+ resolve_log_file_path
139
+ daemonize! if should_daemonize?
140
+ switch_to_root_directory
141
+ catch_termination_signal
142
+ create_pid_file if pid_file
143
+ bootstrap_rc
144
+ initialize_log_file
145
+ load_all_init_files
146
+ init_datasources
147
+ init_components_subsystem
148
+ init_modules
149
+ init_events_subsystem
150
+ load_components
151
+ init_events_file
152
+
153
+ ahn_log "Adhearsion v#{Adhearsion::VERSION::STRING} initialized!"
154
+ Adhearsion.status = :running
155
+
156
+ trigger_after_initialized_hooks
157
+ join_important_threads
158
+
159
+ self
160
+ end
161
+
162
+ def default_pid_path
163
+ File.join AHN_ROOT, 'adhearsion.pid'
164
+ end
165
+
166
+ def resolve_pid_file_path
167
+ @pid_file = if pid_file.equal?(true) then default_pid_path
168
+ elsif pid_file then pid_file
169
+ elsif pid_file.equal?(false) then nil
170
+ # FIXME @pid_file = @daemon? Assignment or equality? I'm assuming equality.
171
+ else @pid_file = @daemon ? default_pid_path : nil
172
+ end
173
+ end
174
+
175
+ def resolve_log_file_path
176
+ @ahn_app_log_directory = AHN_ROOT + '/log'
177
+ @log_file = File.expand_path(ahn_app_log_directory + "/adhearsion.log")
178
+ end
179
+
180
+ def switch_to_root_directory
181
+ Dir.chdir AHN_ROOT
182
+ end
183
+
184
+ def catch_termination_signal
185
+ %w'INT TERM'.each do |process_signal|
186
+ trap process_signal do
187
+ Adhearsion.shutdown!
188
+ end
189
+ end
190
+ end
191
+
192
+ ##
193
+ # This step in the initialization process loads the .ahnrc in the given app folder. With the information in .ahnrc, we
194
+ # can continue the initialization knowing where certain files are specifically.
195
+ #
196
+ def bootstrap_rc
197
+ rules = self.class.get_rules_from AHN_ROOT
198
+
199
+ AHN_CONFIG.ahnrc = rules
200
+
201
+ # DEPRECATION: Check if the old paths format is being used. If so, abort and notify.
202
+ if rules.has_key?("paths") && rules["paths"].kind_of?(Hash)
203
+ paths = rules["paths"].each_pair do |key,value|
204
+ if value.kind_of?(Hash)
205
+ if value.has_key?("directory") || value.has_key?("pattern")
206
+ puts
207
+ puts *caller
208
+ puts
209
+
210
+ abort <<-WARNING
211
+ Deprecation Warning
212
+ -------------------
213
+ The (hidden) .ahnrc file in this app is of an older format and needs to be fixed.
214
+
215
+ There is a rake task to automatically fix it or you can do it manually. Note: it's
216
+ best if you do it manually so you can retain the YAML comments in your .ahnrc file.
217
+
218
+ The rake task is called "deprecations:fix_ahnrc_path_format".
219
+
220
+ To do it manually, find all entries in the "paths" section of your ".ahnrc" file
221
+ which look like the following:
222
+
223
+ paths:
224
+ key_name_could_be_anything:
225
+ directory: some_folder
226
+ pattern: *.rb
227
+
228
+ Note: the "models" section had this syntax before:
229
+
230
+ models:
231
+ directory: models
232
+ pattern: "*.rb"
233
+
234
+ The NEW syntax is as follows (using models as an example):
235
+
236
+ models: models/*.rb
237
+
238
+ This new format is much cleaner.
239
+
240
+ Adhearsion will abort until you fix this. Sorry for the incovenience.
241
+ WARNING
242
+ end
243
+ end
244
+ end
245
+ end
246
+
247
+ gems = rules['gems']
248
+ if gems.kind_of?(Hash) && gems.any? && respond_to?(:gem)
249
+ gems.each_pair do |gem_name,properties_hash|
250
+ if properties_hash && properties_hash["version"]
251
+ gem gem_name, properties_hash["version"]
252
+ else
253
+ gem gem_name
254
+ end
255
+ if properties_hash
256
+ case properties_hash["require"]
257
+ when Array
258
+ properties_hash["require"].each { |lib| require lib }
259
+ when String
260
+ require properties_hash["require"]
261
+ end
262
+ end
263
+ end
264
+ end
265
+ end
266
+
267
+ def load_all_init_files
268
+ init_files_from_rc = AHN_CONFIG.files_from_setting("paths", "init").map { |file| File.expand_path(file) }
269
+ already_loaded_init_files = Array(@loaded_init_files).map { |file| File.expand_path(file) }
270
+ (init_files_from_rc - already_loaded_init_files).each { |init| load init }
271
+ end
272
+
273
+ def init_datasources
274
+ require 'adhearsion/initializer/database.rb'
275
+ require 'adhearsion/initializer/ldap.rb'
276
+
277
+ DatabaseInitializer.start if AHN_CONFIG.database_enabled?
278
+ LdapInitializer.start if AHN_CONFIG.ldap_enabled?
279
+ end
280
+
281
+ def init_modules
282
+
283
+ require 'adhearsion/initializer/asterisk.rb'
284
+ require 'adhearsion/initializer/drb.rb'
285
+ require 'adhearsion/initializer/rails.rb'
286
+ require 'adhearsion/initializer/xmpp.rb'
287
+ # require 'adhearsion/initializer/freeswitch.rb'
288
+
289
+ AsteriskInitializer.start if AHN_CONFIG.asterisk_enabled?
290
+ DrbInitializer.start if AHN_CONFIG.drb_enabled?
291
+ RailsInitializer.start if AHN_CONFIG.rails_enabled?
292
+ XMPPInitializer.start if AHN_CONFIG.xmpp_enabled?
293
+ # FreeswitchInitializer.start if AHN_CONFIG.freeswitch_enabled?
294
+
295
+ end
296
+
297
+ def init_events_subsystem
298
+ application_events_files = AHN_CONFIG.files_from_setting("paths", "events")
299
+ if application_events_files.any?
300
+ Events.register_callback(:shutdown) do
301
+ ahn_log.events "Performing a graceful stop of events subsystem"
302
+ Events.framework_theatre.graceful_stop!
303
+ end
304
+ Events.framework_theatre.start!
305
+ else
306
+ ahn_log.events.warn 'No entries in the "events" section of .ahnrc. Skipping its initialization.'
307
+ end
308
+ end
309
+
310
+ def init_events_file
311
+ application_events_files = AHN_CONFIG.files_from_setting("paths", "events")
312
+ application_events_files.each do |file|
313
+ Events.framework_theatre.load_events_file file
314
+ end
315
+ end
316
+
317
+ def should_daemonize?
318
+ @daemon
319
+ end
320
+
321
+ def daemonize!
322
+ ahn_log "Daemonizing now! Creating #{pid_file}."
323
+ extend Adhearsion::CustomDaemonizer
324
+ daemonize log_file
325
+ end
326
+
327
+ def initialize_log_file
328
+ Dir.mkdir(ahn_app_log_directory) unless File.directory? ahn_app_log_directory
329
+ file_logger = Log4r::FileOutputter.new("Main Adhearsion log file", :filename => log_file, :trunc => false)
330
+
331
+ if should_daemonize?
332
+ Logging::AdhearsionLogger.outputters = file_logger
333
+ else
334
+ Logging::AdhearsionLogger.outputters << file_logger
335
+ end
336
+ Logging::DefaultAdhearsionLogger.redefine_outputters
337
+ end
338
+
339
+ def create_pid_file
340
+ if pid_file
341
+ File.open pid_file, 'w' do |file|
342
+ file.puts Process.pid
343
+ end
344
+
345
+ Events.register_callback :shutdown do
346
+ File.delete(pid_file) if File.exists?(pid_file)
347
+ end
348
+ end
349
+ end
350
+
351
+ def init_components_subsystem
352
+ @components_directory = File.expand_path "components"
353
+ if File.directory? @components_directory
354
+ Components.component_manager = Components::ComponentManager.new @components_directory
355
+ Kernel.send(:const_set, :COMPONENTS, Components.component_manager.lazy_config_loader)
356
+ Components.component_manager.globalize_global_scope!
357
+ Components.component_manager.extend_object_with(Theatre::CallbackDefinitionLoader, :events)
358
+ else
359
+ ahn_log.warn "No components directory found. Not initializing any components."
360
+ end
361
+ end
362
+
363
+ def load_components
364
+ if Components.component_manager
365
+ Components.component_manager.load_components
366
+ end
367
+ end
368
+
369
+ def trigger_after_initialized_hooks
370
+ Events.trigger_immediately :after_initialized
371
+ end
372
+
373
+ ##
374
+ # This method will block Thread.main() until calling join() has returned for all Threads in IMPORTANT_THREADS.
375
+ # Note: IMPORTANT_THREADS won't always contain Thread instances. It simply requires the objects respond to join().
376
+ #
377
+ def join_important_threads
378
+ # Note: we're using this ugly accumulator to ensure that all threads have ended since IMPORTANT_THREADS will almost
379
+ # certainly change sizes after this method is called.
380
+ index = 0
381
+ until index == IMPORTANT_THREADS.size
382
+ begin
383
+ IMPORTANT_THREADS[index].join
384
+ rescue => e
385
+ ahn_log.error "Error after join()ing Thread #{thread.inspect}. #{e.message}"
386
+ ensure
387
+ index = index + 1
388
+ end
389
+ end
390
+ end
391
+
392
+ class InitializationFailedError < StandardError; end
393
+ end
394
+ end