stomp 1.1.7 → 1.1.8

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.
@@ -1,3 +1,14 @@
1
+ == 1.1.8 2010-16-05
2
+
3
+ * Set KEEPALIVE on connection socket options
4
+ * Attempt to support JRuby more robustly (poll remains broken)
5
+ * Switch to ruby supplied IO#ready?
6
+ * Test enhancements for suppress_content_length header
7
+ * Miscellaneous small documentation updates
8
+ * Add parse_timeout parameter for use with hashed logins
9
+ * Allow connection to hosts with a - (dash) in the host name
10
+ * Add limit parameter to thread joins
11
+
1
12
  == 1.1.7 2010-09-01
2
13
 
3
14
  * Binary parse of raw STOMP frame
@@ -1,10 +1,15 @@
1
1
  ==README
2
2
 
3
- http://stomp.rubyforge.org/
3
+ * (http://gitorious.org/projects/stomp/)
4
+ * (https://github.com/morellon/stomp/)
5
+ * (http://stomp.rubyforge.org/)
4
6
 
5
7
  ===Overview
6
8
 
7
- An implementation of the Stomp protocol (http://stomp.codehaus.org/Protocol) for Ruby.
9
+ An implementation of the Stomp protocol for Ruby. See:
10
+
11
+ * [STOMP 1.0] (http://stomp.codehaus.org/Protocol)
12
+ * [STOMP 1.0 and 1.1 Draft] (http://stomp.github.com/index.html)
8
13
 
9
14
 
10
15
  ===Example Usage
@@ -27,7 +32,7 @@ An implementation of the Stomp protocol (http://stomp.codehaus.org/Protocol) for
27
32
  p msg
28
33
  end
29
34
 
30
- ===Hash Example Usage
35
+ ===Hash Login Example Usage
31
36
 
32
37
  hash = {
33
38
  :hosts => [
@@ -44,7 +49,8 @@ An implementation of the Stomp protocol (http://stomp.codehaus.org/Protocol) for
44
49
  :randomize => false,
45
50
  :backup => false,
46
51
  :timeout => -1,
47
- :connect_headers => {}
52
+ :connect_headers => {},
53
+ :parse_timeout => 5,
48
54
  }
49
55
 
50
56
  # for client
@@ -58,25 +64,29 @@ An implementation of the Stomp protocol (http://stomp.codehaus.org/Protocol) for
58
64
 
59
65
  Up until March 2009 the project was maintained and primarily developed by Brian McCallister.
60
66
 
61
- The project is now maintained by Johan Sørensen <johan@johansorensen.com>
67
+ The project is now maintained by Johan Sørensen <johan@johansorensen.com> and others.
62
68
 
63
69
  ===Source Code
64
70
 
71
+ https://github.com/morellon/stomp/
65
72
  http://gitorious.org/projects/stomp/
66
73
  http://github.com/js/stomp/
67
74
 
68
75
  ===Project urls
69
76
 
70
77
  Project Home :
78
+
71
79
  http://gitorious.org/projects/stomp/
72
80
  http://rubyforge.org/projects/stomp/
73
81
 
74
82
  Stomp Protocol Info :
83
+
84
+ http://stomp.github.com/index.html
75
85
  http://stomp.codehaus.org/Protocol
76
86
 
77
87
  = Contributors
78
88
 
79
- The following people have contributed to Stomp (ordered by commits):
89
+ The following people have contributed to Stomp:
80
90
 
81
91
  * Brian McCaliister
82
92
  * Glenn Rempe <glenn@rempe.us>
@@ -89,3 +99,6 @@ The following people have contributed to Stomp (ordered by commits):
89
99
  * Tony Garnock-Jones <tonyg@lshift.net>
90
100
  * chirino
91
101
  * Stefan Saasen
102
+ * Neil Wilson
103
+ * Dinesh Majrekar
104
+
data/Rakefile CHANGED
@@ -31,9 +31,11 @@ begin
31
31
  gem.version = Stomp::Version::STRING
32
32
  gem.summary = %Q{Ruby client for the Stomp messaging protocol}
33
33
  gem.description = %Q{Ruby client for the Stomp messaging protocol}
34
- gem.email = ["brianm@apache.org", 'marius@stones.com', 'morellon@gmail.com']
35
- gem.homepage = "http://stomp.codehaus.org/"
36
- gem.authors = ["Brian McCallister", 'Marius Mathiesen', 'Thiago Morello']
34
+ gem.email = ["brianm@apache.org", 'marius@stones.com', 'morellon@gmail.com',
35
+ 'allard.guy.m@gmail.com' ]
36
+ gem.homepage = "https://rubygems.org/gems/stomp"
37
+ gem.authors = ["Brian McCallister", 'Marius Mathiesen', 'Thiago Morello',
38
+ 'Guy M. Allard']
37
39
  gem.add_development_dependency "rspec", '>= 2.3'
38
40
  end
39
41
  Jeweler::GemcutterTasks.new
@@ -43,7 +45,7 @@ end
43
45
 
44
46
  desc 'Run the specs'
45
47
  RSpec::Core::RakeTask.new(:spec) do |t|
46
- t.spec_opts = ['--colour']
48
+ t.rspec_opts = ['--colour']
47
49
  t.pattern = 'spec/**/*_spec.rb'
48
50
  end
49
51
 
@@ -47,13 +47,13 @@ module Stomp
47
47
 
48
48
  @reliable = true
49
49
 
50
- elsif login =~ /^stomp:\/\/(([\w\.]+):(\w+)@)?([\w\.]+):(\d+)/ # e.g. stomp://login:passcode@host:port or stomp://host:port
50
+ elsif login =~ /^stomp:\/\/#{url_regex}/ # e.g. stomp://login:passcode@host:port or stomp://host:port
51
51
  @login = $2 || ""
52
52
  @passcode = $3 || ""
53
53
  @host = $4
54
54
  @port = $5.to_i
55
55
  @reliable = false
56
- 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
56
+ elsif login =~ /^failover:(\/\/)?\(stomp(\+ssl)?:\/\/#{url_regex}(,stomp(\+ssl)?:\/\/#{url_regex}\))+(\?(.*))?$/ # e.g. failover://(stomp://login1:passcode1@localhost:61616,stomp://login2:passcode2@remotehost:61617)?option1=param
57
57
 
58
58
  first_host = {}
59
59
  first_host[:ssl] = !$2.nil?
@@ -104,8 +104,8 @@ module Stomp
104
104
 
105
105
  # Join the listener thread for this client,
106
106
  # generally used to wait for a quit signal
107
- def join
108
- @listener_thread.join
107
+ def join(limit = nil)
108
+ @listener_thread.join(limit)
109
109
  end
110
110
 
111
111
  # Begin a transaction by name
@@ -241,6 +241,11 @@ module Stomp
241
241
  id
242
242
  end
243
243
 
244
+ # e.g. login:passcode@host:port or host:port
245
+ def url_regex
246
+ '(([\w\.\-]*):(\w*)@)?([\w\.\-]+):(\d+)'
247
+ end
248
+
244
249
  def parse_hosts(url)
245
250
  hosts = []
246
251
 
@@ -1,5 +1,6 @@
1
1
  require 'socket'
2
2
  require 'timeout'
3
+ require 'io/wait'
3
4
 
4
5
  module Stomp
5
6
 
@@ -39,7 +40,9 @@ module Stomp
39
40
  # :max_reconnect_attempts => 0,
40
41
  # :randomize => false,
41
42
  # :backup => false,
42
- # :timeout => -1
43
+ # :timeout => -1,
44
+ # :connect_headers => {},
45
+ # :parse_timeout => 5,
43
46
  # }
44
47
  #
45
48
  # e.g. c = Connection.new(hash)
@@ -68,6 +71,7 @@ module Stomp
68
71
  @connect_headers = connect_headers
69
72
  @ssl = false
70
73
  @parameters = nil
74
+ @parse_timeout = 5 # To override, use hashed parameters
71
75
  end
72
76
 
73
77
  # Use Mutexes: only one lock per each thread
@@ -89,7 +93,7 @@ module Stomp
89
93
  @reliable = true
90
94
  @reconnect_delay = @parameters[:initial_reconnect_delay]
91
95
  @connect_headers = @parameters[:connect_headers]
92
-
96
+ @parse_timeout = @parameters[:parse_timeout]
93
97
  #sets the first host to connect
94
98
  change_host
95
99
  end
@@ -148,7 +152,9 @@ module Stomp
148
152
  :max_reconnect_attempts => 0,
149
153
  :randomize => false,
150
154
  :backup => false,
151
- :timeout => -1
155
+ :timeout => -1,
156
+ # Parse Timeout
157
+ :parse_timeout => 5
152
158
  }
153
159
 
154
160
  default_params.merge(params)
@@ -346,10 +352,12 @@ module Stomp
346
352
  def _receive( read_socket )
347
353
  @read_semaphore.synchronize do
348
354
  line = read_socket.gets
355
+
349
356
  return nil if line.nil?
350
357
 
351
- # If the reading hangs for more than 5 seconds, abort the parsing process
352
- Timeout::timeout(5, Stomp::Error::PacketParsingTimeout) do
358
+ # If the reading hangs for more than X seconds, abort the parsing process.
359
+ # X defaults to 5. Override allowed in connection hash parameters.
360
+ Timeout::timeout(@parse_timeout, Stomp::Error::PacketParsingTimeout) do
353
361
  # Reads the beginning of the message until it runs into a empty line
354
362
  message_header = ''
355
363
  begin
@@ -368,15 +376,24 @@ module Stomp
368
376
  raise Stomp::Error::InvalidMessageLength unless parse_char(read_socket.getc) == "\0"
369
377
  # Else reads, the rest of the message until the first \0
370
378
  else
371
- message_body += char while read_socket.ready? && (char = parse_char(read_socket.getc)) != "\0"
379
+ message_body += char while (char = parse_char(read_socket.getc)) != "\0"
372
380
  end
373
381
 
374
- # If the buffer isn't empty, reads the next char and returns it to the buffer
375
- # unless it's a \n
376
- if read_socket.ready?
382
+ # If the buffer isn't empty, reads trailing new lines.
383
+ # Note: experiments with JRuby seem to show that .ready? never
384
+ # returns true. This means that this code to drain trailing new
385
+ # lines never runs using JRuby.
386
+ while read_socket.ready?
377
387
  last_char = read_socket.getc
378
- read_socket.ungetc(last_char) if parse_char(last_char) != "\n"
388
+ break unless last_char
389
+ if parse_char(last_char) != "\n"
390
+ read_socket.ungetc(last_char)
391
+ break
392
+ end
379
393
  end
394
+ # And so, a JRuby hack. Remove any new lines at the start of the
395
+ # next buffer.
396
+ message_header.gsub!(/^\n?/, "")
380
397
 
381
398
  # Adds the excluded \n and \0 and tries to create a new message with it
382
399
  Message.new(message_header + "\n" + message_body + "\0")
@@ -424,10 +441,6 @@ module Stomp
424
441
 
425
442
  def open_tcp_socket
426
443
  tcp_socket = TCPSocket.open @host, @port
427
- def tcp_socket.ready?
428
- r,w,e = IO.select([self],nil,nil,0)
429
- ! r.nil?
430
- end
431
444
 
432
445
  tcp_socket
433
446
  end
@@ -473,7 +486,8 @@ module Stomp
473
486
  close_socket
474
487
 
475
488
  @closed = false
476
-
489
+ # Use keepalive
490
+ used_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true)
477
491
  used_socket
478
492
  end
479
493
 
@@ -6,6 +6,12 @@ module Stomp
6
6
  end
7
7
  end
8
8
 
9
+ class InvalidServerCommand < RuntimeError
10
+ def message
11
+ "Invalid command from server"
12
+ end
13
+ end
14
+
9
15
  class InvalidMessageLength < RuntimeError
10
16
  def message
11
17
  "Invalid content length received"
@@ -26,7 +26,7 @@ module Stomp
26
26
 
27
27
  # Extract working copies of each frame part
28
28
  work_command = frame[0..command_index-1]
29
- raise Stomp::Error::InvalidFormat, 'nil command' unless @@allowed_commands.include?(work_command)
29
+ raise Stomp::Error::InvalidServerCommand, "invalid command: #{work_command.inspect}" unless @@allowed_commands.include?(work_command)
30
30
  #
31
31
  work_headers = frame[command_index+1..headers_index-1]
32
32
  raise Stomp::Error::InvalidFormat, 'nil headers' unless work_headers
@@ -2,7 +2,7 @@ module Stomp
2
2
  module Version #:nodoc: all
3
3
  MAJOR = 1
4
4
  MINOR = 1
5
- PATCH = 7
5
+ PATCH = 8
6
6
  STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
7
7
  end
8
8
  end
@@ -114,14 +114,32 @@ describe Stomp::Client do
114
114
 
115
115
  end
116
116
 
117
+ describe "(created with non-authenticating stomp:// URL and a host with a '-')" do
118
+
119
+ before(:each) do
120
+ @client = Stomp::Client.new('stomp://foo-bar:12345')
121
+ end
122
+
123
+ it "should properly parse the URL provided" do
124
+ @client.login.should eql('')
125
+ @client.passcode.should eql('')
126
+ @client.host.should eql('foo-bar')
127
+ @client.port.should eql(12345)
128
+ @client.reliable.should be_false
129
+ end
130
+
131
+ it_should_behave_like "standard Client"
132
+
133
+ end
134
+
117
135
  describe "(created with authenticating stomp:// URL and non-TLD host)" do
118
136
 
119
137
  before(:each) do
120
- @client = Stomp::Client.new('stomp://testlogin:testpasscode@foobar:12345')
138
+ @client = Stomp::Client.new('stomp://test-login:testpasscode@foobar:12345')
121
139
  end
122
140
 
123
141
  it "should properly parse the URL provided" do
124
- @client.login.should eql('testlogin')
142
+ @client.login.should eql('test-login')
125
143
  @client.passcode.should eql('testpasscode')
126
144
  @client.host.should eql('foobar')
127
145
  @client.port.should eql(12345)
@@ -132,6 +150,24 @@ describe Stomp::Client do
132
150
 
133
151
  end
134
152
 
153
+ describe "(created with authenticating stomp:// URL and a host with a '-')" do
154
+
155
+ before(:each) do
156
+ @client = Stomp::Client.new('stomp://test-login:testpasscode@foo-bar:12345')
157
+ end
158
+
159
+ it "should properly parse the URL provided" do
160
+ @client.login.should eql('test-login')
161
+ @client.passcode.should eql('testpasscode')
162
+ @client.host.should eql('foo-bar')
163
+ @client.port.should eql(12345)
164
+ @client.reliable.should be_false
165
+ end
166
+
167
+ it_should_behave_like "standard Client"
168
+
169
+ end
170
+
135
171
  describe "(created with non-authenticating stomp:// URL and TLD host)" do
136
172
 
137
173
  before(:each) do
@@ -16,6 +16,7 @@ describe Stomp::Connection do
16
16
  :randomize => false,
17
17
  :backup => false,
18
18
  :timeout => -1,
19
+ :parse_timeout => 5,
19
20
  :connect_headers => {}
20
21
  }
21
22
 
@@ -27,8 +28,8 @@ describe Stomp::Connection do
27
28
 
28
29
  # clone() does a shallow copy, we want a deep one so we can garantee the hosts order
29
30
  normal_parameters = Marshal::load(Marshal::dump(@parameters))
30
-
31
- @tcp_socket = mock(:tcp_socket, :close => nil, :puts => nil, :write => nil)
31
+
32
+ @tcp_socket = mock(:tcp_socket, :close => nil, :puts => nil, :write => nil, :setsockopt => nil)
32
33
  TCPSocket.stub!(:open).and_return @tcp_socket
33
34
  @connection = Stomp::Connection.new(normal_parameters)
34
35
  end
@@ -47,7 +48,8 @@ describe Stomp::Connection do
47
48
  "maxReconnectAttempts" => 0,
48
49
  "randomize" => false,
49
50
  "backup" => false,
50
- "timeout" => -1
51
+ "timeout" => -1,
52
+ "parse_timeout" => 5,
51
53
  }
52
54
 
53
55
  @connection = Stomp::Connection.new(used_hash)
@@ -196,7 +198,7 @@ describe Stomp::Connection do
196
198
 
197
199
  before(:each) do
198
200
  ssl_parameters = {:hosts => [{:login => "login2", :passcode => "passcode2", :host => "remotehost", :ssl => true}]}
199
- @ssl_socket = mock(:ssl_socket, :puts => nil, :write => nil)
201
+ @ssl_socket = mock(:ssl_socket, :puts => nil, :write => nil, :setsockopt => nil)
200
202
 
201
203
  TCPSocket.should_receive(:open).and_return @tcp_socket
202
204
  OpenSSL::SSL::SSLSocket.should_receive(:new).and_return(@ssl_socket)
@@ -260,6 +262,7 @@ describe Stomp::Connection do
260
262
  :randomize => false,
261
263
  :backup => false,
262
264
  :timeout => -1,
265
+ :parse_timeout => 5,
263
266
  :connect_headers => {}
264
267
  }
265
268
 
@@ -288,6 +291,7 @@ describe Stomp::Connection do
288
291
  :randomize => true,
289
292
  :backup => false,
290
293
  :timeout => -1,
294
+ :parse_timeout => 20,
291
295
  :connect_headers => {:lerolero => "ronaldo"},
292
296
  :dead_letter_queue => "queue/Error",
293
297
  :max_redeliveries => 10
@@ -5,13 +5,13 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{stomp}
8
- s.version = "1.1.7"
8
+ s.version = "1.1.8"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Brian McCallister", "Marius Mathiesen", "Thiago Morello"]
12
- s.date = %q{2011-01-14}
11
+ s.authors = ["Brian McCallister", "Marius Mathiesen", "Thiago Morello", "Guy M. Allard"]
12
+ s.date = %q{2011-03-16}
13
13
  s.description = %q{Ruby client for the Stomp messaging protocol}
14
- s.email = ["brianm@apache.org", "marius@stones.com", "morellon@gmail.com"]
14
+ s.email = ["brianm@apache.org", "marius@stones.com", "morellon@gmail.com", "allard.guy.m@gmail.com"]
15
15
  s.executables = ["catstomp", "stompcat"]
16
16
  s.extra_rdoc_files = [
17
17
  "LICENSE",
@@ -44,7 +44,7 @@ Gem::Specification.new do |s|
44
44
  "test/test_helper.rb",
45
45
  "test/test_message.rb"
46
46
  ]
47
- s.homepage = %q{http://stomp.codehaus.org/}
47
+ s.homepage = %q{https://rubygems.org/gems/stomp}
48
48
  s.require_paths = ["lib"]
49
49
  s.rubygems_version = %q{1.3.7}
50
50
  s.summary = %q{Ruby client for the Stomp messaging protocol}
@@ -20,6 +20,20 @@ class TestStomp < Test::Unit::TestCase
20
20
  assert_not_nil @conn
21
21
  end
22
22
 
23
+ def test_no_length
24
+ @conn.subscribe make_destination
25
+ #
26
+ @conn.publish make_destination, "test_stomp#test_no_length",
27
+ { :suppress_content_length => true }
28
+ msg = @conn.receive
29
+ assert_equal "test_stomp#test_no_length", msg.body
30
+ #
31
+ @conn.publish make_destination, "test_stomp#test_\000_length",
32
+ { :suppress_content_length => true }
33
+ msg2 = @conn.receive
34
+ assert_equal "test_stomp#test_", msg2.body
35
+ end
36
+
23
37
  def test_explicit_receive
24
38
  @conn.subscribe make_destination
25
39
  @conn.publish make_destination, "test_stomp#test_explicit_receive"
@@ -79,7 +79,7 @@ class TestMessageKcode < Test::Unit::TestCase
79
79
  aframe = Stomp::Message.new("command\nheaders\n\njunk")
80
80
  }
81
81
  #
82
- assert_raise(Stomp::Error::InvalidFormat) {
82
+ assert_raise(Stomp::Error::InvalidServerCommand) {
83
83
  aframe = Stomp::Message.new("junkcommand\nheaders\n\njunk\0\n\n")
84
84
  }
85
85
  #
@@ -95,6 +95,10 @@ class TestMessageKcode < Test::Unit::TestCase
95
95
  aframe = Stomp::Message.new("MESSAGE\nh1:val1\n\njunk\0\n")
96
96
  }
97
97
  #
98
+ assert_nothing_raised {
99
+ aframe = Stomp::Message.new("MESSAGE\nh2:val2\n\n\0")
100
+ }
101
+ #
98
102
  assert_nothing_raised {
99
103
  aframe = Stomp::Message.new("RECEIPT\nh1:val1\n\njunk\0\n")
100
104
  }
metadata CHANGED
@@ -5,18 +5,19 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 1
8
- - 7
9
- version: 1.1.7
8
+ - 8
9
+ version: 1.1.8
10
10
  platform: ruby
11
11
  authors:
12
12
  - Brian McCallister
13
13
  - Marius Mathiesen
14
14
  - Thiago Morello
15
+ - Guy M. Allard
15
16
  autorequire:
16
17
  bindir: bin
17
18
  cert_chain: []
18
19
 
19
- date: 2011-01-14 00:00:00 -05:00
20
+ date: 2011-03-16 00:00:00 -04:00
20
21
  default_executable:
21
22
  dependencies:
22
23
  - !ruby/object:Gem::Dependency
@@ -38,6 +39,7 @@ email:
38
39
  - brianm@apache.org
39
40
  - marius@stones.com
40
41
  - morellon@gmail.com
42
+ - allard.guy.m@gmail.com
41
43
  executables:
42
44
  - catstomp
43
45
  - stompcat
@@ -73,7 +75,7 @@ files:
73
75
  - test/test_helper.rb
74
76
  - test/test_message.rb
75
77
  has_rdoc: true
76
- homepage: http://stomp.codehaus.org/
78
+ homepage: https://rubygems.org/gems/stomp
77
79
  licenses: []
78
80
 
79
81
  post_install_message: