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
00064
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
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
00107
00108
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
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
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
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();
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
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
00211
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 ) {
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
00234 ++itFile;
00235 ltp.erase(itToItemBeingRemoved);
00236 } else {
00237
00238 ++itFile;
00239 }
00240 }
00241
00242 }
00243
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 }