00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
#ifndef BASICPLUGINMANAGER_H
00026
#define BASICPLUGINMANAGER_H
00027
00028
#include "BasicException.h"
00029
#include "BasicPluginInfo.h"
00030
#include "BasicClassFactoryBase.h"
00031
00032
#include <map>
00033
#include <list>
00034
#include <string>
00035
00036
#include <ltdl.h>
00037
#include <string.h>
00038
#include <glob.h>
00039
00040
template <
class T>
00041 class BasicPluginManager {
00042
public:
00043 typedef typename std::list<BasicPluginInfo *>
infos_t;
00044
00045
private:
00046
typedef typename std::map<std::string, BasicClassFactoryBase<T> *>
00047 factories_t;
00048 typedef typename std::map<std::string, BasicPluginInfo *>
infoMap_t;
00049 typedef typename std::map<std::string, T *>
plugins_t;
00050 typedef typename std::map<std::string, lt_dlhandle>
libraryHandles_t;
00051
00053 factories_t factories;
00054
00056 infoMap_t infoMap;
00057
00059 plugins_t plugins;
00060
00062 libraryHandles_t libraryHandles;
00063
00065 infos_t infos;
00066
00068 BasicException *
pluginException;
00069
00071 bool preloadDeps;
00072
00073
public:
00075
static const char libExtension[];
00076
00077
00078 BasicPluginManager(
bool preloadDeps =
false) :
00079
pluginException(0),
preloadDeps(
preloadDeps) {
00080
int result = lt_dlinit();
00081
if(result != 0) {
00082 std::cout <<
"Error initializing ltdl" << std::endl;
00083 }
00084 }
00085
00090 virtual ~BasicPluginManager() {
00091
unload();
00092
00093
00094 infos_t::iterator it;
00095
for (it =
infos.begin(); it !=
infos.end(); it++)
00096
delete *it;
00097
00098
00099
typename factories_t::iterator fIt;
00100
for (fIt =
factories.begin(); fIt !=
factories.end(); fIt++)
00101
delete fIt->second;
00102
00103
closeLibraries();
00104 }
00105
00113 virtual void init(T *plugin) {}
00114
00118 void destroyPlugin(std::string pluginName) {
00119
if (!
plugins[pluginName])
return;
00120
00121
00122
00123
typename plugins_t::iterator it;
00124
for (it =
plugins.begin(); it !=
plugins.end(); it++)
00125
if (
dependsOn(it->first, pluginName))
00126
destroyPlugin(it->first);
00127
00128
00129
BasicClassFactoryBase<T> *factory =
getPluginFactory(pluginName);
00130 it =
plugins.find(pluginName);
00131 factory->
destroy(it->second);
00132
plugins.erase(it);
00133 }
00134
00136 void unload() {
00137
while (!
plugins.empty()) {
00138
if (!
plugins.begin()->second)
plugins.erase(
plugins.begin());
00139
else destroyPlugin(
plugins.begin()->first);
00140 }
00141 }
00142
00144 void closeLibraries() {
00145
typename libraryHandles_t::iterator it;
00146
for (it =
libraryHandles.begin(); it !=
libraryHandles.end(); it++)
00147
if (it->second) lt_dlclose(it->second);
00148
libraryHandles.clear();
00149 }
00150
00158 bool dependsOn(std::string plugin1, std::string plugin2) {
00159
const BasicPluginInfo *info =
infoMap[plugin1];
00160
if (!info)
return false;
00161
00162
00163 std::string dep;
00164
for (
unsigned int i = 0; i < info->
getNumDeps(); i++) {
00165 dep = info->
getDependency(i);
00166
if (dep == plugin2 ||
dependsOn(dep, plugin2))
return true;
00167 }
00168
return false;
00169 }
00170
00180 T *
get(
const std::string pluginName) {
00181 T *plugin =
plugins[pluginName];
00182
if (plugin)
return plugin;
00183
00184
00185
BasicClassFactoryBase<T> *factory =
getPluginFactory(pluginName);
00186
00187
if (
preloadDeps) {
00188
00189
const BasicPluginInfo *info =
getPluginInfo(pluginName);
00190
for (
unsigned int i = 0; i < info->
getNumDeps(); i++)
00191
get(info->
getDependency(i));
00192 }
00193
00194
00195 plugin = factory->
create();
00196 plugins[pluginName] = plugin;
00197
00198
00199
init(plugin);
00200
00201
return plugin;
00202 }
00203
00204
00206 bool isLoaded(std::string pluginName) {
00207
return plugins[pluginName] != 0;
00208 }
00209
00211 const BasicPluginInfo *
getPluginInfo(
const std::string pluginName) {
00212
typename infoMap_t::iterator it =
infoMap.find(pluginName);
00213
ASSERT_OR_THROW(std::string(
"Plugin '") + pluginName +
" not found!",
00214 it !=
infoMap.end());
00215
00216
return it->second;
00217 }
00218
00222 infos_t &
getPluginInfos() {
return infos;}
00223
00224
00230 void loadLibraries(
const std::string path) {
00231
char *cPath = strdup(path.c_str());
00232
00233
char *aPath = strtok(cPath,
":");
00234
while (aPath != NULL) {
00235
loadSingleLibraryPath(aPath);
00236
00237 aPath = strtok(NULL,
":");
00238 }
00239
00240 free(cPath);
00241 }
00242
00248 void loadLibrary(
const std::string filename) {
00249
00250 std::string name;
00251 std::string::size_type pos = filename.find_last_of(
"/");
00252
if (pos != std::string::npos) name = filename.substr(pos + 1);
00253
else name = filename;
00254
00255
00256
if (
libraryHandles[name] != NULL)
return;
00257
00258 lt_dlhandle handle = lt_dlopen(filename.c_str());
00259
const char *error;
00260
if ((handle == NULL) && (error = lt_dlerror())) {
00261 std::cout <<
"Error Loading " << filename <<
" " << error << endl;
00262
THROW(std::string(
"BasicPluginManager::loadLibrary() ") + error);
00263 }
00264
00265
if (handle)
libraryHandles[name] = handle;
00266
00267
if (
pluginException) {
00268
BasicException e = *
pluginException;
00269
delete pluginException;
00270
throw BasicException(std::string(
"Exception while loading library '") +
00271 filename +
"'", e);
00272 }
00273 }
00274
00281 void registerPlugin(
BasicPluginInfo *info,
00282
BasicClassFactoryBase<T> *factory) {
00283
ASSERT_OR_THROW(
"registerPlugin() Plugin info cannot be null!!",
00284 info);
00285
ASSERT_OR_THROW(
"registerPlugin() Plugin factory cannot be null!!",
00286 factory);
00287
00288
ASSERT_OR_THROW(std::string(
"registerPlugin() A plugin with name ") +
00289 info->
getName() +
" was already registered!",
00290
infoMap[info->
getName()] == NULL);
00291
00292
00293 std::string dep;
00294
for (
unsigned int i = 0; i < info->
getNumDeps(); i++) {
00295 dep = info->
getDependency(i);
00296
if (
dependsOn(dep, info->
getName()))
00297
throw
00298
BasicException(std::string(
"BasicPluginManager::registerPlugin() ") +
00299
"Detected dependency cycle between plugins '" +
00300 info->
getName() +
"' and '" + dep +
"'!");
00301 }
00302
00303
00304
infoMap[info->
getName()] = info;
00305
infos.push_back(info);
00306
factories[info->getName()] = factory;
00307 }
00308
00313 void setPluginException(
BasicException e) {
00314
if (!
pluginException)
00315
pluginException =
new BasicException(e);
00316 }
00317
00318
protected:
00320
BasicClassFactoryBase<T> *
00321 getPluginFactory(
const std::string pluginName) {
00322
typename factories_t::iterator it =
factories.find(pluginName);
00323
ASSERT_OR_THROW(std::string(
"Plugin '") + pluginName +
" not found!",
00324 it !=
factories.end());
00325
00326
return it->second;
00327 }
00328
00334 void loadSingleLibraryPath(
const std::string path) {
00335 glob_t globbuf;
00336 std::string pathGlob = path +
"/" +
"*" +
libExtension;
00337
00338
if (glob(pathGlob.c_str(), 0, NULL, &globbuf) == 0) {
00339
for (
int i = 0; i < globbuf.gl_pathc; i++)
00340
loadLibrary(globbuf.gl_pathv[i]);
00341 }
00342
00343 globfree(&globbuf);
00344 }
00345 };
00346
00347
00348
template<
class T>
00349 const char BasicPluginManager<T>::libExtension[] =
".so";
00350
00351
#endif