Software /
code /
prosody
Comparison
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 |
comparison
equal
deleted
inserted
replaced
437:c1a720db2157 | 438:193f9dd64f17 |
---|---|
1 | 1 |
2 local log = require "util.logger".init("modulemanager") | 2 |
3 local logger = require "util.logger"; | |
4 local log = logger.init("modulemanager") | |
3 | 5 |
4 local loadfile, pcall = loadfile, pcall; | 6 local loadfile, pcall = loadfile, pcall; |
5 local setmetatable, setfenv, getfenv = setmetatable, setfenv, getfenv; | 7 local setmetatable, setfenv, getfenv = setmetatable, setfenv, getfenv; |
6 local pairs, ipairs = pairs, ipairs; | 8 local pairs, ipairs = pairs, ipairs; |
7 local t_insert = table.insert; | 9 local t_insert = table.insert; |
12 local _G = _G; | 14 local _G = _G; |
13 local debug = debug; | 15 local debug = debug; |
14 | 16 |
15 module "modulemanager" | 17 module "modulemanager" |
16 | 18 |
19 local api = {}; -- Module API container | |
20 | |
21 local modulemap = {}; | |
22 | |
17 local handler_info = {}; | 23 local handler_info = {}; |
18 local handlers = {}; | 24 local stanza_handlers = {}; |
19 | 25 |
20 local modulehelpers = setmetatable({}, { __index = _G }); | 26 local modulehelpers = setmetatable({}, { __index = _G }); |
21 | 27 |
22 local function _add_iq_handler(module, origin_type, xmlns, handler) | |
23 handlers[origin_type] = handlers[origin_type] or {}; | |
24 handlers[origin_type].iq = handlers[origin_type].iq or {}; | |
25 if not handlers[origin_type].iq[xmlns] then | |
26 handlers[origin_type].iq[xmlns]= handler; | |
27 handler_info[handler] = module; | |
28 log("debug", "mod_%s now handles tag 'iq' with query namespace '%s'", module.name, xmlns); | |
29 else | |
30 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); | |
31 end | |
32 end | |
33 | 28 |
34 function modulehelpers.add_iq_handler(origin_type, xmlns, handler) | 29 function load(host, module_name, config) |
35 if not (origin_type and handler and xmlns) then return false; end | 30 local mod, err = loadfile("plugins/mod_"..module_name..".lua"); |
36 if type(origin_type) == "table" then | |
37 for _, origin_type in ipairs(origin_type) do | |
38 _add_iq_handler(getfenv(2).module, origin_type, xmlns, handler); | |
39 end | |
40 return; | |
41 end | |
42 _add_iq_handler(getfenv(2).module, origin_type, xmlns, handler); | |
43 end | |
44 | |
45 local function _add_handler(module, origin_type, tag, xmlns, handler) | |
46 handlers[origin_type] = handlers[origin_type] or {}; | |
47 if not handlers[origin_type][tag] then | |
48 handlers[origin_type][tag] = handlers[origin_type][tag] or {}; | |
49 handlers[origin_type][tag][xmlns]= handler; | |
50 handler_info[handler] = module; | |
51 log("debug", "mod_%s now handles tag '%s'", module.name, tag); | |
52 elseif handler_info[handlers[origin_type][tag]] then | |
53 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); | |
54 end | |
55 end | |
56 | |
57 function modulehelpers.add_handler(origin_type, tag, xmlns, handler) | |
58 if not (origin_type and tag and xmlns and handler) then return false; end | |
59 if type(origin_type) == "table" then | |
60 for _, origin_type in ipairs(origin_type) do | |
61 _add_handler(getfenv(2).module, origin_type, tag, xmlns, handler); | |
62 end | |
63 return; | |
64 end | |
65 _add_handler(getfenv(2).module, origin_type, tag, xmlns, handler); | |
66 end | |
67 | |
68 function load(name) | |
69 local mod, err = loadfile("plugins/mod_"..name..".lua"); | |
70 if not mod then | 31 if not mod then |
71 log("error", "Unable to load module '%s': %s", name or "nil", err or "nil"); | 32 log("error", "Unable to load module '%s': %s", module_name or "nil", err or "nil"); |
72 return nil, err; | 33 return nil, err; |
73 end | 34 end |
74 | 35 |
75 local pluginenv = setmetatable({ module = { name = name } }, { __index = modulehelpers }); | 36 if not modulemap[host] then |
37 modulemap[host] = {}; | |
38 stanza_handlers[host] = {}; | |
39 elseif modulemap[host][module_name] then | |
40 log("warn", "%s is already loaded for %s, so not loading again", module_name, host); | |
41 return nil, "module-already-loaded"; | |
42 end | |
43 | |
44 local _log = logger.init(host..":"..module_name); | |
45 local api_instance = setmetatable({ name = module_name, host = host, config = config, _log = _log, log = function (self, ...) return _log(...); end }, { __index = api }); | |
46 | |
47 local pluginenv = setmetatable({ module = api_instance }, { __index = _G }); | |
76 | 48 |
77 setfenv(mod, pluginenv); | 49 setfenv(mod, pluginenv); |
50 | |
78 local success, ret = pcall(mod); | 51 local success, ret = pcall(mod); |
79 if not success then | 52 if not success then |
80 log("error", "Error initialising module '%s': %s", name or "nil", ret or "nil"); | 53 log("error", "Error initialising module '%s': %s", name or "nil", ret or "nil"); |
81 return nil, ret; | 54 return nil, ret; |
82 end | 55 end |
56 | |
57 modulemap[host][module_name] = mod; | |
58 | |
83 return true; | 59 return true; |
84 end | 60 end |
85 | 61 |
86 function handle_stanza(origin, stanza) | 62 function handle_stanza(host, origin, stanza) |
87 local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns, origin.type; | 63 local name, xmlns, origin_type = stanza.name, stanza.attr.xmlns, origin.type; |
88 | 64 |
65 local handlers = stanza_handlers[host]; | |
66 if not handlers then | |
67 log("warn", "No handlers for %s", host); | |
68 return false; | |
69 end | |
70 | |
89 if name == "iq" and xmlns == "jabber:client" and handlers[origin_type] then | 71 if name == "iq" and xmlns == "jabber:client" and handlers[origin_type] then |
90 log("debug", "Stanza is an <iq/>"); | |
91 local child = stanza.tags[1]; | 72 local child = stanza.tags[1]; |
92 if child then | 73 if child then |
93 local xmlns = child.attr.xmlns or xmlns; | 74 local xmlns = child.attr.xmlns or xmlns; |
94 log("debug", "Stanza of type %s from %s has xmlns: %s", name, origin_type, xmlns); | 75 log("debug", "Stanza of type %s from %s has xmlns: %s", name, origin_type, xmlns); |
95 local handler = handlers[origin_type][name] and handlers[origin_type][name][xmlns]; | 76 local handler = handlers[origin_type][name] and handlers[origin_type][name][xmlns]; |
110 end | 91 end |
111 log("debug", "Stanza unhandled by any modules, xmlns: %s", stanza.attr.xmlns); | 92 log("debug", "Stanza unhandled by any modules, xmlns: %s", stanza.attr.xmlns); |
112 return false; -- we didn't handle it | 93 return false; -- we didn't handle it |
113 end | 94 end |
114 | 95 |
96 ----- API functions exposed to modules ----------- | |
97 -- Must all be in api.* | |
98 | |
99 -- Returns the name of the current module | |
100 function api:get_name() | |
101 return self.name; | |
102 end | |
103 | |
104 -- Returns the host that the current module is serving | |
105 function api:get_host() | |
106 return self.host; | |
107 end | |
108 | |
109 | |
110 local function _add_iq_handler(module, origin_type, xmlns, handler) | |
111 local handlers = stanza_handlers[module.host]; | |
112 handlers[origin_type] = handlers[origin_type] or {}; | |
113 handlers[origin_type].iq = handlers[origin_type].iq or {}; | |
114 if not handlers[origin_type].iq[xmlns] then | |
115 handlers[origin_type].iq[xmlns]= handler; | |
116 handler_info[handler] = module; | |
117 module:log("debug", "I now handle tag 'iq' [%s] with payload namespace '%s'", origin_type, xmlns); | |
118 else | |
119 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); | |
120 end | |
121 end | |
122 | |
123 function api:add_iq_handler(origin_type, xmlns, handler) | |
124 if not (origin_type and handler and xmlns) then return false; end | |
125 if type(origin_type) == "table" then | |
126 for _, origin_type in ipairs(origin_type) do | |
127 _add_iq_handler(self, origin_type, xmlns, handler); | |
128 end | |
129 return; | |
130 end | |
131 _add_iq_handler(self, origin_type, xmlns, handler); | |
132 end | |
133 | |
134 | |
115 do | 135 do |
116 local event_handlers = {}; | 136 local event_handlers = {}; |
117 | 137 |
118 function modulehelpers.add_event_hook(name, handler) | 138 function api:add_event_hook(name, handler) |
119 if not event_handlers[name] then | 139 if not event_handlers[name] then |
120 event_handlers[name] = {}; | 140 event_handlers[name] = {}; |
121 end | 141 end |
122 t_insert(event_handlers[name] , handler); | 142 t_insert(event_handlers[name] , handler); |
143 self:log("debug", "Subscribed to %s", name); | |
123 end | 144 end |
124 | 145 |
125 function fire_event(name, ...) | 146 function fire_event(name, ...) |
126 local event_handlers = event_handlers[name]; | 147 local event_handlers = event_handlers[name]; |
127 if event_handlers then | 148 if event_handlers then |
130 end | 151 end |
131 end | 152 end |
132 end | 153 end |
133 end | 154 end |
134 | 155 |
156 | |
157 local function _add_handler(module, origin_type, tag, xmlns, handler) | |
158 local handlers = stanza_handlers[module.host]; | |
159 handlers[origin_type] = handlers[origin_type] or {}; | |
160 if not handlers[origin_type][tag] then | |
161 handlers[origin_type][tag] = handlers[origin_type][tag] or {}; | |
162 handlers[origin_type][tag][xmlns]= handler; | |
163 handler_info[handler] = module; | |
164 module:log("debug", "I now handle tag '%s' [%s] with xmlns '%s'", tag, origin_type, xmlns); | |
165 elseif handler_info[handlers[origin_type][tag]] then | |
166 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); | |
167 end | |
168 end | |
169 | |
170 function api:add_handler(origin_type, tag, xmlns, handler) | |
171 if not (origin_type and tag and xmlns and handler) then return false; end | |
172 if type(origin_type) == "table" then | |
173 for _, origin_type in ipairs(origin_type) do | |
174 _add_handler(self, origin_type, tag, xmlns, handler); | |
175 end | |
176 return; | |
177 end | |
178 _add_handler(self, origin_type, tag, xmlns, handler); | |
179 end | |
180 | |
181 -------------------------------------------------------------------- | |
182 | |
135 return _M; | 183 return _M; |