rsence 2.0.0.6.pre → 2.0.0.7.pre
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/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
@@ -7,45 +7,69 @@
|
|
7
7
|
##
|
8
8
|
|
9
9
|
module ::RSence
|
10
|
-
module Plugins
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
module Plugins
|
11
|
+
|
12
|
+
# Interface to enable plugins under a plugin.
|
13
|
+
# Just include this in your subclass of Plugin.
|
14
|
+
# The plugins loaded using this system are isolated from other plugins.
|
15
|
+
# To address them from this plugin, use @plugin_plugins instead of
|
16
|
+
# @plugins to address them.
|
17
|
+
module PluginPlugins
|
18
|
+
|
19
|
+
# Extended init, delegates calls to the sub-plugins.
|
20
|
+
def init
|
21
|
+
super
|
22
|
+
@plugin_plugins = RSence::PluginManager.new( [ bundle_path('plugins') ] )
|
23
|
+
end
|
24
|
+
|
25
|
+
# Extended open, delegates calls to the sub-plugins.
|
26
|
+
def open
|
27
|
+
super
|
28
|
+
@plugin_plugins.delegate(:open)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Extended close, delegates calls to the sub-plugins.
|
32
|
+
def close
|
33
|
+
super
|
34
|
+
@plugin_plugins.delegate(:close)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Extended flush, delegates calls to the sub-plugins.
|
38
|
+
def flush
|
39
|
+
super
|
40
|
+
@plugin_plugins.delegate(:flush)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Extended idle, delegates calls to the sub-plugins.
|
44
|
+
def idle( msg )
|
45
|
+
super
|
46
|
+
@plugin_plugins.delegate(:idle,msg)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Extended init_ses, delegates calls to the sub-plugins.
|
50
|
+
def init_ses( msg )
|
51
|
+
super
|
52
|
+
@plugin_plugins.delegate(:init_ses,msg)
|
53
|
+
end
|
54
|
+
|
55
|
+
# Extended restore_ses, delegates calls to the sub-plugins.
|
56
|
+
def restore_ses( msg )
|
57
|
+
super
|
58
|
+
@plugin_plugins.delegate(:restore_ses,msg)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Extended cloned_target, delegates calls to the sub-plugins.
|
62
|
+
def cloned_target( msg, source_session )
|
63
|
+
super
|
64
|
+
@plugin_plugins.delegate(:cloned_target,msg,source_session)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Extended cloned_source, delegates calls to the sub-plugins.
|
68
|
+
def cloned_source( msg, target_session )
|
69
|
+
super
|
70
|
+
@plugin_plugins.delegate(:cloned_source,msg,target_session)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
16
74
|
end
|
17
|
-
def open
|
18
|
-
super
|
19
|
-
@plugin_plugins.delegate(:open)
|
20
|
-
end
|
21
|
-
def close
|
22
|
-
super
|
23
|
-
@plugin_plugins.delegate(:close)
|
24
|
-
end
|
25
|
-
def flush
|
26
|
-
super
|
27
|
-
@plugin_plugins.delegate(:flush)
|
28
|
-
end
|
29
|
-
def idle( msg )
|
30
|
-
super
|
31
|
-
@plugin_plugins.delegate(:idle,msg)
|
32
|
-
end
|
33
|
-
def init_ses( msg )
|
34
|
-
super
|
35
|
-
@plugin_plugins.delegate(:init_ses,msg)
|
36
|
-
end
|
37
|
-
def restore_ses( msg )
|
38
|
-
super
|
39
|
-
@plugin_plugins.delegate(:restore_ses,msg)
|
40
|
-
end
|
41
|
-
def cloned_target( msg, source_session )
|
42
|
-
super
|
43
|
-
@plugin_plugins.delegate(:cloned_target,msg,source_session)
|
44
|
-
end
|
45
|
-
def cloned_source( msg, target_session )
|
46
|
-
super
|
47
|
-
@plugin_plugins.delegate(:cloned_source,msg,target_session)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
75
|
end
|
@@ -7,70 +7,70 @@
|
|
7
7
|
##
|
8
8
|
|
9
9
|
module ::RSence
|
10
|
-
module Plugins
|
11
|
-
# Include this module in your plugin class to automatically
|
12
|
-
# create and connect/disconnect an
|
13
|
-
# The plugin instance will have a @db Sequel object
|
14
|
-
# to the sqlite database automatically created
|
15
|
-
module PluginSqliteDB
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
10
|
+
module Plugins
|
11
|
+
# Include this module in your plugin class to automatically
|
12
|
+
# create and connect/disconnect an sqlite database.
|
13
|
+
# The plugin instance will have a @db Sequel object referring
|
14
|
+
# to the sqlite database automatically created
|
15
|
+
module PluginSqliteDB
|
16
|
+
|
17
|
+
# First calls superclass, then creates database directory and database.
|
18
|
+
# Then calls init_db_tables.
|
19
|
+
def init
|
20
|
+
super
|
21
|
+
db_dir = File.join( @path, 'db' )
|
22
|
+
unless File.directory?( db_dir )
|
23
|
+
Dir.mkdir( db_dir )
|
24
|
+
end
|
25
|
+
@db_path = File.join( db_dir, "#{@name}.db" )
|
26
|
+
unless File.exist?( @db_path )
|
27
|
+
@db = Sequel.sqlite( @db_path )
|
28
|
+
create_db_tables
|
29
|
+
@db.disconnect
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Automatically opens the database connection, then calls update_db.
|
34
|
+
def open
|
35
|
+
@db = Sequel.sqlite( @db_path )
|
36
|
+
update_db
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
# Automatically closes (disconnects) the database. Calls flush_db before closing.
|
41
|
+
def close
|
42
|
+
flush_db
|
43
|
+
@db.disconnect
|
44
|
+
super
|
45
|
+
end
|
46
|
+
|
47
|
+
# Extend this method to do something immediately after the @db object is assigned.
|
48
|
+
# An usage scenario would be updating some tables or deleting some junk rows.
|
49
|
+
def update_db
|
50
|
+
end
|
51
|
+
|
52
|
+
# Extend this method to do something immediately before the @db object is disconnected.
|
53
|
+
# An usage scenario would be deleting some junk rows or writing some pending data in memory into the database.
|
54
|
+
def flush_db
|
55
|
+
end
|
56
|
+
|
57
|
+
# Extend this method to define tables or initial data for the tables.
|
58
|
+
# It's called once, when the database is created.
|
59
|
+
#
|
60
|
+
# NOTE: In a future reversion, tables might be defined from a configuration file.
|
61
|
+
#
|
62
|
+
# = Usage:
|
63
|
+
# @db.create_table :my_table do
|
64
|
+
# primary_key :id
|
65
|
+
# String :my_text_column
|
66
|
+
# end
|
67
|
+
# my_table = @db[:my_table]
|
68
|
+
# my_table.insert(:my_text_column => 'Some text')
|
69
|
+
#
|
70
|
+
def create_db_tables
|
71
|
+
end
|
72
|
+
|
30
73
|
end
|
31
74
|
|
32
75
|
end
|
33
|
-
|
34
|
-
# Automatically opens the database connection, then calls update_db.
|
35
|
-
def open
|
36
|
-
@db = Sequel.sqlite( @db_path )
|
37
|
-
update_db
|
38
|
-
super
|
39
|
-
end
|
40
|
-
|
41
|
-
# Automatically closes (disconnects) the database. Calls flush_db before closing.
|
42
|
-
def close
|
43
|
-
flush_db
|
44
|
-
@db.disconnect
|
45
|
-
super
|
46
|
-
end
|
47
|
-
|
48
|
-
# Extend this method to do something immediately after the @db object is assigned.
|
49
|
-
# An usage scenario would be updating some tables or deleting some junk rows.
|
50
|
-
def update_db
|
51
|
-
end
|
52
|
-
|
53
|
-
# Extend this method to do something immediately before the @db object is disconnected.
|
54
|
-
# An usage scenario would be deleting some junk rows or writing some pending data in memory into the database.
|
55
|
-
def flush_db
|
56
|
-
end
|
57
|
-
|
58
|
-
# Extend this method to define tables or initial data for the tables.
|
59
|
-
# It's called once, when the database is created.
|
60
|
-
#
|
61
|
-
# NOTE: In a future reversion, tables might be defined from a configuration file.
|
62
|
-
#
|
63
|
-
# = Usage:
|
64
|
-
# @db.create_table :my_table do
|
65
|
-
# primary_key :id
|
66
|
-
# String :my_text_column
|
67
|
-
# end
|
68
|
-
# my_table = @db[:my_table]
|
69
|
-
# my_table.insert(:my_text_column => 'Some text')
|
70
|
-
#
|
71
|
-
def create_db_tables
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
76
76
|
end
|
data/lib/plugins/plugin_util.rb
CHANGED
@@ -7,110 +7,101 @@
|
|
7
7
|
##
|
8
8
|
|
9
9
|
module ::RSence
|
10
|
-
module Plugins
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
10
|
+
module Plugins
|
11
|
+
|
12
|
+
# This module contains common functionality for both the Plugin and
|
13
|
+
# the Servlet base classes.
|
14
|
+
module PluginUtil
|
15
|
+
|
16
|
+
include RSence
|
17
|
+
|
18
|
+
# Extend to do any initial configuration. Not doing anything by default.
|
19
|
+
def init
|
20
|
+
end
|
21
|
+
|
22
|
+
# Extend this method to open objects like streams and database connections.
|
23
|
+
# It is called when everything is constructed after all plugins are loaded.
|
24
|
+
def open
|
25
|
+
end
|
26
|
+
|
27
|
+
# Extend to save your plugin state or store any data that needs to be
|
28
|
+
# persistent. It's always called before close, but doesn't necessarily mean
|
29
|
+
# a close call is imminent.
|
30
|
+
def flush
|
31
|
+
end
|
32
|
+
|
33
|
+
# Extend this method to close objects like streams and database connections.
|
34
|
+
# It's called when plugins are about to be destructed, so don't expect any
|
35
|
+
# calls after it has been called. When this method is called, it's the last
|
36
|
+
# chance to save persistent data before being destructed, so implement
|
37
|
+
# the +#flush+ method for primarily storing data.
|
38
|
+
def close
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns the contents of the file given as +path+.
|
42
|
+
#
|
43
|
+
# The plugin bundle's path is used as the prefix, unless +path+ starts with '/' or '..'
|
44
|
+
#
|
45
|
+
# If the file doesn't exist, it returns +false+.
|
46
|
+
def file_read( path )
|
47
|
+
path = bundle_path( path )
|
48
|
+
return false unless File.exist?( path )
|
49
|
+
return File.read( path )
|
50
|
+
end
|
51
|
+
|
52
|
+
def yaml_read( path )
|
53
|
+
file_data = file_read( path )
|
54
|
+
if not file_data
|
55
|
+
return false
|
56
|
+
else
|
57
|
+
return YAML.load( file_data )
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Writes the +data+ into the file +path+.
|
62
|
+
#
|
63
|
+
# The plugin bundle's path is used as the prefix, unless +path+ starts with '/' or '..'
|
64
|
+
#
|
65
|
+
# It returns a success code (+false+ for failure and +true+ for success).
|
66
|
+
def file_write( path, data )
|
67
|
+
path = bundle_path( path )
|
68
|
+
begin
|
69
|
+
datafile = File.open( path, 'wb' )
|
70
|
+
datafile.write( data )
|
71
|
+
datafile.close
|
72
|
+
return true
|
73
|
+
rescue => e
|
74
|
+
warn "file_write error for path #{path} #{e}"
|
75
|
+
return false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
alias file_save file_write
|
79
|
+
|
80
|
+
# Makes a full path using the plugin bundle as the 'local path'.
|
81
|
+
# The (optional) +prefix+ is a subdirectory in the bundle,
|
82
|
+
# the +suffix+ is the file extension.
|
83
|
+
def bundle_path( path, prefix=false, suffix=false )
|
84
|
+
if suffix
|
85
|
+
path = "#{path}#{suffix}" unless path.end_with?(suffix)
|
86
|
+
end
|
87
|
+
if prefix
|
88
|
+
path = File.join( prefix, path )
|
89
|
+
end
|
90
|
+
path = File.expand_path( path, @path )
|
91
|
+
return path
|
92
|
+
end
|
93
|
+
|
94
|
+
def compose_plugin_path( *args )
|
95
|
+
warn "'compose_plugin_path' is deprecated. Use 'bundle_path' instead."
|
96
|
+
bundle_path( *args )
|
97
|
+
end
|
98
|
+
|
99
|
+
# Helper method to return the time formatted according to the HTTP RFC
|
100
|
+
def httime(time=false)
|
101
|
+
time = Time.new unless time
|
102
|
+
return time.gmtime.strftime('%a, %d %b %Y %H:%M:%S %Z')
|
103
|
+
end
|
104
|
+
|
66
105
|
end
|
67
106
|
end
|
68
|
-
|
69
|
-
def method_undefined?( *args )
|
70
|
-
puts "Method undefined: #{args.inspect}"
|
71
|
-
end
|
72
|
-
|
73
|
-
# Writes the +data+ into the file +path+.
|
74
|
-
#
|
75
|
-
# The plugin bundle's path is used as the prefix, unless +path+ starts with '/' or '..'
|
76
|
-
#
|
77
|
-
# It returns a success code (+false+ for failure and +true+ for success).
|
78
|
-
def file_write( path, data )
|
79
|
-
path = bundle_path( path )
|
80
|
-
begin
|
81
|
-
datafile = File.open( path, 'wb' )
|
82
|
-
datafile.write( data )
|
83
|
-
datafile.close
|
84
|
-
return true
|
85
|
-
rescue => e
|
86
|
-
warn "file_write error for path #{path} #{e}"
|
87
|
-
return false
|
88
|
-
end
|
89
|
-
end
|
90
|
-
alias file_save file_write
|
91
|
-
|
92
|
-
# Makes a full path using the plugin bundle as the 'local path'.
|
93
|
-
# The (optional) +prefix+ is a subdirectory in the bundle,
|
94
|
-
# the +suffix+ is the file extension.
|
95
|
-
def bundle_path( path, prefix=false, suffix=false )
|
96
|
-
if suffix
|
97
|
-
path = "#{path}#{suffix}" unless path.end_with?(suffix)
|
98
|
-
end
|
99
|
-
if prefix
|
100
|
-
path = File.join( prefix, path )
|
101
|
-
end
|
102
|
-
path = File.expand_path( path, @path )
|
103
|
-
return path
|
104
|
-
end
|
105
|
-
|
106
|
-
alias compose_plugin_path bundle_path
|
107
|
-
|
108
|
-
# Helper method to return the time formatted according to the HTTP RFC
|
109
|
-
def httime(time=false)
|
110
|
-
time = Time.new unless time
|
111
|
-
return time.gmtime.strftime('%a, %d %b %Y %H:%M:%S %Z')
|
112
|
-
end
|
113
|
-
|
114
|
-
end
|
115
|
-
end
|
116
107
|
end
|
@@ -5,166 +5,114 @@
|
|
5
5
|
# You should have received a copy of the GNU General Public License along
|
6
6
|
# with this software package. If not, contact licensing@riassence.com
|
7
7
|
##
|
8
|
-
# if RUBY_VERSION.to_f >= 1.9
|
9
|
-
# # with_module comes from:
|
10
|
-
# # http://coderrr.wordpress.com/2009/05/18/dynamically-adding-a-constant-nesting-in-ruby-1-9/
|
11
|
-
# module Kernel
|
12
|
-
# def with_module(*consts, &blk)
|
13
|
-
# slf = blk.binding.eval('self')
|
14
|
-
# l = lambda { slf.instance_eval(&blk) }
|
15
|
-
# consts.reverse.inject(l) {|l, k| lambda { k.class_eval(&l) } }.call
|
16
|
-
# end
|
17
|
-
# end
|
18
|
-
# end
|
19
|
-
|
20
|
-
# def bundle_loader( params )
|
21
|
-
# src_path = params[:src_path]
|
22
|
-
# mod = Module.new do |m|
|
23
|
-
# @@bundle_path = params[:bundle_path ]
|
24
|
-
# @@bundle_name = params[:bundle_name ]
|
25
|
-
# @@bundle_info = params[:bundle_info ]
|
26
|
-
# @@plugin_manager = params[:plugin_manager]
|
27
|
-
# def m.bundle_path; @@bundle_path; end
|
28
|
-
# def m.bundle_name; @@bundle_name; end
|
29
|
-
# def m.bundle_info; @@bundle_info; end
|
30
|
-
# def m.bundle_manager; @@bundle_manager; end
|
31
|
-
# begin
|
32
|
-
# # if RUBY_VERSION.to_f >= 1.9
|
33
|
-
# # # with_module(m) do
|
34
|
-
# # src = File.read(src_path)
|
35
|
-
# # self.module_eval(
|
36
|
-
# # <<-SRC
|
37
|
-
# # puts %{--- bundle_path: #{bundle_path.inspect}}
|
38
|
-
# # #{src}
|
39
|
-
# # SRC
|
40
|
-
# # )
|
41
|
-
# # # end
|
42
|
-
# # else
|
43
|
-
# if params[:bundle_info][:inits_self] == false or RUBY_VERSION.to_f >= 1.9
|
44
|
-
# m::module_eval( File.read(src_path) )
|
45
|
-
# elsif params[:bundle_info][:reloadable] == false
|
46
|
-
# require src_path[0..-4]
|
47
|
-
# else
|
48
|
-
# load src_path
|
49
|
-
# end
|
50
|
-
# # end
|
51
|
-
# rescue => e
|
52
|
-
# @@plugin_manager.plugin_error(
|
53
|
-
# e,
|
54
|
-
# 'BundleLoaderError',
|
55
|
-
# "An error occurred while loading the plugin bundle #{@@bundle_name}.",
|
56
|
-
# @@bundle_path
|
57
|
-
# )
|
58
|
-
# end
|
59
|
-
# end
|
60
|
-
# return mod
|
61
|
-
# end
|
62
|
-
#
|
63
|
-
|
64
|
-
module RSence
|
65
|
-
|
66
8
|
require 'plugins/plugins'
|
67
9
|
|
68
|
-
|
69
|
-
## PluginManager is the service that loads and provides method delegation
|
70
|
-
## amongst all installed plugins.
|
71
|
-
##
|
72
|
-
## = Usage
|
73
|
-
## plugin_paths = [ 'plugins', '/home/me/rsence/plugins' ]
|
74
|
-
## myPluginManager = RSence::PluginManager.new( plugin_paths )
|
75
|
-
##
|
76
|
-
class PluginManager
|
77
|
-
|
78
|
-
attr_reader :transporter, :sessions
|
10
|
+
module RSence
|
79
11
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
12
|
+
## = Abstract
|
13
|
+
## PluginManager is the service that loads and provides method delegation
|
14
|
+
## amongst its plugin bundles.
|
15
|
+
##
|
16
|
+
## = Usage
|
17
|
+
## plugin_paths = [ 'plugins', '/home/me/rsence/plugins' ]
|
18
|
+
## myPluginManager = RSence::PluginManager.new( plugin_paths )
|
19
|
+
##
|
20
|
+
class PluginManager
|
21
|
+
|
22
|
+
attr_reader :transporter, :sessions
|
23
|
+
|
24
|
+
# Initialize with a list of directories as plugin_paths.
|
25
|
+
# It's an array containing all plugin directories to scan.
|
26
|
+
def initialize( plugin_paths, transporter=nil, autoreload=false, name_prefix=false )
|
27
|
+
if transporter
|
28
|
+
@transporter = transporter
|
29
|
+
@sessions = transporter.sessions
|
30
|
+
end
|
31
|
+
@name_prefix = name_prefix
|
32
|
+
@plugin_paths = plugin_paths
|
33
|
+
puts "Loading #{name_prefix+' ' if name_prefix}plugins..." if RSence.args[:verbose]
|
34
|
+
scan_plugins
|
35
|
+
puts "Plugins #{name_prefix+' ' if name_prefix}loaded." if RSence.args[:verbose]
|
36
|
+
if autoreload
|
37
|
+
@thr = Thread.new do
|
38
|
+
Thread.pass
|
39
|
+
while true
|
40
|
+
begin
|
41
|
+
changed_plugins!
|
42
|
+
rescue => e
|
43
|
+
warn e.inspect
|
44
|
+
end
|
45
|
+
sleep 3
|
99
46
|
end
|
100
|
-
sleep 3
|
101
47
|
end
|
102
48
|
end
|
103
49
|
end
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
50
|
+
|
51
|
+
# By default, calling a method not defined calls a plugin of that name
|
52
|
+
def method_missing( sym, *args, &block )
|
53
|
+
if @registry.has_key?(sym)
|
54
|
+
if args == [] and block == nil
|
55
|
+
return @registry[sym]
|
56
|
+
elsif block == nil
|
57
|
+
call( sym, *args )
|
58
|
+
end
|
112
59
|
end
|
113
60
|
end
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
138
|
-
end
|
139
|
-
else
|
140
|
-
if not @registry.has_key?( bundle_name.to_sym )
|
141
|
-
puts "Loading bundle #{bundle_name}..."
|
142
|
-
online_status = @transporter.online?
|
143
|
-
@transporter.online = false
|
144
|
-
load_bundle( bundle_path, bundle_name.to_sym, bundle_name+'.rb' )
|
145
|
-
call( bundle_name.to_sym, :open )
|
146
|
-
@transporter.online = online_status
|
147
|
-
if RSence.args[:say]
|
148
|
-
Thread.new do
|
149
|
-
Thread.pass
|
150
|
-
system(%{say "Loaded #{bundle_name.to_s}."})
|
61
|
+
|
62
|
+
# Checks for changed plugin bundles and unloads/loads/reloads them accordingly.
|
63
|
+
def changed_plugins!
|
64
|
+
@plugin_paths.each do |path|
|
65
|
+
next unless File.directory? path
|
66
|
+
Dir.entries(path).each do |bundle_name|
|
67
|
+
next if bundle_name =~ /&\./
|
68
|
+
bundle_path = File.expand_path( File.join( path, bundle_name ) )
|
69
|
+
next unless File.directory?( bundle_path )
|
70
|
+
bundle_file = bundle_name+'.rb'
|
71
|
+
next unless File.exists?( File.join( bundle_path, bundle_file ) )
|
72
|
+
if File.exists?( File.join( bundle_path, 'disabled' ) )
|
73
|
+
if @registry.has_key?( bundle_name.to_sym )
|
74
|
+
puts "Disabling bundle #{bundle_name}..."
|
75
|
+
online_status = @transporter.online?
|
76
|
+
@transporter.online = false
|
77
|
+
unload_bundle( bundle_name.to_sym )
|
78
|
+
@transporter.online = online_status
|
79
|
+
if RSence.args[:say]
|
80
|
+
Thread.new do
|
81
|
+
Thread.pass
|
82
|
+
system(%{say "Unloaded #{bundle_name.to_s}."})
|
83
|
+
end
|
151
84
|
end
|
152
85
|
end
|
153
86
|
else
|
154
|
-
|
155
|
-
|
156
|
-
if info[:reloadable] and plugin_changed?( bundle_name.to_sym )
|
157
|
-
puts "Bundle #{bundle_name} has changed, reloading..."
|
87
|
+
if not @registry.has_key?( bundle_name.to_sym )
|
88
|
+
puts "Loading bundle #{bundle_name}..."
|
158
89
|
online_status = @transporter.online?
|
159
90
|
@transporter.online = false
|
160
|
-
unload_bundle( bundle_name.to_sym )
|
161
91
|
load_bundle( bundle_path, bundle_name.to_sym, bundle_name+'.rb' )
|
162
92
|
call( bundle_name.to_sym, :open )
|
163
93
|
@transporter.online = online_status
|
164
94
|
if RSence.args[:say]
|
165
95
|
Thread.new do
|
166
96
|
Thread.pass
|
167
|
-
system(%{say "
|
97
|
+
system(%{say "Loaded #{bundle_name.to_s}."})
|
98
|
+
end
|
99
|
+
end
|
100
|
+
else
|
101
|
+
# puts "Checking if bundle #{bundle_name} is changed..."
|
102
|
+
info = @info[bundle_name.to_sym]
|
103
|
+
if info[:reloadable] and plugin_changed?( bundle_name.to_sym )
|
104
|
+
puts "Bundle #{bundle_name} has changed, reloading..."
|
105
|
+
online_status = @transporter.online?
|
106
|
+
@transporter.online = false
|
107
|
+
unload_bundle( bundle_name.to_sym )
|
108
|
+
load_bundle( bundle_path, bundle_name.to_sym, bundle_name+'.rb' )
|
109
|
+
call( bundle_name.to_sym, :open )
|
110
|
+
@transporter.online = online_status
|
111
|
+
if RSence.args[:say]
|
112
|
+
Thread.new do
|
113
|
+
Thread.pass
|
114
|
+
system(%{say "Reloaded #{bundle_name.to_s}."})
|
115
|
+
end
|
168
116
|
end
|
169
117
|
end
|
170
118
|
end
|
@@ -172,340 +120,351 @@ class PluginManager
|
|
172
120
|
end
|
173
121
|
end
|
174
122
|
end
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
123
|
+
|
124
|
+
# Unloads the plugin bundle named +bundle_name+
|
125
|
+
def unload_bundle( bundle_name )
|
126
|
+
puts "unloading bundle: #{bundle_name.inspect}" if RSence.args[:debug]
|
127
|
+
if @registry.has_key?( bundle_name )
|
128
|
+
call( bundle_name, :flush )
|
129
|
+
call( bundle_name, :close )
|
130
|
+
@registry.delete( bundle_name )
|
131
|
+
@aliases.each do |a_name,b_name|
|
132
|
+
if b_name == bundle_name
|
133
|
+
@aliases.delete( a_name )
|
134
|
+
end
|
135
|
+
end
|
136
|
+
if @servlets.include?( bundle_name )
|
137
|
+
@servlets.delete( bundle_name )
|
138
|
+
end
|
139
|
+
if @info.include?( bundle_name )
|
140
|
+
@info.delete( bundle_name )
|
186
141
|
end
|
187
|
-
end
|
188
|
-
if @servlets.include?( bundle_name )
|
189
|
-
@servlets.delete( bundle_name )
|
190
|
-
end
|
191
|
-
if @info.include?( bundle_name )
|
192
|
-
@info.delete( bundle_name )
|
193
142
|
end
|
194
143
|
end
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
# Top-level method for scanning all plugin directories.
|
205
|
-
# Clears previously loaded plugins.
|
206
|
-
def scan_plugins
|
207
|
-
@registry = {}
|
208
|
-
@info = {}
|
209
|
-
@aliases = {}
|
210
|
-
@servlets = []
|
211
|
-
@plugin_paths.each do |path|
|
212
|
-
next unless File.directory? path
|
213
|
-
scan_plugindir( path )
|
144
|
+
|
145
|
+
# Returns true, if a plugin bundle has changed.
|
146
|
+
# Only compares timestamp, not checksum.
|
147
|
+
def plugin_changed?( plugin_name )
|
148
|
+
info = @info[plugin_name]
|
149
|
+
last_changed = info[:last_changed]
|
150
|
+
newest_change = most_recent( info[:path], last_changed )
|
151
|
+
return last_changed < newest_change
|
214
152
|
end
|
215
|
-
delegate( :open )
|
216
|
-
end
|
217
153
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
# - Skips bundles containing a file or directory named 'disabled'
|
229
|
-
def scan_plugindir( path )
|
230
|
-
Dir.entries(path).each do |bundle_name|
|
231
|
-
next if bundle_name[0].chr == '.'
|
232
|
-
bundle_path = File.expand_path( File.join( path, bundle_name ) )
|
233
|
-
next unless File.directory?( bundle_path )
|
234
|
-
bundle_file = bundle_name+'.rb'
|
235
|
-
if not File.exists?( File.join( bundle_path, bundle_file ) )
|
236
|
-
bundle_file = 'main.rb'
|
237
|
-
next unless File.exists?( File.join( bundle_path, bundle_file ) )
|
154
|
+
# Top-level method for scanning all plugin directories.
|
155
|
+
# Clears previously loaded plugins.
|
156
|
+
def scan_plugins
|
157
|
+
@registry = {}
|
158
|
+
@info = {}
|
159
|
+
@aliases = {}
|
160
|
+
@servlets = []
|
161
|
+
@plugin_paths.each do |path|
|
162
|
+
next unless File.directory? path
|
163
|
+
scan_plugindir( path )
|
238
164
|
end
|
239
|
-
|
165
|
+
delegate( :open )
|
166
|
+
end
|
167
|
+
|
168
|
+
# Returns the registry data for plugin bundle +plugin_name+
|
169
|
+
def registry( plugin_name )
|
170
|
+
return @registry[ plugin_name ]
|
171
|
+
end
|
172
|
+
alias [] registry
|
173
|
+
|
174
|
+
# Scans a directory of plugins, calls +load_plugin+ for bundles that match
|
175
|
+
# the definition of a plugin bundle.
|
176
|
+
# - Skips bundles starting with a dot
|
177
|
+
# - Skips bundles without a ruby source file with the same
|
178
|
+
# name as the directory (plus '.rb').
|
179
|
+
# - Skips bundles containing a file or directory named 'disabled'
|
180
|
+
def scan_plugindir( path )
|
181
|
+
Dir.entries(path).each do |bundle_name|
|
182
|
+
next if bundle_name[0].chr == '.'
|
183
|
+
bundle_path = File.expand_path( File.join( path, bundle_name ) )
|
184
|
+
next unless File.directory?( bundle_path )
|
185
|
+
bundle_file = bundle_name+'.rb'
|
186
|
+
if not File.exists?( File.join( bundle_path, bundle_file ) )
|
187
|
+
bundle_file = 'main.rb'
|
188
|
+
next unless File.exists?( File.join( bundle_path, bundle_file ) )
|
189
|
+
end
|
190
|
+
next if File.exists?( File.join( bundle_path, 'disabled' ) )
|
240
191
|
|
241
|
-
|
192
|
+
load_bundle( bundle_path, bundle_name.to_sym, bundle_file )
|
193
|
+
end
|
242
194
|
end
|
243
|
-
end
|
244
195
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
196
|
+
# Finds the most recent file in the path
|
197
|
+
def most_recent( bundle_path, newest_date=0 )
|
198
|
+
path_date = File.stat( bundle_path ).mtime.to_i
|
199
|
+
is_dir = File.directory?( bundle_path )
|
200
|
+
if path_date > newest_date and not is_dir
|
201
|
+
# puts "File is newer: #{bundle_path}"
|
202
|
+
newest_date = path_date
|
203
|
+
end
|
204
|
+
if is_dir
|
205
|
+
Dir.entries( bundle_path ).each do |entry_name|
|
206
|
+
next if entry_name[0].chr == '.'
|
207
|
+
full_path = File.join( bundle_path, entry_name )
|
208
|
+
unless File.directory?( full_path )
|
209
|
+
next unless entry_name.include?('.') and ['yaml','rb'].include?( entry_name.split('.')[-1] )
|
210
|
+
end
|
211
|
+
newest_date = most_recent( full_path, newest_date )
|
259
212
|
end
|
260
|
-
newest_date = most_recent( full_path, newest_date )
|
261
213
|
end
|
214
|
+
return newest_date
|
262
215
|
end
|
263
|
-
return newest_date
|
264
|
-
end
|
265
216
|
|
266
|
-
|
267
|
-
|
217
|
+
# Gets plugin information
|
218
|
+
def bundle_info( bundle_path )
|
268
219
|
|
269
|
-
|
220
|
+
bundle_name = File.split( bundle_path )[1]
|
270
221
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
222
|
+
# Default bundle information
|
223
|
+
info = {
|
224
|
+
# The human-readable product name of the package
|
225
|
+
:title => bundle_name.capitalize,
|
275
226
|
|
276
|
-
|
277
|
-
|
227
|
+
# The human-readable version of the package
|
228
|
+
:version => '0.0.0',
|
278
229
|
|
279
|
-
|
280
|
-
|
230
|
+
# A brief description of the package (rdoc formatting supported)
|
231
|
+
:description => 'No Description given',
|
281
232
|
|
282
|
-
|
283
|
-
|
233
|
+
# A flag (when false) prevents the plugin from automatically reload when changed.
|
234
|
+
:reloadable => true,
|
284
235
|
|
285
|
-
|
286
|
-
|
287
|
-
|
236
|
+
# A flag (when false) enables automatic construction
|
237
|
+
# of the Plugin and Servlet classes contained.
|
238
|
+
:inits_self => false,
|
288
239
|
|
289
|
-
|
290
|
-
|
240
|
+
# System version requirement.
|
241
|
+
:sys_version => '>= 1.0.0',
|
291
242
|
|
292
|
-
|
293
|
-
|
243
|
+
# Path to bundle
|
244
|
+
:path => bundle_path,
|
294
245
|
|
295
|
-
|
296
|
-
|
246
|
+
# Name of bundle
|
247
|
+
:name => bundle_name.to_sym,
|
297
248
|
|
298
|
-
|
299
|
-
|
249
|
+
# Last change
|
250
|
+
:last_changed => most_recent( bundle_path )
|
300
251
|
|
301
|
-
|
252
|
+
}
|
302
253
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
254
|
+
info_path = File.join( bundle_path, 'info.yaml' )
|
255
|
+
if File.exists?( info_path )
|
256
|
+
info_yaml = YAML.load( File.read( info_path ) )
|
257
|
+
info_yaml.each do |info_key,info_value|
|
258
|
+
info[ info_key.to_sym ] = info_value
|
259
|
+
end
|
308
260
|
end
|
309
|
-
|
310
|
-
return info
|
261
|
+
return info
|
311
262
|
|
312
|
-
end
|
313
|
-
|
314
|
-
# Loads a plugin bundle.
|
315
|
-
def load_bundle( bundle_path, bundle_name, bundle_file )
|
316
|
-
puts "loading bundle: #{bundle_name.inspect}" if RSence.args[:debug]
|
317
|
-
if @registry.has_key?( bundle_name.to_sym )
|
318
|
-
warn "Warning: Bundle #{bundle_name} already loaded."
|
319
|
-
return
|
320
263
|
end
|
264
|
+
|
265
|
+
# Loads a plugin bundle.
|
266
|
+
def load_bundle( bundle_path, bundle_name, bundle_file )
|
267
|
+
puts "loading bundle: #{bundle_name.inspect}" if RSence.args[:debug]
|
268
|
+
if @registry.has_key?( bundle_name.to_sym )
|
269
|
+
warn "Warning: Bundle #{bundle_name} already loaded."
|
270
|
+
return
|
271
|
+
end
|
321
272
|
|
322
|
-
|
273
|
+
bundle_file_path = File.join( bundle_path, bundle_file )
|
323
274
|
|
324
|
-
|
275
|
+
bundle_info = bundle_info( bundle_path )
|
325
276
|
|
326
|
-
|
277
|
+
@info[bundle_name.to_sym] = bundle_info
|
327
278
|
|
328
|
-
|
279
|
+
bundle_src = File.read( bundle_file_path )
|
329
280
|
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
281
|
+
module_ns = Plugins.bundle_loader( {
|
282
|
+
:bundle_path => bundle_path,
|
283
|
+
:bundle_name => bundle_name,
|
284
|
+
:bundle_info => bundle_info,
|
285
|
+
:plugin_manager => self,
|
286
|
+
:src_path => bundle_file_path,
|
287
|
+
:src => bundle_src
|
288
|
+
} )
|
338
289
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
290
|
+
if bundle_info[:inits_self]
|
291
|
+
warn "Plugins can't init them self anymore. Please fix plugin: #{bundle_name.inspect}"
|
292
|
+
else
|
293
|
+
module_ns.constants.each do |module_const_name|
|
294
|
+
module_const = module_ns.const_get( module_const_name )
|
295
|
+
if module_const.class == Class
|
296
|
+
bundle_type = module_const.bundle_type
|
297
|
+
if [:Servlet, :Plugin, :GUIPlugin].include? bundle_type
|
298
|
+
bundle_inst = module_const.new( bundle_name, bundle_info, bundle_path, self )
|
299
|
+
bundle_inst.register( bundle_name ) if [ :Plugin, :GUIPlugin ].include?( bundle_type )
|
300
|
+
break
|
301
|
+
else
|
302
|
+
warn "Can't init class: #{module_const.to_s}"
|
303
|
+
break
|
304
|
+
end
|
350
305
|
else
|
351
|
-
warn "
|
352
|
-
break
|
306
|
+
warn "module_const.class: #{module_const.class.inspect}"
|
353
307
|
end
|
354
|
-
else
|
355
|
-
warn "module_const.class: #{module_const.class.inspect}"
|
356
308
|
end
|
357
309
|
end
|
358
310
|
end
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
311
|
+
|
312
|
+
# Registers plugin class +inst+ into the registry using +bundle_name+
|
313
|
+
def register_bundle( inst, bundle_name )
|
314
|
+
bundle_name = bundle_name.to_sym
|
315
|
+
if @registry.has_key?( bundle_name )
|
316
|
+
if registry[ bundle_name ] != inst
|
317
|
+
warn "Tried to register a conflicting bundle name: #{bundle_name.inspect}; ignoring"
|
318
|
+
else
|
319
|
+
warn "Use @plugins.register_alias to register more than one name per plugin."
|
320
|
+
register_alias( inst.name.to_sym, bundle_name )
|
321
|
+
end
|
366
322
|
else
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
@registry[ bundle_name ] = inst
|
373
|
-
if inst.respond_to?( :match ) and ( inst.respond_to?( :get ) or inst.respond_to?( :post ) )
|
374
|
-
puts " --- servlet: #{bundle_name.inspect}, #{inst.respond_to?(:match)}, #{inst.post}" if bundle_name == :welcome
|
375
|
-
@servlets.push( bundle_name )
|
376
|
-
end
|
377
|
-
end
|
378
|
-
end
|
379
|
-
|
380
|
-
def register_alias( bundle_name, alias_name )
|
381
|
-
if @aliases.has_key?( alias_name.to_sym )
|
382
|
-
warn "Alias already taken: #{alias_name.inspect}"
|
383
|
-
else
|
384
|
-
@aliases[ alias_name ] = bundle_name.to_sym
|
385
|
-
end
|
386
|
-
end
|
387
|
-
|
388
|
-
def plugin_error( e, err_location, err_location_descr, eval_repl=false )
|
389
|
-
err_msg = [
|
390
|
-
"*"*40,
|
391
|
-
err_location,
|
392
|
-
err_location_descr,
|
393
|
-
"#{e.class.to_s}, #{e.message}",
|
394
|
-
"Backtrace:",
|
395
|
-
"\t"+e.backtrace.join("\n\t"),
|
396
|
-
"*"*40
|
397
|
-
].join("\n")+"\n"
|
398
|
-
if eval_repl
|
399
|
-
puts
|
400
|
-
puts "plugin: #{eval_repl}"
|
401
|
-
puts
|
402
|
-
err_msg = err_msg.gsub(/^\t\(eval\)\:/s,"\t#{eval_repl}:")
|
403
|
-
end
|
404
|
-
$stderr.write( err_msg )
|
405
|
-
end
|
406
|
-
|
407
|
-
def match_servlet_uri( uri, req_type=:get )
|
408
|
-
match_score = {}
|
409
|
-
@servlets.each do | servlet_name |
|
410
|
-
servlet = @registry[ servlet_name ]
|
411
|
-
next unless servlet.respond_to?( req_type )
|
412
|
-
begin
|
413
|
-
if servlet.match( uri, req_type )
|
414
|
-
score = servlet.score
|
415
|
-
match_score[ score ] = [] unless match_score.has_key? score
|
416
|
-
match_score[ score ].push( servlet_name )
|
323
|
+
inst.init if inst.respond_to? :init and not inst.inited
|
324
|
+
@registry[ bundle_name ] = inst
|
325
|
+
if inst.respond_to?( :match ) and ( inst.respond_to?( :get ) or inst.respond_to?( :post ) )
|
326
|
+
puts " --- servlet: #{bundle_name.inspect}, #{inst.respond_to?(:match)}, #{inst.post}" if bundle_name == :welcome
|
327
|
+
@servlets.push( bundle_name )
|
417
328
|
end
|
418
|
-
rescue => e
|
419
|
-
plugin_error(
|
420
|
-
e,
|
421
|
-
"RSence::PluginManager.match_servlet_uri",
|
422
|
-
"servlet: #{servlet_name.inspect}, req_type: #{req_type.inspect}, uri: #{uri.inspect}",
|
423
|
-
servlet_name
|
424
|
-
)
|
425
329
|
end
|
426
330
|
end
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
matches_best = match_score[ match_scores[0] ]
|
433
|
-
if matches_best.size > 1
|
434
|
-
matches_best = matches_best[ rand( matches_best.size ) ]
|
331
|
+
|
332
|
+
# Registers alias name for a plugin bundle.
|
333
|
+
def register_alias( bundle_name, alias_name )
|
334
|
+
if @aliases.has_key?( alias_name.to_sym )
|
335
|
+
warn "Alias already taken: #{alias_name.inspect}"
|
435
336
|
else
|
436
|
-
|
337
|
+
@aliases[ alias_name ] = bundle_name.to_sym
|
437
338
|
end
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
339
|
+
end
|
340
|
+
|
341
|
+
# Prettier error handling.
|
342
|
+
def plugin_error( e, err_location, err_location_descr, eval_repl=false )
|
343
|
+
err_msg = [
|
344
|
+
"*"*40,
|
345
|
+
err_location,
|
346
|
+
err_location_descr,
|
347
|
+
"#{e.class.to_s}, #{e.message}",
|
348
|
+
"Backtrace:",
|
349
|
+
"\t"+e.backtrace.join("\n\t"),
|
350
|
+
"*"*40
|
351
|
+
].join("\n")+"\n"
|
352
|
+
if eval_repl
|
353
|
+
puts
|
354
|
+
puts "plugin: #{eval_repl}"
|
355
|
+
puts
|
356
|
+
err_msg = err_msg.gsub(/^\t\(eval\)\:/s,"\t#{eval_repl}:")
|
443
357
|
end
|
444
|
-
|
358
|
+
$stderr.write( err_msg )
|
445
359
|
end
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
360
|
+
|
361
|
+
# Search servlets that match the +uri+ and +req_type+
|
362
|
+
def match_servlet_uri( uri, req_type=:get )
|
363
|
+
match_score = {}
|
364
|
+
@servlets.each do | servlet_name |
|
365
|
+
servlet = @registry[ servlet_name ]
|
366
|
+
next unless servlet.respond_to?( req_type )
|
451
367
|
begin
|
452
|
-
|
368
|
+
if servlet.match( uri, req_type )
|
369
|
+
score = servlet.score
|
370
|
+
match_score[ score ] = [] unless match_score.has_key? score
|
371
|
+
match_score[ score ].push( servlet_name )
|
372
|
+
end
|
453
373
|
rescue => e
|
454
374
|
plugin_error(
|
455
375
|
e,
|
456
|
-
"RSence::PluginManager.
|
457
|
-
"
|
458
|
-
|
376
|
+
"RSence::PluginManager.match_servlet_uri",
|
377
|
+
"servlet: #{servlet_name.inspect}, req_type: #{req_type.inspect}, uri: #{uri.inspect}",
|
378
|
+
servlet_name
|
459
379
|
)
|
460
380
|
end
|
461
381
|
end
|
382
|
+
match_scores = match_score.keys.sort
|
383
|
+
if match_scores.empty?
|
384
|
+
return false
|
385
|
+
else
|
386
|
+
matches_order = []
|
387
|
+
matches_best = match_score[ match_scores[0] ]
|
388
|
+
if matches_best.size > 1
|
389
|
+
matches_best = matches_best[ rand( matches_best.size ) ]
|
390
|
+
else
|
391
|
+
matches_best = matches_best.first
|
392
|
+
end
|
393
|
+
matches_order.push( matches_best )
|
394
|
+
match_score.keys.sort.each do |match_n|
|
395
|
+
match_score[ match_n ].each do | match_name |
|
396
|
+
matches_order.push( match_name ) unless matches_order.include? match_name
|
397
|
+
end
|
398
|
+
end
|
399
|
+
return matches_order
|
400
|
+
end
|
462
401
|
end
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
delegate(
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
402
|
+
|
403
|
+
# Delegates +method_name+ with +args+ to any loaded
|
404
|
+
# plugin that responds to the method.
|
405
|
+
def delegate( method_name, *args )
|
406
|
+
@registry.each do | plugin_name, plugin |
|
407
|
+
if plugin.respond_to?( method_name )
|
408
|
+
begin
|
409
|
+
plugin.send( method_name, *args )
|
410
|
+
rescue => e
|
411
|
+
plugin_error(
|
412
|
+
e,
|
413
|
+
"RSence::PluginManager.delegate error",
|
414
|
+
"plugin_name: #{plugin_name.inspect}, method_name: #{method_name.inspect}",
|
415
|
+
plugin_name
|
416
|
+
)
|
417
|
+
end
|
418
|
+
end
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
# Delegates the +flush+ and +close+ methods to any
|
423
|
+
# loaded plugins, in that order.
|
424
|
+
def shutdown
|
425
|
+
delegate( :flush )
|
426
|
+
delegate( :close )
|
427
|
+
end
|
428
|
+
|
429
|
+
# Calls the method +method_name+ with args +args+ of the plugin +plugin_name+.
|
430
|
+
# Returns false, if no such plugin or method exists.
|
431
|
+
def call( plugin_name, method_name, *args )
|
432
|
+
plugin_name = plugin_name.to_sym
|
433
|
+
if @registry.has_key?( plugin_name )
|
434
|
+
if @registry[ plugin_name ].respond_to?( method_name )
|
435
|
+
return @registry[ plugin_name ].send( method_name, *args )
|
436
|
+
else
|
437
|
+
puts "No method #{method_name.inspect} for plugin #{plugin_name.inspect}"
|
438
|
+
return false
|
439
|
+
end
|
475
440
|
else
|
476
|
-
puts "No
|
441
|
+
puts "No such plugin: #{plugin_name.inspect}"
|
477
442
|
return false
|
478
443
|
end
|
479
|
-
else
|
480
|
-
puts "No such plugin: #{plugin_name.inspect}"
|
481
|
-
return false
|
482
444
|
end
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
445
|
+
alias run_plugin call
|
446
|
+
|
447
|
+
# Calls the servlet that matches the +req_type+ and +req.fullpath+ with
|
448
|
+
# the highest score.
|
449
|
+
def match_servlet( req_type, req, resp, session )
|
450
|
+
req_uri = req.fullpath
|
451
|
+
matches_order = match_servlet_uri( req_uri, req_type )
|
452
|
+
return false unless matches_order
|
453
|
+
matches_order.each do |servlet_name|
|
454
|
+
begin
|
455
|
+
@registry[servlet_name].send( req_type, req, resp, session )
|
456
|
+
return true
|
457
|
+
rescue => e
|
458
|
+
plugin_error(
|
459
|
+
e,
|
460
|
+
"RSence::PluginManager.match_servlet",
|
461
|
+
"servlet_name: #{servlet_name.inspect}, req_type: #{req_type.inspect}",
|
462
|
+
servlet_name
|
463
|
+
)
|
464
|
+
next
|
465
|
+
end
|
504
466
|
end
|
467
|
+
return false
|
505
468
|
end
|
506
|
-
return false
|
507
469
|
end
|
508
|
-
|
509
|
-
end
|
510
|
-
|
511
470
|
end
|