aboutsummaryrefslogtreecommitdiff
path: root/lib/ejabberd/config/config.ex
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ejabberd/config/config.ex')
-rw-r--r--lib/ejabberd/config/config.ex145
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