sipatra 0.0.3
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/lib/sipatra/base.rb +301 -0
- data/lib/sipatra/commons-pool-1.5.5.jar +0 -0
- data/lib/sipatra/extension_modules.rb +21 -0
- data/lib/sipatra/helpers.rb +205 -0
- data/lib/sipatra/sipatra-0.0.3-SNAPSHOT.jar +0 -0
- data/lib/sipatra/slf4j-api-1.4.0.jar +0 -0
- data/lib/sipatra/slf4j-log4j12-1.4.0.jar +0 -0
- data/lib/sipatra-jars.rb +13 -0
- data/lib/sipatra.rb +9 -0
- metadata +93 -0
data/lib/sipatra/base.rb
ADDED
@@ -0,0 +1,301 @@
|
|
1
|
+
require 'sipatra/helpers'
|
2
|
+
require 'sipatra/extension_modules'
|
3
|
+
require 'benchmark'
|
4
|
+
|
5
|
+
module Sipatra
|
6
|
+
VERSION = '1.0.0'
|
7
|
+
|
8
|
+
class Base
|
9
|
+
include HelperMethods
|
10
|
+
attr_accessor :sip_factory, :context, :session, :msg, :params
|
11
|
+
|
12
|
+
def initialize()
|
13
|
+
@params = Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
|
14
|
+
end
|
15
|
+
|
16
|
+
# called from Java to set SIP servlet bindings
|
17
|
+
def set_bindings(*args)
|
18
|
+
@context, @sip_factory, @session, @msg = args
|
19
|
+
session.extend Sipatra::SessionExtension
|
20
|
+
msg.extend Sipatra::MessageExtension
|
21
|
+
end
|
22
|
+
|
23
|
+
def session=(session)
|
24
|
+
@session = session
|
25
|
+
class << @session
|
26
|
+
include SessionExtension
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# called to process a SIP request
|
31
|
+
def do_request
|
32
|
+
call! self.class.req_handlers
|
33
|
+
end
|
34
|
+
|
35
|
+
# called to process a SIP response
|
36
|
+
def do_response
|
37
|
+
call! self.class.resp_handlers
|
38
|
+
end
|
39
|
+
|
40
|
+
# Exit the current block, halts any further processing
|
41
|
+
# of the message.
|
42
|
+
# TODO: handle a response (as param)
|
43
|
+
def halt
|
44
|
+
throw :halt
|
45
|
+
end
|
46
|
+
|
47
|
+
# Pass control to the next matching handler.
|
48
|
+
def pass
|
49
|
+
throw :pass
|
50
|
+
end
|
51
|
+
|
52
|
+
def request?
|
53
|
+
!msg.respond_to?(:getRequest)
|
54
|
+
end
|
55
|
+
|
56
|
+
def response?
|
57
|
+
msg.respond_to?(:getRequest)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def msg_type
|
63
|
+
response? ? :response : :request
|
64
|
+
end
|
65
|
+
|
66
|
+
def eval_options(opts)
|
67
|
+
opts.each_pair { |key, condition|
|
68
|
+
pass unless header? key
|
69
|
+
header_match = condition.match header[key]
|
70
|
+
@params[key] = header_match.to_a if header_match
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
def eval_condition(arg, keys, opts)
|
75
|
+
#clear (for multi usage)
|
76
|
+
@params.clear
|
77
|
+
if request?
|
78
|
+
match = arg.match msg.requestURI.to_s
|
79
|
+
if match
|
80
|
+
eval_options(opts)
|
81
|
+
if keys.any?
|
82
|
+
values = match.captures.to_a #Array of matched values
|
83
|
+
keys.zip(values).each do |(k, v)|
|
84
|
+
@params[k] = v
|
85
|
+
end
|
86
|
+
elsif(match.length > 1)
|
87
|
+
@params[:uri] = match.to_a
|
88
|
+
end
|
89
|
+
return true
|
90
|
+
end
|
91
|
+
else
|
92
|
+
if ((arg == 0) or (arg == msg.status))
|
93
|
+
eval_options(opts)
|
94
|
+
return true
|
95
|
+
end
|
96
|
+
end
|
97
|
+
return false
|
98
|
+
end
|
99
|
+
|
100
|
+
def process_handler(handlers_hash, method_or_joker)
|
101
|
+
if handlers = handlers_hash[method_or_joker]
|
102
|
+
handlers.each do |pattern, keys, opts, block|
|
103
|
+
catch :pass do
|
104
|
+
throw :pass unless eval_condition(pattern, keys, opts)
|
105
|
+
throw :halt, instance_eval(&block)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Run all filters defined on superclasses and then those on the current class.
|
112
|
+
def filter!(type, base = self.class)
|
113
|
+
filter! type, base.superclass if base.superclass.respond_to?(:filters)
|
114
|
+
base.filters[type].each { |block| instance_eval(&block) }
|
115
|
+
end
|
116
|
+
|
117
|
+
def call!(handlers)
|
118
|
+
filter! :before
|
119
|
+
catch(:halt) do
|
120
|
+
process_handler(handlers, msg.method)
|
121
|
+
process_handler(handlers, "_")
|
122
|
+
end
|
123
|
+
ensure
|
124
|
+
filter! :after
|
125
|
+
end
|
126
|
+
|
127
|
+
class << self
|
128
|
+
attr_reader :req_handlers, :resp_handlers, :filters
|
129
|
+
|
130
|
+
# permits configuration of the application
|
131
|
+
def configure(*envs, &block)
|
132
|
+
yield self if envs.empty? || envs.include?(environment.to_sym)
|
133
|
+
end
|
134
|
+
|
135
|
+
# Methods defined in the block and/or in the module
|
136
|
+
# arguments available to handlers.
|
137
|
+
def helpers(*modules, &block)
|
138
|
+
include(*modules) if modules.any?
|
139
|
+
class_eval(&block) if block_given?
|
140
|
+
end
|
141
|
+
|
142
|
+
# Extension modules registered on this class and all superclasses.
|
143
|
+
def extensions
|
144
|
+
if superclass.respond_to?(:extensions)
|
145
|
+
(@extensions + superclass.extensions).uniq
|
146
|
+
else
|
147
|
+
@extensions
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# Extends current class with all modules passed as arguements
|
152
|
+
# if a block is present, creates a module with the block and
|
153
|
+
# extends the current class with it.
|
154
|
+
def register_extension(*extensions, &block)
|
155
|
+
extensions << Module.new(&block) if block_given?
|
156
|
+
@extensions += extensions
|
157
|
+
extensions.each do |extension|
|
158
|
+
extend extension
|
159
|
+
extension.registered(self) if extension.respond_to?(:registered)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def response(*args, &block)
|
164
|
+
method_name = args.shift if (!args.first.kind_of? Hash) and (!args.first.kind_of? Integer)
|
165
|
+
code_int = args.shift if !args.first.kind_of? Hash
|
166
|
+
opts = *args
|
167
|
+
pattern = code_int || 0
|
168
|
+
sip_method_name = method_name ? method_name.to_s.upcase : "_"
|
169
|
+
handler("response_#{sip_method_name} \"#{pattern}\"", sip_method_name, pattern, [], opts || {}, &block)
|
170
|
+
end
|
171
|
+
|
172
|
+
[:ack, :bye, :cancel, :info, :invite, :message,
|
173
|
+
:notify, :options, :prack, :publish, :refer,
|
174
|
+
:register, :subscribe, :update, :request].each do |name|
|
175
|
+
define_method name do |*args, &block|
|
176
|
+
path = args.shift if (!args.first.kind_of? Hash)
|
177
|
+
opts = *args
|
178
|
+
uri = path || //
|
179
|
+
pattern, keys = compile_uri_pattern(uri)
|
180
|
+
sip_method_name = name == :request ? "_" : name.to_s.upcase
|
181
|
+
handler("request_#{sip_method_name} \"#{uri.kind_of?(Regexp) ? uri.source : uri}\"", sip_method_name, pattern, keys , opts || {}, &block)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def before(msg_type = nil, &block)
|
186
|
+
add_filter(:before, msg_type, &block)
|
187
|
+
end
|
188
|
+
|
189
|
+
def after(msg_type = nil, &block)
|
190
|
+
add_filter(:after, msg_type, &block)
|
191
|
+
end
|
192
|
+
|
193
|
+
def reset!
|
194
|
+
@req_handlers = {}
|
195
|
+
@resp_handlers = {}
|
196
|
+
@extensions = []
|
197
|
+
@filters = {:before => [], :after => []}
|
198
|
+
end
|
199
|
+
|
200
|
+
def inherited(subclass)
|
201
|
+
subclass.reset!
|
202
|
+
super
|
203
|
+
end
|
204
|
+
|
205
|
+
def before_filters
|
206
|
+
filters[:before]
|
207
|
+
end
|
208
|
+
|
209
|
+
def after_filters
|
210
|
+
filters[:after]
|
211
|
+
end
|
212
|
+
|
213
|
+
private
|
214
|
+
|
215
|
+
def add_filter(type, message_type = nil, &block)
|
216
|
+
if message_type
|
217
|
+
add_filter(type) do
|
218
|
+
next unless msg_type == message_type
|
219
|
+
instance_eval(&block)
|
220
|
+
end
|
221
|
+
else
|
222
|
+
filters[type] << block
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
# compiles a URI pattern
|
227
|
+
def compile_uri_pattern(uri)
|
228
|
+
keys = []
|
229
|
+
if uri.respond_to? :to_str
|
230
|
+
pattern =
|
231
|
+
uri.to_str.gsub(/\(:(\w+)\)/) do |match|
|
232
|
+
keys << $1.dup
|
233
|
+
"([^:@;=?&]+)"
|
234
|
+
end
|
235
|
+
[/^#{pattern}$/, keys]
|
236
|
+
elsif uri.respond_to? :match
|
237
|
+
[uri, keys]
|
238
|
+
else
|
239
|
+
raise TypeError, uri
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def handler(method_name, verb, pattern, keys, options={}, &block)
|
244
|
+
define_method method_name, &block
|
245
|
+
unbound_method = instance_method(method_name)
|
246
|
+
block =
|
247
|
+
if block.arity != 0
|
248
|
+
proc { unbound_method.bind(self).call(*@block_params) }
|
249
|
+
else
|
250
|
+
proc { unbound_method.bind(self).call }
|
251
|
+
end
|
252
|
+
handler_table(method_name, verb).push([pattern, keys, options, block]).last # TODO: conditions
|
253
|
+
end
|
254
|
+
|
255
|
+
def handler_table(method_name, verb)
|
256
|
+
if method_name.start_with? "response"
|
257
|
+
(@resp_handlers ||= {})[verb] ||= []
|
258
|
+
else
|
259
|
+
(@req_handlers ||= {})[verb] ||= []
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
reset!
|
265
|
+
end
|
266
|
+
|
267
|
+
class Application < Base
|
268
|
+
def self.register_extension(*extensions, &block) #:nodoc:
|
269
|
+
added_methods = extensions.map {|m| m.public_instance_methods }.flatten
|
270
|
+
Delegator.delegate(*added_methods)
|
271
|
+
super(*extensions, &block)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
module Delegator #:nodoc:
|
276
|
+
def self.delegate(*methods)
|
277
|
+
methods.each do |method_name|
|
278
|
+
eval <<-RUBY, binding, '(__DELEGATE__)', 1
|
279
|
+
def #{method_name}(*args, &b)
|
280
|
+
::Sipatra::Application.send(#{method_name.inspect}, *args, &b)
|
281
|
+
end
|
282
|
+
private #{method_name.inspect}
|
283
|
+
RUBY
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
delegate :ack, :bye, :cancel, :info, :invite, :message,
|
288
|
+
:notify, :options, :prack, :publish, :refer,
|
289
|
+
:register, :subscribe, :update,
|
290
|
+
:helpers, :configure,
|
291
|
+
:before, :after, :request, :response
|
292
|
+
end
|
293
|
+
|
294
|
+
def self.helpers(*extensions, &block)
|
295
|
+
Application.helpers(*extensions, &block)
|
296
|
+
end
|
297
|
+
|
298
|
+
def self.register_extension(*extensions, &block)
|
299
|
+
Application.register_extension(*extensions, &block)
|
300
|
+
end
|
301
|
+
end
|
Binary file
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Sipatra
|
2
|
+
module MessageExtension
|
3
|
+
def uri
|
4
|
+
requestURI
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
module SessionExtension
|
9
|
+
def [](name)
|
10
|
+
getAttribute(name.to_s)
|
11
|
+
end
|
12
|
+
|
13
|
+
def []=(name, value)
|
14
|
+
if value.nil?
|
15
|
+
removeAttribute(name.to_s)
|
16
|
+
else
|
17
|
+
setAttribute(name.to_s, value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
module Sipatra
|
2
|
+
STATUS_CODES_MAP = {
|
3
|
+
:accepted => 202,
|
4
|
+
:address_incomplete => 484,
|
5
|
+
:alternative_service => 380,
|
6
|
+
:ambiguous => 485,
|
7
|
+
:bad_event => 489,
|
8
|
+
:bad_extension => 420,
|
9
|
+
:bad_gateway => 502,
|
10
|
+
:bad_identity_info => 436,
|
11
|
+
:bad_request => 400,
|
12
|
+
:busy_everywhere => 600,
|
13
|
+
:busy_here => 486,
|
14
|
+
:call_being_forwarded => 181,
|
15
|
+
:call_leg_done => 481,
|
16
|
+
:call_queued => 182,
|
17
|
+
:conditional_request_failed => 412,
|
18
|
+
:decline => 603,
|
19
|
+
:does_not_exit_anywhere => 604,
|
20
|
+
:extension_required => 421,
|
21
|
+
:forbidden => 403,
|
22
|
+
:gone => 410,
|
23
|
+
:interval_too_brief => 423,
|
24
|
+
:invalid_identity_header => 438,
|
25
|
+
:loop_detected => 482,
|
26
|
+
:message_too_large => 513,
|
27
|
+
:method_not_allowed => 405,
|
28
|
+
:moved_permanently => 301,
|
29
|
+
:moved_temporarily => 302,
|
30
|
+
:multiple_choices => 300,
|
31
|
+
:not_acceptable => 406,
|
32
|
+
:not_acceptable_anywhere => 606,
|
33
|
+
:not_acceptable_here => 488,
|
34
|
+
:not_found => 404,
|
35
|
+
:not_implemented => 501,
|
36
|
+
:ok => 200,
|
37
|
+
:payment_required => 402,
|
38
|
+
:precondition_failure => 580,
|
39
|
+
:provide_referer_identity => 429,
|
40
|
+
:proxy_authentication_required => 407,
|
41
|
+
:request_entity_too_large => 413,
|
42
|
+
:request_pending => 491,
|
43
|
+
:request_terminated => 487,
|
44
|
+
:request_timeout => 408,
|
45
|
+
:request_uri_too_long => 414,
|
46
|
+
:ringing => 180,
|
47
|
+
:security_agreement_required => 494,
|
48
|
+
:server_internal_error => 500,
|
49
|
+
:server_timeout => 504,
|
50
|
+
:service_unavailable => 503,
|
51
|
+
:session_interval_too_small => 422,
|
52
|
+
:session_progress => 183,
|
53
|
+
:temporarily_unavailable => 480,
|
54
|
+
:too_many_hops => 483,
|
55
|
+
:trying => 100,
|
56
|
+
:unauthorized => 401,
|
57
|
+
:undecipherable => 493,
|
58
|
+
:unsupported_certificate => 437,
|
59
|
+
:unsupported_media_type => 415,
|
60
|
+
:unsupported_uri_scheme => 416,
|
61
|
+
:use_identity_header => 428,
|
62
|
+
:use_proxy => 305,
|
63
|
+
:version_not_supported => 505,
|
64
|
+
}
|
65
|
+
|
66
|
+
class HeadersWrapper
|
67
|
+
def initialize(app, plural = false, address = false)
|
68
|
+
@app = app
|
69
|
+
method_definitions = <<-RUBY
|
70
|
+
def [](name)
|
71
|
+
@app.msg.get#{address ? "Address" : ""}Header#{plural ? "s" : ""}(name.to_s)#{plural ? ".to_a" : ""}
|
72
|
+
end
|
73
|
+
RUBY
|
74
|
+
if plural
|
75
|
+
method_definitions += <<-RUBY
|
76
|
+
def []=(name, values)
|
77
|
+
name = name.to_s
|
78
|
+
@app.msg.removeHeader(name)
|
79
|
+
if !values.nil?
|
80
|
+
values.each do |value|
|
81
|
+
@app.msg.add#{address ? "Address" : ""}Header(name, value#{address ? ", true" : ".to_s"})
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
RUBY
|
86
|
+
else
|
87
|
+
method_definitions += <<-RUBY
|
88
|
+
def []=(name, value)
|
89
|
+
if !value.nil?
|
90
|
+
@app.msg.set#{address ? "Address" : ""}Header(name.to_s, value)
|
91
|
+
else
|
92
|
+
@app.msg.removeHeader(name.to_s)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
RUBY
|
96
|
+
end
|
97
|
+
class << self; self; end.class_eval method_definitions
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
module HelperMethods
|
102
|
+
def proxy(*args)
|
103
|
+
uri = args.shift
|
104
|
+
uri, options = nil, uri if uri.kind_of? Hash
|
105
|
+
options ||= args.shift || {}
|
106
|
+
if uri.nil?
|
107
|
+
uri = msg.requestURI
|
108
|
+
else
|
109
|
+
uri = sip_factory.createURI(uri)
|
110
|
+
end
|
111
|
+
proxy = msg.getProxy()
|
112
|
+
proxy.setRecordRoute(options[:record_route]) if options.has_key? :record_route
|
113
|
+
proxy.proxyTo(uri)
|
114
|
+
end
|
115
|
+
|
116
|
+
def header
|
117
|
+
@header_wrapper ||= HeadersWrapper::new(self)
|
118
|
+
end
|
119
|
+
|
120
|
+
def headers
|
121
|
+
@headers_wrapper ||= HeadersWrapper::new(self, true)
|
122
|
+
end
|
123
|
+
|
124
|
+
def address_header
|
125
|
+
@address_header_wrapper ||= HeadersWrapper::new(self, false, true)
|
126
|
+
end
|
127
|
+
|
128
|
+
def address_headers
|
129
|
+
@address_headers_wrapper ||= HeadersWrapper::new(self, true, true)
|
130
|
+
end
|
131
|
+
|
132
|
+
def add_header(name, value)
|
133
|
+
msg.addHeader(name.to_s, value)
|
134
|
+
end
|
135
|
+
|
136
|
+
def add_address_header(name, value, first = true)
|
137
|
+
msg.addAddressHeader(name.to_s, value, first)
|
138
|
+
end
|
139
|
+
|
140
|
+
def header?(name)
|
141
|
+
!msg.getHeader(name.to_s).nil?
|
142
|
+
end
|
143
|
+
|
144
|
+
def modify_header(header_name, pattern = nil, new_value = nil)
|
145
|
+
#FIXME: "JAVA" Code
|
146
|
+
if pattern
|
147
|
+
pattern = Regexp.new(/^#{pattern}$/) unless pattern.kind_of? Regexp
|
148
|
+
headers[header_name] = headers[header_name].map do |value|
|
149
|
+
value.gsub(pattern, new_value)
|
150
|
+
end
|
151
|
+
else
|
152
|
+
headers[header_name] = headers[header_name].map do |value|
|
153
|
+
yield value
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def remove_header(name)
|
159
|
+
msg.removeHeader(name.to_s)
|
160
|
+
end
|
161
|
+
|
162
|
+
def send_response(status, *args)
|
163
|
+
create_args = [convert_status_code(status)]
|
164
|
+
create_args << args.shift unless args.empty? || args.first.kind_of?(Hash)
|
165
|
+
response = msg.createResponse(*create_args)
|
166
|
+
unless args.empty?
|
167
|
+
raise ArgumentError, "last argument should be a Hash" unless args.first.kind_of? Hash
|
168
|
+
args.first.each_pair do |name, value|
|
169
|
+
response.addHeader(name.to_s, value.to_s)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
if block_given?
|
173
|
+
yield response
|
174
|
+
end
|
175
|
+
response.send
|
176
|
+
end
|
177
|
+
|
178
|
+
def create_address(addr, options = {})
|
179
|
+
addr = addr.to_s # TODO: Handle URI instances
|
180
|
+
address = sip_factory.createAddress(addr)
|
181
|
+
address.setExpires(options[:expires]) if options.has_key? :expires
|
182
|
+
address.setDisplayName(options[:display_name]) if options.has_key? :display_name
|
183
|
+
|
184
|
+
address
|
185
|
+
end
|
186
|
+
|
187
|
+
def push_route(route)
|
188
|
+
msg.pushRoute(sip_factory.createAddress(route))
|
189
|
+
end
|
190
|
+
|
191
|
+
private
|
192
|
+
|
193
|
+
def convert_status_code(symbol_or_int)
|
194
|
+
case symbol_or_int
|
195
|
+
when Integer: return symbol_or_int
|
196
|
+
when Symbol:
|
197
|
+
code = STATUS_CODES_MAP[symbol_or_int]
|
198
|
+
raise ArgumentError, "Unknown status code symbol: '#{symbol_or_int}'" unless code
|
199
|
+
code
|
200
|
+
else
|
201
|
+
raise ArgumentError, "Status code value should be a Symbol or Int not '#{symbol_or_int.class}'"
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
data/lib/sipatra-jars.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
module SipatraJars
|
2
|
+
PATH = File.expand_path(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
class << self
|
5
|
+
def all_jar_names
|
6
|
+
@all_jar_names ||= all_jar_paths.map { |path| File::basename(path) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def all_jar_paths
|
10
|
+
@all_jar_paths ||= Dir[PATH + "/sipatra/*.jar"]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/sipatra.rb
ADDED
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sipatra
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 25
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 3
|
10
|
+
version: 0.0.3
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Dominique Broeglin
|
14
|
+
- Jean-Baptiste Morin
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2010-11-30 00:00:00 +01:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
name: rspec
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 13
|
31
|
+
segments:
|
32
|
+
- 1
|
33
|
+
- 2
|
34
|
+
- 9
|
35
|
+
version: 1.2.9
|
36
|
+
type: :development
|
37
|
+
version_requirements: *id001
|
38
|
+
description: Sipatra is a Ruby DSL for easy writting of SIP Servlet applications
|
39
|
+
email:
|
40
|
+
- dominique.broeglin@gmail.com
|
41
|
+
- jean-baptiste.morin@nexcom.fr
|
42
|
+
executables: []
|
43
|
+
|
44
|
+
extensions: []
|
45
|
+
|
46
|
+
extra_rdoc_files: []
|
47
|
+
|
48
|
+
files:
|
49
|
+
- lib/sipatra-jars.rb
|
50
|
+
- lib/sipatra.rb
|
51
|
+
- lib/sipatra/base.rb
|
52
|
+
- lib/sipatra/commons-pool-1.5.5.jar
|
53
|
+
- lib/sipatra/extension_modules.rb
|
54
|
+
- lib/sipatra/helpers.rb
|
55
|
+
- lib/sipatra/sipatra-0.0.3-SNAPSHOT.jar
|
56
|
+
- lib/sipatra/slf4j-api-1.4.0.jar
|
57
|
+
- lib/sipatra/slf4j-log4j12-1.4.0.jar
|
58
|
+
has_rdoc: true
|
59
|
+
homepage: http://confluence.cipango.org/display/DOC/Sipatra
|
60
|
+
licenses: []
|
61
|
+
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options:
|
64
|
+
- --charset=UTF-8
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
hash: 3
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
hash: 3
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
version: "0"
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 1.3.7
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: DSL for easy writting of SIP Servlet applications
|
92
|
+
test_files: []
|
93
|
+
|