Software /
code /
prosody
Diff
core/modulemanager.lua @ 438:193f9dd64f17
Bumper commit for the new modulemanager API \o/ Updates all the modules, though some more changes may be in store.
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Thu, 27 Nov 2008 03:12:12 +0000 |
parent | 400:068a813b6454 |
child | 439:6608ad3a72f3 |
line wrap: on
line diff
--- a/core/modulemanager.lua Thu Nov 27 03:06:29 2008 +0000 +++ b/core/modulemanager.lua Thu Nov 27 03:12:12 2008 +0000 @@ -1,5 +1,7 @@ -local log = require "util.logger".init("modulemanager") + +local logger = require "util.logger"; +local log = logger.init("modulemanager") local loadfile, pcall = loadfile, pcall; local setmetatable, setfenv, getfenv = setmetatable, setfenv, getfenv; @@ -14,80 +16,59 @@ module "modulemanager" +local api = {}; -- Module API container + +local modulemap = {}; + local handler_info = {}; -local handlers = {}; - +local stanza_handlers = {}; + local modulehelpers = setmetatable({}, { __index = _G }); -local function _add_iq_handler(module, origin_type, xmlns, handler) - handlers[origin_type] = handlers[origin_type] or {}; - handlers[origin_type].iq = handlers[origin_type].iq or {}; - if not handlers[origin_type].iq[xmlns] then - handlers[origin_type].iq[xmlns]= handler; - handler_info[handler] = module; - log("debug", "mod_%s now handles tag 'iq' with query namespace '%s'", module.name, xmlns); - else - log("warning", "mod_%s wants to handle tag 'iq' with query namespace '%s' but mod_%s already handles that", module.name, xmlns, handler_info[handlers[origin_type].iq[xmlns]].module.name); - end -end -function modulehelpers.add_iq_handler(origin_type, xmlns, handler) - if not (origin_type and handler and xmlns) then return false; end - if type(origin_type) == "table" then - for _, origin_type in ipairs(origin_type) do - _add_iq_handler(getfenv(2).module, origin_type, xmlns, handler); - end - return; - end - _add_iq_handler(getfenv(2).module, origin_type, xmlns, handler); -end - -local function _add_handler(module, origin_type, tag, xmlns, handler) - handlers[origin_type] = handlers[origin_type] or {}; - if not handlers[origin_type][tag] then - handlers[origin_type][tag] = handlers[origin_type][tag] or {}; - handlers[origin_type][tag][xmlns]= handler; - handler_info[handler] = module; - log("debug", "mod_%s now handles tag '%s'", module.name, tag); - elseif handler_info[handlers[origin_type][tag]] then - log("warning", "mod_%s wants to handle tag '%s' but mod_%s already handles that", module.name, tag, handler_info[handlers[origin_type][tag]].module.name); - end -end - -function modulehelpers.add_handler(origin_type, tag, xmlns, handler) - if not (origin_type and tag and xmlns and handler) then return false; end - if type(origin_type) == "table" then - for _, origin_type in ipairs(origin_type) do - _add_handler(getfenv(2).module, origin_type, tag, xmlns, handler); - end - return; - end - _add_handler(getfenv(2).module, origin_type, tag, xmlns, handler); -end - -function load(name) - local mod, err = loadfile("plugins/mod_"..name..".lua"); +function load(host, module_name, config) + local mod, err = loadfile("plugins/mod_"..module_name..".lua"); if not mod then - log("error", "Unable to load module '%s': %s", name or "nil", err or "nil"); + log("error", "Unable to load module '%s': %s", module_name or "nil", err or "nil"); return nil, err; end - local pluginenv = setmetatable({ module = { name = name } }, { __index = modulehelpers }); + if not modulemap[host] then + modulemap[host] = {}; + stanza_handlers[host] = {}; + elseif modulemap[host][module_name] then + log("warn", "%s is already loaded for %s, so not loading again", module_name, host); + return nil, "module-already-loaded"; + end + + local _log = logger.init(host..":"..module_name); + local api_instance = setmetatable({ name = module_name, host = host, config = config, _log = _log, log = function (self, ...) return _log(...); end }, { __index = api }); + + local pluginenv = setmetatable({ module = api_instance }, { __index = _G }); setfenv(mod, pluginenv); + local success, ret = pcall(mod); if not success then log("error", "Error initialising module '%s': %s", name or "nil", ret or "nil"); return nil, ret; end + + modulemap[host][module_name] = mod; + return true; end -function handle_stanza(origin, stanza) +function handle_stanza(host, origin, stanza) local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns, origin.type; + local handlers = stanza_handlers[host]; + if not handlers then + log("warn", "No handlers for %s", host); + return false; + end + if name == "iq" and xmlns == "jabber:client" and handlers[origin_type] then - log("debug", "Stanza is an <iq/>"); local child = stanza.tags[1]; if child then local xmlns = child.attr.xmlns or xmlns; @@ -112,14 +93,54 @@ return false; -- we didn't handle it end +----- API functions exposed to modules ----------- +-- Must all be in api.* + +-- Returns the name of the current module +function api:get_name() + return self.name; +end + +-- Returns the host that the current module is serving +function api:get_host() + return self.host; +end + + +local function _add_iq_handler(module, origin_type, xmlns, handler) + local handlers = stanza_handlers[module.host]; + handlers[origin_type] = handlers[origin_type] or {}; + handlers[origin_type].iq = handlers[origin_type].iq or {}; + if not handlers[origin_type].iq[xmlns] then + handlers[origin_type].iq[xmlns]= handler; + handler_info[handler] = module; + module:log("debug", "I now handle tag 'iq' [%s] with payload namespace '%s'", origin_type, xmlns); + else + module:log("warn", "I wanted to handle tag 'iq' [%s] with payload namespace '%s' but mod_%s already handles that", origin_type, xmlns, handler_info[handlers[origin_type].iq[xmlns]].name); + end +end + +function api:add_iq_handler(origin_type, xmlns, handler) + if not (origin_type and handler and xmlns) then return false; end + if type(origin_type) == "table" then + for _, origin_type in ipairs(origin_type) do + _add_iq_handler(self, origin_type, xmlns, handler); + end + return; + end + _add_iq_handler(self, origin_type, xmlns, handler); +end + + do local event_handlers = {}; - function modulehelpers.add_event_hook(name, handler) + function api:add_event_hook(name, handler) if not event_handlers[name] then event_handlers[name] = {}; end t_insert(event_handlers[name] , handler); + self:log("debug", "Subscribed to %s", name); end function fire_event(name, ...) @@ -132,4 +153,31 @@ end end + +local function _add_handler(module, origin_type, tag, xmlns, handler) + local handlers = stanza_handlers[module.host]; + handlers[origin_type] = handlers[origin_type] or {}; + if not handlers[origin_type][tag] then + handlers[origin_type][tag] = handlers[origin_type][tag] or {}; + handlers[origin_type][tag][xmlns]= handler; + handler_info[handler] = module; + module:log("debug", "I now handle tag '%s' [%s] with xmlns '%s'", tag, origin_type, xmlns); + elseif handler_info[handlers[origin_type][tag]] then + log("warning", "I wanted to handle tag '%s' [%s] but mod_%s already handles that", tag, origin_type, handler_info[handlers[origin_type][tag]].module.name); + end +end + +function api:add_handler(origin_type, tag, xmlns, handler) + if not (origin_type and tag and xmlns and handler) then return false; end + if type(origin_type) == "table" then + for _, origin_type in ipairs(origin_type) do + _add_handler(self, origin_type, tag, xmlns, handler); + end + return; + end + _add_handler(self, origin_type, tag, xmlns, handler); +end + +-------------------------------------------------------------------- + return _M;