comparison core/configmanager.lua @ 6722:d022cb4486bd

Merge 0.10->trunk
author Matthew Wild <mwild1@gmail.com>
date Tue, 19 May 2015 09:31:12 +0100
parents be98ebe87eef
children 6236668da30a
comparison
equal deleted inserted replaced
6705:c269ab6ab98a 6722:d022cb4486bd
26 26
27 _M.resolve_relative_path = resolve_relative_path; -- COMPAT 27 _M.resolve_relative_path = resolve_relative_path; -- COMPAT
28 28
29 local parsers = {}; 29 local parsers = {};
30 30
31 local config_mt = { __index = function (t, k) return rawget(t, "*"); end}; 31 local config_mt = { __index = function (t, _) return rawget(t, "*"); end};
32 local config = setmetatable({ ["*"] = { } }, config_mt); 32 local config = setmetatable({ ["*"] = { } }, config_mt);
33 33
34 -- When host not found, use global 34 -- When host not found, use global
35 local host_mt = { __index = function(_, k) return config["*"][k] end } 35 local host_mt = { __index = function(_, k) return config["*"][k] end }
36 36
52 if hostconfig then 52 if hostconfig then
53 return rawget(hostconfig, key); 53 return rawget(hostconfig, key);
54 end 54 end
55 end 55 end
56 56
57 local function set(config, host, key, value) 57 local function set(config_table, host, key, value)
58 if host and key then 58 if host and key then
59 local hostconfig = rawget(config, host); 59 local hostconfig = rawget(config_table, host);
60 if not hostconfig then 60 if not hostconfig then
61 hostconfig = rawset(config, host, setmetatable({}, host_mt))[host]; 61 hostconfig = rawset(config_table, host, setmetatable({}, host_mt))[host];
62 end 62 end
63 hostconfig[key] = value; 63 hostconfig[key] = value;
64 return true; 64 return true;
65 end 65 end
66 return false; 66 return false;
71 key, value = value, _oldvalue; --COMPAT with code that still uses "core" 71 key, value = value, _oldvalue; --COMPAT with code that still uses "core"
72 end 72 end
73 return set(config, host, key, value); 73 return set(config, host, key, value);
74 end 74 end
75 75
76 function load(filename, format) 76 function load(filename, config_format)
77 format = format or filename:match("%w+$"); 77 config_format = config_format or filename:match("%w+$");
78 78
79 if parsers[format] and parsers[format].load then 79 if parsers[config_format] and parsers[config_format].load then
80 local f, err = io.open(filename); 80 local f, err = io.open(filename);
81 if f then 81 if f then
82 local new_config = setmetatable({ ["*"] = { } }, config_mt); 82 local new_config = setmetatable({ ["*"] = { } }, config_mt);
83 local ok, err = parsers[format].load(f:read("*a"), filename, new_config); 83 local ok, err = parsers[config_format].load(f:read("*a"), filename, new_config);
84 f:close(); 84 f:close();
85 if ok then 85 if ok then
86 config = new_config; 86 config = new_config;
87 fire_event("config-reloaded", { 87 fire_event("config-reloaded", {
88 filename = filename, 88 filename = filename,
89 format = format, 89 format = config_format,
90 config = config 90 config = config
91 }); 91 });
92 end 92 end
93 return ok, "parser", err; 93 return ok, "parser", err;
94 end 94 end
95 return f, "file", err; 95 return f, "file", err;
96 end 96 end
97 97
98 if not format then 98 if not config_format then
99 return nil, "file", "no parser specified"; 99 return nil, "file", "no parser specified";
100 else 100 else
101 return nil, "file", "no parser for "..(format); 101 return nil, "file", "no parser for "..(config_format);
102 end 102 end
103 end 103 end
104 104
105 function save(filename, format) 105 function addparser(config_format, parser)
106 end 106 if config_format and parser then
107 107 parsers[config_format] = parser;
108 function addparser(format, parser)
109 if format and parser then
110 parsers[format] = parser;
111 end 108 end
112 end 109 end
113 110
114 -- _M needed to avoid name clash with local 'parsers' 111 -- _M needed to avoid name clash with local 'parsers'
115 function _M.parsers() 112 function _M.parsers()
116 local p = {}; 113 local p = {};
117 for format in pairs(parsers) do 114 for config_format in pairs(parsers) do
118 table.insert(p, format); 115 table.insert(p, config_format);
119 end 116 end
120 return p; 117 return p;
121 end 118 end
122 119
123 -- Built-in Lua parser 120 -- Built-in Lua parser
124 do 121 do
125 local pcall, setmetatable = _G.pcall, _G.setmetatable; 122 local pcall = _G.pcall;
126 local rawget = _G.rawget;
127 parsers.lua = {}; 123 parsers.lua = {};
128 function parsers.lua.load(data, config_file, config) 124 function parsers.lua.load(data, config_file, config_table)
129 local env; 125 local env;
130 -- The ' = true' are needed so as not to set off __newindex when we assign the functions below 126 -- The ' = true' are needed so as not to set off __newindex when we assign the functions below
131 env = setmetatable({ 127 env = setmetatable({
132 Host = true, host = true, VirtualHost = true, 128 Host = true, host = true, VirtualHost = true,
133 Component = true, component = true, 129 Component = true, component = true,
134 Include = true, include = true, RunScript = true }, { 130 Include = true, include = true, RunScript = true }, {
135 __index = function (t, k) 131 __index = function (_, k)
136 return rawget(_G, k); 132 return rawget(_G, k);
137 end, 133 end,
138 __newindex = function (t, k, v) 134 __newindex = function (_, k, v)
139 set(config, env.__currenthost or "*", k, v); 135 set(config_table, env.__currenthost or "*", k, v);
140 end 136 end
141 }); 137 });
142 138
143 rawset(env, "__currenthost", "*") -- Default is global 139 rawset(env, "__currenthost", "*") -- Default is global
144 function env.VirtualHost(name) 140 function env.VirtualHost(name)
145 name = nameprep(name); 141 name = nameprep(name);
146 if rawget(config, name) and rawget(config[name], "component_module") then 142 if rawget(config_table, name) and rawget(config_table[name], "component_module") then
147 error(format("Host %q clashes with previously defined %s Component %q, for services use a sub-domain like conference.%s", 143 error(format("Host %q clashes with previously defined %s Component %q, for services use a sub-domain like conference.%s",
148 name, config[name].component_module:gsub("^%a+$", { component = "external", muc = "MUC"}), name, name), 0); 144 name, config_table[name].component_module:gsub("^%a+$", { component = "external", muc = "MUC"}), name, name), 0);
149 end 145 end
150 rawset(env, "__currenthost", name); 146 rawset(env, "__currenthost", name);
151 -- Needs at least one setting to logically exist :) 147 -- Needs at least one setting to logically exist :)
152 set(config, name or "*", "defined", true); 148 set(config_table, name or "*", "defined", true);
153 return function (config_options) 149 return function (config_options)
154 rawset(env, "__currenthost", "*"); -- Return to global scope 150 rawset(env, "__currenthost", "*"); -- Return to global scope
155 for option_name, option_value in pairs(config_options) do 151 for option_name, option_value in pairs(config_options) do
156 set(config, name or "*", option_name, option_value); 152 set(config_table, name or "*", option_name, option_value);
157 end 153 end
158 end; 154 end;
159 end 155 end
160 env.Host, env.host = env.VirtualHost, env.VirtualHost; 156 env.Host, env.host = env.VirtualHost, env.VirtualHost;
161 157
162 function env.Component(name) 158 function env.Component(name)
163 name = nameprep(name); 159 name = nameprep(name);
164 if rawget(config, name) and rawget(config[name], "defined") and not rawget(config[name], "component_module") then 160 if rawget(config_table, name) and rawget(config_table[name], "defined") and not rawget(config_table[name], "component_module") then
165 error(format("Component %q clashes with previously defined Host %q, for services use a sub-domain like conference.%s", 161 error(format("Component %q clashes with previously defined Host %q, for services use a sub-domain like conference.%s",
166 name, name, name), 0); 162 name, name, name), 0);
167 end 163 end
168 set(config, name, "component_module", "component"); 164 set(config_table, name, "component_module", "component");
169 -- Don't load the global modules by default 165 -- Don't load the global modules by default
170 set(config, name, "load_global_modules", false); 166 set(config_table, name, "load_global_modules", false);
171 rawset(env, "__currenthost", name); 167 rawset(env, "__currenthost", name);
172 local function handle_config_options(config_options) 168 local function handle_config_options(config_options)
173 rawset(env, "__currenthost", "*"); -- Return to global scope 169 rawset(env, "__currenthost", "*"); -- Return to global scope
174 for option_name, option_value in pairs(config_options) do 170 for option_name, option_value in pairs(config_options) do
175 set(config, name or "*", option_name, option_value); 171 set(config_table, name or "*", option_name, option_value);
176 end 172 end
177 end 173 end
178 174
179 return function (module) 175 return function (module)
180 if type(module) == "string" then 176 if type(module) == "string" then
181 set(config, name, "component_module", module); 177 set(config_table, name, "component_module", module);
182 return handle_config_options; 178 return handle_config_options;
183 end 179 end
184 return handle_config_options(module); 180 return handle_config_options(module);
185 end 181 end
186 end 182 end
187 env.component = env.Component; 183 env.component = env.Component;
188 184
189 function env.Include(file) 185 function env.Include(file)
186 -- Check whether this is a wildcard Include
190 if file:match("[*?]") then 187 if file:match("[*?]") then
191 local lfs = deps.softreq "lfs"; 188 local lfs = deps.softreq "lfs";
192 if not lfs then 189 if not lfs then
193 error(format("Error expanding wildcard pattern in Include %q - LuaFileSystem not available", file)); 190 error(format("Error expanding wildcard pattern in Include %q - LuaFileSystem not available", file));
194 end 191 end
204 for f in lfs.dir(path) do 201 for f in lfs.dir(path) do
205 if f:sub(1,1) ~= "." and f:match(patt) then 202 if f:sub(1,1) ~= "." and f:match(patt) then
206 env.Include(path..path_sep..f); 203 env.Include(path..path_sep..f);
207 end 204 end
208 end 205 end
209 else 206 return;
210 local file = resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), file); 207 end
211 local f, err = io.open(file); 208 -- Not a wildcard, so resolve (potentially) relative path and run through config parser
212 if f then 209 file = resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), file);
213 local ret, err = parsers.lua.load(f:read("*a"), file, config); 210 local f, err = io.open(file);
214 if not ret then error(err:gsub("%[string.-%]", file), 0); end 211 if f then
215 end 212 local ret, err = parsers.lua.load(f:read("*a"), file, config_table);
216 if not f then error("Error loading included "..file..": "..err, 0); end 213 if not ret then error(err:gsub("%[string.-%]", file), 0); end
217 return f, err; 214 end
218 end 215 if not f then error("Error loading included "..file..": "..err, 0); end
216 return f, err;
219 end 217 end
220 env.include = env.Include; 218 env.include = env.Include;
221 219
222 function env.RunScript(file) 220 function env.RunScript(file)
223 return dofile(resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), file)); 221 return dofile(resolve_relative_path(config_file:gsub("[^"..path_sep.."]+$", ""), file));