diff options
Diffstat (limited to 'lib/ejabberd/config/config.ex')
-rw-r--r-- | lib/ejabberd/config/config.ex | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/lib/ejabberd/config/config.ex b/lib/ejabberd/config/config.ex new file mode 100644 index 000000000..4d1270bc1 --- /dev/null +++ b/lib/ejabberd/config/config.ex @@ -0,0 +1,145 @@ +defmodule Ejabberd.Config do + @moduledoc """ + Base module for configuration file. + + Imports macros for the config DSL and contains functions + for working/starting the configuration parsed. + """ + + alias Ejabberd.Config.EjabberdModule + alias Ejabberd.Config.Attr + alias Ejabberd.Config.EjabberdLogger + + defmacro __using__(_opts) do + quote do + import Ejabberd.Config, only: :macros + import Ejabberd.Logger + + @before_compile Ejabberd.Config + end + end + + # Validate the modules parsed and log validation errors at compile time. + # Could be also possible to interrupt the compilation&execution by throwing + # an exception if necessary. + def __before_compile__(_env) do + get_modules_parsed_in_order + |> EjabberdModule.validate + |> EjabberdLogger.log_errors + end + + @doc """ + Given the path of the config file, it evaluates it. + """ + def init(file_path, force \\ false) do + init_already_executed = Ejabberd.Config.Store.get(:module_name) != [] + + case force do + true -> + Ejabberd.Config.Store.stop + Ejabberd.Config.Store.start_link + do_init(file_path) + false -> + if not init_already_executed, do: do_init(file_path) + end + end + + @doc """ + Returns a list with all the opts, formatted for ejabberd. + """ + def get_ejabberd_opts do + get_general_opts + |> Dict.put(:modules, get_modules_parsed_in_order()) + |> Dict.put(:listeners, get_listeners_parsed_in_order()) + |> Ejabberd.Config.OptsFormatter.format_opts_for_ejabberd + end + + @doc """ + Register the hooks defined inside the elixir config file. + """ + def start_hooks do + get_hooks_parsed_in_order() + |> Enum.each(&Ejabberd.Config.EjabberdHook.start/1) + end + + ### + ### MACROS + ### + + defmacro listen(module, do: block) do + attrs = Attr.extract_attrs_from_block_with_defaults(block) + + quote do + Ejabberd.Config.Store.put(:listeners, %EjabberdModule{ + module: unquote(module), + attrs: unquote(attrs) + }) + end + end + + defmacro module(module, do: block) do + attrs = Attr.extract_attrs_from_block_with_defaults(block) + + quote do + Ejabberd.Config.Store.put(:modules, %EjabberdModule{ + module: unquote(module), + attrs: unquote(attrs) + }) + end + end + + defmacro hook(hook_name, opts, fun) do + quote do + Ejabberd.Config.Store.put(:hooks, %Ejabberd.Config.EjabberdHook{ + hook: unquote(hook_name), + opts: unquote(opts), + fun: unquote(fun) + }) + end + end + + # Private API + + defp do_init(file_path) do + # File evaluation + Code.eval_file(file_path) |> extract_and_store_module_name() + + # Getting start/0 config + Ejabberd.Config.Store.get(:module_name) + |> case do + nil -> IO.puts "[ ERR ] Configuration module not found." + [module] -> call_start_func_and_store_data(module) + end + + # Fetching git modules and install them + get_modules_parsed_in_order() + |> EjabberdModule.fetch_git_repos + end + + # Returns the modules from the store + defp get_modules_parsed_in_order, + do: Ejabberd.Config.Store.get(:modules) |> Enum.reverse + + # Returns the listeners from the store + defp get_listeners_parsed_in_order, + do: Ejabberd.Config.Store.get(:listeners) |> Enum.reverse + + defp get_hooks_parsed_in_order, + do: Ejabberd.Config.Store.get(:hooks) |> Enum.reverse + + # Returns the general config options + defp get_general_opts, + do: Ejabberd.Config.Store.get(:general) |> List.first + + # Gets the general ejabberd options calling + # the start/0 function and stores them. + defp call_start_func_and_store_data(module) do + opts = apply(module, :start, []) + Ejabberd.Config.Store.put(:general, opts) + end + + # Stores the configuration module name + defp extract_and_store_module_name({{:module, mod, _bytes, _}, _}) do + Ejabberd.Config.Store.put(:module_name, mod) + end +end |