20 module "configmanager" |
20 module "configmanager" |
21 |
21 |
22 local parsers = {}; |
22 local parsers = {}; |
23 |
23 |
24 local config_mt = { __index = function (t, k) return rawget(t, "*"); end}; |
24 local config_mt = { __index = function (t, k) return rawget(t, "*"); end}; |
25 local config = setmetatable({ ["*"] = { core = {} } }, config_mt); |
25 local config = setmetatable({ ["*"] = { } }, config_mt); |
26 |
26 |
27 -- When host not found, use global |
27 -- When host not found, use global |
28 local host_mt = { }; |
28 local host_mt = { }; |
29 |
29 |
30 -- When key not found in section, check key in global's section |
|
31 function section_mt(section_name) |
|
32 return { __index = function (t, k) |
|
33 local section = rawget(config["*"], section_name); |
|
34 if not section then return nil; end |
|
35 return section[k]; |
|
36 end |
|
37 }; |
|
38 end |
|
39 |
|
40 function getconfig() |
30 function getconfig() |
41 return config; |
31 return config; |
42 end |
32 end |
43 |
33 |
44 function get(host, section, key) |
34 function get(host, key, _oldkey) |
45 if not key then |
35 if key == "core" then |
46 section, key = "core", section; |
36 key = _oldkey; -- COMPAT with code that still uses "core" |
47 end |
37 end |
48 local sec = config[host][section]; |
38 return config[host][key]; |
49 if sec then |
39 end |
50 return sec[key]; |
40 function _M.rawget(host, key, _oldkey) |
51 end |
41 if key == "core" then |
52 return nil; |
42 key = _oldkey; -- COMPAT with code that still uses "core" |
53 end |
43 end |
54 function _M.rawget(host, section, key) |
|
55 local hostconfig = rawget(config, host); |
44 local hostconfig = rawget(config, host); |
56 if hostconfig then |
45 if hostconfig then |
57 local sectionconfig = rawget(hostconfig, section); |
46 return rawget(hostconfig, key); |
58 if sectionconfig then |
47 end |
59 return rawget(sectionconfig, key); |
48 end |
60 end |
49 |
61 end |
50 local function set(config, host, key, value) |
62 end |
51 if host and key then |
63 |
|
64 local function set(config, host, section, key, value) |
|
65 if host and section and key then |
|
66 local hostconfig = rawget(config, host); |
52 local hostconfig = rawget(config, host); |
67 if not hostconfig then |
53 if not hostconfig then |
68 hostconfig = rawset(config, host, setmetatable({}, host_mt))[host]; |
54 hostconfig = rawset(config, host, setmetatable({}, host_mt))[host]; |
69 end |
55 end |
70 if not rawget(hostconfig, section) then |
56 hostconfig[key] = value; |
71 hostconfig[section] = setmetatable({}, section_mt(section)); |
|
72 end |
|
73 hostconfig[section][key] = value; |
|
74 return true; |
57 return true; |
75 end |
58 end |
76 return false; |
59 return false; |
77 end |
60 end |
78 |
61 |
79 function _M.set(host, section, key, value) |
62 function _M.set(host, key, value, _oldvalue) |
80 return set(config, host, section, key, value); |
63 if key == "core" then |
|
64 key, value = value, _oldvalue; --COMPAT with code that still uses "core" |
|
65 end |
|
66 return set(config, host, key, value); |
81 end |
67 end |
82 |
68 |
83 -- Helper function to resolve relative paths (needed by config) |
69 -- Helper function to resolve relative paths (needed by config) |
84 do |
70 do |
85 local rel_path_start = ".."..path_sep; |
71 local rel_path_start = ".."..path_sep; |
174 env = setmetatable({ |
160 env = setmetatable({ |
175 Host = true, host = true, VirtualHost = true, |
161 Host = true, host = true, VirtualHost = true, |
176 Component = true, component = true, |
162 Component = true, component = true, |
177 Include = true, include = true, RunScript = true }, { |
163 Include = true, include = true, RunScript = true }, { |
178 __index = function (t, k) |
164 __index = function (t, k) |
179 return rawget(_G, k) or |
165 return rawget(_G, k); |
180 function (settings_table) |
|
181 config[__currenthost or "*"][k] = settings_table; |
|
182 end; |
|
183 end, |
166 end, |
184 __newindex = function (t, k, v) |
167 __newindex = function (t, k, v) |
185 set(config, env.__currenthost or "*", "core", k, v); |
168 set(config, env.__currenthost or "*", k, v); |
186 end |
169 end |
187 }); |
170 }); |
188 |
171 |
189 rawset(env, "__currenthost", "*") -- Default is global |
172 rawset(env, "__currenthost", "*") -- Default is global |
190 function env.VirtualHost(name) |
173 function env.VirtualHost(name) |
191 if rawget(config, name) and rawget(config[name].core, "component_module") then |
174 if rawget(config, name) and rawget(config[name], "component_module") then |
192 error(format("Host %q clashes with previously defined %s Component %q, for services use a sub-domain like conference.%s", |
175 error(format("Host %q clashes with previously defined %s Component %q, for services use a sub-domain like conference.%s", |
193 name, config[name].core.component_module:gsub("^%a+$", { component = "external", muc = "MUC"}), name, name), 0); |
176 name, config[name].component_module:gsub("^%a+$", { component = "external", muc = "MUC"}), name, name), 0); |
194 end |
177 end |
195 rawset(env, "__currenthost", name); |
178 rawset(env, "__currenthost", name); |
196 -- Needs at least one setting to logically exist :) |
179 -- Needs at least one setting to logically exist :) |
197 set(config, name or "*", "core", "defined", true); |
180 set(config, name or "*", "defined", true); |
198 return function (config_options) |
181 return function (config_options) |
199 rawset(env, "__currenthost", "*"); -- Return to global scope |
182 rawset(env, "__currenthost", "*"); -- Return to global scope |
200 for option_name, option_value in pairs(config_options) do |
183 for option_name, option_value in pairs(config_options) do |
201 set(config, name or "*", "core", option_name, option_value); |
184 set(config, name or "*", option_name, option_value); |
202 end |
185 end |
203 end; |
186 end; |
204 end |
187 end |
205 env.Host, env.host = env.VirtualHost, env.VirtualHost; |
188 env.Host, env.host = env.VirtualHost, env.VirtualHost; |
206 |
189 |
207 function env.Component(name) |
190 function env.Component(name) |
208 if rawget(config, name) and rawget(config[name].core, "defined") and not rawget(config[name].core, "component_module") then |
191 if rawget(config, name) and rawget(config[name], "defined") and not rawget(config[name], "component_module") then |
209 error(format("Component %q clashes with previously defined Host %q, for services use a sub-domain like conference.%s", |
192 error(format("Component %q clashes with previously defined Host %q, for services use a sub-domain like conference.%s", |
210 name, name, name), 0); |
193 name, name, name), 0); |
211 end |
194 end |
212 set(config, name, "core", "component_module", "component"); |
195 set(config, name, "component_module", "component"); |
213 -- Don't load the global modules by default |
196 -- Don't load the global modules by default |
214 set(config, name, "core", "load_global_modules", false); |
197 set(config, name, "load_global_modules", false); |
215 rawset(env, "__currenthost", name); |
198 rawset(env, "__currenthost", name); |
216 local function handle_config_options(config_options) |
199 local function handle_config_options(config_options) |
217 rawset(env, "__currenthost", "*"); -- Return to global scope |
200 rawset(env, "__currenthost", "*"); -- Return to global scope |
218 for option_name, option_value in pairs(config_options) do |
201 for option_name, option_value in pairs(config_options) do |
219 set(config, name or "*", "core", option_name, option_value); |
202 set(config, name or "*", option_name, option_value); |
220 end |
203 end |
221 end |
204 end |
222 |
205 |
223 return function (module) |
206 return function (module) |
224 if type(module) == "string" then |
207 if type(module) == "string" then |
225 set(config, name, "core", "component_module", module); |
208 set(config, name, "component_module", module); |
226 return handle_config_options; |
209 return handle_config_options; |
227 end |
210 end |
228 return handle_config_options(module); |
211 return handle_config_options(module); |
229 end |
212 end |
230 end |
213 end |