Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 PluginManager::PluginManager(const PluginManager::Config& iConfig) :
00045 searchPath_( iConfig.searchPath() )
00046 {
00047 const boost::filesystem::path kCacheFile(standard::cachefileName());
00048
00049 PluginFactoryManager* pfm = PluginFactoryManager::get();
00050 pfm->newFactory_.connect(boost::bind(boost::mem_fn(&PluginManager::newFactory),this,_1));
00051
00052
00053
00054
00055 for (PluginFactoryManager::const_iterator i = pfm->begin(), e = pfm->end(); i != e; ++i)
00056 {
00057 categoryToInfos_[(*i)->category()] = (*i)->available();
00058 }
00059
00060
00061
00062
00063 std::set<std::string> alreadySeen;
00064 for(SearchPath::const_iterator itPath=searchPath_.begin(), itEnd = searchPath_.end();
00065 itPath != itEnd;
00066 ++itPath) {
00067
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
00090 loadingLibraryNamed_()="<loaded by another plugin system>";
00091 }
00092
00093
00094
00095
00096
00097
00098 PluginManager::~PluginManager()
00099 {
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117 void
00118 PluginManager::newFactory(const PluginFactoryBase*)
00119 {
00120 }
00121
00122
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
00181 if(range.first->loadable_.branch_path() == (range.first+1)->loadable_.branch_path()) {
00182
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
00225 std::map<boost::filesystem::path, boost::shared_ptr<SharedLibrary> >::iterator itLoaded =
00226 loadables_.find(p);
00227 if(itLoaded == loadables_.end()) {
00228
00229 goingToLoad_(p);
00230 Sentry s(loadingLibraryNamed_(), p.native_file_string());
00231
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
00253 std::map<boost::filesystem::path, boost::shared_ptr<SharedLibrary> >::iterator itLoaded =
00254 loadables_.find(p);
00255 if(itLoaded == loadables_.end()) {
00256
00257 goingToLoad_(p);
00258 Sentry s(loadingLibraryNamed_(), p.native_file_string());
00259
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
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 }