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.
- data/CHANGELOG +6 -0
- data/EVENTS +11 -0
- data/LICENSE +456 -0
- data/README.txt +5 -0
- data/Rakefile +120 -0
- data/adhearsion.gemspec +146 -0
- data/app_generators/ahn/USAGE +5 -0
- data/app_generators/ahn/ahn_generator.rb +87 -0
- data/app_generators/ahn/templates/.ahnrc +34 -0
- data/app_generators/ahn/templates/README +8 -0
- data/app_generators/ahn/templates/Rakefile +23 -0
- data/app_generators/ahn/templates/components/ami_remote/ami_remote.rb +15 -0
- data/app_generators/ahn/templates/components/disabled/HOW_TO_ENABLE +7 -0
- data/app_generators/ahn/templates/components/disabled/stomp_gateway/README.markdown +47 -0
- data/app_generators/ahn/templates/components/disabled/stomp_gateway/config.yml +12 -0
- data/app_generators/ahn/templates/components/disabled/stomp_gateway/stomp_gateway.rb +34 -0
- data/app_generators/ahn/templates/components/restful_rpc/README.markdown +11 -0
- data/app_generators/ahn/templates/components/restful_rpc/config.yml +34 -0
- data/app_generators/ahn/templates/components/restful_rpc/example-client.rb +48 -0
- data/app_generators/ahn/templates/components/restful_rpc/restful_rpc.rb +87 -0
- data/app_generators/ahn/templates/components/simon_game/simon_game.rb +56 -0
- data/app_generators/ahn/templates/config/startup.rb +53 -0
- data/app_generators/ahn/templates/dialplan.rb +3 -0
- data/app_generators/ahn/templates/events.rb +32 -0
- data/bin/ahn +28 -0
- data/bin/ahnctl +68 -0
- data/bin/jahn +42 -0
- data/examples/asterisk_manager_interface/standalone.rb +51 -0
- data/lib/adhearsion/cli.rb +223 -0
- data/lib/adhearsion/component_manager/spec_framework.rb +24 -0
- data/lib/adhearsion/component_manager.rb +208 -0
- data/lib/adhearsion/events_support.rb +84 -0
- data/lib/adhearsion/foundation/all.rb +9 -0
- data/lib/adhearsion/foundation/blank_slate.rb +5 -0
- data/lib/adhearsion/foundation/custom_daemonizer.rb +45 -0
- data/lib/adhearsion/foundation/event_socket.rb +203 -0
- data/lib/adhearsion/foundation/future_resource.rb +36 -0
- data/lib/adhearsion/foundation/global.rb +1 -0
- data/lib/adhearsion/foundation/metaprogramming.rb +17 -0
- data/lib/adhearsion/foundation/numeric.rb +13 -0
- data/lib/adhearsion/foundation/pseudo_guid.rb +10 -0
- data/lib/adhearsion/foundation/relationship_properties.rb +42 -0
- data/lib/adhearsion/foundation/string.rb +26 -0
- data/lib/adhearsion/foundation/synchronized_hash.rb +96 -0
- data/lib/adhearsion/foundation/thread_safety.rb +7 -0
- data/lib/adhearsion/host_definitions.rb +67 -0
- data/lib/adhearsion/initializer/asterisk.rb +81 -0
- data/lib/adhearsion/initializer/configuration.rb +254 -0
- data/lib/adhearsion/initializer/database.rb +49 -0
- data/lib/adhearsion/initializer/drb.rb +31 -0
- data/lib/adhearsion/initializer/freeswitch.rb +22 -0
- data/lib/adhearsion/initializer/rails.rb +40 -0
- data/lib/adhearsion/initializer.rb +373 -0
- data/lib/adhearsion/logging.rb +92 -0
- data/lib/adhearsion/tasks/database.rb +5 -0
- data/lib/adhearsion/tasks/deprecations.rb +59 -0
- data/lib/adhearsion/tasks/generating.rb +20 -0
- data/lib/adhearsion/tasks/lint.rb +4 -0
- data/lib/adhearsion/tasks/testing.rb +37 -0
- data/lib/adhearsion/tasks.rb +16 -0
- data/lib/adhearsion/version.rb +9 -0
- data/lib/adhearsion/voip/asterisk/agi_server.rb +81 -0
- data/lib/adhearsion/voip/asterisk/commands.rb +1284 -0
- data/lib/adhearsion/voip/asterisk/config_generators/agents.conf.rb +140 -0
- data/lib/adhearsion/voip/asterisk/config_generators/config_generator.rb +101 -0
- data/lib/adhearsion/voip/asterisk/config_generators/queues.conf.rb +250 -0
- data/lib/adhearsion/voip/asterisk/config_generators/voicemail.conf.rb +240 -0
- data/lib/adhearsion/voip/asterisk/config_manager.rb +71 -0
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rb +1754 -0
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_lexer.rl.rb +286 -0
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_messages.rb +78 -0
- data/lib/adhearsion/voip/asterisk/manager_interface/ami_protocol_lexer_machine.rl +87 -0
- data/lib/adhearsion/voip/asterisk/manager_interface.rb +562 -0
- data/lib/adhearsion/voip/asterisk/special_dial_plan_managers.rb +80 -0
- data/lib/adhearsion/voip/asterisk/super_manager.rb +19 -0
- data/lib/adhearsion/voip/asterisk.rb +4 -0
- data/lib/adhearsion/voip/call.rb +440 -0
- data/lib/adhearsion/voip/call_routing.rb +64 -0
- data/lib/adhearsion/voip/commands.rb +9 -0
- data/lib/adhearsion/voip/constants.rb +39 -0
- data/lib/adhearsion/voip/conveniences.rb +18 -0
- data/lib/adhearsion/voip/dial_plan.rb +218 -0
- data/lib/adhearsion/voip/dsl/dialing_dsl/dialing_dsl_monkey_patches.rb +37 -0
- data/lib/adhearsion/voip/dsl/dialing_dsl.rb +151 -0
- data/lib/adhearsion/voip/dsl/dialplan/control_passing_exception.rb +27 -0
- data/lib/adhearsion/voip/dsl/dialplan/dispatcher.rb +124 -0
- data/lib/adhearsion/voip/dsl/dialplan/parser.rb +71 -0
- data/lib/adhearsion/voip/dsl/dialplan/thread_mixin.rb +16 -0
- data/lib/adhearsion/voip/dsl/numerical_string.rb +117 -0
- data/lib/adhearsion/voip/freeswitch/basic_connection_manager.rb +48 -0
- data/lib/adhearsion/voip/freeswitch/event_handler.rb +58 -0
- data/lib/adhearsion/voip/freeswitch/freeswitch_dialplan_command_factory.rb +129 -0
- data/lib/adhearsion/voip/freeswitch/inbound_connection_manager.rb +38 -0
- data/lib/adhearsion/voip/freeswitch/oes_server.rb +195 -0
- data/lib/adhearsion/voip/menu_state_machine/calculated_match.rb +80 -0
- data/lib/adhearsion/voip/menu_state_machine/matchers.rb +123 -0
- data/lib/adhearsion/voip/menu_state_machine/menu_builder.rb +58 -0
- data/lib/adhearsion/voip/menu_state_machine/menu_class.rb +149 -0
- data/lib/adhearsion.rb +37 -0
- data/lib/theatre/README.markdown +64 -0
- data/lib/theatre/callback_definition_loader.rb +84 -0
- data/lib/theatre/guid.rb +23 -0
- data/lib/theatre/invocation.rb +121 -0
- data/lib/theatre/namespace_manager.rb +153 -0
- data/lib/theatre/version.rb +2 -0
- data/lib/theatre.rb +151 -0
- 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,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
|