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 --------------------------------------------------------------------