Mercurial > prosody-hg
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)); |
