/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __PLUGIN_MANAGER_H__
#define __PLUGIN_MANAGER_H__

#include <dlfcn.h>
#include <sys/types.h>
#include <dirent.h>

#include <utils/String8.h>
#include <utils/Vector.h>
#include <utils/KeyedVector.h>

namespace android {

const char* const PLUGIN_MANAGER_CREATE = "create";
const char* const PLUGIN_MANAGER_DESTROY = "destroy";
const char* const PLUGIN_EXTENSION = ".so";

/**
 * This is the template class for Plugin manager.
 *
 * The DrmManager uses this class to handle the plugins.
 *
 */
template<typename Type>
class TPlugInManager {
private:
    typedef void*      HANDLE;
    typedef Type*      create_t(void);
    typedef void       destroy_t(Type*);
    typedef create_t*  FPCREATE;
    typedef destroy_t* FPDESTORY;

    typedef struct _PlugInContainer {
        String8   sPath;
        HANDLE    hHandle;
        FPCREATE  fpCreate;
        FPDESTORY fpDestory;
        Type*     pInstance;

        _PlugInContainer():
            sPath("")
            ,hHandle(NULL)
            ,fpCreate(NULL)
            ,fpDestory(NULL)
            ,pInstance(NULL)
            {}
    } PlugInContainer;

    typedef KeyedVector<String8, PlugInContainer*> PlugInMap;
    PlugInMap m_plugInMap;

    typedef Vector<String8> PlugInIdList;
    PlugInIdList m_plugInIdList;

public:
    /**
     * Load all the plug-ins in the specified directory
     *
     * @param[in] rsPlugInDirPath
     *     Directory path which plug-ins (dynamic library) are stored
     * @note Plug-ins should be implemented according to the specification
     */
    void loadPlugIns(const String8& rsPlugInDirPath) {
        Vector<String8> plugInFileList = getPlugInPathList(rsPlugInDirPath);

        if (!plugInFileList.isEmpty()) {
            for (size_t i = 0; i < plugInFileList.size(); ++i) {
                loadPlugIn(plugInFileList[i]);
            }
        }
    }

    /**
     * Unload all the plug-ins
     *
     */
    void unloadPlugIns() {
        for (size_t i = 0; i < m_plugInIdList.size(); ++i) {
            unloadPlugIn(m_plugInIdList[i]);
        }
        m_plugInIdList.clear();
    }

    /**
     * Get all the IDs of available plug-ins
     *
     * @return[in] plugInIdList
     *     String type Vector in which all plug-in IDs are stored
     */
    Vector<String8> getPlugInIdList() const {
        return m_plugInIdList;
    }

    /**
     * Get a plug-in reference of specified ID
     *
     * @param[in] rsPlugInId
     *     Plug-in ID to be used
     * @return plugIn
     *     Reference of specified plug-in instance
     */
    Type& getPlugIn(const String8& rsPlugInId) {
        if (!contains(rsPlugInId)) {
            // This error case never happens
        }
        return *(m_plugInMap.valueFor(rsPlugInId)->pInstance);
    }

public:
    /**
     * Load a plug-in stored in the specified path
     *
     * @param[in] rsPlugInPath
     *     Plug-in (dynamic library) file path
     * @note Plug-in should be implemented according to the specification
     */
    void loadPlugIn(const String8& rsPlugInPath) {
        if (contains(rsPlugInPath)) {
            return;
        }

        PlugInContainer* pPlugInContainer = new PlugInContainer();

        pPlugInContainer->hHandle = dlopen(rsPlugInPath.string(), RTLD_LAZY);

        if (NULL == pPlugInContainer->hHandle) {
            delete pPlugInContainer;
            pPlugInContainer = NULL;
            return;
        }

        pPlugInContainer->sPath = rsPlugInPath;
        pPlugInContainer->fpCreate
                = (FPCREATE)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_CREATE);
        pPlugInContainer->fpDestory
                = (FPDESTORY)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_DESTROY);

        if (NULL != pPlugInContainer->fpCreate && NULL != pPlugInContainer->fpDestory) {
            pPlugInContainer->pInstance = (Type*)pPlugInContainer->fpCreate();
            m_plugInIdList.add(rsPlugInPath);
            m_plugInMap.add(rsPlugInPath, pPlugInContainer);
        } else {
            dlclose(pPlugInContainer->hHandle);
            delete pPlugInContainer;
            pPlugInContainer = NULL;
            return;
        }
    }

    /**
     * Unload a plug-in stored in the specified path
     *
     * @param[in] rsPlugInPath
     *     Plug-in (dynamic library) file path
     */
    void unloadPlugIn(const String8& rsPlugInPath) {
        if (!contains(rsPlugInPath)) {
            return;
        }

        PlugInContainer* pPlugInContainer = m_plugInMap.valueFor(rsPlugInPath);
        pPlugInContainer->fpDestory(pPlugInContainer->pInstance);
        dlclose(pPlugInContainer->hHandle);

        m_plugInMap.removeItem(rsPlugInPath);
        delete pPlugInContainer;
        pPlugInContainer = NULL;
    }

private:
    /**
     * True if TPlugInManager contains rsPlugInId
     */
    bool contains(const String8& rsPlugInId) {
        return m_plugInMap.indexOfKey(rsPlugInId) != NAME_NOT_FOUND;
    }

    /**
     * Return file path list of plug-ins stored in the specified directory
     *
     * @param[in] rsDirPath
     *     Directory path in which plug-ins are stored
     * @return plugInFileList
     *     String type Vector in which file path of plug-ins are stored
     */
    Vector<String8> getPlugInPathList(const String8& rsDirPath) {
        Vector<String8> fileList;
        DIR* pDir = opendir(rsDirPath.string());
        struct dirent* pEntry;

        while (NULL != pDir && NULL != (pEntry = readdir(pDir))) {
            if (!isPlugIn(pEntry)) {
                continue;
            }
            String8 plugInPath;
            plugInPath += rsDirPath;
            plugInPath += "/";
            plugInPath += pEntry->d_name;

            fileList.add(plugInPath);
        }

        if (NULL != pDir) {
            closedir(pDir);
        }

        return fileList;
    }

    /**
     * True if the input name denotes plug-in
     */
    bool isPlugIn(const struct dirent* pEntry) const {
        String8 sName(pEntry->d_name);
        String8 extension(sName.getPathExtension());
        // Note that the plug-in extension must exactly match case
        return extension == String8(PLUGIN_EXTENSION);
    }

    /**
     * True if input entry is directory
     */
    bool isDirectory(const struct dirent* pEntry) const {
        return DT_DIR == pEntry->d_type;
    }

    /**
     * True if input entry is regular file
     */
    bool isRegularFile(const struct dirent* pEntry) const {
        return DT_REG == pEntry->d_type;
    }

    /**
     * True if input entry is link
     */
    bool isLink(const struct dirent* pEntry) const {
        return DT_LNK == pEntry->d_type;
    }
};

};

#endif /* __PLUGIN_MANAGER_H__ */

