aeden-jruby-http-reactor 0.0.1

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