jicksta-adhearsion 0.7.999

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 (107) hide show
  1. data/CHANGELOG +6 -0
  2. data/EVENTS +11 -0
  3. data/LICENSE +456 -0
  4. data/README.txt +5 -0
  5. data/Rakefile +120 -0
  6. data/adhearsion.gemspec +146 -0
  7. data/app_generators/ahn/USAGE +5 -0
  8. data/app_generators/ahn/ahn_generator.rb +87 -0
  9. data/app_generators/ahn/templates/.ahnrc +34 -0
  10. data/app_generators/ahn/templates/README +8 -0
  11. data/app_generators/ahn/templates/Rakefile +23 -0
  12. data/app_generators/ahn/templates/components/ami_remote/ami_remote.rb +15 -0
  13. data/app_generators/ahn/templates/components/disabled/HOW_TO_ENABLE +7 -0
  14. data/app_generators/ahn/templates/components/disabled/stomp_gateway/README.markdown +47 -0
  15. data/app_generators/ahn/templates/components/disabled/stomp_gateway/config.yml +12 -0
  16. data/app_generators/ahn/templates/components/disabled/stomp_gateway/stomp_gateway.rb +34 -0
  17. data/app_generators/ahn/templates/components/restful_rpc/README.markdown +11 -0
  18. data/app_generators/ahn/templates/components/restful_rpc/config.yml +34 -0
  19. data/app_generators/ahn/templates/components/restful_rpc/example-client.rb +48 -0
  20. data/app_generators/ahn/templates/components/restful_rpc/restful_rpc.rb +87 -0
  21. data/app_generators/ahn/templates/components/simon_game/simon_game.rb +56 -0
  22. data/app_generators/ahn/templates/config/startup.rb +53 -0
  23. data/app_generators/ahn/templates/dialplan.rb +3 -0
  24. data/app_generators/ahn/templates/events.rb +32 -0
  25. data/bin/ahn +28 -0
  26. data/bin/ahnctl +68 -0
  27. data/bin/jahn +42 -0
  28. data/examples/asterisk_manager_interface/standalone.rb +51 -0
  29. data/lib/adhearsion/cli.rb +223 -0
  30. data/lib/adhearsion/component_manager/spec_framework.rb +24 -0
  31. data/lib/adhearsion/component_manager.rb +208 -0
  32. data/lib/adhearsion/events_support.rb +84 -0
  33. data/lib/adhearsion/foundation/all.rb +9 -0
  34. data/lib/adhearsion/foundation/blank_slate.rb +5 -0
  35. data/lib/adhearsion/foundation/custom_daemonizer.rb +45 -0
  36. data/lib/adhearsion/foundation/event_socket.rb +203 -0
  37. data/lib/adhearsion/foundation/future_resource.rb +36 -0
  38. data/lib/adhearsion/foundation/global.rb +1 -0
  39. data/lib/adhearsion/foundation/metaprogramming.rb +17 -0
  40. data/lib/adhearsion/foundation/numeric.rb +13 -0
  41. data/lib/adhearsion/foundation/pseudo_guid.rb +10 -0
  42. data/lib/adhearsion/foundation/relationship_properties.rb +42 -0
  43. data/lib/adhearsion/foundation/string.rb +26 -0
  44. data/lib/adhearsion/foundation/synchronized_hash.rb +96 -0
  45. data/lib/adhearsion/foundation/thread_safety.rb +7 -0
  46. data/lib/adhearsion/host_definitions.rb +67 -0
  47. data/lib/adhearsion/initializer/asterisk.rb +81 -0
  48. data/lib/adhearsion/initializer/configuration.rb +254 -0
  49. data/lib/adhearsion/initializer/database.rb +49 -0
  50. data/lib/adhearsion/initializer/drb.rb +31 -0
  51. data/lib/adhearsion/initializer/freeswitch.rb +22 -0
  52. data/lib/adhearsion/initializer/rails.rb +40 -0
  53. data/lib/adhearsion/initializer.rb +373 -0
  54. data/lib/adhearsion/logging.rb +92 -0
  55. data/lib/adhearsion/tasks/database.rb +5 -0
  56. data/lib/adhearsion/tasks/deprecations.rb +59 -0
  57. data/lib/adhearsion/tasks/generating.rb +20 -0
  58. data/lib/adhearsion/tasks/lint.rb +4 -0
  59. data/lib/adhearsion/tasks/testing.rb +37 -0
  60. data/lib/adhearsion/tasks.rb +16 -0
  61. data/lib/adhearsion/version.rb +9 -0
  62. data/lib/adhearsion/voip/asterisk/agi_server.rb +81 -0
  63. data/lib/adhearsion/voip/asterisk/commands.rb +1284 -0
  64. data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +140 -0
  65. data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +101 -0
  66. data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +250 -0
  67. data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +240 -0
  68. data/lib/adhearsion/voip/asterisk/config_manager.rb +71 -0
  69. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +1754 -0
  70. data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +286 -0
  71. data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +78 -0
  72. data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +87 -0
  73. data/lib/adhearsion/voip/asterisk/manager_interface.rb +562 -0
  74. data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +80 -0
  75. data/lib/adhearsion/voip/asterisk/super_manager.rb +19 -0
  76. data/lib/adhearsion/voip/asterisk.rb +4 -0
  77. data/lib/adhearsion/voip/call.rb +440 -0
  78. data/lib/adhearsion/voip/call_routing.rb +64 -0
  79. data/lib/adhearsion/voip/commands.rb +9 -0
  80. data/lib/adhearsion/voip/constants.rb +39 -0
  81. data/lib/adhearsion/voip/conveniences.rb +18 -0
  82. data/lib/adhearsion/voip/dial_plan.rb +218 -0
  83. data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +37 -0
  84. data/lib/adhearsion/voip/dsl/dialing_dsl.rb +151 -0
  85. data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +27 -0
  86. data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +124 -0
  87. data/lib/adhearsion/voip/dsl/dialplan/parser.rb +71 -0
  88. data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +16 -0
  89. data/lib/adhearsion/voip/dsl/numerical_string.rb +117 -0
  90. data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +48 -0
  91. data/lib/adhearsion/voip/freeswitch/event_handler.rb +58 -0
  92. data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +129 -0
  93. data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +38 -0
  94. data/lib/adhearsion/voip/freeswitch/oes_server.rb +195 -0
  95. data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +80 -0
  96. data/lib/adhearsion/voip/menu_state_machine/matchers.rb +123 -0
  97. data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +58 -0
  98. data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +149 -0
  99. data/lib/adhearsion.rb +37 -0
  100. data/lib/theatre/README.markdown +64 -0
  101. data/lib/theatre/callback_definition_loader.rb +84 -0
  102. data/lib/theatre/guid.rb +23 -0
  103. data/lib/theatre/invocation.rb +121 -0
  104. data/lib/theatre/namespace_manager.rb +153 -0
  105. data/lib/theatre/version.rb +2 -0
  106. data/lib/theatre.rb +151 -0
  107. metadata +177 -0
