stomp 1.1 → 1.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +6 -0
- data/README.rdoc +39 -0
- data/lib/stomp/client.rb +119 -42
- data/lib/stomp/connection.rb +187 -19
- metadata +6 -4
data/CHANGELOG
CHANGED
data/README.rdoc
CHANGED
@@ -15,6 +15,45 @@ An implementation of the Stomp protocol (http://stomp.codehaus.org/Protocol) for
|
|
15
15
|
p msg
|
16
16
|
end
|
17
17
|
|
18
|
+
===Failover + SSL Example URL Usage
|
19
|
+
|
20
|
+
options = "initialReconnectDelay=5000&randomize=false&useExponentialBackOff=false"
|
21
|
+
|
22
|
+
#remotehost1 uses SSL, remotehost2 doesn't
|
23
|
+
client = Stomp::Client.new("failover:(stomp+ssl://login1:passcode1@remotehost1:61612,stomp://login2:passcode2@remotehost2:61613)?#{options}")
|
24
|
+
|
25
|
+
client.send("/my/queue", "hello world!")
|
26
|
+
client.subscribe("/my/queue") do |msg|
|
27
|
+
p msg
|
28
|
+
end
|
29
|
+
|
30
|
+
===Hash Example Usage
|
31
|
+
|
32
|
+
hash = {
|
33
|
+
:hosts => [
|
34
|
+
{:login => "login1", :passcode => "passcode1", :host => "remotehost1", :port => 61612, :ssl => true},
|
35
|
+
{:login => "login2", :passcode => "passcode2", :host => "remotehost2", :port => 61613, :ssl => false},
|
36
|
+
|
37
|
+
],
|
38
|
+
# These are the default parameters, don't need to be set
|
39
|
+
:initial_reconnect_delay => 0.01,
|
40
|
+
:max_reconnect_delay => 30.0,
|
41
|
+
:use_exponential_back_off => true,
|
42
|
+
:back_off_multiplier => 2,
|
43
|
+
:max_reconnect_attempts => 0,
|
44
|
+
:randomize => false,
|
45
|
+
:backup => false,
|
46
|
+
:timeout => -1,
|
47
|
+
:connect_headers => {}
|
48
|
+
}
|
49
|
+
|
50
|
+
# for client
|
51
|
+
client = Stomp::Client.new(hash)
|
52
|
+
|
53
|
+
# for connection
|
54
|
+
connection = Stomp::Connection.new(hash)
|
55
|
+
|
56
|
+
|
18
57
|
===Contact info
|
19
58
|
|
20
59
|
Up until March 2009 the project was maintained and primarily developed by Brian McCallister.
|
data/lib/stomp/client.rb
CHANGED
@@ -7,7 +7,8 @@ module Stomp
|
|
7
7
|
# in that thread if you have much message volume.
|
8
8
|
class Client
|
9
9
|
|
10
|
-
attr_reader :login, :passcode, :host, :port, :reliable, :running
|
10
|
+
attr_reader :login, :passcode, :host, :port, :reliable, :running, :parameters
|
11
|
+
alias :obj_send :send
|
11
12
|
|
12
13
|
# A new Client object can be initialized using two forms:
|
13
14
|
#
|
@@ -30,22 +31,46 @@ module Stomp
|
|
30
31
|
#
|
31
32
|
def initialize(login = '', passcode = '', host = 'localhost', port = 61613, reliable = false)
|
32
33
|
|
33
|
-
# Parse stomp:// URL's or set
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
@
|
40
|
-
@
|
41
|
-
@
|
42
|
-
@
|
43
|
-
|
44
|
-
@
|
45
|
-
|
46
|
-
|
47
|
-
@
|
34
|
+
# Parse stomp:// URL's or set params
|
35
|
+
if login.is_a?(Hash)
|
36
|
+
@parameters = login
|
37
|
+
|
38
|
+
first_host = @parameters[:hosts][0]
|
39
|
+
|
40
|
+
@login = first_host[:login]
|
41
|
+
@passcode = first_host[:passcode]
|
42
|
+
@host = first_host[:host]
|
43
|
+
@port = first_host[:port] || default_port(first_host[:ssl])
|
44
|
+
|
45
|
+
@reliable = true
|
46
|
+
|
47
|
+
elsif login =~ /^stomp:\/\/(([\w\.]+):(\w+)@)?([\w\.]+):(\d+)/ # e.g. stomp://login:passcode@host:port or stomp://host:port
|
48
|
+
@login = $2 || ""
|
49
|
+
@passcode = $3 || ""
|
50
|
+
@host = $4
|
51
|
+
@port = $5.to_i
|
48
52
|
@reliable = false
|
53
|
+
elsif login =~ /^failover:(\/\/)?\(stomp(\+ssl)?:\/\/(([\w\.]*):(\w*)@)?([\w\.]+):(\d+)(,stomp(\+ssl)?:\/\/(([\w\.]*):(\w*)@)?([\w\.]+):(\d+)\))+(\?(.*))?$/ # e.g. failover://(stomp://login1:passcode1@localhost:61616,stomp://login2:passcode2@remotehost:61617)?option1=param
|
54
|
+
|
55
|
+
first_host = {}
|
56
|
+
first_host[:ssl] = !$2.nil?
|
57
|
+
@login = first_host[:login] = $4 || ""
|
58
|
+
@passcode = first_host[:passcode] = $5 || ""
|
59
|
+
@host = first_host[:host] = $6
|
60
|
+
@port = first_host[:port] = $7.to_i || default_port(first_host[:ssl])
|
61
|
+
|
62
|
+
options = $16 || ""
|
63
|
+
parts = options.split(/&|=/)
|
64
|
+
options = Hash[*parts]
|
65
|
+
|
66
|
+
hosts = [first_host] + parse_hosts(login)
|
67
|
+
|
68
|
+
@parameters = {}
|
69
|
+
@parameters[:hosts] = hosts
|
70
|
+
|
71
|
+
@parameters.merge! filter_options(options)
|
72
|
+
|
73
|
+
@reliable = true
|
49
74
|
else
|
50
75
|
@login = login
|
51
76
|
@passcode = passcode
|
@@ -54,38 +79,21 @@ module Stomp
|
|
54
79
|
@reliable = reliable
|
55
80
|
end
|
56
81
|
|
57
|
-
|
58
|
-
raise ArgumentError if @port.nil? || @port == '' || @port < 1 || @port > 65535
|
59
|
-
raise ArgumentError unless @reliable.is_a?(TrueClass) || @reliable.is_a?(FalseClass)
|
82
|
+
check_arguments!
|
60
83
|
|
61
84
|
@id_mutex = Mutex.new
|
62
85
|
@ids = 1
|
63
|
-
|
64
|
-
@
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
@listener_thread = Thread.start do
|
70
|
-
while @running
|
71
|
-
message = @connection.receive
|
72
|
-
case
|
73
|
-
when message.nil?
|
74
|
-
break
|
75
|
-
when message.command == 'MESSAGE'
|
76
|
-
if listener = @listeners[message.headers['destination']]
|
77
|
-
listener.call(message)
|
78
|
-
end
|
79
|
-
when message.command == 'RECEIPT'
|
80
|
-
if listener = @receipt_listeners[message.headers['receipt-id']]
|
81
|
-
listener.call(message)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
86
|
+
|
87
|
+
if @parameters
|
88
|
+
@connection = Connection.new(@parameters)
|
89
|
+
else
|
90
|
+
@connection = Connection.new(@login, @passcode, @host, @port, @reliable)
|
85
91
|
end
|
92
|
+
|
93
|
+
start_listeners
|
86
94
|
|
87
95
|
end
|
88
|
-
|
96
|
+
|
89
97
|
# Syntactic sugar for 'Client.new' See 'initialize' for usage.
|
90
98
|
def self.open(login = '', passcode = '', host = 'localhost', port = 61613, reliable = false)
|
91
99
|
Client.new(login, passcode, host, port, reliable)
|
@@ -201,7 +209,76 @@ module Stomp
|
|
201
209
|
@receipt_listeners[id] = listener
|
202
210
|
id
|
203
211
|
end
|
212
|
+
|
213
|
+
def default_port(ssl)
|
214
|
+
return 61612 if ssl
|
215
|
+
|
216
|
+
61613
|
217
|
+
end
|
218
|
+
|
219
|
+
def parse_hosts(url)
|
220
|
+
hosts = []
|
221
|
+
|
222
|
+
host_match = /stomp(\+ssl)?:\/\/(([\w\.]*):(\w*)@)?([\w\.]+):(\d+)\)/
|
223
|
+
url.scan(host_match).each do |match|
|
224
|
+
host = {}
|
225
|
+
host[:ssl] = !match[0].nil?
|
226
|
+
host[:login] = match[2] || ""
|
227
|
+
host[:passcode] = match[3] || ""
|
228
|
+
host[:host] = match[4]
|
229
|
+
host[:port] = match[5].to_i
|
230
|
+
|
231
|
+
hosts << host
|
232
|
+
end
|
233
|
+
|
234
|
+
hosts
|
235
|
+
end
|
236
|
+
|
237
|
+
def check_arguments!
|
238
|
+
raise ArgumentError if @host.nil? || @host.empty?
|
239
|
+
raise ArgumentError if @port.nil? || @port == '' || @port < 1 || @port > 65535
|
240
|
+
raise ArgumentError unless @reliable.is_a?(TrueClass) || @reliable.is_a?(FalseClass)
|
241
|
+
end
|
242
|
+
|
243
|
+
def filter_options(options)
|
244
|
+
new_options = {}
|
245
|
+
new_options[:initial_reconnect_delay] = (options["initialReconnectDelay"] || 10).to_f / 1000 # In ms
|
246
|
+
new_options[:max_reconnect_delay] = (options["maxReconnectDelay"] || 30000 ).to_f / 1000 # In ms
|
247
|
+
new_options[:use_exponential_back_off] = !(options["useExponentialBackOff"] == "false") # Default: true
|
248
|
+
new_options[:back_off_multiplier] = (options["backOffMultiplier"] || 2 ).to_i
|
249
|
+
new_options[:max_reconnect_attempts] = (options["maxReconnectAttempts"] || 0 ).to_i
|
250
|
+
new_options[:randomize] = options["randomize"] == "true" # Default: false
|
251
|
+
new_options[:backup] = false # Not implemented yet: I'm using a master X slave solution
|
252
|
+
new_options[:timeout] = -1 # Not implemented yet: a "timeout(5) do ... end" would do the trick, feel free
|
253
|
+
|
254
|
+
new_options
|
255
|
+
end
|
256
|
+
|
257
|
+
def start_listeners
|
258
|
+
@listeners = {}
|
259
|
+
@receipt_listeners = {}
|
260
|
+
@running = true
|
261
|
+
@replay_messages_by_txn = {}
|
204
262
|
|
263
|
+
@listener_thread = Thread.start do
|
264
|
+
while @running
|
265
|
+
message = @connection.receive
|
266
|
+
case
|
267
|
+
when message.nil?
|
268
|
+
break
|
269
|
+
when message.command == 'MESSAGE'
|
270
|
+
if listener = @listeners[message.headers['destination']]
|
271
|
+
listener.call(message)
|
272
|
+
end
|
273
|
+
when message.command == 'RECEIPT'
|
274
|
+
if listener = @receipt_listeners[message.headers['receipt-id']]
|
275
|
+
listener.call(message)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
end
|
205
282
|
end
|
206
283
|
end
|
207
284
|
|
data/lib/stomp/connection.rb
CHANGED
@@ -4,7 +4,7 @@ module Stomp
|
|
4
4
|
# synchronous receives
|
5
5
|
class Connection
|
6
6
|
|
7
|
-
|
7
|
+
alias :obj_send :send
|
8
8
|
# A new Connection object accepts the following parameters:
|
9
9
|
#
|
10
10
|
# login (String, default : '')
|
@@ -14,9 +14,28 @@ module Stomp
|
|
14
14
|
# reliable (Boolean, default : false)
|
15
15
|
# reconnect_delay (Integer, default : 5)
|
16
16
|
#
|
17
|
-
# e.g. c =
|
17
|
+
# e.g. c = Connection.new("username", "password", "localhost", 61613, true)
|
18
|
+
#
|
19
|
+
# Hash:
|
20
|
+
#
|
21
|
+
# hash = {
|
22
|
+
# :hosts => [
|
23
|
+
# {:login => "login1", :passcode => "passcode1", :host => "localhost", :port => 61616, :ssl => false},
|
24
|
+
# {:login => "login2", :passcode => "passcode2", :host => "remotehost", :port => 61617, :ssl => false}
|
25
|
+
# ],
|
26
|
+
# :initial_reconnect_delay => 0.01,
|
27
|
+
# :max_reconnect_delay => 30.0,
|
28
|
+
# :use_exponential_back_off => true,
|
29
|
+
# :back_off_multiplier => 2,
|
30
|
+
# :max_reconnect_attempts => 0,
|
31
|
+
# :randomize => false,
|
32
|
+
# :backup => false,
|
33
|
+
# :timeout => -1
|
34
|
+
# }
|
35
|
+
#
|
36
|
+
# e.g. c = Connection.new(hash)
|
18
37
|
#
|
19
|
-
# TODO
|
38
|
+
# TODO
|
20
39
|
# Stomp URL :
|
21
40
|
# A Stomp URL must begin with 'stomp://' and can be in one of the following forms:
|
22
41
|
#
|
@@ -26,22 +45,42 @@ module Stomp
|
|
26
45
|
# stomp://user:pass@host.domain.tld:port
|
27
46
|
#
|
28
47
|
def initialize(login = '', passcode = '', host = 'localhost', port = 61613, reliable = false, reconnect_delay = 5, connect_headers = {})
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
48
|
+
if login.is_a?(Hash)
|
49
|
+
hashed_initialize(login)
|
50
|
+
else
|
51
|
+
@host = host
|
52
|
+
@port = port
|
53
|
+
@login = login
|
54
|
+
@passcode = passcode
|
55
|
+
@reliable = reliable
|
56
|
+
@reconnect_delay = reconnect_delay
|
57
|
+
@connect_headers = connect_headers
|
58
|
+
@ssl = false
|
59
|
+
@parameters = nil
|
60
|
+
end
|
61
|
+
|
33
62
|
@transmit_semaphore = Mutex.new
|
34
63
|
@read_semaphore = Mutex.new
|
35
64
|
@socket_semaphore = Mutex.new
|
36
|
-
|
37
|
-
@reconnect_delay = reconnect_delay
|
38
|
-
@connect_headers = connect_headers
|
39
|
-
@closed = false
|
65
|
+
|
40
66
|
@subscriptions = {}
|
41
67
|
@failure = nil
|
68
|
+
@connection_attempts = 0
|
69
|
+
|
42
70
|
socket
|
43
71
|
end
|
44
|
-
|
72
|
+
|
73
|
+
def hashed_initialize(params)
|
74
|
+
|
75
|
+
@parameters = refine_params(params)
|
76
|
+
@reliable = true
|
77
|
+
@reconnect_delay = @parameters[:initial_reconnect_delay]
|
78
|
+
@connect_headers = @parameters[:connect_headers]
|
79
|
+
|
80
|
+
#sets the first host to connect
|
81
|
+
change_host
|
82
|
+
end
|
83
|
+
|
45
84
|
# Syntactic sugar for 'Connection.new' See 'initialize' for usage.
|
46
85
|
def Connection.open(login = '', passcode = '', host = 'localhost', port = 61613, reliable = false, reconnect_delay = 5, connect_headers = {})
|
47
86
|
Connection.new(login, passcode, host, port, reliable, reconnect_delay, connect_headers)
|
@@ -50,30 +89,158 @@ module Stomp
|
|
50
89
|
def socket
|
51
90
|
# Need to look into why the following synchronize does not work.
|
52
91
|
#@read_semaphore.synchronize do
|
92
|
+
|
53
93
|
s = @socket;
|
94
|
+
|
95
|
+
s = nil unless connected?
|
96
|
+
|
54
97
|
while s.nil? || !@failure.nil?
|
55
98
|
@failure = nil
|
56
99
|
begin
|
57
|
-
s =
|
58
|
-
|
59
|
-
|
60
|
-
|
100
|
+
s = open_socket
|
101
|
+
@closed = false
|
102
|
+
|
103
|
+
headers = @connect_headers.clone
|
104
|
+
headers[:login] = @login
|
105
|
+
headers[:passcode] = @passcode
|
61
106
|
_transmit(s, "CONNECT", headers)
|
62
107
|
@connect = _receive(s)
|
63
108
|
# replay any subscriptions.
|
64
109
|
@subscriptions.each { |k,v| _transmit(s, "SUBSCRIBE", v) }
|
110
|
+
|
111
|
+
@connection_attempts = 0
|
65
112
|
rescue
|
66
113
|
@failure = $!;
|
67
114
|
s=nil;
|
68
115
|
raise unless @reliable
|
69
|
-
$stderr.print "connect failed: " + $! +" will retry in #{@reconnect_delay}\n";
|
116
|
+
$stderr.print "connect to #{@host} failed: " + $! +" will retry(##{@connection_attempts}) in #{@reconnect_delay}\n";
|
117
|
+
|
118
|
+
raise "Max number of reconnection attempts reached" if max_reconnect_attempts?
|
119
|
+
|
70
120
|
sleep(@reconnect_delay);
|
121
|
+
|
122
|
+
@connection_attempts += 1
|
123
|
+
|
124
|
+
if @parameters
|
125
|
+
change_host
|
126
|
+
increase_reconnect_delay
|
127
|
+
end
|
71
128
|
end
|
72
129
|
end
|
73
130
|
@socket = s
|
74
131
|
return s;
|
75
132
|
#end
|
76
133
|
end
|
134
|
+
|
135
|
+
def connected?
|
136
|
+
begin
|
137
|
+
test_socket = TCPSocket.open @host, @port
|
138
|
+
test_socket.close
|
139
|
+
open?
|
140
|
+
rescue
|
141
|
+
false
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def close_socket
|
146
|
+
begin
|
147
|
+
@socket.close
|
148
|
+
rescue
|
149
|
+
#Ignoring if already closed
|
150
|
+
end
|
151
|
+
|
152
|
+
@closed = true
|
153
|
+
end
|
154
|
+
|
155
|
+
def open_socket
|
156
|
+
return TCPSocket.open @host, @port unless @ssl
|
157
|
+
|
158
|
+
ssl_socket
|
159
|
+
end
|
160
|
+
|
161
|
+
def ssl_socket
|
162
|
+
require 'openssl' unless defined?(OpenSSL)
|
163
|
+
|
164
|
+
ctx = OpenSSL::SSL::SSLContext.new
|
165
|
+
|
166
|
+
# For client certificate authentication:
|
167
|
+
# key_path = ENV["STOMP_KEY_PATH"] || "~/stomp_keys"
|
168
|
+
# ctx.cert = OpenSSL::X509::Certificate.new("#{key_path}/client.cer")
|
169
|
+
# ctx.key = OpenSSL::PKey::RSA.new("#{key_path}/client.keystore")
|
170
|
+
|
171
|
+
# For server certificate authentication:
|
172
|
+
# truststores = OpenSSL::X509::Store.new
|
173
|
+
# truststores.add_file("#{key_path}/client.ts")
|
174
|
+
# ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
175
|
+
# ctx.cert_store = truststores
|
176
|
+
|
177
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
178
|
+
|
179
|
+
tcp_socket = TCPSocket.new @host, @port
|
180
|
+
ssl = OpenSSL::SSL::SSLSocket.new(tcp_socket, ctx)
|
181
|
+
ssl.connect
|
182
|
+
ssl
|
183
|
+
end
|
184
|
+
|
185
|
+
def refine_params(params)
|
186
|
+
params = uncamelized_sym_keys(params)
|
187
|
+
|
188
|
+
{
|
189
|
+
:initial_reconnect_delay => 0.01,
|
190
|
+
:max_reconnect_delay => 30.0,
|
191
|
+
:use_exponential_back_off => true,
|
192
|
+
:back_off_multiplier => 2,
|
193
|
+
:max_reconnect_attempts => 0,
|
194
|
+
:randomize => false,
|
195
|
+
:connect_headers => {},
|
196
|
+
:backup => false,
|
197
|
+
:timeout => -1
|
198
|
+
}.merge(params)
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
def uncamelized_sym_keys(params)
|
203
|
+
uncamelized = {}
|
204
|
+
params.each_pair do |key, value|
|
205
|
+
key = key.to_s.split(/(?=[A-Z])/).join('_').downcase.to_sym
|
206
|
+
uncamelized[key] = value
|
207
|
+
end
|
208
|
+
|
209
|
+
uncamelized
|
210
|
+
end
|
211
|
+
|
212
|
+
def change_host
|
213
|
+
@parameters[:hosts].shuffle! if @parameters[:randomize]
|
214
|
+
|
215
|
+
# Set first as master and send it to the end of array
|
216
|
+
current_host = @parameters[:hosts].shift
|
217
|
+
@parameters[:hosts] << current_host
|
218
|
+
|
219
|
+
@ssl = current_host[:ssl]
|
220
|
+
@host = current_host[:host]
|
221
|
+
@port = current_host[:port] || default_port(@ssl)
|
222
|
+
@login = current_host[:login] || ""
|
223
|
+
@passcode = current_host[:passcode] || ""
|
224
|
+
|
225
|
+
end
|
226
|
+
|
227
|
+
def default_port(ssl)
|
228
|
+
return 61612 if ssl
|
229
|
+
|
230
|
+
61613
|
231
|
+
end
|
232
|
+
|
233
|
+
def max_reconnect_attempts?
|
234
|
+
!(@parameters.nil? || @parameters[:max_reconnect_attempts].nil?) && @parameters[:max_reconnect_attempts] != 0 && @connection_attempts > @parameters[:max_reconnect_attempts]
|
235
|
+
end
|
236
|
+
|
237
|
+
def increase_reconnect_delay
|
238
|
+
|
239
|
+
@reconnect_delay *= @parameters[:back_off_multiplier] if @parameters[:use_exponential_back_off]
|
240
|
+
@reconnect_delay = @parameters[:max_reconnect_delay] if @reconnect_delay > @parameters[:max_reconnect_delay]
|
241
|
+
|
242
|
+
@reconnect_delay
|
243
|
+
end
|
77
244
|
|
78
245
|
# Is this connection open?
|
79
246
|
def open?
|
@@ -145,7 +312,8 @@ module Stomp
|
|
145
312
|
# Close this connection
|
146
313
|
def disconnect(headers = {})
|
147
314
|
transmit("DISCONNECT", headers)
|
148
|
-
|
315
|
+
|
316
|
+
close_socket
|
149
317
|
end
|
150
318
|
|
151
319
|
# Return a pending message if one is available, otherwise
|
@@ -233,7 +401,7 @@ module Stomp
|
|
233
401
|
rescue
|
234
402
|
@failure = $!;
|
235
403
|
raise unless @reliable
|
236
|
-
$stderr.print "transmit failed: " + $!+"\n";
|
404
|
+
$stderr.print "transmit to #{@host} failed: " + $!+"\n";
|
237
405
|
end
|
238
406
|
end
|
239
407
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stomp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian McCallister
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-
|
13
|
+
date: 2009-12-03 00:00:00 -02:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|
@@ -41,6 +41,8 @@ files:
|
|
41
41
|
- test/test_helper.rb
|
42
42
|
has_rdoc: true
|
43
43
|
homepage: http://stomp.codehaus.org/
|
44
|
+
licenses: []
|
45
|
+
|
44
46
|
post_install_message:
|
45
47
|
rdoc_options:
|
46
48
|
- --quiet
|
@@ -69,9 +71,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
69
71
|
requirements: []
|
70
72
|
|
71
73
|
rubyforge_project:
|
72
|
-
rubygems_version: 1.3.
|
74
|
+
rubygems_version: 1.3.5
|
73
75
|
signing_key:
|
74
|
-
specification_version:
|
76
|
+
specification_version: 3
|
75
77
|
summary: Ruby client for the Stomp messaging protocol
|
76
78
|
test_files:
|
77
79
|
- test/test_client.rb
|