eric-adhearsion 0.7.999

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 +3 -0
  2. data/LICENSE +456 -0
  3. data/Manifest.txt +149 -0
  4. data/README.txt +6 -0
  5. data/Rakefile +48 -0
  6. data/ahn_generators/component/USAGE +5 -0
  7. data/ahn_generators/component/component_generator.rb +57 -0
  8. data/ahn_generators/component/templates/configuration.rb +0 -0
  9. data/ahn_generators/component/templates/lib/lib.rb.erb +3 -0
  10. data/ahn_generators/component/templates/test/test.rb.erb +12 -0
  11. data/ahn_generators/component/templates/test/test_helper.rb +14 -0
  12. data/app_generators/ahn/USAGE +5 -0
  13. data/app_generators/ahn/ahn_generator.rb +76 -0
  14. data/app_generators/ahn/templates/.ahnrc +12 -0
  15. data/app_generators/ahn/templates/README +8 -0
  16. data/app_generators/ahn/templates/Rakefile +3 -0
  17. data/app_generators/ahn/templates/components/simon_game/configuration.rb +0 -0
  18. data/app_generators/ahn/templates/components/simon_game/lib/simon_game.rb +61 -0
  19. data/app_generators/ahn/templates/components/simon_game/test/test_helper.rb +14 -0
  20. data/app_generators/ahn/templates/components/simon_game/test/test_simon_game.rb +31 -0
  21. data/app_generators/ahn/templates/config/startup.rb +53 -0
  22. data/app_generators/ahn/templates/dialplan.rb +4 -0
  23. data/bin/ahn +28 -0
  24. data/bin/ahnctl +68 -0
  25. data/bin/jahn +32 -0
  26. data/lib/adhearsion/blank_slate.rb +5 -0
  27. data/lib/adhearsion/cli.rb +106 -0
  28. data/lib/adhearsion/component_manager.rb +277 -0
  29. data/lib/adhearsion/core_extensions/all.rb +9 -0
  30. data/lib/adhearsion/core_extensions/array.rb +0 -0
  31. data/lib/adhearsion/core_extensions/custom_daemonizer.rb +45 -0
  32. data/lib/adhearsion/core_extensions/global.rb +1 -0
  33. data/lib/adhearsion/core_extensions/guid.rb +5 -0
  34. data/lib/adhearsion/core_extensions/hash.rb +0 -0
  35. data/lib/adhearsion/core_extensions/metaprogramming.rb +17 -0
  36. data/lib/adhearsion/core_extensions/numeric.rb +4 -0
  37. data/lib/adhearsion/core_extensions/proc.rb +0 -0
  38. data/lib/adhearsion/core_extensions/pseudo_uuid.rb +11 -0
  39. data/lib/adhearsion/core_extensions/publishable.rb +73 -0
  40. data/lib/adhearsion/core_extensions/relationship_properties.rb +40 -0
  41. data/lib/adhearsion/core_extensions/string.rb +26 -0
  42. data/lib/adhearsion/core_extensions/thread.rb +13 -0
  43. data/lib/adhearsion/core_extensions/thread_safety.rb +7 -0
  44. data/lib/adhearsion/core_extensions/time.rb +0 -0
  45. data/lib/adhearsion/distributed/gateways/dbus_gateway.rb +0 -0
  46. data/lib/adhearsion/distributed/gateways/osa_gateway.rb +0 -0
  47. data/lib/adhearsion/distributed/gateways/rest_gateway.rb +9 -0
  48. data/lib/adhearsion/distributed/gateways/soap_gateway.rb +9 -0
  49. data/lib/adhearsion/distributed/gateways/xmlrpc_gateway.rb +9 -0
  50. data/lib/adhearsion/distributed/peer_finder.rb +0 -0
  51. data/lib/adhearsion/distributed/remote_cli.rb +0 -0
  52. data/lib/adhearsion/hooks.rb +57 -0
  53. data/lib/adhearsion/host_definitions.rb +63 -0
  54. data/lib/adhearsion/initializer/asterisk.rb +59 -0
  55. data/lib/adhearsion/initializer/configuration.rb +202 -0
  56. data/lib/adhearsion/initializer/database.rb +92 -0
  57. data/lib/adhearsion/initializer/drb.rb +25 -0
  58. data/lib/adhearsion/initializer/freeswitch.rb +22 -0
  59. data/lib/adhearsion/initializer/paths.rb +55 -0
  60. data/lib/adhearsion/initializer/rails.rb +40 -0
  61. data/lib/adhearsion/initializer.rb +217 -0
  62. data/lib/adhearsion/logging.rb +92 -0
  63. data/lib/adhearsion/services/scheduler.rb +5 -0
  64. data/lib/adhearsion/tasks/database.rb +5 -0
  65. data/lib/adhearsion/tasks/generating.rb +20 -0
  66. data/lib/adhearsion/tasks/lint.rb +4 -0
  67. data/lib/adhearsion/tasks/testing.rb +37 -0
  68. data/lib/adhearsion/tasks.rb +15 -0
  69. data/lib/adhearsion/version.rb +9 -0
  70. data/lib/adhearsion/voip/asterisk/agi_server.rb +78 -0
  71. data/lib/adhearsion/voip/asterisk/ami/actions.rb +238 -0
  72. data/lib/adhearsion/voip/asterisk/ami/machine.rb +871 -0
  73. data/lib/adhearsion/voip/asterisk/ami/machine.rl +109 -0
  74. data/lib/adhearsion/voip/asterisk/ami/parser.rb +262 -0
  75. data/lib/adhearsion/voip/asterisk/ami.rb +147 -0
  76. data/lib/adhearsion/voip/asterisk/commands.rb +1182 -0
  77. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +140 -0
  78. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +101 -0
  79. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +250 -0
  80. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +240 -0
  81. data/lib/adhearsion/voip/asterisk/config_manager.rb +71 -0
  82. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +80 -0
  83. data/lib/adhearsion/voip/asterisk.rb +4 -0
  84. data/lib/adhearsion/voip/call.rb +391 -0
  85. data/lib/adhearsion/voip/call_routing.rb +64 -0
  86. data/lib/adhearsion/voip/commands.rb +9 -0
  87. data/lib/adhearsion/voip/constants.rb +39 -0
  88. data/lib/adhearsion/voip/conveniences.rb +18 -0
  89. data/lib/adhearsion/voip/dial_plan.rb +205 -0
  90. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +37 -0
  91. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +151 -0
  92. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +27 -0
  93. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +124 -0
  94. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +75 -0
  95. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +16 -0
  96. data/lib/adhearsion/voip/dsl/numerical_string.rb +117 -0
  97. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +48 -0
  98. data/lib/adhearsion/voip/freeswitch/event_handler.rb +58 -0
  99. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +129 -0
  100. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +38 -0
  101. data/lib/adhearsion/voip/freeswitch/oes_server.rb +195 -0
  102. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +80 -0
  103. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +123 -0
  104. data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +58 -0
  105. data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +149 -0
  106. data/lib/adhearsion.rb +31 -0
  107. data/script/destroy +14 -0
  108. data/script/generate +14 -0
  109. data/spec/fixtures/dialplan.rb +3 -0
  110. data/spec/initializer/test_configuration.rb +267 -0
  111. data/spec/initializer/test_loading.rb +162 -0
  112. data/spec/initializer/test_paths.rb +43 -0
  113. data/spec/silence.rb +10 -0
  114. data/spec/test_ahn_command.rb +149 -0
  115. data/spec/test_code_quality.rb +87 -0
  116. data/spec/test_component_manager.rb +97 -0
  117. data/spec/test_constants.rb +8 -0
  118. data/spec/test_drb.rb +104 -0
  119. data/spec/test_helper.rb +94 -0
  120. data/spec/test_hooks.rb +37 -0
  121. data/spec/test_host_definitions.rb +79 -0
  122. data/spec/test_initialization.rb +105 -0
  123. data/spec/test_logging.rb +80 -0
  124. data/spec/test_relationship_properties.rb +54 -0
  125. data/spec/voip/asterisk/ami_response_definitions.rb +23 -0
  126. data/spec/voip/asterisk/config_file_generators/test_agents.rb +253 -0
  127. data/spec/voip/asterisk/config_file_generators/test_queues.rb +325 -0
  128. data/spec/voip/asterisk/config_file_generators/test_voicemail.rb +306 -0
  129. data/spec/voip/asterisk/menu_command/test_calculated_match.rb +111 -0
  130. data/spec/voip/asterisk/menu_command/test_matchers.rb +98 -0
  131. data/spec/voip/asterisk/mock_ami_server.rb +176 -0
  132. data/spec/voip/asterisk/test_agi_server.rb +451 -0
  133. data/spec/voip/asterisk/test_ami.rb +227 -0
  134. data/spec/voip/asterisk/test_commands.rb +2006 -0
  135. data/spec/voip/asterisk/test_config_manager.rb +129 -0
  136. data/spec/voip/dsl/dispatcher_spec_helper.rb +45 -0
  137. data/spec/voip/dsl/test_dialing_dsl.rb +268 -0
  138. data/spec/voip/dsl/test_dispatcher.rb +82 -0
  139. data/spec/voip/dsl/test_parser.rb +87 -0
  140. data/spec/voip/freeswitch/test_basic_connection_manager.rb +39 -0
  141. data/spec/voip/freeswitch/test_inbound_connection_manager.rb +39 -0
  142. data/spec/voip/freeswitch/test_oes_server.rb +9 -0
  143. data/spec/voip/test_call_routing.rb +127 -0
  144. data/spec/voip/test_dialplan_manager.rb +372 -0
  145. data/spec/voip/test_numerical_string.rb +48 -0
  146. data/spec/voip/test_phone_number.rb +36 -0
  147. data/test/test_ahn_generator.rb +59 -0
  148. data/test/test_component_generator.rb +52 -0
  149. data/test/test_generator_helper.rb +20 -0
  150. metadata +254 -0
