rsence 2.0.0.6.pre → 2.0.0.7.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/INSTALL.rdoc +39 -25
- data/VERSION +1 -1
- data/conf/default_conf.yaml +0 -3
- data/lib/conf/default.rb +59 -60
- data/lib/daemon/daemon.rb +269 -280
- data/lib/http/broker.rb +47 -14
- data/lib/http/rackup.rb +4 -0
- data/lib/http/request.rb +47 -49
- data/lib/http/response.rb +47 -45
- data/lib/plugins/gui_plugin.rb +22 -21
- data/lib/plugins/guiparser.rb +95 -94
- data/lib/plugins/plugin.rb +300 -295
- data/lib/plugins/plugin_plugins.rb +64 -40
- data/lib/plugins/plugin_sqlite_db.rb +63 -63
- data/lib/plugins/plugin_util.rb +95 -104
- data/lib/plugins/pluginmanager.rb +373 -414
- data/lib/plugins/plugins.rb +11 -4
- data/lib/plugins/servlet.rb +10 -9
- data/lib/session/msg.rb +249 -248
- data/lib/session/sessionmanager.rb +364 -373
- data/lib/session/sessionstorage.rb +265 -272
- data/lib/transporter/transporter.rb +164 -169
- data/lib/util/gzstring.rb +2 -0
- data/lib/values/hvalue.rb +224 -224
- data/lib/values/valuemanager.rb +98 -98
- data/plugins/index_html/index_html.rb +1 -32
- metadata +4 -4
data/lib/http/broker.rb
CHANGED
@@ -21,14 +21,11 @@ require 'http/response'
|
|
21
21
|
## Minimally WEBrick -compatible request object
|
22
22
|
require 'http/request'
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
Broker routes requests to the proper request processing instance
|
27
|
-
|
28
|
-
=end
|
29
|
-
|
24
|
+
# Broker routes requests to the proper request processing instance.
|
25
|
+
# It's the top-level http handler.
|
30
26
|
class Broker
|
31
27
|
|
28
|
+
# This method is called from Rack. The env is the Rack environment.
|
32
29
|
def call(env)
|
33
30
|
sleep @@ping_sim if @@ping_sim
|
34
31
|
unless @@transporter.online?
|
@@ -45,14 +42,18 @@ class Broker
|
|
45
42
|
response = Response.new
|
46
43
|
request_method = request.request_method.downcase
|
47
44
|
dispatcher = dispatcher_class.new( request, response )
|
48
|
-
dispatcher.send(request_method)
|
45
|
+
dispatcher.send( request_method )
|
49
46
|
content_type = dispatcher.content_type
|
50
|
-
# puts "encoding: #{response.body.encoding.inspect}"
|
51
47
|
response.header['Content-Length'] = response.body.length.to_s unless response.header.has_key?('Content-Length')
|
52
|
-
# puts [response.status, response.header, response.body].inspect
|
53
48
|
return [response.status, response.header, response.body]
|
54
49
|
end
|
55
50
|
|
51
|
+
# Returns a dynamically created "REST Dispatcher" kind of class that has
|
52
|
+
# request and response as instance variables and the rest of the Broker
|
53
|
+
# class as the superclass.
|
54
|
+
# It calls the method according to the http method.
|
55
|
+
# Called from #call
|
56
|
+
# Broker currently implements only get and post methods.
|
56
57
|
def dispatcher_class
|
57
58
|
@dispatcher ||= Class.new(self.class) do
|
58
59
|
attr_accessor :content_type
|
@@ -63,13 +64,23 @@ class Broker
|
|
63
64
|
end
|
64
65
|
end
|
65
66
|
|
66
|
-
|
67
|
+
# This method is used to create the Rack instance
|
68
|
+
# and set up itself accordingly.
|
69
|
+
# The transporter parameter is an instance of the Transporter class,
|
70
|
+
# which does all the actual delegation.
|
71
|
+
# The conf parameter contains a hash with at least the following:
|
72
|
+
# :bind_address, :port, :rack_require
|
73
|
+
def self.start( transporter, conf )
|
74
|
+
|
75
|
+
host = conf[:bind_address]
|
76
|
+
port = conf[:port]
|
77
|
+
|
67
78
|
@@transporter = transporter
|
68
|
-
|
69
|
-
if
|
79
|
+
latency = ::RSence.config[:http_server][:latency]
|
80
|
+
if latency == 0
|
70
81
|
@@ping_sim = false
|
71
82
|
else
|
72
|
-
@@ping_sim =
|
83
|
+
@@ping_sim = latency/1000.0
|
73
84
|
end
|
74
85
|
Thread.new do
|
75
86
|
Thread.pass
|
@@ -80,13 +91,34 @@ class Broker
|
|
80
91
|
end
|
81
92
|
@@transporter.online = true
|
82
93
|
end
|
94
|
+
|
95
|
+
require 'rack'
|
96
|
+
|
97
|
+
# Loads the selected web-server (default is 'mongrel')
|
98
|
+
rack_require = conf[:rack_require]
|
99
|
+
puts conf.inspect
|
100
|
+
puts "rack require: #{rack_require.inspect}" if RSence.args[:debug]
|
101
|
+
require rack_require
|
102
|
+
|
103
|
+
# Selects the handler for Rack
|
104
|
+
handler = {
|
105
|
+
'webrick' => lambda { Rack::Handler::WEBrick },
|
106
|
+
'ebb' => lambda { Rack::Handler::Ebb },
|
107
|
+
'thin' => lambda { Rack::Handler::Thin },
|
108
|
+
'mongrel' => lambda { Rack::Handler::Mongrel },
|
109
|
+
'unicorn' => lambda { Rack::Handler::Unicorn },
|
110
|
+
'rainbows' => lambda { Rack::Handler::Rainbows }
|
111
|
+
}[rack_require].call
|
112
|
+
|
83
113
|
handler.run( Rack::Lint.new(self.new), :Host => host, :Port => port )
|
114
|
+
|
84
115
|
end
|
85
116
|
|
86
|
-
def self.included(receiver)
|
117
|
+
def self.included( receiver )
|
87
118
|
receiver.extend( SingletonMethods )
|
88
119
|
end
|
89
120
|
|
121
|
+
# Generic 404 handler
|
90
122
|
def not_found
|
91
123
|
puts "/404: #{@request.fullpath.inspect}" if RSence.args[:verbose]
|
92
124
|
@response.status = 404
|
@@ -114,6 +146,7 @@ class Broker
|
|
114
146
|
|
115
147
|
end
|
116
148
|
|
149
|
+
### -- Add more http methods here when we have some apps to test with, caldav implementation maybe? ++
|
117
150
|
|
118
151
|
end
|
119
152
|
|
data/lib/http/rackup.rb
CHANGED
data/lib/http/request.rb
CHANGED
@@ -13,57 +13,55 @@ require 'rubygems'
|
|
13
13
|
require 'rack'
|
14
14
|
|
15
15
|
module RSence
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
16
|
+
|
17
|
+
# Simple Request class, slightly more involved
|
18
|
+
# than the Rack::Request it's extending.
|
19
|
+
class Request < Rack::Request
|
20
|
+
attr_reader :header, :path, :query
|
21
|
+
def initialize(env)
|
22
|
+
@header = {}
|
23
|
+
super
|
24
|
+
env2header()
|
25
|
+
@path = path_info()
|
26
|
+
@query = params()
|
27
|
+
end
|
28
|
+
def unparsed_uri
|
29
|
+
return @header['request-uri']
|
30
|
+
end
|
31
|
+
def env2header
|
32
|
+
[ ['SERVER_NAME', 'server-name'],
|
33
|
+
['HTTP_USER_AGENT', 'user-agent'],
|
34
|
+
['HTTP_ACCEPT_ENCODING', 'accept-encoding'],
|
35
|
+
['PATH_INFO', 'path-info'],
|
36
|
+
['HTTP_HOST', 'host'],
|
37
|
+
['HTTP_ACCEPT_LANGUAGE', 'accept-language'],
|
38
|
+
['SERVER_PROTOCOL', 'server-protocol'],
|
39
|
+
['REQUEST_PATH', 'request-path'],
|
40
|
+
['HTTP_KEEP_ALIVE', 'keep-alive'],
|
41
|
+
['SERVER_SOFTWARE', 'server-software'],
|
42
|
+
['REMOTE_ADDR', 'remote-addr'],
|
43
|
+
['HTTP_REFERER', 'referer'],
|
44
|
+
['HTTP_VERSION', 'version'],
|
45
|
+
['HTTP_ACCEPT_CHARSET', 'accept-charset'],
|
46
|
+
['REQUEST_URI', 'request-uri'],
|
47
|
+
['SERVER_PORT', 'server-port'],
|
48
|
+
['QUERY_STRING', 'query-string'],
|
49
|
+
['HTTP_ACCEPT', 'accept'],
|
50
|
+
['REQUEST_METHOD', 'request-method'],
|
51
|
+
['HTTP_CONNECTION', 'connection'],
|
52
|
+
['HTTP_SOAPACTION', 'soapaction'],
|
53
|
+
['HTTP_FORWARDED_HOST', 'forwarded-host']
|
54
|
+
].each do |env_key,header_key|
|
55
|
+
if @env.has_key?(env_key)
|
56
|
+
@header[header_key] = @env[env_key]
|
57
|
+
end
|
58
|
+
if env_key.start_with?( 'HTTP_' )
|
59
|
+
x_env_key = "HTTP_X#{env_key[4..-1]}"
|
60
|
+
if @env.has_key?( x_env_key )
|
61
|
+
@header["x-#{header_key}"] = @env[ x_env_key ]
|
62
|
+
end
|
62
63
|
end
|
63
64
|
end
|
64
65
|
end
|
65
66
|
end
|
66
67
|
end
|
67
|
-
|
68
|
-
|
69
|
-
end
|
data/lib/http/response.rb
CHANGED
@@ -10,54 +10,56 @@
|
|
10
10
|
|
11
11
|
|
12
12
|
module RSence
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
|
14
|
+
# Simply adds the + method "operator" to an extended Array.
|
15
|
+
# Used for pushing http body data.
|
16
|
+
class ResponseBody < Array
|
17
|
+
def +(body_data)
|
18
|
+
self.push(body_data)
|
19
|
+
end
|
17
20
|
end
|
18
|
-
end
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
class Response
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
22
|
+
# Classic WEBrick -compatible Response object for Rack.
|
23
|
+
# Implements only the methods used by the framework.
|
24
|
+
class Response
|
25
|
+
def initialize
|
26
|
+
@body = ResponseBody.new(1)
|
27
|
+
@body[0] = ''
|
28
|
+
@status = 200
|
29
|
+
@header = {
|
30
|
+
'Content-Type' => 'text/plain',
|
31
|
+
'Server' => 'RSence'
|
32
|
+
}
|
33
|
+
end
|
34
|
+
def body=(body_data)
|
35
|
+
@body = ResponseBody.new(1)
|
36
|
+
@body[0] = body_data
|
37
|
+
end
|
38
|
+
def body
|
39
|
+
@body.join
|
40
|
+
end
|
41
|
+
def content_type=(new_content_type)
|
42
|
+
@header['Content-Type'] = new_content_type
|
43
|
+
end
|
44
|
+
def content_type
|
45
|
+
@header['Content-Type']
|
46
|
+
end
|
47
|
+
def camelize( header_key )
|
48
|
+
header_key.capitalize.gsub(/\-([a-z])/) { '-'+$1.upcase }
|
49
|
+
end
|
50
|
+
def []=(header_key,header_val)
|
51
|
+
@header[camelize( header_key )] = header_val.to_s
|
52
|
+
end
|
53
|
+
def status=(new_val)
|
54
|
+
@status = new_val.to_i
|
55
|
+
end
|
56
|
+
def status
|
57
|
+
@status
|
58
|
+
end
|
59
|
+
def header
|
60
|
+
@header
|
61
|
+
end
|
44
62
|
end
|
45
|
-
def camelize( header_key )
|
46
|
-
header_key.capitalize.gsub(/\-([a-z])/) { '-'+$1.upcase }
|
47
|
-
end
|
48
|
-
def []=(header_key,header_val)
|
49
|
-
@header[camelize( header_key )] = header_val.to_s
|
50
|
-
end
|
51
|
-
def status=(new_val)
|
52
|
-
@status = new_val.to_i
|
53
|
-
end
|
54
|
-
def status
|
55
|
-
@status
|
56
|
-
end
|
57
|
-
def header
|
58
|
-
@header
|
59
|
-
end
|
60
|
-
end
|
61
63
|
|
62
64
|
end
|
63
65
|
|
data/lib/plugins/gui_plugin.rb
CHANGED
@@ -6,28 +6,29 @@
|
|
6
6
|
# with this software package. If not, contact licensing@riassence.com
|
7
7
|
##
|
8
8
|
|
9
|
-
## The GUIPlugin extends Plugin by automatically initializing an GUIParser
|
10
|
-
## instance as @gui
|
11
|
-
## It makes the include_js method public to enable automatic dependency
|
12
|
-
## loading based on the dependencies item in the YAML gui declaration.
|
13
|
-
## It also makes the @path public.
|
14
|
-
## It inits the gui automatically.
|
15
|
-
## Extend the gui_params method to define your own params for the gui data.
|
16
|
-
##
|
17
|
-
## HValues can be defined inside values.yaml at the root directory of
|
18
|
-
## plugin. The HValues may be linked directly with methods on the values.yaml
|
19
|
-
## as well.
|
20
|
-
##
|
21
|
-
## == Values.yaml
|
22
|
-
## :valuename: # name of the HValue
|
23
|
-
## :value: 2.56 # defined value
|
24
|
-
## :responders: # methods responding to the value on ruby code upon change
|
25
|
-
## - :method: validate_convert_factor
|
26
|
-
##
|
27
|
-
##
|
28
|
-
##
|
29
9
|
module ::RSence
|
30
10
|
module Plugins
|
11
|
+
|
12
|
+
## The GUIPlugin extends Plugin by automatically initializing an GUIParser
|
13
|
+
## instance as @gui
|
14
|
+
## It makes the include_js method public to enable automatic dependency
|
15
|
+
## loading based on the dependencies item in the YAML gui declaration.
|
16
|
+
## It also makes the @path public.
|
17
|
+
## It inits the gui automatically.
|
18
|
+
## Extend the gui_params method to define your own params for the gui data.
|
19
|
+
##
|
20
|
+
## HValues can be defined inside values.yaml at the root directory of
|
21
|
+
## plugin. The HValues may be linked directly with methods on the values.yaml
|
22
|
+
## as well.
|
23
|
+
##
|
24
|
+
## == Values.yaml
|
25
|
+
## :valuename: # name of the HValue
|
26
|
+
## :value: 2.56 # defined value
|
27
|
+
## :responders: # methods responding to the value on ruby code upon change
|
28
|
+
## - :method: validate_convert_factor
|
29
|
+
##
|
30
|
+
##
|
31
|
+
##
|
31
32
|
class GUIPluginTemplate < PluginTemplate
|
32
33
|
def self.bundle_type; :GUIPlugin; end
|
33
34
|
|
@@ -35,7 +36,7 @@ module ::RSence
|
|
35
36
|
type: GUITree
|
36
37
|
version: 0.6
|
37
38
|
|
38
|
-
class:
|
39
|
+
class: RSence.GUIApp
|
39
40
|
options:
|
40
41
|
label: "Dummy Application"
|
41
42
|
|
data/lib/plugins/guiparser.rb
CHANGED
@@ -7,112 +7,113 @@
|
|
7
7
|
##
|
8
8
|
|
9
9
|
module ::RSence
|
10
|
-
module Plugins
|
11
|
-
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# @gui.
|
21
|
-
|
10
|
+
module Plugins
|
11
|
+
|
12
|
+
# This class automatically loads a YAML file from "gui" subdirectory of a plugin.
|
13
|
+
# Extend your plugin from the GUIPlugin class instead of the Plugin class to make
|
14
|
+
# this work automatically.
|
15
|
+
# = Usage:
|
16
|
+
# Initialize like this from inside a plugin method. This will load the "gui/my_gui.yaml" file.
|
17
|
+
# @gui = GUIParser.new( self, 'my_gui' )
|
18
|
+
# To make the client render the contents of the yaml do this:
|
19
|
+
# ses = get_ses( msg )
|
20
|
+
# params = { :values => @gui.values( ses ) }
|
21
|
+
# @gui.init( msg, params )
|
22
|
+
class GUIParser
|
22
23
|
|
23
|
-
|
24
|
+
include ::RSence
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
26
|
+
# Use this method to send the client all commands required to construct the GUI Tree using JSONRenderer.
|
27
|
+
# = Parameters
|
28
|
+
# +msg+:: The +Message+ instance +msg+ used all over the place.
|
29
|
+
# +params+:: An hash containing all parameters referred from the YAML file.
|
30
|
+
def init( msg, params )
|
31
|
+
gui_data = YAML.load( @yaml_src )
|
32
|
+
parse_gui( gui_data, params )
|
33
|
+
if gui_data.has_key?('dependencies')
|
34
|
+
@parent.include_js( msg, gui_data['dependencies'] )
|
35
|
+
gui_data.delete('dependencies')
|
36
|
+
end
|
37
|
+
if gui_data.has_key?('include')
|
38
|
+
gui_data['include'].each do | js_file |
|
39
|
+
js_src = @parent.read_js_once( msg, js_file )
|
40
|
+
msg.reply( js_src )
|
41
|
+
end
|
42
|
+
end
|
43
|
+
gui_name = @parent.name
|
44
|
+
json_data = JSON.dump( gui_data )
|
45
|
+
msg.reply( "JSONRenderer.nu(#{json_data});", true )
|
40
46
|
end
|
41
|
-
end
|
42
|
-
gui_name = @parent.name
|
43
|
-
json_data = JSON.dump( gui_data )
|
44
|
-
msg.reply( "JSONRenderer.nu(#{json_data});", true )
|
45
|
-
end
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
48
|
+
# Use this method to extract all the value id's of the +ses+ hash.
|
49
|
+
def values( ses )
|
50
|
+
ids = {}
|
51
|
+
ses.each do | key, value |
|
52
|
+
if value.class == HValue
|
53
|
+
ids[ key ] = value.val_id
|
54
|
+
end
|
55
|
+
end
|
56
|
+
return ids
|
53
57
|
end
|
54
|
-
end
|
55
|
-
return ids
|
56
|
-
end
|
57
58
|
|
58
|
-
private
|
59
|
+
private
|
59
60
|
|
60
|
-
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
# Parses the gui data using params. Called from +init+.
|
65
|
-
def parse_gui( gui_data, params )
|
66
|
-
data_class = gui_data.class
|
67
|
-
if data_class == Array
|
68
|
-
gui_data.each_with_index do | item, i |
|
69
|
-
gui_data[i] = parse_gui( item, params )
|
70
|
-
end
|
71
|
-
elsif data_class == Hash
|
72
|
-
gui_data.each do | key, value |
|
73
|
-
gui_data[key] = parse_gui( value, params )
|
61
|
+
def json_fun( value )
|
62
|
+
JSON.parse( "[#{value}]" ).first
|
74
63
|
end
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
64
|
+
|
65
|
+
# Parses the gui data using params. Called from +init+.
|
66
|
+
def parse_gui( gui_data, params )
|
67
|
+
data_class = gui_data.class
|
68
|
+
if data_class == Array
|
69
|
+
gui_data.each_with_index do | item, i |
|
70
|
+
gui_data[i] = parse_gui( item, params )
|
71
|
+
end
|
72
|
+
elsif data_class == Hash
|
73
|
+
gui_data.each do | key, value |
|
74
|
+
gui_data[key] = parse_gui( value, params )
|
75
|
+
end
|
76
|
+
elsif data_class == Symbol
|
77
|
+
sym_str = gui_data.to_s
|
78
|
+
if sym_str.include? '.'
|
79
|
+
sym_arr = sym_str.split('.')
|
80
|
+
else
|
81
|
+
sym_arr = [ sym_str ]
|
82
|
+
end
|
83
|
+
return get_params( sym_arr, params )
|
84
|
+
elsif data_class == String and gui_data.strip.start_with?('function(')
|
85
|
+
return @parent.plugins[:client_pkg].squeeze( "a="+json_fun( gui_data.to_json ) )[2..-1]
|
86
|
+
end
|
87
|
+
return gui_data
|
81
88
|
end
|
82
|
-
return get_params( sym_arr, params )
|
83
|
-
elsif data_class == String and gui_data.strip.start_with?('function(')
|
84
|
-
return @parent.plugins[:client_pkg].squeeze( "a="+json_fun( gui_data.to_json ) )[2..-1]
|
85
|
-
end
|
86
|
-
return gui_data
|
87
|
-
end
|
88
89
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
90
|
+
# Searches the params hash for parameters whenever encountered a Symbol in the YAML.
|
91
|
+
def get_params( params_path, params )
|
92
|
+
item = params_path.shift
|
93
|
+
if params.class == Hash
|
94
|
+
has_str = params.has_key?( item )
|
95
|
+
has_sym = params.has_key?( item.to_sym )
|
96
|
+
item = item.to_sym if has_sym
|
97
|
+
if has_str or has_sym
|
98
|
+
if params_path.size == 0
|
99
|
+
return params[item]
|
100
|
+
else
|
101
|
+
return get_params( params_path, params[ item ] )
|
102
|
+
end
|
103
|
+
end
|
101
104
|
end
|
105
|
+
return ''
|
102
106
|
end
|
103
|
-
end
|
104
|
-
return ''
|
105
|
-
end
|
106
107
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
108
|
+
# Loads the YAML file.
|
109
|
+
# = Parameters
|
110
|
+
# +parent+:: The Plugin instance called from, use +self+ when constructing in a Plugin method.
|
111
|
+
# +yaml_src+:: The YAML source template for the GUI
|
112
|
+
def initialize( parent, yaml_src )
|
113
|
+
@parent = parent
|
114
|
+
@yaml_src = yaml_src
|
115
|
+
end
|
115
116
|
|
116
|
-
end
|
117
|
-
end
|
117
|
+
end
|
118
|
+
end
|
118
119
|
end
|