Software /
code /
prosody
Comparison
core/modulemanager.lua @ 670:d5cf10b7fc44
Modulemanager: Basic modules can now be unloaded correctly
author | Waqas Hussain <waqas20@gmail.com> |
---|---|
date | Sat, 03 Jan 2009 18:45:51 +0500 |
parent | 637:30b8ad9f7b70 |
child | 672:7db1044d2fab |
child | 674:4f506c627b49 |
comparison
equal
deleted
inserted
replaced
669:9255abbb3068 | 670:d5cf10b7fc44 |
---|---|
32 local loadfile, pcall = loadfile, pcall; | 32 local loadfile, pcall = loadfile, pcall; |
33 local setmetatable, setfenv, getfenv = setmetatable, setfenv, getfenv; | 33 local setmetatable, setfenv, getfenv = setmetatable, setfenv, getfenv; |
34 local pairs, ipairs = pairs, ipairs; | 34 local pairs, ipairs = pairs, ipairs; |
35 local t_insert = table.insert; | 35 local t_insert = table.insert; |
36 local type = type; | 36 local type = type; |
37 local next = next; | |
37 | 38 |
38 local tostring, print = tostring, print; | 39 local tostring, print = tostring, print; |
39 | 40 |
40 -- We need this to let modules access the real global namespace | 41 -- We need this to let modules access the real global namespace |
41 local _G = _G; | 42 local _G = _G; |
48 | 49 |
49 local stanza_handlers = multitable_new(); | 50 local stanza_handlers = multitable_new(); |
50 local handler_info = {}; | 51 local handler_info = {}; |
51 | 52 |
52 local modulehelpers = setmetatable({}, { __index = _G }); | 53 local modulehelpers = setmetatable({}, { __index = _G }); |
54 | |
55 local features_table = multitable_new(); | |
56 local handler_table = multitable_new(); | |
57 local NULL = {}; | |
53 | 58 |
54 -- Load modules when a host is activated | 59 -- Load modules when a host is activated |
55 function load_modules_for_host(host) | 60 function load_modules_for_host(host) |
56 -- Load modules from global section | 61 -- Load modules from global section |
57 local modules_enabled = config.get("*", "core", "modules_enabled"); | 62 local modules_enabled = config.get("*", "core", "modules_enabled"); |
114 log("error", "Error initialising module '%s': %s", name or "nil", ret or "nil"); | 119 log("error", "Error initialising module '%s': %s", name or "nil", ret or "nil"); |
115 return nil, ret; | 120 return nil, ret; |
116 end | 121 end |
117 | 122 |
118 -- Use modified host, if the module set one | 123 -- Use modified host, if the module set one |
119 modulemap[api_instance.host][module_name] = mod; | 124 modulemap[api_instance.host][module_name] = pluginenv; |
120 | 125 |
121 return true; | 126 return true; |
122 end | 127 end |
123 | 128 |
124 function is_loaded(host, name) | 129 function is_loaded(host, name) |
127 | 132 |
128 function unload(host, name, ...) | 133 function unload(host, name, ...) |
129 local mod = modulemap[host] and modulemap[host][name]; | 134 local mod = modulemap[host] and modulemap[host][name]; |
130 if not mod then return nil, "module-not-loaded"; end | 135 if not mod then return nil, "module-not-loaded"; end |
131 | 136 |
132 if type(mod.unload) == "function" then | 137 --[[if type(mod.unload) == "function" then |
133 local ok, err = pcall(mod.unload, ...) | 138 local ok, err = pcall(mod.unload, ...) |
134 if (not ok) and err then | 139 if (not ok) and err then |
135 log("warn", "Non-fatal error unloading module '%s' from '%s': %s", name, host, err); | 140 log("warn", "Non-fatal error unloading module '%s' from '%s': %s", name, host, err); |
136 end | 141 end |
137 end | 142 end]] |
138 | 143 modulemap[host][name] = nil; |
144 features_table:remove(host, name); | |
145 local params = handler_table:get(host, name); -- , {module.host, origin_type, tag, xmlns} | |
146 for _, param in pairs(params) do | |
147 local handlers = stanza_handlers:get(param[1], param[2], param[3], param[4]); | |
148 handler_info[handlers[1]] = nil; | |
149 stanza_handlers:remove(param[1], param[2], param[3], param[4]); | |
150 end | |
151 return true; | |
139 end | 152 end |
140 | 153 |
141 function handle_stanza(host, origin, stanza) | 154 function handle_stanza(host, origin, stanza) |
142 local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns, origin.type; | 155 local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns, origin.type; |
143 if name == "iq" and xmlns == "jabber:client" then | 156 if name == "iq" and xmlns == "jabber:client" then |
176 local handlers = stanza_handlers:get(module.host, origin_type, tag, xmlns); | 189 local handlers = stanza_handlers:get(module.host, origin_type, tag, xmlns); |
177 local msg = (tag == "iq") and "namespace" or "payload namespace"; | 190 local msg = (tag == "iq") and "namespace" or "payload namespace"; |
178 if not handlers then | 191 if not handlers then |
179 stanza_handlers:add(module.host, origin_type, tag, xmlns, handler); | 192 stanza_handlers:add(module.host, origin_type, tag, xmlns, handler); |
180 handler_info[handler] = module; | 193 handler_info[handler] = module; |
194 handler_table:add(module.host, module.name, {module.host, origin_type, tag, xmlns}); | |
181 module:log("debug", "I now handle tag '%s' [%s] with %s '%s'", tag, origin_type, msg, xmlns); | 195 module:log("debug", "I now handle tag '%s' [%s] with %s '%s'", tag, origin_type, msg, xmlns); |
182 else | 196 else |
183 module:log("warn", "I wanted to handle tag '%s' [%s] with %s '%s' but mod_%s already handles that", tag, origin_type, msg, xmlns, handler_info[handlers[1]].module.name); | 197 module:log("warn", "I wanted to handle tag '%s' [%s] with %s '%s' but mod_%s already handles that", tag, origin_type, msg, xmlns, handler_info[handlers[1]].module.name); |
184 end | 198 end |
185 end | 199 end |
196 end | 210 end |
197 function api:add_iq_handler(origin_type, xmlns, handler) | 211 function api:add_iq_handler(origin_type, xmlns, handler) |
198 self:add_handler(origin_type, "iq", xmlns, handler); | 212 self:add_handler(origin_type, "iq", xmlns, handler); |
199 end | 213 end |
200 | 214 |
215 addDiscoInfoHandler("*host", function(reply, to, from, node) | |
216 if #node == 0 then | |
217 local done = {}; | |
218 for module, features in pairs(features_table:get(to) or NULL) do -- for each module | |
219 for feature in pairs(features) do | |
220 if not done[feature] then | |
221 reply:tag("feature", {var = feature}):up(); -- TODO cache | |
222 done[feature] = true; | |
223 end | |
224 end | |
225 end | |
226 return next(done) ~= nil; | |
227 end | |
228 end); | |
229 | |
201 function api:add_feature(xmlns) | 230 function api:add_feature(xmlns) |
202 addDiscoInfoHandler(self.host, function(reply, to, from, node) | 231 features_table:set(self.host, self.name, xmlns, true); |
203 if #node == 0 then | |
204 reply:tag("feature", {var = xmlns}):up(); | |
205 return true; | |
206 end | |
207 end); | |
208 end | 232 end |
209 | 233 |
210 function api:add_event_hook (...) return eventmanager.add_event_hook(...); end | 234 function api:add_event_hook (...) return eventmanager.add_event_hook(...); end |
211 | 235 |
212 -------------------------------------------------------------------- | 236 -------------------------------------------------------------------- |