lib/plugins/pluginmanager.rb in rsence-2.0.0.6.pre vs lib/plugins/pluginmanager.rb in rsence-2.0.0.7.pre

- old
+ new

@@ -3,509 +3,468 @@ # http://riassence.com/ # # You should have received a copy of the GNU General Public License along # with this software package. If not, contact licensing@riassence.com ## -# if RUBY_VERSION.to_f >= 1.9 -# # with_module comes from: -# # http://coderrr.wordpress.com/2009/05/18/dynamically-adding-a-constant-nesting-in-ruby-1-9/ -# module Kernel -# def with_module(*consts, &blk) -# slf = blk.binding.eval('self') -# l = lambda { slf.instance_eval(&blk) } -# consts.reverse.inject(l) {|l, k| lambda { k.class_eval(&l) } }.call -# end -# end -# end - -# def bundle_loader( params ) -# src_path = params[:src_path] -# mod = Module.new do |m| -# @@bundle_path = params[:bundle_path ] -# @@bundle_name = params[:bundle_name ] -# @@bundle_info = params[:bundle_info ] -# @@plugin_manager = params[:plugin_manager] -# def m.bundle_path; @@bundle_path; end -# def m.bundle_name; @@bundle_name; end -# def m.bundle_info; @@bundle_info; end -# def m.bundle_manager; @@bundle_manager; end -# begin -# # if RUBY_VERSION.to_f >= 1.9 -# # # with_module(m) do -# # src = File.read(src_path) -# # self.module_eval( -# # <<-SRC -# # puts %{--- bundle_path: #{bundle_path.inspect}} -# # #{src} -# # SRC -# # ) -# # # end -# # else -# if params[:bundle_info][:inits_self] == false or RUBY_VERSION.to_f >= 1.9 -# m::module_eval( File.read(src_path) ) -# elsif params[:bundle_info][:reloadable] == false -# require src_path[0..-4] -# else -# load src_path -# end -# # end -# rescue => e -# @@plugin_manager.plugin_error( -# e, -# 'BundleLoaderError', -# "An error occurred while loading the plugin bundle #{@@bundle_name}.", -# @@bundle_path -# ) -# end -# end -# return mod -# end -# - -module RSence - require 'plugins/plugins' -## = Abstract -## PluginManager is the service that loads and provides method delegation -## amongst all installed plugins. -## -## = Usage -## plugin_paths = [ 'plugins', '/home/me/rsence/plugins' ] -## myPluginManager = RSence::PluginManager.new( plugin_paths ) -## -class PluginManager +module RSence - attr_reader :transporter, :sessions - - # Initialize with a list of directories as plugin_paths. - # It's an array containing all plugin directories to scan. - def initialize( plugin_paths, transporter=nil, autoreload=false ) - if transporter - @transporter = transporter - @sessions = transporter.sessions - end - @plugin_paths = plugin_paths - puts "Loading plugins..." if RSence.args[:verbose] - scan_plugins - puts "Plugins loaded." if RSence.args[:verbose] - if autoreload - @thr = Thread.new do - Thread.pass - while true - begin - changed_plugins! - rescue => e - warn e.inspect + ## = Abstract + ## PluginManager is the service that loads and provides method delegation + ## amongst its plugin bundles. + ## + ## = Usage + ## plugin_paths = [ 'plugins', '/home/me/rsence/plugins' ] + ## myPluginManager = RSence::PluginManager.new( plugin_paths ) + ## + class PluginManager + + attr_reader :transporter, :sessions + + # Initialize with a list of directories as plugin_paths. + # It's an array containing all plugin directories to scan. + def initialize( plugin_paths, transporter=nil, autoreload=false, name_prefix=false ) + if transporter + @transporter = transporter + @sessions = transporter.sessions + end + @name_prefix = name_prefix + @plugin_paths = plugin_paths + puts "Loading #{name_prefix+' ' if name_prefix}plugins..." if RSence.args[:verbose] + scan_plugins + puts "Plugins #{name_prefix+' ' if name_prefix}loaded." if RSence.args[:verbose] + if autoreload + @thr = Thread.new do + Thread.pass + while true + begin + changed_plugins! + rescue => e + warn e.inspect + end + sleep 3 end - sleep 3 end end end - end - - def method_missing( sym, *args, &block ) - if @registry.has_key?(sym) - if args == [] and block == nil - return @registry[sym] - elsif block == nil - call( sym, *args ) + + # By default, calling a method not defined calls a plugin of that name + def method_missing( sym, *args, &block ) + if @registry.has_key?(sym) + if args == [] and block == nil + return @registry[sym] + elsif block == nil + call( sym, *args ) + end end end - end - - def changed_plugins! - @plugin_paths.each do |path| - next unless File.directory? path - Dir.entries(path).each do |bundle_name| - next if bundle_name =~ /&\./ - bundle_path = File.expand_path( File.join( path, bundle_name ) ) - next unless File.directory?( bundle_path ) - bundle_file = bundle_name+'.rb' - next unless File.exists?( File.join( bundle_path, bundle_file ) ) - if File.exists?( File.join( bundle_path, 'disabled' ) ) - if @registry.has_key?( bundle_name.to_sym ) - puts "Disabling bundle #{bundle_name}..." - online_status = @transporter.online? - @transporter.online = false - unload_bundle( bundle_name.to_sym ) - @transporter.online = online_status - if RSence.args[:say] - Thread.new do - Thread.pass - system(%{say "Unloaded #{bundle_name.to_s}."}) + + # Checks for changed plugin bundles and unloads/loads/reloads them accordingly. + def changed_plugins! + @plugin_paths.each do |path| + next unless File.directory? path + Dir.entries(path).each do |bundle_name| + next if bundle_name =~ /&\./ + bundle_path = File.expand_path( File.join( path, bundle_name ) ) + next unless File.directory?( bundle_path ) + bundle_file = bundle_name+'.rb' + next unless File.exists?( File.join( bundle_path, bundle_file ) ) + if File.exists?( File.join( bundle_path, 'disabled' ) ) + if @registry.has_key?( bundle_name.to_sym ) + puts "Disabling bundle #{bundle_name}..." + online_status = @transporter.online? + @transporter.online = false + unload_bundle( bundle_name.to_sym ) + @transporter.online = online_status + if RSence.args[:say] + Thread.new do + Thread.pass + system(%{say "Unloaded #{bundle_name.to_s}."}) + end end end - end - else - if not @registry.has_key?( bundle_name.to_sym ) - puts "Loading bundle #{bundle_name}..." - online_status = @transporter.online? - @transporter.online = false - load_bundle( bundle_path, bundle_name.to_sym, bundle_name+'.rb' ) - call( bundle_name.to_sym, :open ) - @transporter.online = online_status - if RSence.args[:say] - Thread.new do - Thread.pass - system(%{say "Loaded #{bundle_name.to_s}."}) - end - end else - # puts "Checking if bundle #{bundle_name} is changed..." - info = @info[bundle_name.to_sym] - if info[:reloadable] and plugin_changed?( bundle_name.to_sym ) - puts "Bundle #{bundle_name} has changed, reloading..." + if not @registry.has_key?( bundle_name.to_sym ) + puts "Loading bundle #{bundle_name}..." online_status = @transporter.online? @transporter.online = false - unload_bundle( bundle_name.to_sym ) load_bundle( bundle_path, bundle_name.to_sym, bundle_name+'.rb' ) call( bundle_name.to_sym, :open ) @transporter.online = online_status if RSence.args[:say] Thread.new do Thread.pass - system(%{say "Reloaded #{bundle_name.to_s}."}) + system(%{say "Loaded #{bundle_name.to_s}."}) end end + else + # puts "Checking if bundle #{bundle_name} is changed..." + info = @info[bundle_name.to_sym] + if info[:reloadable] and plugin_changed?( bundle_name.to_sym ) + puts "Bundle #{bundle_name} has changed, reloading..." + online_status = @transporter.online? + @transporter.online = false + unload_bundle( bundle_name.to_sym ) + load_bundle( bundle_path, bundle_name.to_sym, bundle_name+'.rb' ) + call( bundle_name.to_sym, :open ) + @transporter.online = online_status + if RSence.args[:say] + Thread.new do + Thread.pass + system(%{say "Reloaded #{bundle_name.to_s}."}) + end + end + end end end end end end - end - - def unload_bundle( bundle_name ) - puts "unloading bundle: #{bundle_name.inspect}" if RSence.args[:debug] - if @registry.has_key?( bundle_name ) - call( bundle_name, :flush ) - call( bundle_name, :close ) - @registry.delete( bundle_name ) - @aliases.each do |a_name,b_name| - if b_name == bundle_name - @aliases.delete( a_name ) + + # Unloads the plugin bundle named +bundle_name+ + def unload_bundle( bundle_name ) + puts "unloading bundle: #{bundle_name.inspect}" if RSence.args[:debug] + if @registry.has_key?( bundle_name ) + call( bundle_name, :flush ) + call( bundle_name, :close ) + @registry.delete( bundle_name ) + @aliases.each do |a_name,b_name| + if b_name == bundle_name + @aliases.delete( a_name ) + end end + if @servlets.include?( bundle_name ) + @servlets.delete( bundle_name ) + end + if @info.include?( bundle_name ) + @info.delete( bundle_name ) + end end - if @servlets.include?( bundle_name ) - @servlets.delete( bundle_name ) - end - if @info.include?( bundle_name ) - @info.delete( bundle_name ) - end end - end - - def plugin_changed?( plugin_name ) - info = @info[plugin_name] - last_changed = info[:last_changed] - newest_change = most_recent( info[:path], last_changed ) - return last_changed < newest_change - end - - # Top-level method for scanning all plugin directories. - # Clears previously loaded plugins. - def scan_plugins - @registry = {} - @info = {} - @aliases = {} - @servlets = [] - @plugin_paths.each do |path| - next unless File.directory? path - scan_plugindir( path ) + + # Returns true, if a plugin bundle has changed. + # Only compares timestamp, not checksum. + def plugin_changed?( plugin_name ) + info = @info[plugin_name] + last_changed = info[:last_changed] + newest_change = most_recent( info[:path], last_changed ) + return last_changed < newest_change end - delegate( :open ) - end - def registry( plugin_name ) - return @registry[ plugin_name ] - end - alias [] registry - - # Scans a directory of plugins, calls +load_plugin+ for bundles that match - # the definition of a plugin bundle. - # - Skips bundles starting with a dot - # - Skips bundles without a ruby source file with the same - # name as the directory (plus '.rb'). - # - Skips bundles containing a file or directory named 'disabled' - def scan_plugindir( path ) - Dir.entries(path).each do |bundle_name| - next if bundle_name[0].chr == '.' - bundle_path = File.expand_path( File.join( path, bundle_name ) ) - next unless File.directory?( bundle_path ) - bundle_file = bundle_name+'.rb' - if not File.exists?( File.join( bundle_path, bundle_file ) ) - bundle_file = 'main.rb' - next unless File.exists?( File.join( bundle_path, bundle_file ) ) + # Top-level method for scanning all plugin directories. + # Clears previously loaded plugins. + def scan_plugins + @registry = {} + @info = {} + @aliases = {} + @servlets = [] + @plugin_paths.each do |path| + next unless File.directory? path + scan_plugindir( path ) end - next if File.exists?( File.join( bundle_path, 'disabled' ) ) + delegate( :open ) + end + + # Returns the registry data for plugin bundle +plugin_name+ + def registry( plugin_name ) + return @registry[ plugin_name ] + end + alias [] registry + + # Scans a directory of plugins, calls +load_plugin+ for bundles that match + # the definition of a plugin bundle. + # - Skips bundles starting with a dot + # - Skips bundles without a ruby source file with the same + # name as the directory (plus '.rb'). + # - Skips bundles containing a file or directory named 'disabled' + def scan_plugindir( path ) + Dir.entries(path).each do |bundle_name| + next if bundle_name[0].chr == '.' + bundle_path = File.expand_path( File.join( path, bundle_name ) ) + next unless File.directory?( bundle_path ) + bundle_file = bundle_name+'.rb' + if not File.exists?( File.join( bundle_path, bundle_file ) ) + bundle_file = 'main.rb' + next unless File.exists?( File.join( bundle_path, bundle_file ) ) + end + next if File.exists?( File.join( bundle_path, 'disabled' ) ) - load_bundle( bundle_path, bundle_name.to_sym, bundle_file ) + load_bundle( bundle_path, bundle_name.to_sym, bundle_file ) + end end - end - # Finds the most recent file in the path - def most_recent( bundle_path, newest_date=0 ) - path_date = File.stat( bundle_path ).mtime.to_i - is_dir = File.directory?( bundle_path ) - if path_date > newest_date and not is_dir - # puts "File is newer: #{bundle_path}" - newest_date = path_date - end - if is_dir - Dir.entries( bundle_path ).each do |entry_name| - next if entry_name[0].chr == '.' - full_path = File.join( bundle_path, entry_name ) - unless File.directory?( full_path ) - next unless entry_name.include?('.') and ['yaml','rb'].include?( entry_name.split('.')[-1] ) + # Finds the most recent file in the path + def most_recent( bundle_path, newest_date=0 ) + path_date = File.stat( bundle_path ).mtime.to_i + is_dir = File.directory?( bundle_path ) + if path_date > newest_date and not is_dir + # puts "File is newer: #{bundle_path}" + newest_date = path_date + end + if is_dir + Dir.entries( bundle_path ).each do |entry_name| + next if entry_name[0].chr == '.' + full_path = File.join( bundle_path, entry_name ) + unless File.directory?( full_path ) + next unless entry_name.include?('.') and ['yaml','rb'].include?( entry_name.split('.')[-1] ) + end + newest_date = most_recent( full_path, newest_date ) end - newest_date = most_recent( full_path, newest_date ) end + return newest_date end - return newest_date - end - # Gets plugin information - def bundle_info( bundle_path ) + # Gets plugin information + def bundle_info( bundle_path ) - bundle_name = File.split( bundle_path )[1] + bundle_name = File.split( bundle_path )[1] - # Default bundle information - info = { - # The human-readable product name of the package - :title => bundle_name.capitalize, + # Default bundle information + info = { + # The human-readable product name of the package + :title => bundle_name.capitalize, - # The human-readable version of the package - :version => '0.0.0', + # The human-readable version of the package + :version => '0.0.0', - # A brief description of the package (rdoc formatting supported) - :description => 'No Description given', + # A brief description of the package (rdoc formatting supported) + :description => 'No Description given', - # A flag (when false) prevents the plugin from automatically reload when changed. - :reloadable => true, + # A flag (when false) prevents the plugin from automatically reload when changed. + :reloadable => true, - # A flag (when false) enables automatic construction - # of the Plugin and Servlet classes contained. - :inits_self => false, + # A flag (when false) enables automatic construction + # of the Plugin and Servlet classes contained. + :inits_self => false, - # System version requirement. - :sys_version => '>= 1.0.0', + # System version requirement. + :sys_version => '>= 1.0.0', - # Path to bundle - :path => bundle_path, + # Path to bundle + :path => bundle_path, - # Name of bundle - :name => bundle_name.to_sym, + # Name of bundle + :name => bundle_name.to_sym, - # Last change - :last_changed => most_recent( bundle_path ) + # Last change + :last_changed => most_recent( bundle_path ) - } + } - info_path = File.join( bundle_path, 'info.yaml' ) - if File.exists?( info_path ) - info_yaml = YAML.load( File.read( info_path ) ) - info_yaml.each do |info_key,info_value| - info[ info_key.to_sym ] = info_value + info_path = File.join( bundle_path, 'info.yaml' ) + if File.exists?( info_path ) + info_yaml = YAML.load( File.read( info_path ) ) + info_yaml.each do |info_key,info_value| + info[ info_key.to_sym ] = info_value + end end - end - return info + return info - end - - # Loads a plugin bundle. - def load_bundle( bundle_path, bundle_name, bundle_file ) - puts "loading bundle: #{bundle_name.inspect}" if RSence.args[:debug] - if @registry.has_key?( bundle_name.to_sym ) - warn "Warning: Bundle #{bundle_name} already loaded." - return end + + # Loads a plugin bundle. + def load_bundle( bundle_path, bundle_name, bundle_file ) + puts "loading bundle: #{bundle_name.inspect}" if RSence.args[:debug] + if @registry.has_key?( bundle_name.to_sym ) + warn "Warning: Bundle #{bundle_name} already loaded." + return + end - bundle_file_path = File.join( bundle_path, bundle_file ) + bundle_file_path = File.join( bundle_path, bundle_file ) - bundle_info = bundle_info( bundle_path ) + bundle_info = bundle_info( bundle_path ) - @info[bundle_name.to_sym] = bundle_info + @info[bundle_name.to_sym] = bundle_info - bundle_src = File.read( bundle_file_path ) + bundle_src = File.read( bundle_file_path ) - module_ns = Plugins.bundle_loader( { - :bundle_path => bundle_path, - :bundle_name => bundle_name, - :bundle_info => bundle_info, - :plugin_manager => self, - :src_path => bundle_file_path, - :src => bundle_src - } ) + module_ns = Plugins.bundle_loader( { + :bundle_path => bundle_path, + :bundle_name => bundle_name, + :bundle_info => bundle_info, + :plugin_manager => self, + :src_path => bundle_file_path, + :src => bundle_src + } ) - if bundle_info[:inits_self] - warn "Plugins can't init them self anymore. Please fix plugin: #{bundle_name.inspect}" - else - module_ns.constants.each do |module_const_name| - module_const = module_ns.const_get( module_const_name ) - if module_const.class == Class - bundle_type = module_const.bundle_type - if [:Servlet, :Plugin, :GUIPlugin].include? bundle_type - bundle_inst = module_const.new( bundle_name, bundle_info, bundle_path, self ) - bundle_inst.register( bundle_name ) if [ :Plugin, :GUIPlugin ].include?( bundle_type ) - break + if bundle_info[:inits_self] + warn "Plugins can't init them self anymore. Please fix plugin: #{bundle_name.inspect}" + else + module_ns.constants.each do |module_const_name| + module_const = module_ns.const_get( module_const_name ) + if module_const.class == Class + bundle_type = module_const.bundle_type + if [:Servlet, :Plugin, :GUIPlugin].include? bundle_type + bundle_inst = module_const.new( bundle_name, bundle_info, bundle_path, self ) + bundle_inst.register( bundle_name ) if [ :Plugin, :GUIPlugin ].include?( bundle_type ) + break + else + warn "Can't init class: #{module_const.to_s}" + break + end else - warn "Can't init class: #{module_const.to_s}" - break + warn "module_const.class: #{module_const.class.inspect}" end - else - warn "module_const.class: #{module_const.class.inspect}" end end end - end - - def register_bundle( inst, bundle_name ) - bundle_name = bundle_name.to_sym - if @registry.has_key?( bundle_name ) - if registry[ bundle_name ] != inst - warn "Tried to register a conflicting bundle name: #{bundle_name.inspect}; ignoring" + + # Registers plugin class +inst+ into the registry using +bundle_name+ + def register_bundle( inst, bundle_name ) + bundle_name = bundle_name.to_sym + if @registry.has_key?( bundle_name ) + if registry[ bundle_name ] != inst + warn "Tried to register a conflicting bundle name: #{bundle_name.inspect}; ignoring" + else + warn "Use @plugins.register_alias to register more than one name per plugin." + register_alias( inst.name.to_sym, bundle_name ) + end else - warn "Use @plugins.register_alias to register more than one name per plugin." - register_alias( inst.name.to_sym, bundle_name ) - end - else - inst.init if inst.respond_to? :init and not inst.inited - @registry[ bundle_name ] = inst - if inst.respond_to?( :match ) and ( inst.respond_to?( :get ) or inst.respond_to?( :post ) ) - puts " --- servlet: #{bundle_name.inspect}, #{inst.respond_to?(:match)}, #{inst.post}" if bundle_name == :welcome - @servlets.push( bundle_name ) - end - end - end - - def register_alias( bundle_name, alias_name ) - if @aliases.has_key?( alias_name.to_sym ) - warn "Alias already taken: #{alias_name.inspect}" - else - @aliases[ alias_name ] = bundle_name.to_sym - end - end - - def plugin_error( e, err_location, err_location_descr, eval_repl=false ) - err_msg = [ - "*"*40, - err_location, - err_location_descr, - "#{e.class.to_s}, #{e.message}", - "Backtrace:", - "\t"+e.backtrace.join("\n\t"), - "*"*40 - ].join("\n")+"\n" - if eval_repl - puts - puts "plugin: #{eval_repl}" - puts - err_msg = err_msg.gsub(/^\t\(eval\)\:/s,"\t#{eval_repl}:") - end - $stderr.write( err_msg ) - end - - def match_servlet_uri( uri, req_type=:get ) - match_score = {} - @servlets.each do | servlet_name | - servlet = @registry[ servlet_name ] - next unless servlet.respond_to?( req_type ) - begin - if servlet.match( uri, req_type ) - score = servlet.score - match_score[ score ] = [] unless match_score.has_key? score - match_score[ score ].push( servlet_name ) + inst.init if inst.respond_to? :init and not inst.inited + @registry[ bundle_name ] = inst + if inst.respond_to?( :match ) and ( inst.respond_to?( :get ) or inst.respond_to?( :post ) ) + puts " --- servlet: #{bundle_name.inspect}, #{inst.respond_to?(:match)}, #{inst.post}" if bundle_name == :welcome + @servlets.push( bundle_name ) end - rescue => e - plugin_error( - e, - "RSence::PluginManager.match_servlet_uri", - "servlet: #{servlet_name.inspect}, req_type: #{req_type.inspect}, uri: #{uri.inspect}", - servlet_name - ) end end - match_scores = match_score.keys.sort - if match_scores.empty? - return false - else - matches_order = [] - matches_best = match_score[ match_scores[0] ] - if matches_best.size > 1 - matches_best = matches_best[ rand( matches_best.size ) ] + + # Registers alias name for a plugin bundle. + def register_alias( bundle_name, alias_name ) + if @aliases.has_key?( alias_name.to_sym ) + warn "Alias already taken: #{alias_name.inspect}" else - matches_best = matches_best.first + @aliases[ alias_name ] = bundle_name.to_sym end - matches_order.push( matches_best ) - match_score.keys.sort.each do |match_n| - match_score[ match_n ].each do | match_name | - matches_order.push( match_name ) unless matches_order.include? match_name - end + end + + # Prettier error handling. + def plugin_error( e, err_location, err_location_descr, eval_repl=false ) + err_msg = [ + "*"*40, + err_location, + err_location_descr, + "#{e.class.to_s}, #{e.message}", + "Backtrace:", + "\t"+e.backtrace.join("\n\t"), + "*"*40 + ].join("\n")+"\n" + if eval_repl + puts + puts "plugin: #{eval_repl}" + puts + err_msg = err_msg.gsub(/^\t\(eval\)\:/s,"\t#{eval_repl}:") end - return matches_order + $stderr.write( err_msg ) end - end - - def delegate( method_name, *args ) - @registry.each do | plugin_name, plugin | - if plugin.respond_to?( method_name ) + + # Search servlets that match the +uri+ and +req_type+ + def match_servlet_uri( uri, req_type=:get ) + match_score = {} + @servlets.each do | servlet_name | + servlet = @registry[ servlet_name ] + next unless servlet.respond_to?( req_type ) begin - plugin.send( method_name, *args ) + if servlet.match( uri, req_type ) + score = servlet.score + match_score[ score ] = [] unless match_score.has_key? score + match_score[ score ].push( servlet_name ) + end rescue => e plugin_error( e, - "RSence::PluginManager.delegate error", - "plugin_name: #{plugin_name.inspect}, method_name: #{method_name.inspect}", - plugin_name + "RSence::PluginManager.match_servlet_uri", + "servlet: #{servlet_name.inspect}, req_type: #{req_type.inspect}, uri: #{uri.inspect}", + servlet_name ) end end + match_scores = match_score.keys.sort + if match_scores.empty? + return false + else + matches_order = [] + matches_best = match_score[ match_scores[0] ] + if matches_best.size > 1 + matches_best = matches_best[ rand( matches_best.size ) ] + else + matches_best = matches_best.first + end + matches_order.push( matches_best ) + match_score.keys.sort.each do |match_n| + match_score[ match_n ].each do | match_name | + matches_order.push( match_name ) unless matches_order.include? match_name + end + end + return matches_order + end end - end - - def shutdown - delegate( :flush ) - delegate( :close ) - end - - def call( plugin_name, method_name, *args ) - plugin_name = plugin_name.to_sym - if @registry.has_key?( plugin_name ) - if @registry[ plugin_name ].respond_to?( method_name ) - return @registry[ plugin_name ].send( method_name, *args ) + + # Delegates +method_name+ with +args+ to any loaded + # plugin that responds to the method. + def delegate( method_name, *args ) + @registry.each do | plugin_name, plugin | + if plugin.respond_to?( method_name ) + begin + plugin.send( method_name, *args ) + rescue => e + plugin_error( + e, + "RSence::PluginManager.delegate error", + "plugin_name: #{plugin_name.inspect}, method_name: #{method_name.inspect}", + plugin_name + ) + end + end + end + end + + # Delegates the +flush+ and +close+ methods to any + # loaded plugins, in that order. + def shutdown + delegate( :flush ) + delegate( :close ) + end + + # Calls the method +method_name+ with args +args+ of the plugin +plugin_name+. + # Returns false, if no such plugin or method exists. + def call( plugin_name, method_name, *args ) + plugin_name = plugin_name.to_sym + if @registry.has_key?( plugin_name ) + if @registry[ plugin_name ].respond_to?( method_name ) + return @registry[ plugin_name ].send( method_name, *args ) + else + puts "No method #{method_name.inspect} for plugin #{plugin_name.inspect}" + return false + end else - puts "No method #{method_name.inspect} for plugin #{plugin_name.inspect}" + puts "No such plugin: #{plugin_name.inspect}" return false end - else - puts "No such plugin: #{plugin_name.inspect}" - return false end - end - - alias run_plugin call - - def match_servlet( req_type, req, resp, session ) - req_uri = req.fullpath - matches_order = match_servlet_uri( req_uri, req_type ) - return false unless matches_order - matches_order.each do |servlet_name| - # puts "servlet name: #{servlet_name.inspect}" if RSence.args[:debug] - begin - @registry[servlet_name].send( req_type, req, resp, session ) - return true - rescue => e - plugin_error( - e, - "RSence::PluginManager.match_servlet", - "servlet_name: #{servlet_name.inspect}, req_type: #{req_type.inspect}", - servlet_name - ) - next + alias run_plugin call + + # Calls the servlet that matches the +req_type+ and +req.fullpath+ with + # the highest score. + def match_servlet( req_type, req, resp, session ) + req_uri = req.fullpath + matches_order = match_servlet_uri( req_uri, req_type ) + return false unless matches_order + matches_order.each do |servlet_name| + begin + @registry[servlet_name].send( req_type, req, resp, session ) + return true + rescue => e + plugin_error( + e, + "RSence::PluginManager.match_servlet", + "servlet_name: #{servlet_name.inspect}, req_type: #{req_type.inspect}", + servlet_name + ) + next + end end + return false end - return false end - -end - end