@@ -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", :events => true
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,3 @@
1
+ adhearsion {
2
+ simon_game
3
+ }
@@ -0,0 +1,32 @@
1
+ ##
2
+ # In this file you can define callbacks for different aspects of the framework. Below is an example:
3
+ ##
4
+ #
5
+ # events.asterisk.before_call.each do |call|
6
+ # # This simply logs the extension for all calls going through this Adhearsion app.
7
+ # extension = call.variables[:extension]
8
+ # ahn_log "Got a new call with extension #{extension}"
9
+ # end
10
+ #
11
+ ##
12
+ # Asterisk Manager Interface example:
13
+ #
14
+ # events.asterisk.manager_interface.each do |event|
15
+ # p event
16
+ # end
17
+ #
18
+ # This assumes you gave :events => true to the config.asterisk.enable_ami method in config/startup.rb
19
+ #
20
+ ##
21
+ # Here is a list of the events included by default:
22
+ #
23
+ # - events.asterisk.manager_interface
24
+ # - events.after_initialized
25
+ # - events.shutdown
26
+ # - events.asterisk.before_call
27
+ # - events.asterisk.failed_call
28
+ # - events.asterisk.call_hangup
29
+ #
30
+ #
31
+ # Note: events are mostly for components to register and expose to you.
32
+ ##
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,42 @@
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
+ abort(<<-MESSAGE) unless RUBY_PLATFORM =~ /java/
33
+ You must use jahn with JRuby! Are you running this script after installing Adhearsion with non-JRuby RubyGems?
34
+
35
+ If you don't want to install Adhearsion with the JRuby version of RubyGems, try running jahn directly with an absolute path:
36
+
37
+ #{File.expand_path(__FILE__)} start your_app_name
38
+
39
+ Note: You must have the jruby executable in your $PATH and $JRUBY_HOME set.
40
+ MESSAGE
41
+
42
+ Adhearsion::CLI::AhnCommand.execute!
@@ -0,0 +1,51 @@
1
+ # This is a file which shows you how to use the Asterisk Manager Interface library in a standalone Ruby script.
2
+
3
+ PATH_TO_ADHEARSION = File.join(File.dirname(__FILE__), "/../..")
4
+
5
+ MANAGER_CONNECTION_INFORMATION = {
6
+ :host => "10.0.1.97",
7
+ :username => "jicksta",
8
+ :password => "roflcopter",
9
+ :events => true
10
+ }
11
+
12
+ require 'rubygems'
13
+ begin
14
+ require 'adhearsion'
15
+ rescue LoadError
16
+ begin
17
+ require File.join(PATH_TO_ADHEARSION, "/lib/adhearsion")
18
+ rescue LoadError
19
+ abort "Could not find Adhearsion! Please update the PATH_TO_ADHEARSION constant in this file"
20
+ end
21
+ end
22
+
23
+ require 'adhearsion/voip/asterisk/manager_interface'
24
+
25
+ # If you'd like to see the AMI protocol data, change this to :debug
26
+ Adhearsion::Logging.logging_level = :warn
27
+
28
+ # This makes addressing the ManagerInterface class a little cleaner
29
+ include Adhearsion::VoIP::Asterisk::Manager
30
+
31
+ # Let's instantiate a new ManagerInterface object and have it automatically connect using the Hash we defined above.
32
+ interface = ManagerInterface.connect MANAGER_CONNECTION_INFORMATION
33
+
34
+ # Send an AMI action with our new ManagerInterface object. This will return an Array of SIPPeer events.
35
+ sip_peers = interface.send_action "SIPPeers"
36
+
37
+ # Pretty-print the SIP peers on the server
38
+
39
+ if sip_peers.any?
40
+ sip_peers.each do |peer|
41
+ # Uncomment the following line to view all the headers for each peer.
42
+ # p peer.headers
43
+
44
+ peer_name = peer.headers["ObjectName"]
45
+ peer_status = peer.headers["Status"]
46
+
47
+ puts "#{peer_name}: #{peer_status}"
48
+ end
49
+ else
50
+ puts "This Asterisk server has no SIP peers!"
51
+ end
@@ -0,0 +1,223 @@
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] [/path/to/directory]
10
+ ahn version|-v|--v|-version|--version
11
+ ahn help|-h|--h|--help|-help
12
+
13
+ ahn enable component COMPONENT_NAME
14
+ ahn disable component COMPONENT_NAME
15
+ ahn create component COMPONENT_NAME
16
+ USAGE
17
+
18
+ def self.execute!
19
+ CommandHandler.send(*parse_arguments)
20
+ rescue CommandHandler::CLIException => error
21
+ fail_and_print_usage error
22
+ end
23
+
24
+ ##
25
+ # Provides a small abstraction of Kernel::abort().
26
+ #
27
+ def self.fail_and_print_usage(error)
28
+ Kernel.abort "#{error.message}\n\n#{USAGE}"
29
+ end
30
+
31
+ def self.parse_arguments(args=ARGV.clone)
32
+ action = args.shift
33
+ case action
34
+ when /^-?-?h(elp)?$/, nil then [:help]
35
+ when /^-?-?v(ersion)?$/ then [:version]
36
+ when "create"
37
+ [:create, *args]
38
+ when 'start'
39
+ pid_file_regexp = /^--pid-file=(.+)$/
40
+ if args.size > 3
41
+ fail_and_print_usage "Too many arguments supplied!" if args.size > 3
42
+ elsif args.size == 3
43
+ fail_and_print_usage "Unrecognized final argument #{args.last}" unless args.last =~ pid_file_regexp
44
+ pid_file = args.pop[pid_file_regexp, 1]
45
+ else
46
+ pid_file = nil
47
+ end
48
+
49
+ if args.first == 'daemon' && args.size == 2
50
+ path = args.last
51
+ daemon = true
52
+ elsif args.size == 1
53
+ path, daemon = args.first, false
54
+ else
55
+ fail_and_print_usage "Invalid format for the start CLI command!"
56
+ end
57
+ [:start, path, daemon, pid_file]
58
+ when '-'
59
+ [:start, Dir.pwd]
60
+ when "enable", "disable"
61
+ if args.size == 1
62
+ raise CommandHandler::UnknownCommand, "Must supply an argument for what you wish to #{action}"
63
+ elsif args.size == 2
64
+ [action, *args]
65
+ else
66
+ raise CommandHandler::UnknownCommand, "Too many arguments supplied!"
67
+ end
68
+ else
69
+ [action, *args]
70
+ end
71
+ end
72
+
73
+ module CommandHandler
74
+ class << self
75
+
76
+ def create(*args)
77
+ if args.size.zero?
78
+ raise CommandHandler::UnknownCommand.new("Must specify something to create!")
79
+ elsif args.size == 1
80
+ # We're creating a project
81
+ path = args.first
82
+ require 'rubigen'
83
+ require 'rubigen/scripts/generate'
84
+ source = RubiGen::PathSource.new(:application,
85
+ File.join(File.dirname(__FILE__), "../../app_generators"))
86
+ RubiGen::Base.reset_sources
87
+ RubiGen::Base.append_sources source
88
+ RubiGen::Scripts::Generate.new.run([path], :generator => 'ahn')
89
+ elsif args.size == 2
90
+ # We're creating a feature (e.g. a component)
91
+ feature_type, component_name = args
92
+
93
+ if feature_type != "component"
94
+ # At the moment, only components can be created.
95
+ raise CommandHandler::UnknownCommand.new("Don't know how to create '#{feature_type}'")
96
+ end
97
+
98
+ if component_name !~ /^[a-z][\w_]+$/
99
+ raise CommandHandler::ComponentError.new("Component name must be lowercase alphanumeric characters " +
100
+ "and begin with a character")
101
+ end
102
+
103
+ app_path = PathString.from_application_subdirectory Dir.pwd
104
+
105
+ raise PathInvalid.new(Dir.pwd) if app_path.nil?
106
+
107
+ new_component_dir = app_path + "/components/#{component_name}"
108
+ raise ComponentError.new("Component #{component_name} already exists!") if File.exists?(new_component_dir)
109
+
110
+ # Everything's good. Let's create the component
111
+ Dir.mkdir new_component_dir
112
+ File.open(new_component_dir + "/#{component_name}.rb","w") do |file|
113
+ file.puts <<-RUBY
114
+ # See http://docs.adhearsion.com for more information on how to write components or
115
+ # look at the examples in newly-created projects.
116
+ RUBY
117
+ end
118
+ File.open(new_component_dir + "/config.yml","w") do |file|
119
+ file.puts '# You can use this file for component-specific configuration.'
120
+ end
121
+ puts "Created blank component '#{component_name}' at components/#{component_name}"
122
+ else
123
+ raise CommandHandler::UnknownCommand.new("Provided too many arguments to 'create'")
124
+ end
125
+ end
126
+
127
+ def start(path, daemon=false, pid_file=nil)
128
+ raise PathInvalid, path unless File.exists? path + "/.ahnrc"
129
+ Adhearsion::Initializer.start path, :daemon => daemon, :pid_file => pid_file
130
+ end
131
+
132
+ def version
133
+ puts "Adhearsion v#{Adhearsion::VERSION::STRING}"
134
+ end
135
+
136
+ def help
137
+ puts USAGE
138
+ end
139
+
140
+ def enable(type, name)
141
+ case type
142
+ when "component"
143
+ app_path = PathString.from_application_subdirectory Dir.pwd
144
+ if app_path
145
+ disabled_component_path = File.join app_path, "components", "disabled", name
146
+ enabled_component_path = File.join app_path, "components", name
147
+ if File.directory? disabled_component_path
148
+ FileUtils.mv disabled_component_path, enabled_component_path
149
+ puts "Enabled component #{name}"
150
+ else
151
+ raise ComponentError.new("There is no components/disabled directory!")
152
+ end
153
+ else
154
+ raise PathInvalid.new(Dir.pwd)
155
+ end
156
+ else
157
+ raise UnknownCommand.new("enable #{type}")
158
+ end
159
+ end
160
+
161
+ def disable(type, name)
162
+ case type
163
+ when "component"
164
+ app_path = PathString.from_application_subdirectory Dir.pwd
165
+ if app_path
166
+ disabled_dir = File.join app_path, "components", "disabled"
167
+
168
+ disabled_component_path = File.join disabled_dir, name
169
+ enabled_component_path = File.join app_path, "components", name
170
+
171
+ Dir.mkdir disabled_dir unless File.directory?(disabled_dir)
172
+
173
+ if File.directory? enabled_component_path
174
+ if File.directory?(disabled_component_path)
175
+ raise ComponentError.new("There is already a disabled component at #{disabled_component_path}")
176
+ else
177
+ FileUtils.mv enabled_component_path, disabled_component_path
178
+ puts "Disabled component #{name}"
179
+ end
180
+ else
181
+ raise ComponentError.new("Could not find component #{name} at #{enabled_component_path} !")
182
+ end
183
+ else
184
+ raise PathInvalid.new(Dir.pwd)
185
+ end
186
+ else
187
+ raise UnknownCommand.new("disable #{type}")
188
+ end
189
+ end
190
+
191
+ def method_missing(action, *args)
192
+ raise UnknownCommand, [action, *args] * " "
193
+ end
194
+
195
+ private
196
+
197
+ end
198
+
199
+ class CLIException < Exception; end
200
+
201
+ class UnknownCommand < CLIException
202
+ def initialize(cmd)
203
+ super "Unknown command: #{cmd}"
204
+ end
205
+ end
206
+
207
+ class ComponentError < CLIException; end
208
+
209
+ class UnknownProject < CLIException
210
+ def initialize(project)
211
+ super "Application #{project} does not exist! Have you installed it?"
212
+ end
213
+ end
214
+
215
+ class PathInvalid < CLIException
216
+ def initialize(path)
217
+ super "Directory #{path} does not belong to an Adhearsion project!"
218
+ end
219
+ end
220
+ end
221
+ end
222
+ end
223
+ end
@@ -0,0 +1,24 @@
1
+ require 'adhearsion/component_manager/component_tester'
2
+ begin
3
+ require 'spec'
4
+ rescue LoadError
5
+ abort 'You do not have the "rspec" gem installed! You must install it to continue.\n\nsudo gem install rspec\n\n'
6
+ end
7
+
8
+ begin
9
+ require 'rr'
10
+ rescue LoadError
11
+ abort 'You do not have the "rr" gem installed! You must install it to continue.\n\nsudo gem install rr\n\n'
12
+ end
13
+
14
+ module ComponentConfigurationSpecHelper
15
+ def mock_component_config_with(new_config)
16
+ Object.send(:remove_const, :COMPONENTS) rescue nil
17
+ Object.send(:const_set, :COMPONENTS, OpenStruct.new(new_config))
18
+ end
19
+ end
20
+
21
+ Spec::Runner.configure do |config|
22
+ config.mock_with :rr
23
+ config.include ComponentConfigurationSpecHelper
24
+ end