Software /
code /
prosody
Comparison
core/modulemanager.lua @ 4531:c778ce7e3c78
modulemanager: Move in-module API functions to core.moduleapi (half the file size, yay)
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Sun, 22 Jan 2012 18:41:55 +0000 |
parent | 4454:c73793664bfb |
child | 4532:d8dbf569766c |
comparison
equal
deleted
inserted
replaced
4481:408c2f688e4e | 4531:c778ce7e3c78 |
---|---|
43 -- We need this to let modules access the real global namespace | 43 -- We need this to let modules access the real global namespace |
44 local _G = _G; | 44 local _G = _G; |
45 | 45 |
46 module "modulemanager" | 46 module "modulemanager" |
47 | 47 |
48 api = {}; | 48 local api = _G.require "core.moduleapi"; -- Module API container |
49 local api = api; -- Module API container | |
50 | 49 |
51 local modulemap = { ["*"] = {} }; | 50 local modulemap = { ["*"] = {} }; |
52 | 51 |
53 local modulehelpers = setmetatable({}, { __index = _G }); | 52 local modulehelpers = setmetatable({}, { __index = _G }); |
54 | 53 |
251 else | 250 else |
252 return false, "no-such-method"; | 251 return false, "no-such-method"; |
253 end | 252 end |
254 end | 253 end |
255 | 254 |
256 ----- API functions exposed to modules ----------- | |
257 -- Must all be in api.* | |
258 | |
259 -- Returns the name of the current module | |
260 function api:get_name() | |
261 return self.name; | |
262 end | |
263 | |
264 -- Returns the host that the current module is serving | |
265 function api:get_host() | |
266 return self.host; | |
267 end | |
268 | |
269 function api:get_host_type() | |
270 return hosts[self.host].type; | |
271 end | |
272 | |
273 function api:set_global() | |
274 self.host = "*"; | |
275 -- Update the logger | |
276 local _log = logger.init("mod_"..self.name); | |
277 self.log = function (self, ...) return _log(...); end; | |
278 self._log = _log; | |
279 end | |
280 | |
281 function api:add_feature(xmlns) | |
282 self:add_item("feature", xmlns); | |
283 end | |
284 function api:add_identity(category, type, name) | |
285 self:add_item("identity", {category = category, type = type, name = name}); | |
286 end | |
287 function api:add_extension(data) | |
288 self:add_item("extension", data); | |
289 end | |
290 | |
291 function api:fire_event(...) | |
292 return (hosts[self.host] or prosody).events.fire_event(...); | |
293 end | |
294 | |
295 function api:hook(event, handler, priority) | |
296 hooks:set(self.host, self.name, event, handler, true); | |
297 (hosts[self.host] or prosody).events.add_handler(event, handler, priority); | |
298 end | |
299 | |
300 function api:hook_global(event, handler, priority) | |
301 hooks:set("*", self.name, event, handler, true); | |
302 prosody.events.add_handler(event, handler, priority); | |
303 end | |
304 | |
305 function api:hook_stanza(xmlns, name, handler, priority) | |
306 if not handler and type(name) == "function" then | |
307 -- If only 2 options then they specified no xmlns | |
308 xmlns, name, handler, priority = nil, xmlns, name, handler; | |
309 elseif not (handler and name) then | |
310 self:log("warn", "Error: Insufficient parameters to module:hook_stanza()"); | |
311 return; | |
312 end | |
313 return api.hook(self, "stanza/"..(xmlns and (xmlns..":") or "")..name, function (data) return handler(data.origin, data.stanza, data); end, priority); | |
314 end | |
315 | |
316 function api:require(lib) | |
317 local f, n = pluginloader.load_code(self.name, lib..".lib.lua"); | |
318 if not f then | |
319 f, n = pluginloader.load_code(lib, lib..".lib.lua"); | |
320 end | |
321 if not f then error("Failed to load plugin library '"..lib.."', error: "..n); end -- FIXME better error message | |
322 setfenv(f, self.environment); | |
323 return f(); | |
324 end | |
325 | |
326 function api:get_option(name, default_value) | |
327 local value = config.get(self.host, self.name, name); | |
328 if value == nil then | |
329 value = config.get(self.host, "core", name); | |
330 if value == nil then | |
331 value = default_value; | |
332 end | |
333 end | |
334 return value; | |
335 end | |
336 | |
337 function api:get_option_string(name, default_value) | |
338 local value = self:get_option(name, default_value); | |
339 if type(value) == "table" then | |
340 if #value > 1 then | |
341 self:log("error", "Config option '%s' does not take a list, using just the first item", name); | |
342 end | |
343 value = value[1]; | |
344 end | |
345 if value == nil then | |
346 return nil; | |
347 end | |
348 return tostring(value); | |
349 end | |
350 | |
351 function api:get_option_number(name, ...) | |
352 local value = self:get_option(name, ...); | |
353 if type(value) == "table" then | |
354 if #value > 1 then | |
355 self:log("error", "Config option '%s' does not take a list, using just the first item", name); | |
356 end | |
357 value = value[1]; | |
358 end | |
359 local ret = tonumber(value); | |
360 if value ~= nil and ret == nil then | |
361 self:log("error", "Config option '%s' not understood, expecting a number", name); | |
362 end | |
363 return ret; | |
364 end | |
365 | |
366 function api:get_option_boolean(name, ...) | |
367 local value = self:get_option(name, ...); | |
368 if type(value) == "table" then | |
369 if #value > 1 then | |
370 self:log("error", "Config option '%s' does not take a list, using just the first item", name); | |
371 end | |
372 value = value[1]; | |
373 end | |
374 if value == nil then | |
375 return nil; | |
376 end | |
377 local ret = value == true or value == "true" or value == 1 or nil; | |
378 if ret == nil then | |
379 ret = (value == false or value == "false" or value == 0); | |
380 if ret then | |
381 ret = false; | |
382 else | |
383 ret = nil; | |
384 end | |
385 end | |
386 if ret == nil then | |
387 self:log("error", "Config option '%s' not understood, expecting true/false", name); | |
388 end | |
389 return ret; | |
390 end | |
391 | |
392 function api:get_option_array(name, ...) | |
393 local value = self:get_option(name, ...); | |
394 | |
395 if value == nil then | |
396 return nil; | |
397 end | |
398 | |
399 if type(value) ~= "table" then | |
400 return array{ value }; -- Assume any non-list is a single-item list | |
401 end | |
402 | |
403 return array():append(value); -- Clone | |
404 end | |
405 | |
406 function api:get_option_set(name, ...) | |
407 local value = self:get_option_array(name, ...); | |
408 | |
409 if value == nil then | |
410 return nil; | |
411 end | |
412 | |
413 return set.new(value); | |
414 end | |
415 | |
416 local t_remove = _G.table.remove; | |
417 local module_items = multitable_new(); | |
418 function api:add_item(key, value) | |
419 self.items = self.items or {}; | |
420 self.items[key] = self.items[key] or {}; | |
421 t_insert(self.items[key], value); | |
422 self:fire_event("item-added/"..key, {source = self, item = value}); | |
423 end | |
424 function api:remove_item(key, value) | |
425 local t = self.items and self.items[key] or NULL; | |
426 for i = #t,1,-1 do | |
427 if t[i] == value then | |
428 t_remove(self.items[key], i); | |
429 self:fire_event("item-removed/"..key, {source = self, item = value}); | |
430 return value; | |
431 end | |
432 end | |
433 end | |
434 | |
435 function api:get_host_items(key) | |
436 local result = {}; | |
437 for mod_name, module in pairs(modulemap[self.host]) do | |
438 module = module.module; | |
439 if module.items then | |
440 for _, item in ipairs(module.items[key] or NULL) do | |
441 t_insert(result, item); | |
442 end | |
443 end | |
444 end | |
445 for mod_name, module in pairs(modulemap["*"]) do | |
446 module = module.module; | |
447 if module.items then | |
448 for _, item in ipairs(module.items[key] or NULL) do | |
449 t_insert(result, item); | |
450 end | |
451 end | |
452 end | |
453 return result; | |
454 end | |
455 | |
456 function api:handle_items(type, added_cb, removed_cb, existing) | |
457 self:hook("item-added/"..type, added_cb); | |
458 self:hook("item-removed/"..type, removed_cb); | |
459 if existing ~= false then | |
460 for _, item in ipairs(self:get_host_items(type)) do | |
461 added_cb({ item = item }); | |
462 end | |
463 end | |
464 end | |
465 | |
466 return _M; | 255 return _M; |