From 4e5132f63a210beb766ebfe52bea7424903403ae Mon Sep 17 00:00:00 2001 From: zedshaw Date: Tue, 28 Feb 2006 05:17:23 +0000 Subject: [PATCH] Implemented the basic plugin system for Mongrel to replace pluginfactory with something more manageable (and cool). git-svn-id: svn+ssh://rubyforge.org/var/svn/mongrel/trunk@64 19e92222-5c0b-0410-8929-a290d50e31e9 --- lib/mongrel.rb | 20 ++++++++- lib/mongrel/plugins.rb | 74 ++++++++++++++++++++++++++++++++++ test/plugins/commands/test1.rb | 21 ++++++++++ test/test_plugins.rb | 30 ++++++++++++++ test/test_uriclassifier.rb | 6 ++- 5 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 lib/mongrel/plugins.rb create mode 100644 test/plugins/commands/test1.rb create mode 100644 test/test_plugins.rb diff --git a/lib/mongrel.rb b/lib/mongrel.rb index f7ae112d..dc928bc0 100644 --- a/lib/mongrel.rb +++ b/lib/mongrel.rb @@ -4,12 +4,29 @@ require 'thread' require 'stringio' require 'mongrel/cgi' require 'mongrel/handlers' +require 'mongrel/plugins' + # Mongrel module containing all of the classes (include C extensions) for running # a Mongrel web server. It contains a minimalist HTTP server with just enough # functionality to service web application requests fast as possible. module Mongrel + class URIClassifier + # Returns the URIs that have been registered with this classifier so far. + # The URIs returned should not be modified as this will cause a memory leak. + # You can use this to inspect the contents of the URIClassifier. + def uris + @handler_map.keys + end + + # Simply does an inspect that looks like a Hash inspect. + def inspect + @handler_map.inspect + end + end + + # Used to stop the HttpServer via Thread.raise. class StopServer < Exception end @@ -441,7 +458,8 @@ module Mongrel # off the request queue before finally exiting. def stop @acceptor[:stopped] = true - @acceptor.raise(StopServer.new) + exc = StopServer.new + @acceptor.raise(exc) end end diff --git a/lib/mongrel/plugins.rb b/lib/mongrel/plugins.rb new file mode 100644 index 00000000..9778e9b6 --- /dev/null +++ b/lib/mongrel/plugins.rb @@ -0,0 +1,74 @@ +require 'singleton' + +module Mongrel + class PluginManager + include Singleton + + def initialize + @plugins = URIClassifier.new + end + + def load(path) + Dir.chdir(path) do + Dir["**/*.rb"].each do |rbfile| + require rbfile + end + end + end + + def register(category, name, klass) + cat, ignored, map = @plugins.resolve(category) + if not cat + map = {name => klass} + @plugins.register(category, map) + else + map[name] = klass + end + end + + + def create(name, options = {}) + category, plugin, map = @plugins.resolve(name) + if category and plugin and plugin.length > 0 + STDERR.puts "found: #{category} #{plugin} for #{name}" + map[plugin].new(options) + else + raise "Plugin #{name} does not exist" + end + end + + def available + map = {} + @plugins.uris.each do |u| + cat, name, plugins = @plugins.resolve(u) + map[cat] ||= [] + map[cat] += plugins.keys + end + + return map + end + + end + + class PluginBase + + def PluginBase.inherited(klass) + + PluginManager.instance.register(@@category, klass.to_s.downcase, klass) + end + + def PluginBase.category=(category) + @@category = category + end + end + + def Plugin(c) + PluginBase.category = c + PluginBase + end + +end + + + + diff --git a/test/plugins/commands/test1.rb b/test/plugins/commands/test1.rb new file mode 100644 index 00000000..b999d38f --- /dev/null +++ b/test/plugins/commands/test1.rb @@ -0,0 +1,21 @@ + +include Mongrel + +class First < Plugin "/commands" + def initialize(options = {}) + puts "First with options: #{options.inspect}" + end +end + +class Second < Plugin "/commands" + def initialize(options = {}) + puts "Second with options: #{options.inspect}" + end +end + +class Last < Plugin "/commands" + def initialize(options = {}) + puts "Last with options: #{options.inspect}" + end +end + diff --git a/test/test_plugins.rb b/test/test_plugins.rb new file mode 100644 index 00000000..680dac56 --- /dev/null +++ b/test/test_plugins.rb @@ -0,0 +1,30 @@ +require 'test/unit' +require 'mongrel' + + +include Mongrel + +class PluginTest < Test::Unit::TestCase + + def setup + @pmgr = PluginManager.instance + @categories = ["/commands"] + @names = ["FirstCommand", "SecondCommand", "LastCommands"] + end + + def test_load_plugins + @pmgr.load(File.join(File.dirname(__FILE__),"plugins")) + puts "#{@pmgr.available.inspect}" + @pmgr.available.each {|cat,plugins| + plugins.each do |p| + puts "TEST: #{cat}/#{p}" + assert @names.include?(p) + end + } + + @pmgr.available.each do |name| + plugin = @pmgr.create(name, options={"name" => name}) + end + end + +end diff --git a/test/test_uriclassifier.rb b/test/test_uriclassifier.rb index b9b27784..f7c104be 100644 --- a/test/test_uriclassifier.rb +++ b/test/test_uriclassifier.rb @@ -30,7 +30,9 @@ class URIClassifierTest < Test::Unit::TestCase assert val != nil, "didn't resolve" assert_equal prefix,sn, "wrong script name" assert_equal test[sn.length .. -1],pi, "wrong path info" - + + assert u.inspect != nil, "No inspect for classifier" + assert u.uris[0] == prefix, "URI list didn't match" end def test_not_finding @@ -172,5 +174,7 @@ class URIClassifierTest < Test::Unit::TestCase assert_equal root,sn, "didn't get right script name" assert_equal 1,h, "didn't find handler" end + + end