backchat 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .ruby-version
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in backchat.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Zach Pendleton
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,72 @@
1
+ # Backchat
2
+
3
+ Backchat is a JRuby-only gem that provides the
4
+ [Smack](http://www.igniterealtime.org/projects/smack/) XMPP libraries
5
+ and adds connection-pooling resources to them. It exists because there
6
+ are [no](https://github.com/ln/xmpp4r) [good](https://github.com/blaine/xmpp4r-simple)
7
+ [native](https://github.com/bryanwoods/babylon) XMPP libraries for Ruby.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'backchat'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install backchat
22
+
23
+ ## Usage
24
+
25
+ You'll need to require all of the Smack libraries you need inside your app with
26
+ the standard JRuby syntax:
27
+
28
+ ```ruby
29
+ java_import 'org.jivesoftware.smacmx.muc.MultiUserChat'
30
+ java_import 'org.jivesoftware.smacmx.Form'
31
+ ...
32
+ ```
33
+
34
+ But you'll get connection pooling for free. Yay! Inside your app, configure
35
+ Backchat's pool in some kind of initializer:
36
+
37
+ ```ruby
38
+ Backchat::ConnectionPool.configure do
39
+ host 'jabber.org'
40
+ username 'admin'
41
+ password 's3cr3t$@ren0fun'
42
+ pool_size: 5 # five connections is the default
43
+ end
44
+
45
+ # configure also accepts a hash
46
+ Backchat::ConnectionPool.configure(host: 'jabber.org', username: 'admin',
47
+ password: 's3cr3t$@ren0fun', pool_size: 5)
48
+ ```
49
+
50
+ Once Backchat is configured, you can use the connection pool like magic:
51
+
52
+ ```ruby
53
+ # connection_pool takes a block and passes it an XMPPConnection.
54
+ Backchat.connection_pool do |conn|
55
+ chat = MultiUserChat.new(conn, 'my-room@solonely.localhost')
56
+ chat.create('me')
57
+ end
58
+ ```
59
+
60
+ The connection pool is created on the first call to `Backchat#connection_pool`,
61
+ provides authenticated connections, and blocks until a connection is available.
62
+ In the future it seems like it'd be nice to have a group of unauthenticated
63
+ connections so the pool could be used with multiple users, but my current use
64
+ case doesn't require it so it's missing in this version.
65
+
66
+ ## Contributing
67
+
68
+ 1. Fork it
69
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
70
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
71
+ 4. Push to the branch (`git push origin my-new-feature`)
72
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ task default: [:test]
5
+
6
+ Rake::TestTask.new do |t|
7
+ t.pattern = 'test/**/test_*.rb'
8
+ end
data/backchat.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'backchat/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'backchat'
8
+ spec.version = Backchat::VERSION
9
+ spec.authors = ['Zach Pendleton']
10
+ spec.email = ['zachpendleton@gmail.com']
11
+ spec.description = %q{Smack XMPP libraries for JRuby. With connection pooling!!}
12
+ spec.summary = %q{Include Smack XMPP libraries in JRuby and use them with connection pooling.}
13
+ spec.homepage = 'https://github.com/zachpendleton/backchat'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.3'
22
+ spec.add_development_dependency 'minitest', '~> 4.6.2'
23
+ spec.add_development_dependency 'mocha', '~> 0.13.3'
24
+ spec.add_development_dependency 'pry'
25
+ spec.add_development_dependency 'rake', '>= 0.9.6'
26
+ end
data/lib/backchat.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'java/smack'
2
+ require 'java/smackx'
3
+ java_import 'org.jivesoftware.smack.XMPPConnection'
4
+ java_import 'java.util.concurrent.ArrayBlockingQueue'
5
+ require 'backchat/connection_pool'
6
+ require 'backchat/version'
7
+
8
+ module Backchat
9
+ # Your code goes here...
10
+ end
@@ -0,0 +1,90 @@
1
+ module Backchat
2
+ class ConnectionPool
3
+ include Enumerable
4
+
5
+ DEFAULT_SETTINGS = {
6
+ host: 'localhost',
7
+ username: 'admin',
8
+ password: 'password',
9
+ pool_size: 5 }
10
+
11
+ @settings = DEFAULT_SETTINGS
12
+
13
+ def initialize(count = self.class.settings[:pool_size])
14
+ @queue = fill(ArrayBlockingQueue.new(count))
15
+ end
16
+
17
+ def each(&block)
18
+ queue.each(&block)
19
+ end
20
+
21
+ def take
22
+ queue.take
23
+ end
24
+
25
+ def add(connection)
26
+ queue.add(connection)
27
+ end
28
+
29
+ def with_connection
30
+ connection = take
31
+ yield connection
32
+ ensure
33
+ add(connection)
34
+ end
35
+
36
+
37
+ class << self
38
+ attr_reader :settings
39
+
40
+ def configure(settings = {}, &block)
41
+ if block_given?
42
+ instance_eval(&block)
43
+ else
44
+ @settings.merge!(settings)
45
+ end
46
+ end
47
+
48
+ def connection(credentials = {})
49
+ connection = XMPPConnection.new(settings[:host])
50
+ connection.connect
51
+ if (credentials.keys & [:username, :password]).count == 2
52
+ connection.login(*credentials.values_at(:username, :password))
53
+ end
54
+
55
+ yield connection
56
+ ensure
57
+ connection.disconnect
58
+ end
59
+
60
+ private
61
+ [:host, :username, :password, :pool_size].each do |key|
62
+ define_method("#{key}") do |val|
63
+ @settings ||= {}
64
+ @settings[key] = val
65
+ end
66
+ end
67
+ end
68
+
69
+ private
70
+ attr_reader :queue
71
+
72
+ def fill(queue)
73
+ while queue.remaining_capacity > 0
74
+ conn = XMPPConnection.new(self.class.settings[:host])
75
+ conn.connect
76
+ conn.login(self.class.settings[:username],
77
+ self.class.settings[:password], conn.connection_id)
78
+
79
+ queue.add(conn)
80
+ end
81
+
82
+ queue
83
+ end
84
+ end
85
+
86
+ def self.connection_pool(&block)
87
+ @connection_pool = ConnectionPool.new
88
+ block_given? ? @connection_pool.with_connection(&block) : @connection_pool
89
+ end
90
+ end
@@ -0,0 +1,3 @@
1
+ module Backchat
2
+ VERSION = '0.0.1'
3
+ end
Binary file
Binary file
@@ -0,0 +1,124 @@
1
+ require File.expand_path('../../test_helper', File.dirname(__FILE__))
2
+
3
+ class BackchatConnectionPoolTest < MiniTest::Unit::TestCase
4
+ def setup
5
+ XMPPConnection.any_instance.stubs(:connect).returns(nil)
6
+ XMPPConnection.any_instance.stubs(:login).returns(nil)
7
+
8
+ @pool = Backchat::ConnectionPool.new(5)
9
+ end
10
+
11
+ def test_configure_saves_settings_passed_in_a_block
12
+ Backchat::ConnectionPool.configure do
13
+ host 'example.com'
14
+ username 'don_draper'
15
+ password 'secret'
16
+ pool_size 1
17
+ end
18
+
19
+ assert_equal Backchat::ConnectionPool.settings, { host: 'example.com',
20
+ username: 'don_draper',
21
+ password: 'secret',
22
+ pool_size: 1 }
23
+ end
24
+
25
+ def test_configure_accepts_a_hash
26
+ Backchat::ConnectionPool.configure(host: 'example.com', username: 'don_draper',
27
+ password: 'secret', pool_size: 1)
28
+
29
+ assert_equal Backchat::ConnectionPool.settings, { host: 'example.com',
30
+ username: 'don_draper',
31
+ password: 'secret',
32
+ pool_size: 1 }
33
+ end
34
+
35
+ def test_configure_allows_partial_settings_in_a_block
36
+ Backchat::ConnectionPool.configure { host 'example.com' }
37
+
38
+ assert_equal Backchat::ConnectionPool.settings,
39
+ Backchat::ConnectionPool::DEFAULT_SETTINGS.merge(host: 'example.com')
40
+ end
41
+
42
+ def test_configure_allows_partial_settings_in_a_hash
43
+ Backchat::ConnectionPool.configure(host: 'example.com')
44
+
45
+ assert_equal Backchat::ConnectionPool.settings,
46
+ Backchat::ConnectionPool::DEFAULT_SETTINGS.merge(host: 'example.com')
47
+ end
48
+
49
+ def test_initialize_creates_a_queue
50
+ assert_includes @pool.instance_variables, :@queue
51
+ end
52
+
53
+ def test_queue_is_an_array_blocking_queue
54
+ assert_instance_of ArrayBlockingQueue, @pool.instance_variable_get(:@queue)
55
+ end
56
+
57
+ def test_initialize_fills_the_pool_with_connections
58
+ assert_equal 5, @pool.count
59
+ end
60
+
61
+ def test_initialize_fills_the_pool_with_the_number_of_connections_it_is_passed
62
+ assert_equal 1, Backchat::ConnectionPool.new(1).count
63
+ end
64
+
65
+ def test_initialize_connects_new_connections
66
+ XMPPConnection.any_instance.expects(:connect)
67
+ Backchat::ConnectionPool.new(1)
68
+ end
69
+
70
+ def test_initialize_authenticates_new_connections
71
+ XMPPConnection.any_instance.expects(:login)
72
+ Backchat::ConnectionPool.new(1)
73
+ end
74
+
75
+ def test_take_removes_a_connection_from_the_queue
76
+ @pool.take
77
+ assert_equal 4, @pool.count
78
+ end
79
+
80
+ def test_add_adds_a_connection_to_the_queue
81
+ conn = @pool.take
82
+ @pool.add(conn)
83
+
84
+ assert_equal 5, @pool.count
85
+ end
86
+
87
+ def test_with_connection_yields_a_block_with_a_connection
88
+ @pool.with_connection do |conn|
89
+ assert_instance_of XMPPConnection, conn
90
+ end
91
+ end
92
+
93
+ def test_with_connection_removes_a_connection_from_the_pool_and_returns_it
94
+ @pool.with_connection do |conn|
95
+ assert_equal 4, @pool.count
96
+ end
97
+
98
+ assert_equal 5, @pool.count
99
+ end
100
+
101
+ def test_with_connection_ensures_that_a_connection_is_returned_to_the_pool
102
+ @pool.with_connection { |conn| raise 'Error' }
103
+ rescue
104
+ assert_equal 5, @pool.count
105
+ end
106
+
107
+ def test_connection_yields_with_an_unauthenticated_connection
108
+ XMPPConnection.any_instance.expects(:login).never
109
+
110
+ Backchat::ConnectionPool.connection { |conn| }
111
+ end
112
+
113
+ def test_connection_accepts_credentials
114
+ XMPPConnection.any_instance.expects(:login)
115
+
116
+ Backchat::ConnectionPool.connection(username: 'don_draper',
117
+ password: 'secret') { |conn| }
118
+ end
119
+
120
+ def test_backchat_connection_pool_creates_a_pool
121
+ refute Backchat.instance_variable_get(:@connection_pool)
122
+ assert_instance_of Backchat::ConnectionPool, Backchat.connection_pool
123
+ end
124
+ end
@@ -0,0 +1,10 @@
1
+ require 'bundler'
2
+ Bundler.require
3
+
4
+ require 'minitest/autorun'
5
+ require 'mocha/setup'
6
+ require 'pry'
7
+
8
+ $:.unshift(File.expand_path('../lib', File.dirname(__FILE__)))
9
+
10
+ require 'backchat'
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: backchat
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Zach Pendleton
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ version_requirements: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.3'
21
+ none: false
22
+ requirement: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ none: false
28
+ prerelease: false
29
+ type: :development
30
+ - !ruby/object:Gem::Dependency
31
+ name: minitest
32
+ version_requirements: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - "~>"
35
+ - !ruby/object:Gem::Version
36
+ version: 4.6.2
37
+ none: false
38
+ requirement: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - "~>"
41
+ - !ruby/object:Gem::Version
42
+ version: 4.6.2
43
+ none: false
44
+ prerelease: false
45
+ type: :development
46
+ - !ruby/object:Gem::Dependency
47
+ name: mocha
48
+ version_requirements: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - "~>"
51
+ - !ruby/object:Gem::Version
52
+ version: 0.13.3
53
+ none: false
54
+ requirement: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - "~>"
57
+ - !ruby/object:Gem::Version
58
+ version: 0.13.3
59
+ none: false
60
+ prerelease: false
61
+ type: :development
62
+ - !ruby/object:Gem::Dependency
63
+ name: pry
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: !binary |-
69
+ MA==
70
+ none: false
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: !binary |-
76
+ MA==
77
+ none: false
78
+ prerelease: false
79
+ type: :development
80
+ - !ruby/object:Gem::Dependency
81
+ name: rake
82
+ version_requirements: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: 0.9.6
87
+ none: false
88
+ requirement: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 0.9.6
93
+ none: false
94
+ prerelease: false
95
+ type: :development
96
+ description: Smack XMPP libraries for JRuby. With connection pooling!!
97
+ email:
98
+ - zachpendleton@gmail.com
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - ".gitignore"
104
+ - Gemfile
105
+ - LICENSE.txt
106
+ - README.md
107
+ - Rakefile
108
+ - backchat.gemspec
109
+ - lib/backchat.rb
110
+ - lib/backchat/connection_pool.rb
111
+ - lib/backchat/version.rb
112
+ - lib/java/smack.jar
113
+ - lib/java/smackx.jar
114
+ - test/lib/backchat/test_connection_pool.rb
115
+ - test/test_helper.rb
116
+ homepage: https://github.com/zachpendleton/backchat
117
+ licenses:
118
+ - MIT
119
+ post_install_message:
120
+ rdoc_options: []
121
+ require_paths:
122
+ - lib
123
+ required_ruby_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: !binary |-
128
+ MA==
129
+ none: false
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: !binary |-
135
+ MA==
136
+ none: false
137
+ requirements: []
138
+ rubyforge_project:
139
+ rubygems_version: 1.8.24
140
+ signing_key:
141
+ specification_version: 3
142
+ summary: Include Smack XMPP libraries in JRuby and use them with connection pooling.
143
+ test_files:
144
+ - test/lib/backchat/test_connection_pool.rb
145
+ - test/test_helper.rb