@@ -0,0 +1,57 @@
1
+ class ComponentGenerator < RubiGen::Base
2
+
3
+ default_options :author => nil
4
+
5
+ attr_reader :name, :class_name
6
+
7
+ def initialize(runtime_args, runtime_options = {})
8
+ super
9
+ usage if args.empty?
10
+ @name = args.shift
11
+ @name = @name.underscore
12
+ @class_name = @name.camelize
13
+ extract_options
14
+ end
15
+
16
+ def manifest
17
+ record do |m|
18
+ # Ensure appropriate folder(s) exists
19
+ m.directory "components/#{name}/lib"
20
+ m.directory "components/#{name}/test"
21
+
22
+ # Create stubs
23
+ m.file "configuration.rb", "components/#{name}/configuration.rb"
24
+ m.template "lib/lib.rb.erb", "components/#{name}/lib/#{name}.rb"
25
+ m.template "test/test.rb.erb", "components/#{name}/test/test_#{name}.rb"
26
+ m.file "test/test_helper.rb", "components/#{name}/test/test_helper.rb"
27
+
28
+ end
29
+ end
30
+
31
+ protected
32
+ def banner
33
+ <<-EOS
34
+ Creates a ...
35
+
36
+ USAGE: #{$0} #{spec.name} name"
37
+ EOS
38
+ end
39
+
40
+ def add_options!(opts)
41
+ # opts.separator ''
42
+ # opts.separator 'Options:'
43
+ # For each option below, place the default
44
+ # at the top of the file next to "default_options"
45
+ # opts.on("-a", "--author=\"Your Name\"", String,
46
+ # "Some comment about this option",
47
+ # "Default: none") { |options[:author]| }
48
+ # opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
49
+ end
50
+
51
+ def extract_options
52
+ # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
53
+ # Templates can access these value via the attr_reader-generated methods, but not the
54
+ # raw instance variable value.
55
+ # @author = options[:author]
56
+ end
57
+ end
@@ -0,0 +1,3 @@
1
+ class <%= class_name %>
2
+
3
+ end
@@ -0,0 +1,12 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ class Test<%= class_name %> < Test::Unit::TestCase
4
+
5
+ def setup
6
+ @<%= name %> = <%= class_name %>.new
7
+ end
8
+
9
+ def test_truth
10
+
11
+ end
12
+ end
@@ -0,0 +1,14 @@
1
+ $:.unshift File.dirname(__FILE__) + '/../../../../../lib'
2
+ require 'adhearsion'
3
+ require 'test/unit'
4
+ require 'flexmock/test_unit'
5
+ AHN_ROOT = Adhearsion::PathString.new(File.dirname(__FILE__) + '/../../..')
6
+ Adhearsion::ComponentManager.load
7
+ Adhearsion::ComponentManager.start
8
+
9
+ class Test::Unit::TestCase
10
+ Adhearsion::ComponentManager.components_with_call_context.each_pair do |component_class_name, component_configuration|
11
+ const_set(component_class_name, component_configuration.component_class)
12
+ const_get(component_class_name).send(:attr_accessor, :call_context)
13
+ end
14
+ end
@@ -0,0 +1,5 @@
1
+ Description:
2
+
3
+
4
+ Usage:
5
+
@@ -0,0 +1,76 @@
1
+ class AhnGenerator < RubiGen::Base
2
+
3
+ DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
4
+ Config::CONFIG['ruby_install_name'])
5
+
6
+ default_options :author => nil
7
+
8
+ attr_reader :name, :component
9
+
10
+ def initialize(runtime_args, runtime_options = {})
11
+ super
12
+ usage if args.empty?
13
+ @destination_root = File.expand_path(args.shift)
14
+ @name = base_name
15
+ @component = 'simon_game'
16
+ extract_options
17
+ end
18
+
19
+ def manifest
20
+ record do |m|
21
+ # Ensure appropriate folder(s) exists
22
+ m.directory ''
23
+ BASEDIRS.each { |path| m.directory path }
24
+
25
+ m.file *[".ahnrc"]*2
26
+
27
+ m.file *["components/simon_game/configuration.rb"]*2
28
+ m.file *["components/simon_game/lib/simon_game.rb"]*2
29
+ m.file *["components/simon_game/test/test_helper.rb"]*2
30
+ m.file *["components/simon_game/test/test_simon_game.rb"]*2
31
+
32
+ m.file *["config/startup.rb"]*2
33
+ m.file *["dialplan.rb"]*2
34
+ m.file *["README"]*2
35
+ m.file *["Rakefile"]*2
36
+
37
+ m.dependency "install_rubigen_scripts", [destination_root, 'ahn', 'adhearsion', 'test_spec'],
38
+ :shebang => options[:shebang], :collision => :force
39
+ end
40
+ end
41
+
42
+ protected
43
+ def banner
44
+ <<-EOS
45
+ Creates a ...
46
+
47
+ USAGE: #{spec.name} name"
48
+ EOS
49
+ end
50
+
51
+ def add_options!(opts)
52
+ opts.separator ''
53
+ opts.separator 'Options:'
54
+ # For each option below, place the default
55
+ # at the top of the file next to "default_options"
56
+ # opts.on("-a", "--author=\"Your Name\"", String,
57
+ # "Some comment about this option",
58
+ # "Default: none") { |options[:author]| }
59
+ opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
60
+ end
61
+
62
+ def extract_options
63
+ # for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
64
+ # Templates can access these value via the attr_reader-generated methods, but not the
65
+ # raw instance variable value.
66
+ # @author = options[:author]
67
+ end
68
+
69
+ # Installation skeleton. Intermediate directories are automatically
70
+ # created so don't sweat their absence here.
71
+ BASEDIRS = %w(
72
+ components/simon_game/lib
73
+ components/simon_game/test
74
+ config
75
+ )
76
+ end
@@ -0,0 +1,12 @@
1
+ # Adhearsion Runtime Configuration.
2
+
3
+ paths:
4
+
5
+ # All paths are relative to this file's directory
6
+ init: config/startup.rb
7
+
8
+ dialplan: dialplan.rb
9
+
10
+ models:
11
+ directory: models
12
+ pattern: "*.rb"
@@ -0,0 +1,8 @@
1
+ Start your new app with "ahn start /path/to/your/app"
2
+
3
+ If you wish to use Adhearsion to control Asterisk's dialplan,
4
+ change the contexts you wish to be affected in your
5
+ /etc/asterisk/extensions.conf file to the following:
6
+
7
+ [your_context_name]
8
+ exten => _X.,1,AGI(agi://1.2.3.4) ; This IP here
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'adhearsion'
3
+ require 'adhearsion/tasks'
@@ -0,0 +1,61 @@
1
+ class SimonGame
2
+ add_call_context :as => :call_context
3
+
4
+ attr_accessor :number, :attempt
5
+ def initialize
6
+ initialize_number
7
+ initialize_attempt
8
+ end
9
+
10
+ def start
11
+ loop do
12
+ say_number
13
+ collect_attempt
14
+ verify_attempt
15
+ end
16
+ end
17
+
18
+ def random_number
19
+ rand(10).to_s
20
+ end
21
+
22
+ def update_number
23
+ initialize_attempt
24
+ @number << random_number
25
+ end
26
+
27
+ def say_number
28
+ update_number
29
+ call_context.say_digits number
30
+ end
31
+
32
+ def collect_attempt
33
+ @attempt = call_context.input(number.size)
34
+ end
35
+
36
+ def verify_attempt
37
+ if attempt_correct?
38
+ call_context.play 'good'
39
+ else
40
+ call_context.play %W(#{number.size - 1} times wrong-try-again-smarty)
41
+ reset
42
+ end
43
+ end
44
+
45
+ def attempt_correct?
46
+ attempt == number
47
+ end
48
+
49
+ def initialize_attempt
50
+ @attempt ||= ''
51
+ end
52
+
53
+ def initialize_number
54
+ @number ||= ''
55
+ end
56
+
57
+ def reset
58
+ @attempt, @number = '', ''
59
+ end
60
+
61
+ end
@@ -0,0 +1,14 @@
1
+ $:.unshift File.dirname(__FILE__) + '/../../../../../lib'
2
+ require 'adhearsion'
3
+ require 'test/unit'
4
+ require 'flexmock/test_unit'
5
+ AHN_ROOT = Adhearsion::PathString.new(File.dirname(__FILE__) + '/../../..')
6
+ Adhearsion::ComponentManager.load
7
+ Adhearsion::ComponentManager.start
8
+
9
+ class Test::Unit::TestCase
10
+ Adhearsion::ComponentManager.components_with_call_context.each_pair do |component_class_name, component_configuration|
11
+ const_set(component_class_name, component_configuration.component_class)
12
+ const_get(component_class_name).send(:attr_accessor, :call_context)
13
+ end
14
+ end
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + "/test_helper"
2
+
3
+ class TestSimonGame < Test::Unit::TestCase
4
+ attr_reader :game
5
+ def setup
6
+ @game = SimonGame.new
7
+ @game.call_context = mock_call_context
8
+ end
9
+
10
+ def test_game_executes_say_digits_when_asked_to_say_number
11
+ flexmock(game).should_receive(:random_number).and_return("2")
12
+ mock_call_context.should_receive(:say_digits).once.with('2')
13
+ @game.say_number
14
+ end
15
+
16
+
17
+ # Didn't get very far on this
18
+ def xtest_can_play_one_round_and_receive_the_players_score
19
+ flexmock(game).should_receive(:random_number).and_return("2")
20
+ assert_equal(3, 'x')
21
+ end
22
+
23
+ private
24
+ def mock_call_context
25
+ @mock_call_context ||= flexmock("Mock Call Context")
26
+ end
27
+
28
+ def stub_random_number
29
+
30
+ end
31
+ end
@@ -0,0 +1,53 @@
1
+ unless defined? Adhearsion
2
+ if File.exists? File.dirname(__FILE__) + "/../adhearsion/lib/adhearsion.rb"
3
+ # If you wish to freeze a copy of Adhearsion to this app, simply place a copy of Adhearsion
4
+ # into a folder named "adhearsion" within this app's main directory.
5
+ require File.dirname(__FILE__) + "/../adhearsion/lib/adhearsion.rb"
6
+ else
7
+ require 'rubygems'
8
+ gem 'adhearsion', '>= 0.7.999'
9
+ require 'adhearsion'
10
+ end
11
+ end
12
+
13
+ Adhearsion::Configuration.configure do |config|
14
+
15
+ # Supported levels (in increasing severity) -- :debug < :info < :warn < :error < :fatal
16
+ config.logging :level => :info
17
+
18
+ # Whether incoming calls be automatically answered. Defaults to true.
19
+ # config.automatically_answer_incoming_calls = false
20
+
21
+ # Whether the other end hanging up should end the call immediately. Defaults to true.
22
+ # config.end_call_on_hangup = false
23
+
24
+ # Whether to end the call immediately if an unrescued exception is caught. Defaults to true.
25
+ # config.end_call_on_error = false
26
+
27
+ # By default Asterisk is enabled with the default settings
28
+ config.enable_asterisk
29
+ # config.asterisk.enable_ami :host => "127.0.0.1", :username => "admin", :password => "password"
30
+
31
+ # To change the host IP or port on which the AGI server listens, use this:
32
+ # config.enable_asterisk :listening_port => 4574, :listening_host => "127.0.0.1"
33
+
34
+ # config.enable_drb
35
+
36
+ # Streamlined Rails integration! The first argument should be a relative or absolute path to
37
+ # the Rails app folder with which you're integrating. The second argument must be one of the
38
+ # the following: :development, :production, or :test.
39
+
40
+ # config.enable_rails :path => 'gui', :env => :development
41
+
42
+ # Note: You CANNOT do enable_rails and enable_database at the same time. When you enable Rails,
43
+ # it will automatically connect to same database Rails does and load the Rails app's models.
44
+
45
+ # Configure a database to use ActiveRecord-backed models. See ActiveRecord::Base.establish_connection
46
+ # for the appropriate settings here.
47
+ # config.enable_database :adapter => 'mysql',
48
+ # :username => 'joe',
49
+ # :password => 'secret',
50
+ # :host => 'db.example.org'
51
+ end
52
+
53
+ Adhearsion::Initializer.start_from_init_file(__FILE__, File.dirname(__FILE__) + "/..")
@@ -0,0 +1,4 @@
1
+ adhearsion {
2
+ simon = new_simon_game
3
+ simon.start
4
+ }
data/bin/ahn ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # This is the main executable file.
4
+
5
+ # Adhearsion, open source collaboration framework
6
+ # Copyright (C) 2006,2007,2008 Jay Phillips
7
+ #
8
+ # This library is free software; you can redistribute it and/or modify it under
9
+ # the terms of the GNU Lesser General Public License as published by the Free
10
+ # Software Foundation; either version 2.1 of the License, or (at your option)
11
+ # any later version.
12
+ #
13
+ # This library is distributed in the hope that it will be useful, but WITHOUT
14
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16
+ # details.
17
+ #
18
+ # You should have received a copy of the GNU Lesser General Public License along
19
+ # with this library; if not, write to the Free Software Foundation, Inc.,
20
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
+
22
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
23
+
24
+ require 'rubygems'
25
+ require 'adhearsion'
26
+ require 'adhearsion/cli'
27
+
28
+ Adhearsion::CLI::AhnCommand.execute!
data/bin/ahnctl ADDED
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # ahnctl - Adhearsion daemon controller
4
+ #
5
+ # Adhearsion, open source collaboration framework
6
+ # Copyright (C) 2006,2007,2008 Jay Phillips
7
+ #
8
+ # This library is free software; you can redistribute it and/or
9
+ # modify it under the terms of the GNU Lesser General Public
10
+ # License as published by the Free Software Foundation; either
11
+ # version 2.1 of the License, or (at your option) any later version.
12
+ #
13
+ # This library is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
+ # Lesser General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU Lesser General Public
19
+ # License along with this library; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
+
22
+ USAGE = "Usage: ahnctl start|stop|restart /path/to/adhearsion/app [--pid-file=/path/to/pid_file.pid]"
23
+
24
+ # Blow up if the CLI arguments are invalid
25
+ abort USAGE unless (2..3).include?(ARGV.size) && %w[start stop restart].include?(ARGV.first)
26
+
27
+ # By default, ahnctl will use the version of Adhearsion it was installed with.
28
+
29
+ pid_file = ARGV.pop if ARGV.size == 3
30
+ ahn_command = File.expand_path File.dirname(__FILE__) + "/ahn"
31
+ app_dir = File.expand_path ARGV.last
32
+
33
+ pid_file_path_regexp = /^--pid-file=(.+)$/
34
+ abort USAGE if pid_file && pid_file !~ pid_file_path_regexp
35
+
36
+ # If pid_file is not nil, let's extract the path specified.
37
+ pid_file &&= File.expand_path pid_file[pid_file_path_regexp,1]
38
+
39
+ # If there was no third argument and pid_file is still nil, let's use the default.
40
+ pid_file ||= app_dir + '/adhearsion.pid'
41
+
42
+ abort "Directory is not an Adhearsion application!" unless File.exists?(app_dir + "/.ahnrc")
43
+
44
+ def terminate(pid) `kill -s TERM #{pid} 2> /dev/null` end
45
+ def kill(pid) `kill -s KILL #{pid} 2> /dev/null` end
46
+
47
+ # Even if we're starting Adhearsion, we need to make sure to clean up after any stale
48
+ # pid files. In effect, start is the same as restart.
49
+ puts "Stopping Adhearsion app at #{app_dir}" if %w[stop restart].include? ARGV.first
50
+
51
+ if File.exists?(pid_file)
52
+ # An Adhearsion process may still be running. Let's kill the other one as cleanly as possible
53
+ pid = File.read(pid_file).to_i
54
+
55
+ # Time to spend waiting for Adhearsion to exit
56
+ waiting_timeout = Time.now + 15
57
+
58
+ terminate pid
59
+ sleep 0.25 until `ps -p #{pid} | sed -e '1d'`.strip.empty? || Time.now > waiting_timeout
60
+ kill pid
61
+
62
+ `rm -f #{pid_file}`
63
+ end
64
+
65
+ if ['start', 'restart'].include? ARGV.first
66
+ puts "Starting Adhearsion app at #{app_dir}"
67
+ `#{ahn_command} start daemon #{app_dir} --pid-file=#{pid_file}`
68
+ end
data/bin/jahn ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env jruby
2
+
3
+ # This "jahn" script is "ahn" for JRUBY!
4
+
5
+ # Adhearsion, open source collaboration framework
6
+ # Copyright (C) 2006,2007,2008 Jay Phillips
7
+ #
8
+ # This library is free software; you can redistribute it and/or modify it under
9
+ # the terms of the GNU Lesser General Public License as published by the Free
10
+ # Software Foundation; either version 2.1 of the License, or (at your option)
11
+ # any later version.
12
+ #
13
+ # This library is distributed in the hope that it will be useful, but WITHOUT
14
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
16
+ # details.
17
+ #
18
+ # You should have received a copy of the GNU Lesser General Public License along
19
+ # with this library; if not, write to the Free Software Foundation, Inc.,
20
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
+
22
+ $:.unshift File.expand_path(File.dirname(__FILE__) + "/../lib")
23
+
24
+ require 'rubygems'
25
+ require 'adhearsion'
26
+ require 'adhearsion/cli'
27
+
28
+ # jahn will soon have JRuby-specific behavior such as creating a compiled .jar
29
+ # file from an app.
30
+ # require 'adhearsion/jruby'
31
+
32
+ Adhearsion::CLI::AhnCommand.execute!
@@ -0,0 +1,5 @@
1
+ class BlankSlate
2
+ instance_methods.each do |method|
3
+ undef_method method unless method =~ /^__/ || method == 'instance_eval'
4
+ end
5
+ end
@@ -0,0 +1,106 @@
1
+ require 'fileutils'
2
+
3
+ module Adhearsion
4
+ module CLI
5
+ module AhnCommand
6
+ USAGE = <<USAGE
7
+ Usage:
8
+ ahn create /path/to/directory
9
+ ahn start [daemon] [directory]
10
+ ahn version|-v|--v|-version|--version
11
+ ahn help|-h|--h|--help|-help
12
+
13
+ Under development:
14
+ ahn create:projectname /path/to/directory
15
+ USAGE
16
+
17
+ def self.execute!
18
+ CommandHandler.send(*parse_arguments)
19
+ end
20
+
21
+ def self.parse_arguments(args=ARGV.clone)
22
+ action = args.shift
23
+ case action
24
+ when /^-?-?h(elp)?$/, nil then [:help]
25
+ when /^-?-?v(ersion)?$/ then [:version]
26
+ when /^create(:([\w_.]+))?$/
27
+ [:create, args.shift, $LAST_PAREN_MATCH || :default]
28
+ when 'start'
29
+ pid_file_regexp = /^--pid-file=(.+)$/
30
+ if args.size > 3
31
+ raise CommandHandler::UnknownCommand, "Too many arguments supplied!" if args.size > 3
32
+ elsif args.size == 3
33
+ raise CommandHandler::UnknownCommand, "Unrecognized final argument #{args.last}" unless args.last =~ pid_file_regexp
34
+ pid_file = args.pop[pid_file_regexp, 1]
35
+ else
36
+ pid_file = nil
37
+ end
38
+
39
+ if args.first == 'daemon' && args.size == 2
40
+ path = args.last
41
+ daemon = true
42
+ elsif args.size == 1
43
+ path, daemon = args.first, false
44
+ else
45
+ raise CommandHandler::UnknownCommand, "Invalid format for the start CLI command!"
46
+ end
47
+ [:start, path, daemon, pid_file]
48
+ when '-'
49
+ [:start, Dir.pwd]
50
+ else
51
+ [action, *args]
52
+ end
53
+ end
54
+
55
+ module CommandHandler
56
+ class << self
57
+ def create(path, project=:default)
58
+ raise UnknownProject.new(project) if project != :default # TODO: Support other projects
59
+ require 'rubigen'
60
+ require 'rubigen/scripts/generate'
61
+ source = RubiGen::PathSource.new(:application,
62
+ File.join(File.dirname(__FILE__), "../../app_generators"))
63
+ RubiGen::Base.reset_sources
64
+ RubiGen::Base.append_sources source
65
+ RubiGen::Scripts::Generate.new.run([path], :generator => 'ahn')
66
+ end
67
+
68
+ def start(path, daemon=false, pid_file=nil)
69
+ raise PathInvalid, path unless File.exists? path + "/.ahnrc"
70
+ Adhearsion::Initializer.new path, :daemon => daemon, :pid_file => pid_file
71
+ end
72
+
73
+ def version
74
+ puts "Adhearsion v#{Adhearsion::VERSION::STRING}"
75
+ end
76
+
77
+ def help
78
+ puts USAGE
79
+ end
80
+
81
+ def method_missing(action, *args)
82
+ raise UnknownCommand, [action, *args] * " "
83
+ end
84
+ end
85
+
86
+ class UnknownCommand < Exception
87
+ def initialize(cmd)
88
+ super "Unknown command: #{cmd}\n#{USAGE}"
89
+ end
90
+ end
91
+
92
+ class UnknownProject < Exception
93
+ def initialize(project)
94
+ super "Application #{project} does not exist! Have you installed it?"
95
+ end
96
+ end
97
+
98
+ class PathInvalid < Exception
99
+ def initialize(path)
100
+ super "Directory #{path} does not contain an Adhearsion project!"
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end