jubilee 1.1.0-java
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.
- checksums.yaml +7 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/CHANGELOG +32 -0
- data/Gemfile +35 -0
- data/Gemfile.lock +244 -0
- data/Guardfile +24 -0
- data/KNOWN_ISSUES +6 -0
- data/LICENSE.txt +20 -0
- data/README.md +147 -0
- data/ROADMAP +5 -0
- data/Rakefile +98 -0
- data/bin/jubilee +6 -0
- data/bin/jubilee_d +13 -0
- data/examples/chatapp/Gemfile +5 -0
- data/examples/chatapp/Gemfile.lock +27 -0
- data/examples/chatapp/README.md +17 -0
- data/examples/chatapp/app.rb +57 -0
- data/examples/chatapp/config.ru +3 -0
- data/examples/chatapp/public/assets/javascripts/application.js +67 -0
- data/examples/chatapp/public/assets/javascripts/jquery.js +5 -0
- data/examples/chatapp/public/assets/javascripts/sockjs-0.3.4.min.js +27 -0
- data/examples/chatapp/public/assets/javascripts/vertxbus.js +216 -0
- data/examples/chatapp/public/assets/stylesheets/application.css +29 -0
- data/examples/client/sockjs-0.3.4.min.js +27 -0
- data/examples/client/vertxbus.js +216 -0
- data/examples/jubilee.conf.rb +12 -0
- data/examples/jubilee/keystore.jks +0 -0
- data/examples/jubilee/server-keystore.jks +0 -0
- data/jars/hazelcast-2.6.3.jar +0 -0
- data/jars/jackson-annotations-2.2.2.jar +0 -0
- data/jars/jackson-core-2.2.2.jar +0 -0
- data/jars/jackson-databind-2.2.2.jar +0 -0
- data/jars/netty-all-4.0.13.Final.jar +0 -0
- data/jars/vertx-core-2.1M3-SNAPSHOT.jar +0 -0
- data/jars/vertx-hazelcast-2.1M3-SNAPSHOT.jar +0 -0
- data/java/src/jubilee/JubileeService.java +20 -0
- data/java/src/org/jruby/jubilee/Const.java +32 -0
- data/java/src/org/jruby/jubilee/RackApplication.java +103 -0
- data/java/src/org/jruby/jubilee/RackEnvironment.java +150 -0
- data/java/src/org/jruby/jubilee/RackEnvironmentHash.java +449 -0
- data/java/src/org/jruby/jubilee/RackInput.java +62 -0
- data/java/src/org/jruby/jubilee/RackResponse.java +11 -0
- data/java/src/org/jruby/jubilee/RubyHttpServerResponse.java +88 -0
- data/java/src/org/jruby/jubilee/RubyServer.java +171 -0
- data/java/src/org/jruby/jubilee/deploy/Starter.java +26 -0
- data/java/src/org/jruby/jubilee/impl/RubyIORackInput.java +201 -0
- data/java/src/org/jruby/jubilee/impl/RubyNullIO.java +107 -0
- data/java/src/org/jruby/jubilee/utils/RubyHelper.java +37 -0
- data/java/src/org/jruby/jubilee/vertx/JubileeVertx.java +38 -0
- data/jubilee.gemspec +201 -0
- data/lib/jubilee.rb +17 -0
- data/lib/jubilee/application.rb +13 -0
- data/lib/jubilee/cli.rb +127 -0
- data/lib/jubilee/configuration.rb +177 -0
- data/lib/jubilee/const.rb +40 -0
- data/lib/jubilee/jubilee.jar +0 -0
- data/lib/jubilee/response.rb +69 -0
- data/lib/jubilee/server.rb +12 -0
- data/lib/jubilee/version.rb +10 -0
- data/lib/rack/chunked.rb +38 -0
- data/lib/rack/handler/jubilee.rb +44 -0
- data/lib/vertx.rb +26 -0
- data/lib/vertx/README.md +7 -0
- data/lib/vertx/buffer.rb +251 -0
- data/lib/vertx/event_bus.rb +206 -0
- data/lib/vertx/shared_data.rb +214 -0
- data/spec/apps/rack/basic/config.ru +50 -0
- data/spec/apps/rails4/basic/.gitignore +16 -0
- data/spec/apps/rails4/basic/Gemfile +41 -0
- data/spec/apps/rails4/basic/Gemfile.lock +127 -0
- data/spec/apps/rails4/basic/README.rdoc +28 -0
- data/spec/apps/rails4/basic/Rakefile +6 -0
- data/spec/apps/rails4/basic/app/assets/images/.keep +0 -0
- data/spec/apps/rails4/basic/app/assets/images/rails.png +0 -0
- data/spec/apps/rails4/basic/app/assets/javascripts/application.js +12 -0
- data/spec/apps/rails4/basic/app/assets/stylesheets/application.css +13 -0
- data/spec/apps/rails4/basic/app/controllers/application_controller.rb +5 -0
- data/spec/apps/rails4/basic/app/controllers/concerns/.keep +0 -0
- data/spec/apps/rails4/basic/app/controllers/reloader_controller.rb +11 -0
- data/spec/apps/rails4/basic/app/controllers/reloader_controller.rb.erb +11 -0
- data/spec/apps/rails4/basic/app/controllers/root_controller.rb +14 -0
- data/spec/apps/rails4/basic/app/helpers/application_helper.rb +2 -0
- data/spec/apps/rails4/basic/app/mailers/.keep +0 -0
- data/spec/apps/rails4/basic/app/models/.keep +0 -0
- data/spec/apps/rails4/basic/app/models/concerns/.keep +0 -0
- data/spec/apps/rails4/basic/app/views/layouts/application.html.erb +14 -0
- data/spec/apps/rails4/basic/app/views/reloader/index.html.erb +1 -0
- data/spec/apps/rails4/basic/app/views/root/index.html.erb +8 -0
- data/spec/apps/rails4/basic/app/views/root/streaming.html.erb +6 -0
- data/spec/apps/rails4/basic/bin/bundle +3 -0
- data/spec/apps/rails4/basic/bin/rails +4 -0
- data/spec/apps/rails4/basic/bin/rake +4 -0
- data/spec/apps/rails4/basic/config.ru +4 -0
- data/spec/apps/rails4/basic/config/application.rb +23 -0
- data/spec/apps/rails4/basic/config/boot.rb +4 -0
- data/spec/apps/rails4/basic/config/database.yml +20 -0
- data/spec/apps/rails4/basic/config/environment.rb +5 -0
- data/spec/apps/rails4/basic/config/environments/development.rb +29 -0
- data/spec/apps/rails4/basic/config/environments/production.rb +80 -0
- data/spec/apps/rails4/basic/config/environments/test.rb +36 -0
- data/spec/apps/rails4/basic/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/apps/rails4/basic/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/apps/rails4/basic/config/initializers/inflections.rb +16 -0
- data/spec/apps/rails4/basic/config/initializers/mime_types.rb +5 -0
- data/spec/apps/rails4/basic/config/initializers/secret_token.rb +12 -0
- data/spec/apps/rails4/basic/config/initializers/session_store.rb +2 -0
- data/spec/apps/rails4/basic/config/initializers/wrap_parameters.rb +14 -0
- data/spec/apps/rails4/basic/config/locales/en.yml +23 -0
- data/spec/apps/rails4/basic/config/routes.rb +5 -0
- data/spec/apps/rails4/basic/db/seeds.rb +7 -0
- data/spec/apps/rails4/basic/lib/assets/.keep +0 -0
- data/spec/apps/rails4/basic/lib/tasks/.keep +0 -0
- data/spec/apps/rails4/basic/public/404.html +58 -0
- data/spec/apps/rails4/basic/public/422.html +58 -0
- data/spec/apps/rails4/basic/public/500.html +57 -0
- data/spec/apps/rails4/basic/public/favicon.ico +0 -0
- data/spec/apps/rails4/basic/public/robots.txt +5 -0
- data/spec/apps/rails4/basic/public/some_page.html +7 -0
- data/spec/apps/rails4/basic/test/controllers/.keep +0 -0
- data/spec/apps/rails4/basic/test/fixtures/.keep +0 -0
- data/spec/apps/rails4/basic/test/helpers/.keep +0 -0
- data/spec/apps/rails4/basic/test/integration/.keep +0 -0
- data/spec/apps/rails4/basic/test/mailers/.keep +0 -0
- data/spec/apps/rails4/basic/test/models/.keep +0 -0
- data/spec/apps/rails4/basic/test/test_helper.rb +15 -0
- data/spec/apps/rails4/basic/vendor/assets/javascripts/.keep +0 -0
- data/spec/apps/rails4/basic/vendor/assets/stylesheets/.keep +0 -0
- data/spec/apps/sinatra/basic/Gemfile +4 -0
- data/spec/apps/sinatra/basic/Gemfile.lock +20 -0
- data/spec/apps/sinatra/basic/basic.rb +27 -0
- data/spec/apps/sinatra/basic/config.ru +7 -0
- data/spec/apps/sinatra/basic/public/some_page.html +7 -0
- data/spec/apps/sinatra/basic/views/index.erb +4 -0
- data/spec/apps/sinatra/basic/views/posted.haml +2 -0
- data/spec/apps/sinatra/basic/views/poster.haml +4 -0
- data/spec/apps/sinatra/basic/views/request_mapping.haml +4 -0
- data/spec/integration/basic_rack_spec.rb +89 -0
- data/spec/integration/basic_rails4_spec.rb +64 -0
- data/spec/integration/basic_sinatra_spec.rb +80 -0
- data/spec/spec_helper.rb +13 -0
- data/test/.ruby-version +1 -0
- data/test/config/app.rb +5 -0
- data/test/jubilee/test_cli.rb +11 -0
- data/test/jubilee/test_configuration.rb +31 -0
- data/test/jubilee/test_rack_server.rb +137 -0
- data/test/jubilee/test_response.rb +272 -0
- data/test/jubilee/test_server.rb +72 -0
- data/test/jubilee/test_upload.rb +301 -0
- data/test/sinatra_app/app.rb +31 -0
- data/test/sinatra_app/config.ru +6 -0
- data/test/sinatra_app/public/test.html +10 -0
- data/test/sinatra_app/unicorn.conf.rb +29 -0
- data/test/test_helper.rb +93 -0
- metadata +242 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# Copyright 2011 the original author or authors.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
require 'rubygems'
|
|
16
|
+
require 'json'
|
|
17
|
+
|
|
18
|
+
module Vertx
|
|
19
|
+
|
|
20
|
+
# This class represents a distributed lightweight event bus which can encompass multiple vert.x instances.
|
|
21
|
+
# It is very useful for otherwise isolated vert.x application instances to communicate with each other.
|
|
22
|
+
#
|
|
23
|
+
# The event bus implements both publish / subscribe network and point to point messaging.
|
|
24
|
+
#
|
|
25
|
+
# For publish / subscribe, messages can be published to an address using one of the publish methods. An
|
|
26
|
+
# address is a simple String instance. Handlers are registered against an address. There can be multiple handlers
|
|
27
|
+
# registered against each address, and a particular handler can be registered against multiple addresses.
|
|
28
|
+
# The event bus will route a sent message to all handlers which are registered against that address.
|
|
29
|
+
|
|
30
|
+
# For point to point messaging, messages can be sent to an address using the send method.
|
|
31
|
+
# The messages will be delivered to a single handler, if one is registered on that address. If more than one
|
|
32
|
+
# handler is registered on the same address, Vert.x will choose one and deliver the message to that. Vert.x will
|
|
33
|
+
# aim to fairly distribute messages in a round-robin way, but does not guarantee strict round-robin under all
|
|
34
|
+
# circumstances.
|
|
35
|
+
#
|
|
36
|
+
# All messages sent over the bus are transient. On event of failure of all or part of the event bus messages
|
|
37
|
+
# may be lost. Applications should be coded to cope with lost messages, e.g. by resending them,
|
|
38
|
+
# and making application services idempotent.
|
|
39
|
+
#
|
|
40
|
+
# The order of messages received by any specific handler from a specific sender should match the order of messages
|
|
41
|
+
# sent from that sender.
|
|
42
|
+
#
|
|
43
|
+
# When sending a message, a reply handler can be provided. If so, it will be called when the reply from the receiver
|
|
44
|
+
# has been received. Reply messages can also be replied to, etc, ad infinitum.
|
|
45
|
+
#
|
|
46
|
+
# Different event bus instances can be clustered together over a network, to give a single logical event bus.
|
|
47
|
+
#
|
|
48
|
+
# When receiving a message in a handler the received object is an instance of EventBus::Message - this contains
|
|
49
|
+
# the actual message plus a reply method which can be used to reply to it.
|
|
50
|
+
#
|
|
51
|
+
# @author {http://tfox.org Tim Fox}
|
|
52
|
+
class EventBus
|
|
53
|
+
|
|
54
|
+
@@handler_map = {}
|
|
55
|
+
|
|
56
|
+
@@j_eventbus = org.jruby.jubilee.vertx.JubileeVertx.vertx().eventBus()
|
|
57
|
+
|
|
58
|
+
# Send a message on the event bus
|
|
59
|
+
# @param message [Hash] The message to send
|
|
60
|
+
# @param reply_handler [Block] An optional reply handler.
|
|
61
|
+
# It will be called when the reply from a receiver is received.
|
|
62
|
+
def EventBus.send(address, message, &reply_handler)
|
|
63
|
+
EventBus.send_or_pub(true, address, message, reply_handler)
|
|
64
|
+
self
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Publish a message on the event bus
|
|
68
|
+
# @param message [Hash] The message to publish
|
|
69
|
+
def EventBus.publish(address, message)
|
|
70
|
+
EventBus.send_or_pub(false, address, message)
|
|
71
|
+
self
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# @private
|
|
75
|
+
def EventBus.send_or_pub(send, address, message, reply_handler = nil)
|
|
76
|
+
raise "An address must be specified" if !address
|
|
77
|
+
raise "A message must be specified" if message == nil
|
|
78
|
+
message = convert_msg(message)
|
|
79
|
+
if send
|
|
80
|
+
if reply_handler != nil
|
|
81
|
+
@@j_eventbus.send(address, message, InternalHandler.new(reply_handler))
|
|
82
|
+
else
|
|
83
|
+
@@j_eventbus.send(address, message)
|
|
84
|
+
end
|
|
85
|
+
else
|
|
86
|
+
@@j_eventbus.publish(address, message)
|
|
87
|
+
end
|
|
88
|
+
self
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Register a handler.
|
|
92
|
+
# @param address [String] The address to register for. Messages sent to that address will be
|
|
93
|
+
# received by the handler. A single handler can be registered against many addresses.
|
|
94
|
+
# @param local_only [Boolean] If true then handler won't be propagated across cluster
|
|
95
|
+
# @param message_hndlr [Block] The handler
|
|
96
|
+
# @return [FixNum] id of the handler which can be used in {EventBus.unregister_handler}
|
|
97
|
+
def EventBus.register_handler(address, local_only = false, &message_hndlr)
|
|
98
|
+
raise "An address must be specified" if !address
|
|
99
|
+
raise "A message handler must be specified" if !message_hndlr
|
|
100
|
+
internal = InternalHandler.new(message_hndlr)
|
|
101
|
+
if local_only
|
|
102
|
+
@@j_eventbus.registerLocalHandler(address, internal)
|
|
103
|
+
else
|
|
104
|
+
@@j_eventbus.registerHandler(address, internal)
|
|
105
|
+
end
|
|
106
|
+
id = java.util.UUID.randomUUID.toString
|
|
107
|
+
@@handler_map[id] = [address, internal]
|
|
108
|
+
id
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Registers a handler against a uniquely generated address, the address is returned as the id
|
|
112
|
+
# received by the handler. A single handler can be registered against many addresses.
|
|
113
|
+
# @param local_only [Boolean] If true then handler won't be propagated across cluster
|
|
114
|
+
# @param message_hndlr [Block] The handler
|
|
115
|
+
# @return [FixNum] id of the handler which can be used in {EventBus.unregister_handler}
|
|
116
|
+
def EventBus.register_simple_handler(local_only = false, &message_hndlr)
|
|
117
|
+
raise "A message handler must be specified" if !message_hndlr
|
|
118
|
+
internal = InternalHandler.new(message_hndlr)
|
|
119
|
+
id = java.util.UUID.randomUUID.toString
|
|
120
|
+
if local_only
|
|
121
|
+
@@j_eventbus.registerLocalHandler(id, internal)
|
|
122
|
+
else
|
|
123
|
+
@@j_eventbus.registerHandler(id, internal)
|
|
124
|
+
end
|
|
125
|
+
@@handler_map[id] = [id, internal]
|
|
126
|
+
id
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Unregisters a handler
|
|
130
|
+
# @param handler_id [FixNum] The id of the handler to unregister. Returned from {EventBus.register_handler}
|
|
131
|
+
def EventBus.unregister_handler(handler_id)
|
|
132
|
+
raise "A handler_id must be specified" if !handler_id
|
|
133
|
+
tuple = @@handler_map.delete(handler_id)
|
|
134
|
+
raise "Cannot find handler for id #{handler_id}" if !tuple
|
|
135
|
+
@@j_eventbus.unregisterHandler(tuple.first, tuple.last)
|
|
136
|
+
self
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# @private
|
|
140
|
+
def EventBus.convert_msg(message)
|
|
141
|
+
if message.is_a? Hash
|
|
142
|
+
message = org.vertx.java.core.json.JsonObject.new(JSON.generate(message))
|
|
143
|
+
elsif message.is_a? Buffer
|
|
144
|
+
message = message._to_java_buffer
|
|
145
|
+
elsif message.is_a? Fixnum
|
|
146
|
+
message = java.lang.Long.new(message)
|
|
147
|
+
elsif message.is_a? Float
|
|
148
|
+
message = java.lang.Double.new(message)
|
|
149
|
+
end
|
|
150
|
+
message
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# @private
|
|
156
|
+
class InternalHandler
|
|
157
|
+
include org.vertx.java.core.Handler
|
|
158
|
+
|
|
159
|
+
def initialize(hndlr)
|
|
160
|
+
@hndlr = hndlr
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def handle(message)
|
|
164
|
+
@hndlr.call(Message.new(message))
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Represents a message received from the event bus
|
|
169
|
+
# @author {http://tfox.org Tim Fox}
|
|
170
|
+
class Message
|
|
171
|
+
|
|
172
|
+
attr_reader :body
|
|
173
|
+
|
|
174
|
+
# @private
|
|
175
|
+
def initialize(message)
|
|
176
|
+
|
|
177
|
+
@j_del = message
|
|
178
|
+
if message.body.is_a? org.vertx.java.core.json.JsonObject
|
|
179
|
+
@body = JSON.parse(message.body.encode)
|
|
180
|
+
elsif message.body.is_a? org.vertx.java.core.buffer.Buffer
|
|
181
|
+
@body = Buffer.new(message.body)
|
|
182
|
+
else
|
|
183
|
+
@body = message.body
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Reply to this message. If the message was sent specifying a receipt handler, that handler will be
|
|
188
|
+
# called when it has received a reply. If the message wasn't sent specifying a receipt handler
|
|
189
|
+
# this method does nothing.
|
|
190
|
+
# Replying to a message this way is equivalent to sending a message to an address which is the same as the message id
|
|
191
|
+
# of the original message.
|
|
192
|
+
# @param [Hash] Message send as reply
|
|
193
|
+
def reply(reply, &reply_handler)
|
|
194
|
+
raise "A reply message must be specified" if reply == nil
|
|
195
|
+
reply = EventBus.convert_msg(reply)
|
|
196
|
+
if reply_handler != nil
|
|
197
|
+
@j_del.reply(reply, InternalHandler.new(reply_handler))
|
|
198
|
+
else
|
|
199
|
+
@j_del.reply(reply)
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
end
|
|
206
|
+
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# Copyright 2011 the original author or authors.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
require 'delegate'
|
|
16
|
+
|
|
17
|
+
module Vertx
|
|
18
|
+
|
|
19
|
+
# Sometimes it is desirable to share immutable data between different event loops, for example to implement a
|
|
20
|
+
# cache of data.
|
|
21
|
+
#
|
|
22
|
+
# This class allows data structures to be looked up and used from different event loops.
|
|
23
|
+
# The data structures themselves will only allow certain data types to be stored into them. This shields the
|
|
24
|
+
# user from worrying about any thread safety issues might occur if mutable objects were shared between event loops.
|
|
25
|
+
#
|
|
26
|
+
# The following types can be stored in a shareddata data structure:
|
|
27
|
+
#
|
|
28
|
+
# String
|
|
29
|
+
# FixNum
|
|
30
|
+
# Float
|
|
31
|
+
# {Buffer} this will be automatically copied, and the copy will be stored in the structure.
|
|
32
|
+
#
|
|
33
|
+
# @author {http://tfox.org Tim Fox}
|
|
34
|
+
class SharedData
|
|
35
|
+
|
|
36
|
+
@@j_sd = org.jruby.jubilee.vertx.JubileeVertx.vertx().sharedData()
|
|
37
|
+
|
|
38
|
+
# Return a Hash with the specific name. All invocations of this method with the same value of name
|
|
39
|
+
# are guaranteed to return the same Hash instance.
|
|
40
|
+
# @param [String] key. Get the hash with the key.
|
|
41
|
+
# @return [Hash] the hash.
|
|
42
|
+
def SharedData.get_hash(key)
|
|
43
|
+
map = @@j_sd.getMap(key)
|
|
44
|
+
SharedHash.new(map)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Return a Set with the specific name. All invocations of this method with the same value of name
|
|
48
|
+
# are guaranteed to return the same Set instance.
|
|
49
|
+
# @param [String] key. Get the set with the key.
|
|
50
|
+
# @return [SharedSet] the set.
|
|
51
|
+
def SharedData.get_set(key)
|
|
52
|
+
set = @@j_sd.getSet(key)
|
|
53
|
+
SharedSet.new(set)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Remove the hash
|
|
57
|
+
# @param [String] key. The key of the hash.
|
|
58
|
+
def SharedData.remove_hash(key)
|
|
59
|
+
@@j_sd.removeMap(key)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Remove the set
|
|
63
|
+
# @param [String] key. The key of the set.
|
|
64
|
+
def SharedData.remove_set(key)
|
|
65
|
+
@@j_sd.removeSet(key)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Convert to corresponding Java objects
|
|
69
|
+
# And make copies where appropriate (the underlying java map will also make copies for some data types too)
|
|
70
|
+
# @private
|
|
71
|
+
def SharedData.check_obj(obj)
|
|
72
|
+
if obj.is_a?(Buffer)
|
|
73
|
+
obj = obj._to_java_buffer
|
|
74
|
+
end
|
|
75
|
+
obj
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# @private
|
|
79
|
+
class SharedHash < DelegateClass(Hash)
|
|
80
|
+
|
|
81
|
+
def initialize(hash)
|
|
82
|
+
@hash = hash
|
|
83
|
+
# Pass the object to be delegated to the superclass.
|
|
84
|
+
super(@hash)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def []=(key, val)
|
|
88
|
+
key = SharedData.check_obj(key)
|
|
89
|
+
val = SharedData.check_obj(val)
|
|
90
|
+
super(key, val)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
alias store []=
|
|
94
|
+
|
|
95
|
+
def [](key)
|
|
96
|
+
# We call the java class directly
|
|
97
|
+
obj = @hash.get(key)
|
|
98
|
+
obj = Buffer.new(obj) if obj.is_a? org.vertx.java.core.buffer.Buffer
|
|
99
|
+
obj
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def ==(other)
|
|
103
|
+
if other.is_a?(SharedHash)
|
|
104
|
+
@hash.equal?(other._to_java_map)
|
|
105
|
+
else
|
|
106
|
+
false
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def _to_java_map
|
|
111
|
+
@hash
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
#
|
|
117
|
+
# @private
|
|
118
|
+
class SharedSet
|
|
119
|
+
|
|
120
|
+
# @private
|
|
121
|
+
def initialize(j_set)
|
|
122
|
+
@j_set = j_set
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def ==(other)
|
|
126
|
+
if other.is_a?(SharedSet)
|
|
127
|
+
@j_set.equal?(other._to_java_set)
|
|
128
|
+
else
|
|
129
|
+
false
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
# Add an object to the set
|
|
134
|
+
# @param [Object] obj. The object to add
|
|
135
|
+
# @return [SharedSet} self
|
|
136
|
+
def add(obj)
|
|
137
|
+
obj = SharedData.check_obj(obj)
|
|
138
|
+
@j_set.add(obj)
|
|
139
|
+
self
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Add an object to the set
|
|
143
|
+
# @param [Object] obj. The object to add
|
|
144
|
+
# @return [SharedSet] self if the object is not already in the set, otherwise nil
|
|
145
|
+
def add?(obj)
|
|
146
|
+
obj = SharedData.check_obj(obj)
|
|
147
|
+
if !@j_set.contains(obj)
|
|
148
|
+
@j_set.add(obj)
|
|
149
|
+
self
|
|
150
|
+
else
|
|
151
|
+
nil
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# Clear the set
|
|
156
|
+
def clear
|
|
157
|
+
@j_set.clear
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Delete an object from the set
|
|
161
|
+
# @param [Object] obj. The object to delete
|
|
162
|
+
def delete(obj)
|
|
163
|
+
@j_set.remove(obj)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Delete an object from the set
|
|
167
|
+
# @param [Object] obj. The object to delete
|
|
168
|
+
# @return [SharedSet] self if the object was in the set before the remove, nil otherwise.
|
|
169
|
+
def delete?(obj)
|
|
170
|
+
if @j_set.contains(obj)
|
|
171
|
+
@j_set.remove(obj)
|
|
172
|
+
self
|
|
173
|
+
else
|
|
174
|
+
nil
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
# Call the block for every element of the set
|
|
179
|
+
# @param [Blovk] block. The block to call.
|
|
180
|
+
def each(&block)
|
|
181
|
+
iter = @j_set.iterator
|
|
182
|
+
while iter.hasNext do
|
|
183
|
+
obj = iter.next
|
|
184
|
+
obj = Buffer.new(obj) if obj.is_a? org.vertx.java.core.buffer.Buffer
|
|
185
|
+
block.call(obj)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
# @return [Boolean] true if the set is empty
|
|
190
|
+
def empty?
|
|
191
|
+
@j_set.isEmpty
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# Does the set contain an element?
|
|
195
|
+
# @param [Object] obj, the object to check if the set contains
|
|
196
|
+
# @return [Boolean] true if the object is contained in the set
|
|
197
|
+
def include?(obj)
|
|
198
|
+
obj = obj._to_java_buffer if obj.is_a? Buffer
|
|
199
|
+
@j_set.contains(obj)
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# @return [FixNum] The number of elements in the set
|
|
203
|
+
def size
|
|
204
|
+
@j_set.size
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# @private
|
|
208
|
+
def _to_java_set
|
|
209
|
+
@j_set
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'rack'
|
|
2
|
+
|
|
3
|
+
class BasicMiddleware
|
|
4
|
+
def initialize(app, options={})
|
|
5
|
+
@app = app
|
|
6
|
+
end
|
|
7
|
+
def call(env)
|
|
8
|
+
# We had a bug triggered at one point by trying to access any HTTP
|
|
9
|
+
# header with a key less than 10 bytes long
|
|
10
|
+
env['HTTP_foo']
|
|
11
|
+
# Save off the accept header before Rack::Lint messes with it
|
|
12
|
+
env['tb.accept_header'] = env['HTTP_ACCEPT']
|
|
13
|
+
@app.call(env)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
use BasicMiddleware
|
|
18
|
+
use Rack::Lint
|
|
19
|
+
|
|
20
|
+
app = lambda { |env|
|
|
21
|
+
body = <<-EOF
|
|
22
|
+
<div id='success' class='basic-rack'>it worked</div>
|
|
23
|
+
<div id='ruby-version'>#{RUBY_VERSION}</div>
|
|
24
|
+
<div id='path'>#{__FILE__}</div>
|
|
25
|
+
<div id='script_name'>#{env['SCRIPT_NAME']}</div>
|
|
26
|
+
<div id='path_info'>#{env['PATH_INFO']}</div>
|
|
27
|
+
<div id='request_uri'>#{env['REQUEST_URI']}</div>
|
|
28
|
+
<div id='accept_header'>#{env['tb.accept_header']}</div>
|
|
29
|
+
EOF
|
|
30
|
+
if env['REQUEST_METHOD'] == 'POST'
|
|
31
|
+
input = env['rack.input']
|
|
32
|
+
if env['PATH_INFO'] == '/basic-rack/gets'
|
|
33
|
+
posted = ''
|
|
34
|
+
posted_line = input.gets
|
|
35
|
+
while posted_line != nil
|
|
36
|
+
posted << posted_line
|
|
37
|
+
posted_line = input.gets
|
|
38
|
+
end
|
|
39
|
+
elsif env['PATH_INFO'] == '/basic-rack/read'
|
|
40
|
+
posted = input.read(2)
|
|
41
|
+
posted << input.read
|
|
42
|
+
elsif env['PATH_INFO'] == '/basic-rack/each'
|
|
43
|
+
posted = ""
|
|
44
|
+
input.each { |str| posted << str}
|
|
45
|
+
end
|
|
46
|
+
body << "<div id='posted'>#{posted}</div>"
|
|
47
|
+
end
|
|
48
|
+
[200, { 'Content-Type' => 'text/html' }, [body]]
|
|
49
|
+
}
|
|
50
|
+
run app
|