CMS 3D CMS Logo

/data/doxygen/doxygen-1.7.3/gen/CMSSW_4_2_8/src/FWCore/PluginManager/src/PluginManager.cc

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // Package:     PluginManager
00004 // Class  :     PluginManager
00005 // 
00006 // Implementation:
00007 //     <Notes on implementation>
00008 //
00009 // Original Author:  Chris Jones
00010 //         Created:  Wed Apr  4 14:28:58 EDT 2007
00011 // $Id: PluginManager.cc,v 1.11 2010/10/05 16:35:12 eulisse Exp $
00012 //
00013 
00014 // system include files
00015 #include <boost/bind.hpp>
00016 #include <boost/mem_fn.hpp>
00017 
00018 #include <boost/filesystem/operations.hpp>
00019 
00020 #include <fstream>
00021 #include <set>
00022 
00023 // user include files
00024 #include "FWCore/PluginManager/interface/PluginManager.h"
00025 #include "FWCore/PluginManager/interface/PluginFactoryBase.h"
00026 #include "FWCore/PluginManager/interface/PluginFactoryManager.h"
00027 #include "FWCore/PluginManager/interface/CacheParser.h"
00028 #include "FWCore/Utilities/interface/Exception.h"
00029 
00030 #include "FWCore/PluginManager/interface/standard.h"
00031 
00032 namespace edmplugin {
00033 //
00034 // constants, enums and typedefs
00035 //
00036 
00037 //
00038 // static data member definitions
00039 //
00040 
00041 //
00042 // constructors and destructor
00043 //
00044 PluginManager::PluginManager(const PluginManager::Config& iConfig) :
00045   searchPath_( iConfig.searchPath() )
00046 {
00047     const boost::filesystem::path kCacheFile(standard::cachefileName());
00048     //NOTE: This may not be needed :/
00049     PluginFactoryManager* pfm = PluginFactoryManager::get();
00050     pfm->newFactory_.connect(boost::bind(boost::mem_fn(&PluginManager::newFactory),this,_1));
00051 
00052     // When building a single big executable the plugins are already registered in the 
00053     // PluginFactoryManager, we therefore only need to populate the categoryToInfos_ map
00054     // with the relevant information.
00055     for (PluginFactoryManager::const_iterator i = pfm->begin(), e = pfm->end(); i != e; ++i)
00056     {
00057         categoryToInfos_[(*i)->category()] = (*i)->available();
00058     }
00059 
00060     //read in the files
00061     //Since we are looping in the 'precidence' order then the lists in categoryToInfos_ will also be
00062     // in that order
00063     std::set<std::string> alreadySeen;
00064     for(SearchPath::const_iterator itPath=searchPath_.begin(), itEnd = searchPath_.end();
00065         itPath != itEnd;
00066         ++itPath) {
00067       //take care of the case where the same path is passed in multiple times
00068       if (alreadySeen.find(*itPath) != alreadySeen.end() ) {
00069         continue;
00070       }
00071       alreadySeen.insert(*itPath);
00072       boost::filesystem::path dir(*itPath);
00073       if( exists( dir) ) {
00074         if(not is_directory(dir) ) {
00075           throw cms::Exception("PluginManagerBadPath") <<"The path '"<<dir.native_file_string()<<"' for the PluginManager is not a directory";
00076         }
00077         boost::filesystem::path cacheFile = dir/kCacheFile;
00078         
00079         if(exists(cacheFile) ) {
00080           std::ifstream file(cacheFile.native_file_string().c_str());
00081           if(not file) {
00082             throw cms::Exception("PluginMangerCacheProblem")<<"Unable to open the cache file '"<<cacheFile.native_file_string()
00083             <<"'. Please check permissions on file";
00084           }
00085           CacheParser::read(file, dir, categoryToInfos_);          
00086         }
00087       }
00088     }
00089     //Since this should not be called until after 'main' has started, we can set the value
00090     loadingLibraryNamed_()="<loaded by another plugin system>";
00091 }
00092 
00093 // PluginManager::PluginManager(const PluginManager& rhs)
00094 // {
00095 //    // do actual copying here;
00096 // }
00097 
00098 PluginManager::~PluginManager()
00099 {
00100 }
00101 
00102 //
00103 // assignment operators
00104 //
00105 // const PluginManager& PluginManager::operator=(const PluginManager& rhs)
00106 // {
00107 //   //An exception safe implementation is
00108 //   PluginManager temp(rhs);
00109 //   swap(rhs);
00110 //
00111 //   return *this;
00112 // }
00113 
00114 //
00115 // member functions
00116 //
00117 void
00118 PluginManager::newFactory(const PluginFactoryBase*)
00119 {
00120 }
00121 //
00122 // const member functions
00123 //
00124 namespace {
00125   struct PICompare {
00126     bool operator()(const PluginInfo& iLHS,
00127                     const PluginInfo& iRHS) const {
00128                       return iLHS.name_ < iRHS.name_;
00129                     }
00130   };
00131 }
00132 
00133 const boost::filesystem::path& 
00134 PluginManager::loadableFor(const std::string& iCategory,
00135                              const std::string& iPlugin)
00136 {
00137   bool throwIfFail = true;
00138   return loadableFor_(iCategory, iPlugin,throwIfFail);
00139 }
00140 
00141 const boost::filesystem::path& 
00142 PluginManager::loadableFor_(const std::string& iCategory,
00143                                             const std::string& iPlugin,
00144                                             bool& ioThrowIfFailElseSucceedStatus)
00145 {
00146   const bool throwIfFail = ioThrowIfFailElseSucceedStatus;
00147   ioThrowIfFailElseSucceedStatus = true;
00148   CategoryToInfos::iterator itFound = categoryToInfos_.find(iCategory);
00149   if(itFound == categoryToInfos_.end()) {
00150     if(throwIfFail) {
00151       throw cms::Exception("PluginNotFound")<<"Unable to find plugin '"<<iPlugin<<
00152       "' because the category '"<<iCategory<<"' has no known plugins";
00153     } else {
00154       ioThrowIfFailElseSucceedStatus = false;
00155       static boost::filesystem::path s_path;
00156       return s_path;
00157     }
00158   }
00159   
00160   PluginInfo i;
00161   i.name_ = iPlugin;
00162   typedef std::vector<PluginInfo>::iterator PIItr;
00163   std::pair<PIItr,PIItr> range = std::equal_range(itFound->second.begin(),
00164                                                   itFound->second.end(),
00165                                                   i,
00166                                                   PICompare() );
00167   
00168   if(range.first == range.second) {
00169     if(throwIfFail) {
00170       throw cms::Exception("PluginNotFound")<<"Unable to find plugin '"<<iPlugin
00171       <<"'. Please check spelling of name.";
00172     } else {
00173       ioThrowIfFailElseSucceedStatus = false;
00174       static boost::filesystem::path s_path;
00175       return s_path;
00176     }
00177   }
00178   
00179   if(range.second - range.first > 1 ) {
00180     //see if the come from the same directory
00181     if(range.first->loadable_.branch_path() == (range.first+1)->loadable_.branch_path()) {
00182       //std::cout<<range.first->name_ <<" " <<(range.first+1)->name_<<std::endl;
00183       throw cms::Exception("MultiplePlugins")<<"The plugin '"<<iPlugin<<"' is found in multiple files \n"
00184       " '"<<range.first->loadable_.leaf()<<"'\n '"
00185       <<(range.first+1)->loadable_.leaf()<<"'\n"
00186       "in directory '"<<range.first->loadable_.branch_path().native_file_string()<<"'.\n"
00187       "The code must be changed so the plugin only appears in one plugin file. "
00188       "You will need to remove the macro which registers the plugin so it only appears in"
00189       " one of these files.\n"
00190       "  If none of these files register such a plugin, "
00191       "then the problem originates in a library to which all these files link.\n"
00192       "The plugin registration must be removed from that library since plugins are not allowed in regular libraries.";
00193     }
00194   }
00195   
00196   return range.first->loadable_;
00197 }
00198 
00199 namespace {
00200   class Sentry {
00201 public:
00202     Sentry( std::string& iPath, const std::string& iNewPath):
00203       path_(iPath),
00204       oldPath_(iPath)
00205     {
00206       path_ = iNewPath;
00207     }
00208     ~Sentry() {
00209       path_ = oldPath_;
00210     }
00211 private:
00212       std::string& path_;
00213       std::string oldPath_;
00214   };
00215 }
00216 
00217 const SharedLibrary& 
00218 PluginManager::load(const std::string& iCategory,
00219                       const std::string& iPlugin)
00220 {
00221   askedToLoadCategoryWithPlugin_(iCategory,iPlugin);
00222   const boost::filesystem::path& p = loadableFor(iCategory,iPlugin);
00223   
00224   //have we already loaded this?
00225   std::map<boost::filesystem::path, boost::shared_ptr<SharedLibrary> >::iterator itLoaded = 
00226     loadables_.find(p);
00227   if(itLoaded == loadables_.end()) {
00228     //try to make one
00229     goingToLoad_(p);
00230     Sentry s(loadingLibraryNamed_(), p.native_file_string());
00231     //boost::filesystem::path native(p.native_file_string());
00232     boost::shared_ptr<SharedLibrary> ptr( new SharedLibrary(p) );
00233     loadables_[p]=ptr;
00234     justLoaded_(*ptr);
00235     return *ptr;
00236   }
00237   return *(itLoaded->second);
00238 }
00239 
00240 const SharedLibrary* 
00241 PluginManager::tryToLoad(const std::string& iCategory,
00242                          const std::string& iPlugin)
00243 {
00244   askedToLoadCategoryWithPlugin_(iCategory,iPlugin);
00245   bool ioThrowIfFailElseSucceedStatus = false;
00246   const boost::filesystem::path& p = loadableFor_(iCategory,iPlugin, ioThrowIfFailElseSucceedStatus);
00247   
00248   if( not ioThrowIfFailElseSucceedStatus ) {
00249     return 0;
00250   }
00251   
00252   //have we already loaded this?
00253   std::map<boost::filesystem::path, boost::shared_ptr<SharedLibrary> >::iterator itLoaded = 
00254     loadables_.find(p);
00255   if(itLoaded == loadables_.end()) {
00256     //try to make one
00257     goingToLoad_(p);
00258     Sentry s(loadingLibraryNamed_(), p.native_file_string());
00259     //boost::filesystem::path native(p.native_file_string());
00260     boost::shared_ptr<SharedLibrary> ptr( new SharedLibrary(p) );
00261     loadables_[p]=ptr;
00262     justLoaded_(*ptr);
00263     return ptr.get();
00264   }
00265   return (itLoaded->second).get();
00266 }
00267 
00268 //
00269 // static member functions
00270 //
00271 PluginManager* 
00272 PluginManager::get()
00273 {
00274   PluginManager* manager = singleton();
00275   if(0==manager) {
00276     throw cms::Exception("PluginManagerNotConfigured")<<"PluginManager::get() was called before PluginManager::configure.";
00277   }
00278   return manager;
00279 }
00280 
00281 PluginManager& 
00282 PluginManager::configure(const Config& iConfig )
00283 {
00284   PluginManager*& s = singleton();
00285   if( 0 != s ){
00286     throw cms::Exception("PluginManagerReconfigured");
00287   }
00288   
00289   Config realConfig = iConfig;
00290   if (realConfig.searchPath().empty() ) {
00291     throw cms::Exception("PluginManagerEmptySearchPath");
00292   }
00293   s = new PluginManager (realConfig);
00294   return *s;
00295 }
00296 
00297 
00298 const std::string& 
00299 PluginManager::staticallyLinkedLoadingFileName()
00300 {
00301   static std::string s_name("static");
00302   return s_name;
00303 }
00304 
00305 std::string& 
00306 PluginManager::loadingLibraryNamed_()
00307 {
00308   static std::string s_name(staticallyLinkedLoadingFileName());
00309   return s_name;
00310 }
00311 
00312 PluginManager*& PluginManager::singleton()
00313 {
00314   static PluginManager* s_singleton;
00315   return s_singleton;
00316 }
00317 
00318 bool
00319 PluginManager::isAvailable()
00320 {
00321   return 0 != singleton();
00322 }
00323 
00324 }