aeden-jruby-http-reactor 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/README.rdoc ADDED
@@ -0,0 +1 @@
1
+ A client that uses the Apache HttpCore NIO library to do stuff.
data/Rakefile ADDED
@@ -0,0 +1,35 @@
1
+ require 'rake'
2
+ require 'rake/rdoctask'
3
+
4
+ desc 'Default: run tests.'
5
+ task :default => [:test]
6
+
7
+ desc 'Run tests.'
8
+ task :test do
9
+ require File.dirname(__FILE__) + '/test/client_test'
10
+ end
11
+
12
+ desc 'Generate documentation.'
13
+ Rake::RDocTask.new(:rdoc) do |rdoc|
14
+ rdoc.rdoc_dir = 'rdoc'
15
+ rdoc.title = 'JRuby HTTP Reactor'
16
+ rdoc.options << '--line-numbers' << '--inline-source'
17
+ rdoc.rdoc_files.include('README.rdoc')
18
+ rdoc.rdoc_files.include('lib/*.rb')
19
+ rdoc.rdoc_files.include('lib/**/*.rb')
20
+ end
21
+
22
+ begin
23
+ require 'jeweler'
24
+ Jeweler::Tasks.new do |gemspec|
25
+ gemspec.name = "jruby-http-reactor"
26
+ gemspec.summary = "JRuby NIO HTTP client."
27
+ gemspec.email = "anthonyeden@gmail.com"
28
+ gemspec.homepage = "http://github.com/aeden/jruby-http-reactor"
29
+ gemspec.description = ""
30
+ gemspec.authors = ["Anthony Eden"]
31
+ gemspec.files.exclude 'docs/**/*'
32
+ end
33
+ rescue LoadError
34
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
35
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,208 @@
1
+ module HttpReactor #:nodoc:
2
+ class RequestExecutionHandler #:nodoc:
3
+ import org.apache.http.protocol
4
+ import org.apache.http.nio.protocol
5
+ include HttpRequestExecutionHandler
6
+
7
+ REQUEST_SENT = "request-sent"
8
+ RESPONSE_RECEIVED = "response-received"
9
+
10
+ HTTP_TARGET_PATH = 'http_target_path'
11
+
12
+ def initialize(request_count, handler_proc)
13
+ @request_count = request_count
14
+ @handler_proc = handler_proc
15
+ end
16
+
17
+ def initalize_context(context, attachment)
18
+ context.set_attribute(ExecutionContext.HTTP_TARGET_HOST, attachment[:host]);
19
+ context.set_attribute(HTTP_TARGET_PATH, attachment[:path])
20
+ end
21
+
22
+ def finalize_context(context)
23
+ flag = context.get_attribute(RESPONSE_RECEIVED)
24
+ @request_count.count_down() unless flag
25
+ end
26
+
27
+ def submit_request(context)
28
+ target_host = context.get_attribute(ExecutionContext.HTTP_TARGET_HOST);
29
+ target_path = context.get_attribute(HTTP_TARGET_PATH)
30
+ flag = context.get_attribute(REQUEST_SENT);
31
+ if flag.nil?
32
+ # Stick some object into the context
33
+ context.set_attribute(REQUEST_SENT, true);
34
+
35
+ puts "--------------"
36
+ puts "Sending request to #{target_host}#{target_path}"
37
+ puts "--------------"
38
+
39
+ org.apache.http.message.BasicHttpRequest.new("GET", target_path)
40
+ else
41
+ # No new request to submit
42
+ end
43
+ end
44
+
45
+ def handle_response(response, context)
46
+ @handler_proc.call(response, context)
47
+
48
+ context.setAttribute(RESPONSE_RECEIVED, true)
49
+
50
+ # Signal completion of the request execution
51
+ @request_count.count_down()
52
+ end
53
+ end
54
+
55
+ class SessionRequestCallback #:nodoc:
56
+ include org.apache.http.nio.reactor.SessionRequestCallback
57
+
58
+ def initialize(request_count)
59
+ @request_count = request_count
60
+ end
61
+
62
+ def cancelled(request)
63
+ puts "Connect request cancelled: #{request.remote_address}"
64
+ @request_count.count_down()
65
+ end
66
+
67
+ def completed(request); end
68
+
69
+ def failed(request)
70
+ puts "Connect request failed: #{request.remote_address}"
71
+ @request_count.count_down()
72
+ end
73
+
74
+ def timeout(request)
75
+ puts "Connect request timed out: #{request.remote_address}"
76
+ @request_count.count_down()
77
+ end
78
+ end
79
+
80
+ class EventLogger #:nodoc:
81
+ import org.apache.http.nio.protocol
82
+ include EventListener
83
+ def connection_open(conn)
84
+ puts "Connection open: #{conn}"
85
+ end
86
+ def connection_timeout(conn)
87
+ puts "Connection timed out: #{conn}"
88
+ end
89
+ def connection_closed(conn)
90
+ puts "Connection closed: #{conn}"
91
+ end
92
+ def fatalIOException(ex, onn)
93
+ puts "Fatal I/O error: #{ex.message}"
94
+ end
95
+ def fatal_protocol_exception(ex, conn)
96
+ puts "HTTP error: #{ex.message}"
97
+ end
98
+ end
99
+
100
+ # An HTTP client that uses the Reactor pattern.
101
+ class Client
102
+ import org.apache.http
103
+ import org.apache.http.params
104
+ import org.apache.http.protocol
105
+ import org.apache.http.nio.protocol
106
+ import org.apache.http.impl.nio
107
+ import org.apache.http.impl.nio.reactor
108
+
109
+ # Create a new HttpReactor client that will request the given URIs.
110
+ #
111
+ # Parameters:
112
+ # * <tt>uris</tt>: An array of URI objects.
113
+ # * <tt>handler_proc</tt>: A Proc that will be called with the response and context
114
+ # * <tt>session_request_callback</tt>: A class that implements the session request
115
+ # callback interface found in the HttpCore library.
116
+ def initialize(uris=[], handler_proc=nil, session_request_callback=SessionRequestCallback)
117
+ handler_proc ||= default_handler_proc
118
+
119
+ params = BasicHttpParams.new
120
+ params.set_int_parameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
121
+ params.set_int_parameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000)
122
+ params.set_int_parameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
123
+ params.set_boolean_parameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
124
+ params.set_boolean_parameter(CoreConnectionPNames.TCP_NODELAY, true)
125
+ params.set_parameter(CoreProtocolPNames.USER_AGENT, "JRubyHttpReactor/0.0.1")
126
+
127
+ io_reactor = DefaultConnectingIOReactor.new(2, params);
128
+
129
+ httpproc = BasicHttpProcessor.new;
130
+ httpproc.add_interceptor(RequestContent.new);
131
+ httpproc.add_interceptor(RequestTargetHost.new);
132
+ httpproc.add_interceptor(RequestConnControl.new);
133
+ httpproc.add_interceptor(RequestUserAgent.new);
134
+ httpproc.add_interceptor(RequestExpectContinue.new);
135
+
136
+ # We are going to use this object to synchronize between the
137
+ # I/O event and main threads
138
+ request_count = java.util.concurrent.CountDownLatch.new(uris.length);
139
+
140
+ handler = BufferingHttpClientHandler.new(
141
+ httpproc,
142
+ RequestExecutionHandler.new(request_count, handler_proc),
143
+ org.apache.http.impl.DefaultConnectionReuseStrategy.new,
144
+ params
145
+ )
146
+
147
+ handler.event_listener = EventLogger.new
148
+
149
+ io_event_dispatch = DefaultClientIOEventDispatch.new(handler, params)
150
+
151
+ Thread.abort_on_exception = true
152
+ t = Thread.new do
153
+ begin
154
+ puts "Executing IO reactor"
155
+ io_reactor.execute(io_event_dispatch)
156
+ rescue java.io.InterruptedIOException => e
157
+ puts "Interrupted"
158
+ rescue java.io.IOException => e
159
+ puts "I/O error in reactor execution thread: #{e.message}"
160
+ end
161
+ puts "Shutdown"
162
+ end
163
+
164
+ uris.each do |uri|
165
+ io_reactor.connect(
166
+ java.net.InetSocketAddress.new(uri.host, uri.port),
167
+ nil,
168
+ {:host => HttpHost.new(uri.host), :path => uri.path},
169
+ session_request_callback.new(request_count)
170
+ )
171
+ end
172
+
173
+ # Block until all connections signal
174
+ # completion of the request execution
175
+ request_count.await()
176
+
177
+ puts "Shutting down I/O reactor"
178
+
179
+ io_reactor.shutdown()
180
+
181
+ puts "Done"
182
+ end
183
+
184
+ private
185
+ def default_handler_proc
186
+ Proc.new { |response, context|
187
+ target_host = context.get_attribute(ExecutionContext.HTTP_TARGET_HOST);
188
+ target_path = context.get_attribute(RequestExecutionHandler::HTTP_TARGET_PATH)
189
+
190
+ entity = response.entity
191
+ begin
192
+ content = org.apache.http.util.EntityUtils.toString(entity)
193
+
194
+ puts "--------------"
195
+ puts "Response from #{target_host}#{target_path}"
196
+ puts "--------------"
197
+ puts response.status_line
198
+ puts "--------------"
199
+ puts "Document length: #{content.length}"
200
+ puts "--------------"
201
+ rescue java.io.IOException => ex
202
+ puts "I/O error in handle_response: #{ex.message}"
203
+ end
204
+ }
205
+ end
206
+
207
+ end
208
+ end
@@ -0,0 +1,12 @@
1
+ require 'java'
2
+ require File.dirname(__FILE__) + '/../vendor/httpcore-4.0.1.jar'
3
+ require File.dirname(__FILE__) + '/../vendor/httpcore-nio-4.0.1.jar'
4
+
5
+ # The Ruby module that contains wrappers for the the Apache
6
+ # HTTP NIO implementation.
7
+ module HttpReactor
8
+ end
9
+
10
+ $:.unshift(File.dirname(__FILE__))
11
+
12
+ require 'http_reactor/client'
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class ClientTest < Test::Unit::TestCase
4
+ def uris
5
+ @uris ||= [
6
+ 'http://www.yahoo.com/',
7
+ 'http://www.google.com/',
8
+ 'http://www.apache.org/',
9
+ 'http://anthony.mp/about_me'
10
+ ].map { |url_string| URI.parse(url_string) }
11
+ end
12
+
13
+ def test_new
14
+ assert_nothing_raised do
15
+ HttpReactor::Client.new(uris)
16
+ end
17
+ end
18
+
19
+ def test_proc
20
+ handler = Proc.new { |response, context|
21
+ puts "Response: #{response.status_line.status_code}"
22
+ }
23
+ HttpReactor::Client.new(uris, handler)
24
+ end
25
+ end
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/http_reactor'
Binary file
Binary file
metadata ADDED
@@ -0,0 +1,63 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aeden-jruby-http-reactor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Anthony Eden
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-13 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: ""
17
+ email: anthonyeden@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.rdoc
24
+ files:
25
+ - README.rdoc
26
+ - Rakefile
27
+ - VERSION
28
+ - lib/http_reactor.rb
29
+ - lib/http_reactor/client.rb
30
+ - test/client_test.rb
31
+ - test/test_helper.rb
32
+ - vendor/httpcore-4.0.1.jar
33
+ - vendor/httpcore-nio-4.0.1.jar
34
+ has_rdoc: true
35
+ homepage: http://github.com/aeden/jruby-http-reactor
36
+ licenses:
37
+ post_install_message:
38
+ rdoc_options:
39
+ - --charset=UTF-8
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ requirements: []
55
+
56
+ rubyforge_project:
57
+ rubygems_version: 1.3.5
58
+ signing_key:
59
+ specification_version: 2
60
+ summary: JRuby NIO HTTP client.
61
+ test_files:
62
+ - test/client_test.rb
63
+ - test/test_helper.rb