Merge 0.9->0.10
[prosody.git] / core / moduleapi.lua
index da44db5ff9147ddc0fbe9bfaa053d9134b881d2a..e32c116aa7fe57d694df7a79b86d9c0251bfb887 100644 (file)
@@ -1,23 +1,26 @@
 -- Prosody IM
 -- Copyright (C) 2008-2012 Matthew Wild
 -- Copyright (C) 2008-2012 Waqas Hussain
--- 
+--
 -- This project is MIT/X11 licensed. Please see the
 -- COPYING file in the source package for more information.
 --
 
 local config = require "core.configmanager";
-local modulemanager = require "modulemanager"; -- This is necessary to avoid require loops
+local modulemanager; -- This gets set from modulemanager
 local array = require "util.array";
 local set = require "util.set";
 local logger = require "util.logger";
 local pluginloader = require "util.pluginloader";
 local timer = require "util.timer";
+local resolve_relative_path = require"util.paths".resolve_relative_path;
+local measure = require "core.statsmanager".measure;
 
 local t_insert, t_remove, t_concat = table.insert, table.remove, table.concat;
 local error, setmetatable, type = error, setmetatable, type;
 local ipairs, pairs, select, unpack = ipairs, pairs, select, unpack;
 local tonumber, tostring = tonumber, tostring;
+local require = require;
 
 local prosody = prosody;
 local hosts = prosody.hosts;
@@ -44,7 +47,7 @@ function api:get_host()
 end
 
 function api:get_host_type()
-       return self.host ~= "*" and hosts[self.host].type or nil;
+       return (self.host == "*" and "global") or hosts[self.host].type or "local";
 end
 
 function api:set_global()
@@ -74,7 +77,7 @@ end
 function api:has_identity(category, type, name)
        for _, id in ipairs(self:get_host_items("identity")) do
                if id.category == category and id.type == type and id.name == name then
-                       return true; 
+                       return true;
                end
        end
        return false;
@@ -113,6 +116,10 @@ function api:hook_tag(xmlns, name, handler, priority)
 end
 api.hook_stanza = api.hook_tag; -- COMPAT w/pre-0.9
 
+function api:unhook(event, handler)
+       return self:unhook_object_event((hosts[self.host] or prosody).events, event, handler);
+end
+
 function api:require(lib)
        local f, n = pluginloader.load_code(self.name, lib..".lib.lua", self.environment);
        if not f then
@@ -252,24 +259,36 @@ function api:get_option_array(name, ...)
        if value == nil then
                return nil;
        end
-       
+
        if type(value) ~= "table" then
                return array{ value }; -- Assume any non-list is a single-item list
        end
-       
+
        return array():append(value); -- Clone
 end
 
 function api:get_option_set(name, ...)
        local value = self:get_option_array(name, ...);
-       
+
        if value == nil then
                return nil;
        end
-       
+
        return set.new(value);
 end
 
+function api:get_option_inherited_set(name, ...)
+       local value = self:get_option_set(name, ...);
+       local global_value = self:context("*"):get_option_set(name, ...);
+       if not value then
+               return global_value;
+       elseif not global_value then
+               return value;
+       end
+       value:include(global_value);
+       return value;
+end
+
 function api:context(host)
        return setmetatable({host=host or "*"}, {__index=self,__newindex=self});
 end
@@ -307,7 +326,13 @@ function api:handle_items(type, added_cb, removed_cb, existing)
 end
 
 function api:provides(name, item)
-       if not item then item = self.environment; end
+       -- if not item then item = setmetatable({}, { __index = function(t,k) return rawget(self.environment, k); end }); end
+       if not item then
+               item = {}
+               for k,v in pairs(self.environment) do
+                       if k ~= "module" then item[k] = v; end
+               end
+       end
        if not item.name then
                local item_name = self.name;
                -- Strip a provider prefix to find the item name
@@ -317,6 +342,7 @@ function api:provides(name, item)
                end
                item.name = item_name;
        end
+       item._provided_by = self.name;
        self:add_item(name.."-provider", item);
 end
 
@@ -337,12 +363,21 @@ function api:get_directory()
 end
 
 function api:load_resource(path, mode)
-       path = config.resolve_relative_path(self:get_directory(), path);
+       path = resolve_relative_path(self:get_directory(), path);
        return io.open(path, mode);
 end
 
 function api:open_store(name, type)
-       return storagemanager.open(self.host, name or self.name, type);
+       return require"core.storagemanager".open(self.host, name or self.name, type);
+end
+
+function api:measure(name, type)
+       return measure(type, "/"..self.host.."/mod_"..self.name.."/"..name);
+end
+
+function api.init(mm)
+       modulemanager = mm;
+       return api;
 end
 
 return api;