25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-12-26 17:38:45 +01:00

Allow {mod_}opt_type to transform values passed to it, and for better error reporting

This commit is contained in:
Paweł Chmielowski 2016-06-21 12:25:29 +02:00
parent b2f53fb962
commit 4b9613e8fe
2 changed files with 48 additions and 24 deletions

View File

@ -770,22 +770,32 @@ add_option(Opt, Val) ->
-spec prepare_opt_val(any(), any(), check_fun(), any()) -> any().
prepare_opt_val(Opt, Val, F, Default) ->
Res = case F of
Call = case F of
{Mod, Fun} ->
catch Mod:Fun(Val);
fun() -> Mod:Fun(Val) end;
_ ->
catch F(Val)
fun() -> F(Val) end
end,
case Res of
{'EXIT', _} ->
try Call() of
Res ->
Res
catch {replace_with, NewRes} ->
NewRes;
{invalid_syntax, Error} ->
?WARNING_MSG("incorrect value '~s' of option '~s', "
"using '~s' as fallback: ~s",
[format_term(Val),
format_term(Opt),
format_term(Default),
Error]),
Default;
_:_ ->
?WARNING_MSG("incorrect value '~s' of option '~s', "
"using '~s' as fallback",
[format_term(Val),
format_term(Opt),
format_term(Default)]),
Default;
_ ->
Res
Default
end.
-type check_fun() :: fun((any()) -> any()) | {module(), atom()}.
@ -908,19 +918,26 @@ get_modules_with_options() ->
validate_opts(#state{opts = Opts} = State) ->
ModOpts = get_modules_with_options(),
NewOpts = lists:filter(
fun(#local_config{key = {Opt, _Host}, value = Val}) ->
NewOpts = lists:filtermap(
fun(#local_config{key = {Opt, _Host}, value = Val} = In) ->
case dict:find(Opt, ModOpts) of
{ok, [Mod|_]} ->
VFun = Mod:opt_type(Opt),
case catch VFun(Val) of
{'EXIT', _} ->
try VFun(Val) of
_ ->
true
catch {replace_with, NewVal} ->
{true, In#local_config{value = NewVal}};
{invalid_syntax, Error} ->
?ERROR_MSG("ignoring option '~s' with "
"invalid value: ~p: ~s",
[Opt, Val, Error]),
false;
_:_ ->
?ERROR_MSG("ignoring option '~s' with "
"invalid value: ~p",
[Opt, Val]),
false;
_ ->
true
false
end;
_ ->
?ERROR_MSG("unknown option '~s' will be likely"

View File

@ -266,18 +266,25 @@ get_opt_host(Host, Opts, Default) ->
ejabberd_regexp:greplace(Val, <<"@HOST@">>, Host).
validate_opts(Module, Opts) ->
lists:filter(
lists:filtermap(
fun({Opt, Val}) ->
case catch Module:mod_opt_type(Opt) of
VFun when is_function(VFun) ->
case catch VFun(Val) of
{'EXIT', _} ->
try VFun(Val) of
_ ->
true
catch {replace_with, NewVal} ->
{true, {Opt, NewVal}};
{invalid_syntax, Error} ->
?ERROR_MSG("ignoring invalid value '~p' for "
"option '~s' of module '~s': ~s",
[Val, Opt, Module, Error]),
false;
_:_ ->
?ERROR_MSG("ignoring invalid value '~p' for "
"option '~s' of module '~s'",
[Val, Opt, Module]),
false;
_ ->
true
false
end;
L when is_list(L) ->
SOpts = str:join([[$', atom_to_list(A), $'] || A <- L], <<", ">>),