stomp 1.1.7 → 1.1.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: