CMS 3D CMS Logo

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

Go to the documentation of this file.
00001 
00002 #include <boost/filesystem/path.hpp>
00003 #include <boost/filesystem/operations.hpp>
00004 #include <boost/bind.hpp>
00005 #include <boost/mem_fn.hpp>
00006 
00007 #include <boost/program_options.hpp>
00008 
00009 #include <fstream>
00010 #include <iostream>
00011 #include <utility>
00012 #include <cstdlib>
00013 #include <string>
00014 #include <set>
00015 #include <algorithm>
00016 
00017 #include "FWCore/PluginManager/interface/PluginFactoryManager.h"
00018 #include "FWCore/PluginManager/interface/PluginFactoryBase.h"
00019 #include "FWCore/Utilities/interface/Exception.h"
00020 #include "FWCore/Utilities/interface/Algorithms.h"
00021 #include "FWCore/PluginManager/interface/CacheParser.h"
00022 #include "FWCore/PluginManager/interface/SharedLibrary.h"
00023 
00024 #include "FWCore/PluginManager/interface/PluginCapabilities.h"
00025 #include "FWCore/PluginManager/interface/standard.h"
00026 
00027 using namespace edmplugin;
00028 
00029 namespace std {
00030 ostream& operator<<(std::ostream& o, const vector<std::string>& iValue) {
00031   std::string sep("");
00032   std::string commaSep(",");
00033   for(std::vector<std::string>::const_iterator it=iValue.begin(), itEnd=iValue.end();
00034       it != itEnd;
00035       ++it) {    
00036     o <<sep<<*it;
00037     sep = commaSep;
00038   }
00039   return o;
00040 }
00041 }
00042 namespace {
00043   struct Listener {
00044     typedef edmplugin::CacheParser::NameAndType NameAndType;
00045     typedef edmplugin::CacheParser::NameAndTypes NameAndTypes;
00046     
00047     void newFactory(const edmplugin::PluginFactoryBase* iBase) {
00048       iBase->newPluginAdded_.connect(boost::bind(boost::mem_fn(&Listener::newPlugin),this,_1,_2));
00049     }
00050     void newPlugin(const std::string& iCategory, const edmplugin::PluginInfo& iInfo) {
00051       nameAndTypes_.push_back(NameAndType(iInfo.name_,iCategory));
00052     }
00053     
00054     NameAndTypes nameAndTypes_;
00055   };
00056 }
00057 int main (int argc, char **argv)
00058 {
00059   using namespace boost::program_options;
00060   
00061   static const char* const kPathsOpt = "paths";
00062   static const char* const kPathsCommandOpt = "paths,p";
00063   //static const char* const kAllOpt = "all";
00064   //static const char* const kAllCommandOpt = "all,a";
00065   static const char* const kHelpOpt = "help";
00066   static const char* const kHelpCommandOpt = "help,h";
00067   
00068   std::string descString(argv[0]);
00069   descString += " [options] [[--";
00070   descString += kPathsOpt;
00071   descString += "] path [path]] \nAllowed options";
00072   options_description desc(descString);
00073   std::string defaultDir(".");
00074   std::vector<std::string> defaultDirList = edmplugin::standard::config().searchPath();
00075   if( not defaultDirList.empty() ) {
00076     defaultDir = defaultDirList[0];
00077   }
00078   desc.add_options()
00079     (kHelpCommandOpt, "produce help message")
00080     (kPathsCommandOpt,value<std::vector<std::string> >()->default_value(
00081                           std::vector<std::string>(1,defaultDir))
00082      , "a directory or a list of files to scan")
00083     //(kAllCommandOpt,"when no paths given, try to update caches for all known directories [default is to only scan the first directory]")
00084     ;
00085   
00086   positional_options_description p;
00087   p.add(kPathsOpt, -1);
00088   
00089   variables_map vm;
00090   try {
00091     store(command_line_parser(argc,argv).options(desc).positional(p).run(),vm);
00092     notify(vm);
00093   } catch(const error& iException) {
00094     std::cerr <<iException.what();
00095     return 1;
00096   }
00097   
00098   if(vm.count(kHelpOpt)) {
00099     std::cout << desc <<std::endl;
00100     return 0;
00101   }
00102   
00103   
00104   using boost::filesystem::path;
00105   
00106   /*if(argc ==1) {
00107     std::cerr <<"Requires at least one argument.  Please pass either one directory or a list of files (all in the same directory)."<<std::endl;
00108     return 1;
00109   } */
00110 
00111   int returnValue = EXIT_SUCCESS;
00112 
00113   try {
00114     std::vector<std::string> requestedPaths(vm[kPathsOpt].as<std::vector<std::string> >());
00115     
00116     //first find the directory and create a list of files to look at in that directory
00117     path directory(requestedPaths[0]);
00118     std::vector<std::string> files;
00119     bool removeMissingFiles = false;
00120     if(boost::filesystem::is_directory(directory)) {
00121       if (requestedPaths.size()>1) {
00122         std::cerr <<"if a directory is given then only one argument is allowed"<<std::endl;
00123         return 1;
00124       }
00125       
00126       //if asked to look at whole directory, then we can also remove missing files
00127       removeMissingFiles = true;
00128       
00129       boost::filesystem::directory_iterator       file (directory);
00130       boost::filesystem::directory_iterator       end;
00131 
00132       path cacheFile(directory);
00133       cacheFile /= standard::cachefileName();
00134 
00135       std::time_t cacheLastChange(0);
00136       if(exists(cacheFile)) {
00137         cacheLastChange = last_write_time(cacheFile);
00138       }
00139       for (; file != end; ++file)
00140       {
00141 
00142         path  filename (*file);
00143         path shortName(file->leaf());
00144         std::string stringName = shortName.string();
00145         
00146         static std::string kPluginPrefix(standard::pluginPrefix());
00147         if (stringName.size() < kPluginPrefix.size()) {
00148           continue;
00149         }
00150         if(stringName.substr(0,kPluginPrefix.size()) != kPluginPrefix) {
00151           continue;
00152         }
00153 
00154         if(last_write_time(filename) > cacheLastChange) {
00155           files.push_back(stringName);
00156         }
00157       }
00158     } else {
00159       //we have files
00160       directory = directory.branch_path();
00161       for(std::vector<std::string>::iterator it=requestedPaths.begin(), itEnd=requestedPaths.end();
00162           it != itEnd; ++it) {
00163         boost::filesystem::path f(*it);
00164         if ( not exists(f) ) {
00165           std::cerr <<"the file '"<<f.native_file_string()<<"' does not exist"<<std::endl;
00166           return 1;
00167         }
00168         if (is_directory(f) ) {
00169           std::cerr <<"either one directory or a list of files are allowed as arguments"<<std::endl;
00170           return 1;
00171         }
00172         if(directory != f.branch_path()) {
00173           std::cerr <<"all files must have be in the same directory ("<<directory.native_file_string()<<")\n"
00174           " the file "<<f.native_file_string()<<" does not."<<std::endl;
00175         }
00176         files.push_back(f.leaf());
00177       }
00178     }
00179 
00180     path cacheFile(directory);
00181     cacheFile /= edmplugin::standard::cachefileName();//path(s_cacheFile);
00182 
00183     CacheParser::LoadableToPlugins ltp;
00184     if(exists(cacheFile) ) {
00185       std::ifstream cf(cacheFile.native_file_string().c_str());
00186       if(!cf) {
00187         cms::Exception("FailedToOpen")<<"unable to open file '"<<cacheFile.native_file_string()<<"' for reading even though it is present.\n"
00188         "Please check permissions on the file.";
00189       }
00190       CacheParser::read(cf, ltp);
00191     }
00192     
00193     
00194     //load each file and 'listen' to which plugins are loaded
00195     Listener listener;
00196     edmplugin::PluginFactoryManager* pfm =  edmplugin::PluginFactoryManager::get();
00197     pfm->newFactory_.connect(boost::bind(boost::mem_fn(&Listener::newFactory),&listener,_1));
00198     edm::for_all(*pfm, boost::bind(boost::mem_fn(&Listener::newFactory),&listener,_1));
00199     
00200     for(std::vector<std::string>::iterator itFile = files.begin();
00201         itFile != files.end();
00202         ++itFile) {
00203 
00204       path loadableFile(directory);
00205       loadableFile /=(*itFile);
00206       listener.nameAndTypes_.clear();
00207       try {
00208          edmplugin::SharedLibrary lib(loadableFile);
00209       
00210          //PluginCapabilities is special, the plugins do not call it.  Instead, for each shared library load
00211          // we need to ask it to try to find plugins
00212          PluginCapabilities::get()->tryToFind(lib);
00213       
00214          ltp[*itFile]=listener.nameAndTypes_;
00215       } catch(const cms::Exception& iException) {
00216          if(iException.category() == "PluginLibraryLoadError") {
00217             std::cerr <<"Caught exception "<<iException.what()<<" will ignore "<<*itFile<<" and continue."<<std::endl;
00218          } else {
00219             throw;
00220          }
00221       }
00222     }
00223     
00224     if(removeMissingFiles) {
00225       for(CacheParser::LoadableToPlugins::iterator itFile = ltp.begin();
00226           itFile != ltp.end();
00227           /*don't advance the iterator here because it may have become invalid */) {
00228         path loadableFile(directory);
00229         loadableFile /=(itFile->first);
00230         if(not exists(loadableFile)) {
00231           std::cout <<"removing file '"<<loadableFile.native_file_string()<<"'"<<std::endl;
00232           CacheParser::LoadableToPlugins::iterator itToItemBeingRemoved = itFile;
00233           //advance the iterator while it is still valid
00234           ++itFile;
00235           ltp.erase(itToItemBeingRemoved);
00236         } else {
00237           //since we are not advancing the iterator in the for loop, do it here
00238           ++itFile;
00239         }
00240       }
00241       //now get rid of the items 
00242     }
00243     //now write our new results
00244     std::ofstream cf(cacheFile.native_file_string().c_str());
00245     if(!cf) {
00246       cms::Exception("FailedToOpen")<<"unable to open file '"<<cacheFile.native_file_string()<<"' for writing.\n"
00247       "Please check permissions on the file.";
00248     }
00249     CacheParser::write(ltp,cf);
00250   }catch(std::exception& iException) {
00251     std::cerr <<"Caught exception "<<iException.what()<<std::endl;
00252     returnValue = 1;
00253   }
00254 
00255     return returnValue;
00256 }