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