warren 0.8.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,70 @@
1
+ begin
2
+ require "hmac-sha2"
3
+ rescue LoadError => e
4
+ puts "Error loading the `ruby-hmac` gem."
5
+ exit!
6
+ end
7
+
8
+ module Warren
9
+ class MessageFilter
10
+ # Hashes the message using a secret salt, stores the hash
11
+ # in the message and then checks its the same when pulled
12
+ # off the other end.
13
+ #
14
+ # Basic trust implementation to make sure the message
15
+ # hasn't been tampered with in transit and came from
16
+ # an "authorised" app.
17
+ #
18
+ # Make sure both the publisher and subscriber use the same
19
+ # key else you'll get KeyValidationError error raised.
20
+ #
21
+ class SharedSecret
22
+ # Raised when no key (salt) is provided
23
+ class NoKeyError < Exception; end
24
+ # Raised when there is a key mismatch error
25
+ class KeyValidationError < Exception; end
26
+
27
+ # Sets the key to use
28
+ def self.key= key
29
+ @@key = key
30
+ end
31
+
32
+ # Returns the current key
33
+ # Raises NoKeyError if no key has been assigned yet
34
+ def self.key
35
+ raise NoKeyError if @@key.nil?
36
+ @@key
37
+ end
38
+
39
+ # Returns the hashed message
40
+ #
41
+ # Expects that msg#to_s returns a string
42
+ # to hash against.
43
+ #
44
+ def self.secret msg
45
+ HMAC::SHA256.hexdigest(self.key, msg.to_s)
46
+ end
47
+
48
+ # Called when the message is being packed for
49
+ # transit. Returns a hash.
50
+ def self.pack msg
51
+ # Make sure its a hash
52
+ msg = {:secret_msg => msg} unless msg.is_a? Hash
53
+ # And add our secret into the hash
54
+ msg[:secret] = self.secret(msg.to_s)
55
+ msg
56
+ end
57
+
58
+ # Called when unpacking the message from transit.
59
+ # Returns the original object.
60
+ def self.unpack msg
61
+ # Check the secret exists in the msg and matches the secret_string
62
+ raise KeyValidationError unless msg.delete(:secret) == self.secret(msg)
63
+ # see if its a hash we created, it'll only contain the key "secret_msg" if it is
64
+ msg = msg[:secret_msg] if msg.keys == [:secret_msg]
65
+ msg
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,20 @@
1
+ require "yaml"
2
+
3
+ module Warren
4
+ class MessageFilter
5
+ # Packs the message into a YAML string
6
+ # for transferring safely across the wire
7
+ class Yaml < MessageFilter
8
+
9
+ # Returns a YAML string
10
+ def self.pack msg
11
+ YAML.dump(msg)
12
+ end
13
+
14
+ # Returns original message
15
+ def self.unpack msg
16
+ YAML.load(msg)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,76 @@
1
+ module Warren
2
+ # Handles filtering messages going onto/coming off the queue
3
+ class MessageFilter
4
+ # Array of filters to be run on the message before its
5
+ # pushed to rabbit.
6
+ #
7
+ # NB: These get called in reverse order from the array -
8
+ # the last filter to be added gets called first.
9
+ @@filters = []
10
+
11
+ class << self
12
+ # Adds a filter to the list
13
+ #
14
+ # A valid filter is just a class that defines
15
+ # <tt>self.pack</tt> and <tt>self.unpack</tt>
16
+ # methods, which both accept a single argument,
17
+ # act upon it, and return the output.
18
+ #
19
+ # Example filter class (See also message_filters/*.rb)
20
+ #
21
+ # class Foo
22
+ # def self.pack msg
23
+ # msg.reverse # Assumes msg responds to reverse
24
+ # end
25
+ #
26
+ # def self.unpack msg
27
+ # msg.reverse # Does the opposite of Foo#pack
28
+ # end
29
+ # end
30
+ #
31
+ def << filter
32
+ @@filters << filter
33
+ end
34
+ alias :add_filter :<<
35
+ end
36
+
37
+ # Called when a subclass is created, adds the subclass to the queue
38
+ def self.inherited klass
39
+ add_filter klass
40
+ end
41
+
42
+ # Returns current array of filters
43
+ def self.filters
44
+ @@filters
45
+ end
46
+
47
+ # Resets the filters to default
48
+ def self.reset_filters
49
+ @@filters = [Warren::MessageFilter::Yaml]
50
+ end
51
+
52
+ # Runs the raw message through all the filters
53
+ # and returns the filtered version
54
+ def self.pack msg
55
+ @@filters.reverse.each do |f|
56
+ # puts "Packing with #{f}"
57
+ msg = f.send(:pack, msg)
58
+ end
59
+ msg
60
+ end
61
+
62
+ # Runs the filtered message through all the
63
+ # filters and returns the raw version
64
+ def self.unpack msg
65
+ @@filters.each do |f|
66
+ # puts "Unpacking with #{f}"
67
+ msg = f.unpack(msg)
68
+ end
69
+ msg
70
+ end
71
+
72
+ end
73
+ end
74
+
75
+ # Make sure the YAML filter is added first
76
+ require File.expand_path(File.dirname(__FILE__) + "/filters/yaml")
@@ -0,0 +1,89 @@
1
+ module Warren
2
+ class Queue
3
+ @@connection = nil
4
+ @@adapter = nil
5
+
6
+ #
7
+ # Raised if no connection has been defined yet.
8
+ #
9
+ NoConnectionDetails = Class.new(Exception)
10
+
11
+ #
12
+ # Raised if a block is expected by the method but none is given.
13
+ #
14
+ NoBlockGiven = Class.new(Exception)
15
+
16
+ #
17
+ # Raised if an adapter isn't set
18
+ #
19
+ NoAdapterSet = Class.new(Exception)
20
+
21
+ #
22
+ # Raised if the adapter is missing a method
23
+ # Check the message for details of the missing method.
24
+ #
25
+ InvalidAdapter = Class.new(Exception)
26
+
27
+ #
28
+ # Sets the current connection
29
+ #
30
+ def self.connection= conn
31
+ @@connection = (conn.is_a?(Warren::Connection) ? conn : Warren::Connection.new(conn) )
32
+ end
33
+
34
+ #
35
+ # Returns the current connection details
36
+ #
37
+ def self.connection
38
+ @@connection ||= Warren::Connection.new
39
+ end
40
+
41
+ #
42
+ # Sets the adapter when this class is subclassed.
43
+ #
44
+ def self.inherited klass
45
+ @@adapter = klass
46
+ end
47
+
48
+ #
49
+ # Sets the adapter manually
50
+ #
51
+ def self.adapter= klass
52
+ @@adapter = klass
53
+ end
54
+
55
+ #
56
+ # Returns the current adapter or raises NoAdapterSet exception
57
+ #
58
+ def self.adapter
59
+ @@adapter || raise(NoAdapterSet)
60
+ end
61
+
62
+ #
63
+ # Publishes the message to the queue
64
+ #
65
+ def self.publish *args, &blk
66
+ raise(InvalidAdapter, "publish method missing") unless @@adapter.respond_to?(:publish)
67
+ self.adapter.publish(*args, &blk)
68
+ end
69
+
70
+ #
71
+ # Sends the subscribe message to the adapter class
72
+ #
73
+ def self.subscribe *args, &blk
74
+ raise(InvalidAdapter.new("subscribe method missing")) unless @@adapter.respond_to?(:subscribe)
75
+ self.adapter.subscribe(*args, &blk)
76
+ end
77
+
78
+ def self.logger
79
+ unless @@logger
80
+ @@logger = Logger.new(nil)
81
+ end
82
+ @@logger
83
+ end
84
+
85
+ def self.logger=(l)
86
+ @@logger = l
87
+ end
88
+ end
89
+ end
data/lib/warren.rb ADDED
@@ -0,0 +1,23 @@
1
+ require "yaml"
2
+ require "logger"
3
+ #
4
+ # Library for pushing messages onto RabbitMQ queues,
5
+ # and receiving them at the other end.
6
+ #
7
+ # It handles authentication + filtering messages with custom
8
+ # classes if needed.
9
+ #
10
+ # Start with Warren::Queue for details and see also
11
+ # examples/
12
+ #
13
+ module Warren
14
+ end
15
+
16
+ WARREN_ENV = ENV['WARREN_ENV'] || ((defined?(RAILS_ENV) ? RAILS_ENV : "development")) unless defined?(WARREN_ENV)
17
+ WARREN_ROOT = (defined?(RAILS_ROOT) ? RAILS_ROOT : File.dirname($0)) unless defined?(WARREN_ROOT)
18
+ WARREN_LIB_ROOT = File.expand_path(File.dirname(__FILE__)) unless defined? WARREN_LIB_ROOT
19
+
20
+ # Require everything in the lib folder
21
+ Dir["#{WARREN_LIB_ROOT}/warren/*.rb"].each do |file|
22
+ require file
23
+ end
data/readme.rdoc ADDED
@@ -0,0 +1,46 @@
1
+ = Warren
2
+
3
+ Library for sending and receiving messages, complete with en/decrypting messages on either side of the transport.
4
+
5
+ It was written to handle sending messages between two nodes using RabbitMQ, which is why the two default adapters are for synchronous and asynchronous rabbitmq client libraries. You can delegate the sending & receiving to any custom class you want, simply by subclassing Warren::Queue. (Isn't ruby magic marvelous!)
6
+
7
+ The filtering works in much the same way as the adapter class. There is a default YAML filter that is always called last before sending the message and first when receiving the message, simply to make sure the message is a string when sent + received. You can then add custom classes onto the stack in any order you want, simply by subclassing Warren::MessageFilter. Add them in the same order on the receiving side and warren takes care of calling them in reverse order.
8
+
9
+ Start by looking at examples/ to see how to use it, and then lib/warren/adapters/ to see how to implement your own adapter class and lib/warren/filters to see how to implement your own filters.
10
+
11
+ == Installation
12
+
13
+ gem install brightbox-warren
14
+
15
+ == Usage
16
+
17
+ require "rubygems"
18
+ require "warren"
19
+ # Use the bunny adapter to connect to RabbitMQ (Bunny is an AMQP client that works with Rails/Passenger apps)
20
+ require "warren/adapters/bunny_adapter"
21
+ # If you're running in development and don't want to actually push messages onto the queue then instead of loading the bunny adapter use the dummy adapter
22
+ require "warren/adapters/dummy_adapter"
23
+
24
+ # See examples/ for more
25
+
26
+ == Rails
27
+
28
+ Add this to your environment.rb
29
+
30
+ config.gem "brightbox-warren", :lib => "warren", :version => ">= 0.8"
31
+
32
+ Add the config into config/warren.yml with the details for each environment. Works just the same as database.yml:
33
+
34
+ development:
35
+ user: rabbit
36
+ pass: carrots53
37
+ host: rabbit.warren
38
+ logging: false
39
+
40
+ And then in an initializer file (or bottom of environment.rb) require the adapter you want to use (for rabbitmq I suggest bunny - amqp uses eventmachine and was giving me issues under passenger.) And then any filters you want to use.
41
+
42
+ require "warren/adapters/bunny_adapter"
43
+
44
+ == License
45
+
46
+ Licensed under the MIT license. See LICENSE for more details.
data/spec/spec.opts ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --format progress
3
+ --loadby mtime
@@ -0,0 +1,12 @@
1
+ require File.join(File.dirname(__FILE__) + "/../lib/warren")
2
+
3
+ # Hacky and I hate it, but needed to
4
+ # change constants in tests
5
+ # from http://is.gd/12JVp
6
+ def silently(&block)
7
+ warn_level = $VERBOSE
8
+ $VERBOSE = nil
9
+ result = block.call
10
+ $VERBOSE = warn_level
11
+ result
12
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+ require "#{File.dirname(__FILE__)}/../../../lib/warren/adapters/test_adapter.rb"
3
+
4
+ describe TestAdapter do
5
+
6
+ before(:all) do
7
+ @file_name = "#{WARREN_ROOT}/tmp/warren.txt"
8
+ end
9
+
10
+ it "should return true from publish without a tmp file" do
11
+ TestAdapter.publish(:queue_name, :payload).should == true
12
+ end
13
+
14
+ it "should return true from publish with a tmp file which doesn't say \"FAIL\"" do
15
+ File.should_receive(:exists?).with(@file_name).and_return(true)
16
+ File.should_receive(:read).with(@file_name, 4).and_return("blah")
17
+
18
+ TestAdapter.publish(:queue_name, :payload).should == true
19
+ end
20
+
21
+ it "should raise an error when tmp file exists and says \"FAIL\"" do
22
+ File.should_receive(:exists?).with(@file_name).and_return(true)
23
+ File.should_receive(:read).with(@file_name, 4).and_return("FAIL")
24
+
25
+ lambda { TestAdapter.publish(:queue_name, :payload) }.
26
+ should raise_error(TestAdapter::ConnectionFailed)
27
+ end
28
+
29
+ end
@@ -0,0 +1,122 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Warren::Connection do
4
+
5
+ before(:each) do
6
+ setup_adapter
7
+ end
8
+
9
+ it "should read from warren.yml" do
10
+ setup_config_file
11
+
12
+ Warren::Connection.new
13
+ end
14
+
15
+ it "should read from an arbitrary file" do
16
+ File.should_receive(:exists?).with("my_awesome_config.yml").and_return(true)
17
+ YAML.should_receive(:load_file).with("my_awesome_config.yml").and_return({"development" => {}})
18
+
19
+ Warren::Connection.new("my_awesome_config.yml")
20
+ end
21
+
22
+ describe "parsing config with file" do
23
+
24
+ before do
25
+ setup_config_file
26
+ end
27
+
28
+ it "should parse the right config out" do
29
+ conn = Warren::Connection.new
30
+ WARREN_ENV.should == "development"
31
+ conn.instance_variable_get("@options").should == {
32
+ :user => "rspec",
33
+ :pass => "password",
34
+ :host => "localhost",
35
+ :logging => false,
36
+ }
37
+ end
38
+
39
+ it "should raise if no details for current environment" do
40
+ silently { WARREN_ENV = "rspec" }
41
+
42
+ lambda { Warren::Connection.new }.
43
+ should raise_error(
44
+ Warren::Connection::InvalidConnectionDetails,
45
+ "No details for current environment 'rspec'"
46
+ )
47
+
48
+ silently { WARREN_ENV = "development" }
49
+ end
50
+
51
+ it "should symbolize keys in a hash" do
52
+ conn = Warren::Connection.new
53
+ hash = {"one" => "two", "three" => {"four" => 7}, :five => "six"}
54
+ conn.send(:symbolize_keys, hash).should == {
55
+ :one => "two",
56
+ :three => {:four => 7},
57
+ :five => "six"
58
+ }
59
+ end
60
+
61
+ it "should raise if no adapter set to check against" do
62
+ Warren::Queue.adapter = nil
63
+ lambda { Warren::Connection.new }.
64
+ should raise_error(Warren::Queue::NoAdapterSet)
65
+ end
66
+
67
+ it "should successfully check against adapter" do
68
+ _adapter = mock 'queue', :check_connection_details => true
69
+ _adapter.should_receive(:check_connection_details)
70
+ Warren::Queue.adapter = _adapter
71
+
72
+ Warren::Connection.new
73
+ end
74
+
75
+ it "should raise errors for missing connection details" do
76
+ _adapter = stub 'queue', :check_connection_details => ["one", "two"]
77
+
78
+ Warren::Connection.new
79
+ end
80
+
81
+ it "should raise errors for other prerequisits in the adapter" do
82
+ Adapter = Class.new(Warren::Queue) do
83
+ def self.check_connection_details params
84
+ raise Warren::Connection::InvalidConnectionDetails, "Missing prerequisites"
85
+ end
86
+ end
87
+
88
+ lambda { Warren::Connection.new }.
89
+ should raise_error(Warren::Connection::InvalidConnectionDetails, "Missing prerequisites")
90
+ end
91
+
92
+ end
93
+
94
+ def setup_config_file
95
+ config_file = "#{File.dirname($0)}/config/warren.yml"
96
+ File.should_receive(:exists?).with(config_file).and_return(true)
97
+ YAML.should_receive(:load_file).with(config_file).and_return(yaml_data)
98
+ end
99
+
100
+ def setup_adapter
101
+ _adapter = stub 'queue'
102
+ Warren::Queue.adapter = _adapter
103
+ end
104
+
105
+ def yaml_data
106
+ {
107
+ "development" => {
108
+ "host" => "localhost",
109
+ "user" => "rspec",
110
+ "pass" => "password",
111
+ "logging" => false
112
+ },
113
+ "test" => {
114
+ "host" => "localhost-test",
115
+ "user" => "rspec-test",
116
+ "pass" => "password-test",
117
+ "logging" => true
118
+ }
119
+ }
120
+ end
121
+
122
+ end
@@ -0,0 +1,91 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Warren::Queue do
4
+
5
+ describe "connection" do
6
+
7
+ before(:all) do
8
+ @conn = stub 'connection'
9
+ end
10
+
11
+ it "should create a new Warren::Connection if one doesn't exist" do
12
+ Warren::Connection.should_receive(:new).and_return(@conn)
13
+
14
+ Warren::Queue.connection.should == @conn
15
+ end
16
+
17
+ it "should only create a connection once" do
18
+ # Already created the connection object in the first it
19
+ Warren::Connection.should_not_receive(:new)
20
+
21
+ Warren::Queue.connection.should == @conn
22
+ Warren::Queue.connection.should == @conn
23
+ end
24
+ end
25
+
26
+ describe "adapter" do
27
+
28
+ before(:each) do
29
+ @adapter = mock 'adapter', :publish => "publish", :subscribe => "subscribe"
30
+ Warren::Queue.adapter = @adapter
31
+ end
32
+
33
+ it "should have an adapter set" do
34
+ Warren::Queue.adapter.should == @adapter
35
+ end
36
+
37
+ it "should have a publish method" do
38
+ my_adapter = mock 'adapter'
39
+ Warren::Queue.adapter = my_adapter
40
+
41
+ lambda { Warren::Queue.publish }.should \
42
+ raise_error(Warren::Queue::InvalidAdapter, "publish method missing")
43
+ end
44
+
45
+ it "should have a subscribe method" do
46
+ my_adapter = mock 'adapter'
47
+ Warren::Queue.adapter = my_adapter
48
+
49
+ Warren::Queue.adapter.should == my_adapter
50
+
51
+ lambda { Warren::Queue.subscribe}.should \
52
+ raise_error(Warren::Queue::InvalidAdapter, "subscribe method missing")
53
+ end
54
+
55
+ it "should pass publish through to the adapter" do
56
+ @adapter.should_receive(:publish)
57
+ Warren::Queue.publish.should == "publish"
58
+ end
59
+
60
+ it "should pass arguments through to adapter#publish" do
61
+ @adapter.should_receive(:publish).with("foo", "bar")
62
+
63
+ Warren::Queue.publish("foo", "bar").should == "publish"
64
+ end
65
+
66
+ it "should pass a block through to adapter#publish" do
67
+ block = lambda { true }
68
+ @adapter.should_receive(:publish).with("foo", "bar", block)
69
+
70
+ Warren::Queue.publish("foo", "bar", block).should == "publish"
71
+ end
72
+
73
+ it "should pass subscribe through to the adapter" do
74
+ @adapter.should_receive(:subscribe)
75
+ Warren::Queue.subscribe.should == "subscribe"
76
+ end
77
+
78
+ it "should pass arguments through to adapter#subscribe" do
79
+ @adapter.should_receive(:subscribe).with("foo", "bar")
80
+
81
+ Warren::Queue.subscribe("foo", "bar").should == "subscribe"
82
+ end
83
+
84
+ it "should pass a block through to adapter#subscribe" do
85
+ block = lambda { true }
86
+ @adapter.should_receive(:subscribe).with("foo", "bar", block)
87
+
88
+ Warren::Queue.subscribe("foo", "bar", block).should == "subscribe"
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,9 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Warren do
4
+
5
+ it "should have a default environment" do
6
+ WARREN_ENV.should == "development"
7
+ end
8
+
9
+ end
data/tasks/rdoc.rake ADDED
@@ -0,0 +1,7 @@
1
+ require "rake/rdoctask"
2
+
3
+ Rake::RDocTask.new do |rd|
4
+ rd.main = "lib/warren.rb"
5
+ rd.rdoc_files.include("lib/**/*.rb")
6
+ rd.rdoc_dir = "doc"
7
+ end
data/tasks/rspec.rake ADDED
@@ -0,0 +1,24 @@
1
+ # Borrowed from http://github.com/rsim/ruby-plsql/tree/master/tasks/rspec.rake
2
+ # Github++
3
+ begin
4
+ require "spec"
5
+ rescue LoadError
6
+ require "rubygems"
7
+ require "spec"
8
+ end
9
+
10
+ begin
11
+ require "spec/rake/spectask"
12
+ rescue LoadError
13
+ puts <<-EOS
14
+ To use rspec for testing you must install rspec gem:
15
+ [sudo] gem install rspec
16
+ EOS
17
+ exit(0)
18
+ end
19
+
20
+ desc "Run the specs under spec/*"
21
+ Spec::Rake::SpecTask.new do |t|
22
+ t.spec_opts = ["--options", "spec/spec.opts"]
23
+ t.spec_files = FileList["spec/**/*_spec.rb"]
24
+ end
data/warren.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{warren}
5
+ s.version = "0.8.9"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Caius Durling, David Smalley"]
9
+ s.date = %q{2009-10-15}
10
+ s.description = %q{Library for pushing messages onto and off RabbitMQ queues}
11
+ s.email = %q{support@brightbox.co.uk}
12
+ s.extra_rdoc_files = ["CHANGELOG", "lib/warren/adapters/amqp_adapter.rb", "lib/warren/adapters/bunny_adapter.rb", "lib/warren/adapters/dummy_adapter.rb", "lib/warren/adapters/test_adapter.rb", "lib/warren/connection.rb", "lib/warren/filters/shared_secret.rb", "lib/warren/filters/yaml.rb", "lib/warren/message_filter.rb", "lib/warren/queue.rb", "lib/warren.rb", "LICENSE", "tasks/rdoc.rake", "tasks/rspec.rake"]
13
+ s.files = ["CHANGELOG", "examples/authed/receiver.rb", "examples/authed/secret.rb", "examples/authed/sender.rb", "examples/simple/amqp_mass_sender.rb", "examples/simple/amqp_receiver.rb", "examples/simple/amqp_sender.rb", "examples/simple/bunny_receiver.rb", "examples/simple/bunny_sender.rb", "lib/warren/adapters/amqp_adapter.rb", "lib/warren/adapters/bunny_adapter.rb", "lib/warren/adapters/dummy_adapter.rb", "lib/warren/adapters/test_adapter.rb", "lib/warren/connection.rb", "lib/warren/filters/shared_secret.rb", "lib/warren/filters/yaml.rb", "lib/warren/message_filter.rb", "lib/warren/queue.rb", "lib/warren.rb", "LICENSE", "Manifest", "Rakefile", "readme.rdoc", "spec/spec.opts", "spec/spec_helper.rb", "spec/warren/adapters/test_adapter_spec.rb", "spec/warren/connection_spec.rb", "spec/warren/queue_spec.rb", "spec/warren/warren_spec.rb", "tasks/rdoc.rake", "tasks/rspec.rake", "warren.gemspec"]
14
+ s.homepage = %q{http://github.com/brightbox/warren}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Warren", "--main", "readme.rdoc"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{warren}
18
+ s.rubygems_version = %q{1.3.5}
19
+ s.summary = %q{Library for pushing messages onto and off RabbitMQ queues}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
+ s.add_runtime_dependency(%q<amqp>, [">= 0.6.0"])
27
+ else
28
+ s.add_dependency(%q<amqp>, [">= 0.6.0"])
29
+ end
30
+ else
31
+ s.add_dependency(%q<amqp>, [">= 0.6.0"])
32
+ end
33
+ end