127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi/*
227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * Copyright (C) 2010 The Android Open Source Project
327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi *
427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * Licensed under the Apache License, Version 2.0 (the "License");
527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * you may not use this file except in compliance with the License.
627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * You may obtain a copy of the License at
727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi *
827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi *      http://www.apache.org/licenses/LICENSE-2.0
927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi *
1027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * Unless required by applicable law or agreed to in writing, software
1127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * distributed under the License is distributed on an "AS IS" BASIS,
1227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * See the License for the specific language governing permissions and
1427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * limitations under the License.
1527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi */
1627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
1727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#ifndef __PLUGIN_MANAGER_H__
1827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#define __PLUGIN_MANAGER_H__
1927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
2027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <dlfcn.h>
2127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <sys/types.h>
2227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <dirent.h>
2327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
2427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <utils/String8.h>
2527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <utils/Vector.h>
2627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#include <utils/KeyedVector.h>
2727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
2827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshinamespace android {
2927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
3027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiconst char* const PLUGIN_MANAGER_CREATE = "create";
3127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiconst char* const PLUGIN_MANAGER_DESTROY = "destroy";
3227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiconst char* const PLUGIN_EXTENSION = ".so";
3327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
3427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi/**
3527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * This is the template class for Plugin manager.
3627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi *
3727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi * The DrmManager uses this class to handle the plugins.
3827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi *
3927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi */
4027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshitemplate<typename Type>
4127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiclass TPlugInManager {
4227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiprivate:
4327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    typedef void*      HANDLE;
4427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    typedef Type*      create_t(void);
4527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    typedef void       destroy_t(Type*);
4627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    typedef create_t*  FPCREATE;
4727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    typedef destroy_t* FPDESTORY;
4827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
4927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    typedef struct _PlugInContainer {
5027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        String8   sPath;
5127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        HANDLE    hHandle;
5227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        FPCREATE  fpCreate;
5327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        FPDESTORY fpDestory;
5427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        Type*     pInstance;
5527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
5627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        _PlugInContainer():
5727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            sPath("")
5827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            ,hHandle(NULL)
5927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            ,fpCreate(NULL)
6027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            ,fpDestory(NULL)
6127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            ,pInstance(NULL)
6227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            {}
6327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    } PlugInContainer;
6427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
6527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    typedef KeyedVector<String8, PlugInContainer*> PlugInMap;
6627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    PlugInMap m_plugInMap;
6727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
6827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    typedef Vector<String8> PlugInIdList;
6927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    PlugInIdList m_plugInIdList;
7027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
7127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshipublic:
7227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    /**
7327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * Load all the plug-ins in the specified directory
7427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     *
7527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * @param[in] rsPlugInDirPath
7627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     *     Directory path which plug-ins (dynamic library) are stored
7727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * @note Plug-ins should be implemented according to the specification
7827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     */
7927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    void loadPlugIns(const String8& rsPlugInDirPath) {
8027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        Vector<String8> plugInFileList = getPlugInPathList(rsPlugInDirPath);
8127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
8227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        if (!plugInFileList.isEmpty()) {
833ab368e0810d894dcbc0971350c095049478a055Mark Salyzyn            for (size_t i = 0; i < plugInFileList.size(); ++i) {
8427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi                loadPlugIn(plugInFileList[i]);
8527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            }
8627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        }
8727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    }
8827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
8927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    /**
9027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * Unload all the plug-ins
9127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     *
9227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     */
9327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    void unloadPlugIns() {
943ab368e0810d894dcbc0971350c095049478a055Mark Salyzyn        for (size_t i = 0; i < m_plugInIdList.size(); ++i) {
9527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            unloadPlugIn(m_plugInIdList[i]);
9627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        }
9727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        m_plugInIdList.clear();
9827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    }
9927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
10027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    /**
10127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * Get all the IDs of available plug-ins
10227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     *
10327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * @return[in] plugInIdList
10427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     *     String type Vector in which all plug-in IDs are stored
10527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     */
10627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    Vector<String8> getPlugInIdList() const {
10727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        return m_plugInIdList;
10827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    }
10927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
11027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    /**
11127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * Get a plug-in reference of specified ID
11227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     *
11327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * @param[in] rsPlugInId
11427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     *     Plug-in ID to be used
11527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * @return plugIn
11627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     *     Reference of specified plug-in instance
11727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     */
11827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    Type& getPlugIn(const String8& rsPlugInId) {
11927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        if (!contains(rsPlugInId)) {
12027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            // This error case never happens
12127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        }
12227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        return *(m_plugInMap.valueFor(rsPlugInId)->pInstance);
12327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    }
12427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
12527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshipublic:
12627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    /**
12727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * Load a plug-in stored in the specified path
12827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     *
12927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * @param[in] rsPlugInPath
13027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     *     Plug-in (dynamic library) file path
13127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * @note Plug-in should be implemented according to the specification
13227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     */
13327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    void loadPlugIn(const String8& rsPlugInPath) {
13427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        if (contains(rsPlugInPath)) {
13527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            return;
13627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        }
13727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
13827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        PlugInContainer* pPlugInContainer = new PlugInContainer();
13927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
14027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        pPlugInContainer->hHandle = dlopen(rsPlugInPath.string(), RTLD_LAZY);
14127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
14227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        if (NULL == pPlugInContainer->hHandle) {
14327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            delete pPlugInContainer;
14427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            pPlugInContainer = NULL;
14527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            return;
14627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        }
14727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
14827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        pPlugInContainer->sPath = rsPlugInPath;
14927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        pPlugInContainer->fpCreate
15027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi                = (FPCREATE)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_CREATE);
15127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        pPlugInContainer->fpDestory
15227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi                = (FPDESTORY)dlsym(pPlugInContainer->hHandle, PLUGIN_MANAGER_DESTROY);
15327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
15427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        if (NULL != pPlugInContainer->fpCreate && NULL != pPlugInContainer->fpDestory) {
15527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            pPlugInContainer->pInstance = (Type*)pPlugInContainer->fpCreate();
15627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            m_plugInIdList.add(rsPlugInPath);
15727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            m_plugInMap.add(rsPlugInPath, pPlugInContainer);
15827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        } else {
15927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            dlclose(pPlugInContainer->hHandle);
16027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            delete pPlugInContainer;
16127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            pPlugInContainer = NULL;
16227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            return;
16327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        }
16427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    }
16527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
16627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    /**
16727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * Unload a plug-in stored in the specified path
16827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     *
16927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * @param[in] rsPlugInPath
17027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     *     Plug-in (dynamic library) file path
17127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     */
17227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    void unloadPlugIn(const String8& rsPlugInPath) {
17327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        if (!contains(rsPlugInPath)) {
17427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            return;
17527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        }
17627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
17727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        PlugInContainer* pPlugInContainer = m_plugInMap.valueFor(rsPlugInPath);
17827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        pPlugInContainer->fpDestory(pPlugInContainer->pInstance);
17927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        dlclose(pPlugInContainer->hHandle);
18027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
18127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        m_plugInMap.removeItem(rsPlugInPath);
18227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        delete pPlugInContainer;
18327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        pPlugInContainer = NULL;
18427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    }
18527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
18627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshiprivate:
18727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    /**
18827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * True if TPlugInManager contains rsPlugInId
18927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     */
19027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    bool contains(const String8& rsPlugInId) {
19127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        return m_plugInMap.indexOfKey(rsPlugInId) != NAME_NOT_FOUND;
19227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    }
19327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
19427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    /**
19527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * Return file path list of plug-ins stored in the specified directory
19627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     *
19727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * @param[in] rsDirPath
19827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     *     Directory path in which plug-ins are stored
19927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * @return plugInFileList
20027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     *     String type Vector in which file path of plug-ins are stored
20127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     */
20227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    Vector<String8> getPlugInPathList(const String8& rsDirPath) {
20327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        Vector<String8> fileList;
20427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        DIR* pDir = opendir(rsDirPath.string());
205c10ce33302f91896fc2a87c13b00518a4bc26e3aGloria Wang        struct dirent* pEntry;
20627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
20727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        while (NULL != pDir && NULL != (pEntry = readdir(pDir))) {
20827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            if (!isPlugIn(pEntry)) {
20927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi                continue;
21027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            }
21127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            String8 plugInPath;
21227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            plugInPath += rsDirPath;
21327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            plugInPath += "/";
21427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            plugInPath += pEntry->d_name;
21527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
21627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            fileList.add(plugInPath);
21727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        }
21827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
21927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        if (NULL != pDir) {
22027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi            closedir(pDir);
22127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        }
22227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
22327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        return fileList;
22427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    }
22527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
22627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    /**
22727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * True if the input name denotes plug-in
22827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     */
22927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    bool isPlugIn(const struct dirent* pEntry) const {
23027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        String8 sName(pEntry->d_name);
23141b3d3be18b54e72a44813cbdd180aae7e77b444Glenn Kasten        String8 extension(sName.getPathExtension());
23241b3d3be18b54e72a44813cbdd180aae7e77b444Glenn Kasten        // Note that the plug-in extension must exactly match case
23341b3d3be18b54e72a44813cbdd180aae7e77b444Glenn Kasten        return extension == String8(PLUGIN_EXTENSION);
23427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    }
23527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
23627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    /**
23727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * True if the input entry is "." or ".."
23827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     */
23927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    bool isDotOrDDot(const struct dirent* pEntry) const {
24027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        String8 sName(pEntry->d_name);
24127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        return "." == sName || ".." == sName;
24227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    }
24327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
24427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    /**
24527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * True if input entry is directory
24627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     */
24727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    bool isDirectory(const struct dirent* pEntry) const {
24827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        return DT_DIR == pEntry->d_type;
24927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    }
25027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
25127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    /**
25227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * True if input entry is regular file
25327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     */
25427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    bool isRegularFile(const struct dirent* pEntry) const {
25527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        return DT_REG == pEntry->d_type;
25627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    }
25727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
25827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    /**
25927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     * True if input entry is link
26027ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi     */
26127ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    bool isLink(const struct dirent* pEntry) const {
26227ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi        return DT_LNK == pEntry->d_type;
26327ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi    }
26427ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi};
26527ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
26627ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi};
26727ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
26827ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi#endif /* __PLUGIN_MANAGER_H__ */
26927ed8ad2db653f6ac07dcf8bcc05e2409c8bb024aimitakeshi
270