00001
00002
00003 #include "Iguana/Framework/interface/IgPluginManager.h"
00004 #include "Iguana/Framework/interface/IgPluginInfo.h"
00005 #include "Iguana/Framework/interface/IgPluginFactoryBase.h"
00006 #include "Iguana/Framework/interface/IgModuleCache.h"
00007 #include "Iguana/Framework/interface/IgModule.h"
00008 #include "debug.h"
00009 #include "Iguana/Framework/interface/IgModuleDescriptor.h"
00010 #include "classlib/utils/SystemError.h"
00011 #include "classlib/utils/Log.h"
00012 #include <algorithm>
00013 #include <functional>
00014 #include <typeinfo>
00015
00016
00017
00018
00019
00021 class IgDirectoryByName {
00022 lat::Filename m_which;
00023 public:
00024 IgDirectoryByName (lat::Filename name) : m_which (name) {}
00025 bool operator() (const IgModuleCache *dir) {
00026 return dir->directory () == m_which;
00027 }
00028 };
00029
00031 class IgPluginManagerDestructor {
00032 IgPluginManager *m_manager;
00033 bool m_destroy;
00034
00035 public:
00036 IgPluginManagerDestructor (void)
00037 : m_manager (0),
00038 #if ! __GNUC__ || __GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
00039 m_destroy (true)
00040 #else
00041 m_destroy (false)
00042 #endif
00043 {}
00044 ~IgPluginManagerDestructor (void)
00045 {
00046 if (m_destroy && m_manager)
00047 {
00048 LOG (0, trace, LFplugin_manager, "destroying plug-in manager\n" << lat::indent);
00049 delete m_manager;
00050 m_manager = 0;
00051 LOG (0, trace, LFplugin_manager, lat::undent);
00052 }
00053 }
00054
00055 void policy (bool destroy) { m_destroy = destroy; }
00056 void object (IgPluginManager *manager) { m_manager = manager; }
00057 };
00058
00059
00060
00061 static IgPluginManagerDestructor s_destructor;
00062
00063
00064
00065
00066
00067
00068
00077 IgPluginManager *
00078 IgPluginManager::get (void)
00079 {
00080
00081 static IgPluginManager *s_db = 0;
00082 if (! s_db)
00083 {
00084 std::string path;
00085 if (const char *p = getenv ("IGUANA_PLUGINS"))
00086 path = p;
00087 else
00088 path = lat::SharedLibrary::path ();
00089
00090 LOG (0, trace, LFplugin_manager,
00091 "initialising plugin manager with path <" << path << ">");
00092 s_db = new IgPluginManager (lat::SearchPath (path));
00093 s_destructor.object (s_db);
00094 }
00095 return s_db;
00096 }
00097
00109 void
00110 IgPluginManager::destroyOnExit (bool destroy)
00111 { s_destructor.policy (destroy); }
00112
00116 IgPluginManager::IgPluginManager (const lat::SearchPath &path)
00117 : m_initialised (false),
00118 m_searchPath (path)
00119 {}
00120
00122 IgPluginManager::~IgPluginManager (void)
00123 {
00124
00125 DirectoryIterator dir = beginDirectories ();
00126 for ( ; dir != endDirectories (); ++dir)
00127 delete *dir;
00128
00129
00130
00131
00132
00133
00134 while (! m_factories.empty ())
00135 delete *m_factories.begin ();
00136 }
00137
00153 void
00154 IgPluginManager::initialise (void)
00155 {
00156 if (m_initialised) return;
00157 m_initialised = true;
00158
00159 lat::SearchPath::const_iterator dir = m_searchPath.begin ();
00160 for ( ; dir != m_searchPath.end (); ++dir)
00161 {
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 if (! dir->empty ())
00172 {
00173 try {
00174 m_directories.push_back (new IgModuleCache (this, *dir));
00175 } catch (lat::Error &error) {
00176 LOG (0, warning, LFplugin_manager, lat::undent << lat::undent
00177 << "directory " << *dir << " ignored: "
00178 << typeid(error).name () << " ("
00179 << error.explain ().c_str () << ")\n");
00180 continue;
00181 }
00182 }
00183 }
00184
00185 rebuild ();
00186 }
00187
00191
00192 void
00193 IgPluginManager::addInfo (IgPluginInfo *info)
00194 {
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 IgPluginFactoryBase *factory = findFactory (info->category ());
00217 ASSERT (factory);
00218 factory->addInfo (info);
00219 }
00220
00221
00222 void
00223 IgPluginManager::removeInfo (IgPluginInfo *info)
00224 {
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 IgPluginFactoryBase *factory = findFactory (info->category ());
00246 ASSERT (factory);
00247 factory->removeInfo (info);
00248 }
00249
00250
00251
00252
00253 void
00254 IgPluginManager::restore (IgModule *module, IgModuleDescriptor *from)
00255 {
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271 ASSERT (from);
00272 ASSERT (from->tokens () >= 2);
00273 if (IgPluginFactoryBase *factory = findFactory (from->token (0)))
00274 factory->restore (module, from);
00275 }
00276
00280
00284 void
00285 IgPluginManager::addFactory (IgPluginFactoryBase *factory)
00286 {
00287
00288
00289
00290
00291 m_factories.push_back (factory);
00292 }
00293
00298 void
00299 IgPluginManager::removeFactory (IgPluginFactoryBase *factory)
00300 {
00301 FactoryIterator pos = std::find (m_factories.begin (), m_factories.end (), factory);
00302 ASSERT (pos != m_factories.end ());
00303 m_factories.erase (pos);
00304 }
00305
00309 IgPluginFactoryBase *
00310 IgPluginManager::findFactory (const std::string &name)
00311 {
00312 FactoryIterator pos = m_factories.begin ();
00313 while (pos != m_factories.end () && (*pos)->category () != name)
00314 ++pos;
00315
00316 return pos != m_factories.end () ? *pos : 0;
00317 }
00318
00322
00328 void
00329 IgPluginManager::rebuild (void)
00330 {
00331 ModuleMap modules;
00332 IgModuleCache::Iterator module;
00333 DirectoryIterator dir;
00334
00335
00336 for (dir = beginDirectories (); dir != endDirectories (); ++dir)
00337 for (module = (*dir)->begin (); module != (*dir)->end (); ++module)
00338 if (! modules.count ((*module)->libraryName ()))
00339 modules [(*module)->libraryName ()] = *module;
00340
00341
00342 m_modules.swap (modules);
00343
00344
00345
00346
00347
00348
00349 }
00350
00361 void
00362 IgPluginManager::refresh (void)
00363 {
00364 DirectoryIterator dir = beginDirectories ();
00365 for ( ; dir != endDirectories (); ++dir)
00366 (*dir)->refresh ();
00367
00368 rebuild ();
00369 }
00370
00374
00375 IgPluginManager::DirectoryIterator
00376 IgPluginManager::beginDirectories (void) const
00377 { return m_directories.begin (); }
00378
00380 IgPluginManager::DirectoryIterator
00381 IgPluginManager::endDirectories (void) const
00382 { return m_directories.end (); }
00383
00385 IgPluginManager::DirectoryIterator
00386 IgPluginManager::locateDirectory (const lat::Filename &name) const
00387 {
00388 return std::find_if (beginDirectories (), endDirectories (),
00389 IgDirectoryByName (name));
00390 }
00391
00395 IgModuleCache *
00396 IgPluginManager::directory (const lat::Filename &name) const
00397 {
00398 DirectoryIterator pos = locateDirectory (name);
00399 return pos != endDirectories () ? *pos : 0;
00400 }
00401
00403
00406 IgPluginManager::ModuleIterator
00407 IgPluginManager::beginModules (void) const
00408 { return ModuleIterator (m_modules.begin ()); }
00409
00413 IgPluginManager::ModuleIterator
00414 IgPluginManager::endModules (void) const
00415 { return ModuleIterator (m_modules.end ()); }
00416
00420 IgPluginManager::ModuleIterator
00421 IgPluginManager::locateModule (const lat::Filename &libraryName) const
00422 { return ModuleIterator (m_modules.find (libraryName)); }
00423
00428 IgModule *
00429 IgPluginManager::module (const lat::Filename &libraryName) const
00430 {
00431 ModuleIterator pos = locateModule (libraryName);
00432 return pos != endModules () ? *pos : 0;
00433 }
00434
00436
00437 void
00438 IgPluginManager::addFeedback (FeedbackCB callback)
00439 { m_feedbacks.push_back (callback); }
00440
00442 void
00443 IgPluginManager::removeFeedback (FeedbackCB callback)
00444 { m_feedbacks.remove (callback); }
00445
00447 void
00448 IgPluginManager::feedback (FeedbackData data)
00449 {
00450 FeedbackIterator i;
00451 for (i = m_feedbacks.begin (); i != m_feedbacks.end (); ++i)
00452 (*i) (data);
00453 }
00454
00456 void
00457 IgPluginManager::feedback (FeedbackCode code,
00458 const lat::Filename &scope,
00459 lat::Error *error )
00460 { feedback (FeedbackData (code, (std::string) scope, error)); }
00461
00463 void
00464 IgPluginManager::feedback (FeedbackCode code,
00465 const std::string &scope,
00466 lat::Error *error )
00467 { feedback (FeedbackData (code, scope, error)); }