backchat 0.0.1

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.
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