core/configmanager.lua
changeset 5357 ac530c44772e
parent 5124 a4a74a0e9b9c
child 5380 e119e378b1d9
equal deleted inserted replaced
5354:18ebc3874364 5357:ac530c44772e
    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;
   120 	format = format or filename:match("%w+$");
   106 	format = format or filename:match("%w+$");
   121 
   107 
   122 	if parsers[format] and parsers[format].load then
   108 	if parsers[format] and parsers[format].load then
   123 		local f, err = io.open(filename);
   109 		local f, err = io.open(filename);
   124 		if f then
   110 		if f then
   125 			local new_config = setmetatable({ ["*"] = { core = {} } }, config_mt);
   111 			local new_config = setmetatable({ ["*"] = { } }, config_mt);
   126 			local ok, err = parsers[format].load(f:read("*a"), filename, new_config);
   112 			local ok, err = parsers[format].load(f:read("*a"), filename, new_config);
   127 			f:close();
   113 			f:close();
   128 			if ok then
   114 			if ok then
   129 				config = new_config;
   115 				config = new_config;
   130 				fire_event("config-reloaded", {
   116 				fire_event("config-reloaded", {
   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