Software /
code /
prosody
Diff
core/modulemanager.lua @ 4532:d8dbf569766c
modulemanager: Some reorganisation. Only external change is (should be) that module-unloaded and module-loaded are no longer fired when reloading a module, the new event module-reloaded is fired instead.
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Sun, 22 Jan 2012 18:46:17 +0000 |
parent | 4531:c778ce7e3c78 |
child | 4533:c6480d17be1e |
line wrap: on
line diff
--- a/core/modulemanager.lua Sun Jan 22 18:41:55 2012 +0000 +++ b/core/modulemanager.lua Sun Jan 22 18:46:17 2012 +0000 @@ -90,77 +90,9 @@ prosody_events.add_handler("host-activated", load_modules_for_host); -- -function load(host, module_name, config) - if not (host and module_name) then - return nil, "insufficient-parameters"; - elseif not hosts[host] then - return nil, "unknown-host"; - end - - if not modulemap[host] then - modulemap[host] = {}; - end - - if 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"; - elseif modulemap["*"][module_name] then - return nil, "global-module-already-loaded"; - end - - - local mod, err = pluginloader.load_code(module_name); - if not mod then - log("error", "Unable to load module '%s': %s", module_name or "nil", err or "nil"); - return nil, err; - end - - local _log = logger.init(host..":"..module_name); - local api_instance = setmetatable({ name = module_name, host = host, path = err, _log = _log, log = function (self, ...) return _log(...); end }, { __index = api }); +--- Private helpers --- - local pluginenv = setmetatable({ module = api_instance }, { __index = _G }); - api_instance.environment = pluginenv; - - setfenv(mod, pluginenv); - hosts[host].modules = modulemap[host]; - modulemap[host][module_name] = pluginenv; - - local success, err = pcall(mod); - if success then - if module_has_method(pluginenv, "load") then - success, err = call_module_method(pluginenv, "load"); - if not success then - log("warn", "Error loading module '%s' on '%s': %s", module_name, host, err or "nil"); - end - end - - -- Use modified host, if the module set one - if api_instance.host == "*" and host ~= "*" then - modulemap[host][module_name] = nil; - modulemap["*"][module_name] = pluginenv; - api_instance:set_global(); - end - else - log("error", "Error initializing module '%s' on '%s': %s", module_name, host, err or "nil"); - end - if success then - (hosts[api_instance.host] or prosody).events.fire_event("module-loaded", { module = module_name, host = host }); - return true; - else -- load failed, unloading - unload(api_instance.host, module_name); - return nil, err; - end -end - -function get_module(host, name) - return modulemap[host] and modulemap[host][name]; -end - -function is_loaded(host, name) - return modulemap[host] and modulemap[host][name] and true; -end - -function unload(host, name, ...) +local function do_unload_module(host, name) local mod = get_module(host, name); if not mod then return nil, "module-not-loaded"; end @@ -193,11 +125,70 @@ end end modulemap[host][name] = nil; - (hosts[host] or prosody).events.fire_event("module-unloaded", { module = name, host = host }); return true; end -function reload(host, name, ...) +local function do_load_module(host, module_name) + if not (host and module_name) then + return nil, "insufficient-parameters"; + elseif not hosts[host] then + return nil, "unknown-host"; + end + + if not modulemap[host] then + modulemap[host] = {}; + end + + if 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"; + elseif modulemap["*"][module_name] then + return nil, "global-module-already-loaded"; + end + + + local mod, err = pluginloader.load_code(module_name); + if not mod then + log("error", "Unable to load module '%s': %s", module_name or "nil", err or "nil"); + return nil, err; + end + + local _log = logger.init(host..":"..module_name); + local api_instance = setmetatable({ name = module_name, host = host, path = err, + _log = _log, log = function (self, ...) return _log(...); end } + , { __index = api }); + + local pluginenv = setmetatable({ module = api_instance }, { __index = _G }); + api_instance.environment = pluginenv; + + setfenv(mod, pluginenv); + hosts[host].modules = modulemap[host]; + modulemap[host][module_name] = pluginenv; + + local ok, err = pcall(mod); + if ok then + -- Call module's "load" + if module_has_method(pluginenv, "load") then + ok, err = call_module_method(pluginenv, "load"); + if not ok then + log("warn", "Error loading module '%s' on '%s': %s", module_name, host, err or "nil"); + end + end + + -- Use modified host, if the module set one + if api_instance.host == "*" and host ~= "*" then + modulemap[host][module_name] = nil; + modulemap["*"][module_name] = pluginenv; + api_instance:set_global(); + end + else + log("error", "Error initializing module '%s' on '%s': %s", module_name, host, err or "nil"); + do_unload_module(api_instance.host, module_name); -- Ignore error, module may be partially-loaded + end + return ok and mod, err; +end + +local function do_reload_module(host, name) local mod = get_module(host, name); if not mod then return nil, "module-not-loaded"; end @@ -224,8 +215,8 @@ end end - unload(host, name, ...); - local ok, err = load(host, name, ...); + do_unload_module(host, name); + local ok, err = do_load_module(host, name); if ok then mod = get_module(host, name); if module_has_method(mod, "restore") then @@ -234,11 +225,52 @@ log("warn", "Error restoring module '%s' from '%s': %s", name, host, err); end end - return true; + end + return ok and mod, err; +end + +--- Public API --- + +-- Load a module and fire module-loaded event +function load(host, name) + local mod, err = do_load_module(host, name); + if mod then + (hosts[mod.host] or prosody).events.fire_event("module-loaded", { module = module_name, host = host }); + end + return mod, err; +end + +-- Unload a module and fire module-unloaded +function unload(host, name) + local ok, err = do_unload_module(host, name); + if ok then + (hosts[host] or prosody).events.fire_event("module-unloaded", { module = name, host = host }); end return ok, err; end +function reload(host, name) + local ok, err = do_reload_module(host, name); + if ok then + (hosts[host] or prosody).events.fire_event("module-reloaded", { module = name, host = host }); + elseif not is_loaded(host, name) then + (hosts[host] or prosody).events.fire_event("module-unloaded", { module = name, host = host }); + end + return ok, err; +end + +function get_module(host, name) + return modulemap[host] and modulemap[host][name]; +end + +function get_modules(host) + return modulemap[host]; +end + +function is_loaded(host, name) + return modulemap[host] and modulemap[host][name] and true; +end + function module_has_method(module, method) return type(module.module[method]) == "function"; end