00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <string>
00015 #include <iostream>
00016 #include <map>
00017 #include "TROOT.h"
00018 #include "TInterpreter.h"
00019 #include "G__ci.h"
00020
00021
00022 #include "FWCore/RootAutoLibraryLoader/interface/RootAutoLibraryLoader.h"
00023 #include "FWCore/RootAutoLibraryLoader/src/stdNamespaceAdder.h"
00024
00025 #include "FWCore/PluginManager/interface/PluginManager.h"
00026 #include "FWCore/PluginManager/interface/ProblemTracker.h"
00027 #include "FWCore/PluginManager/interface/PluginCapabilities.h"
00028 #include "FWCore/Utilities/interface/DictionaryTools.h"
00029 #include "FWCore/Utilities/interface/Exception.h"
00030
00031 #include "Cintex/Cintex.h"
00032 #include "TClass.h"
00033
00034
00035
00036
00037
00038
00039 namespace {
00040
00041
00042
00043 class RootLoadFileSentry {
00044 public:
00045 RootLoadFileSentry() {
00046 G__setfilecontext("{CMS auto library loader}", &oldIFile_);
00047 }
00048
00049 ~RootLoadFileSentry() {
00050 G__input_file* ifile = G__get_ifile();
00051 if (ifile) {
00052 *ifile = oldIFile_;
00053 }
00054 }
00055
00056 private:
00057 G__input_file oldIFile_;
00058 };
00059 }
00060
00061
00062
00063
00064
00065 typedef int (*CallbackPtr)(char*, char*);
00066 static CallbackPtr gPrevious = nullptr;
00067 static char const* kDummyLibName = "*dummy";
00068
00069
00070
00071 extern CallbackPtr G__p_class_autoloading;
00072
00073 namespace ROOT {
00074 namespace Cintex {
00075 std::string CintName(std::string const&);
00076 }
00077 }
00078
00079 namespace edm {
00080 namespace {
00081
00082 std::map<std::string, std::string>&
00083 cintToReflexSpecialCasesMap() {
00084 static std::map<std::string, std::string> s_map;
00085 return s_map;
00086 }
00087
00088 void
00089 addWrapperOfVectorOfBuiltin(std::map<std::string, std::string>& iMap, char const* iBuiltin) {
00090 static std::string sReflexPrefix("edm::Wrapper<std::vector<");
00091 static std::string sReflexPostfix("> >");
00092
00093
00094 static std::string sCintPrefix("Wrapper<vector<");
00095 static std::string sCintMiddle(",allocator<");
00096 static std::string sCintPostfix("> > >");
00097
00098 std::string type(iBuiltin);
00099 iMap.insert(make_pair(sCintPrefix + type + sCintMiddle + type + sCintPostfix,
00100 sReflexPrefix + type + sReflexPostfix));
00101 }
00102
00103 std::string
00104 classNameForRoot(std::string const& classname) {
00105
00106 return ROOT::Cintex::CintName(classname);
00107 }
00108
00109 bool
00110 isDictionaryLoaded(std::string const& rootclassname) {
00111
00112
00113
00114 ClassInfo_t* info = gInterpreter->ClassInfo_Factory(rootclassname.c_str());
00115 return gInterpreter->ClassInfo_IsValid(info);
00116 }
00117
00118 bool loadLibraryForClass(char const* classname) {
00119
00120 if(nullptr == classname) {
00121 return false;
00122 }
00123
00124 std::string const& cPrefix = dictionaryPlugInPrefix();
00125
00126 std::string rootclassname = classNameForRoot(classname);
00127 try {
00128
00129 RootLoadFileSentry sentry;
00130 if(edmplugin::PluginCapabilities::get()->tryToLoad(cPrefix + classname)) {
00131 if(!isDictionaryLoaded(rootclassname)) {
00132
00133
00134
00135 return false;
00136 }
00137 } else {
00138
00139 std::string name = root::stdNamespaceAdder(classname);
00140
00141 if (not edmplugin::PluginCapabilities::get()->tryToLoad(cPrefix + name)) {
00142
00143 return false;
00144 }
00145 if(!isDictionaryLoaded(rootclassname)) {
00146
00147 return false;
00148 }
00149 }
00150 } catch(cms::Exception& e) {
00151
00152 return false;
00153 }
00154
00155 return true;
00156 }
00157
00158
00159
00160 int ALL_AutoLoadCallback(char* c, char* l) {
00161
00162
00163 if(nullptr == c || nullptr == l || l[0] == 0) {
00164 return 0;
00165 }
00166 ULong_t varp = G__getgvp();
00167 G__setgvp((long)G__PVOID);
00168 int result = loadLibraryForClass(c) ? 1:0;
00169 G__setgvp(varp);
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 if(!result && 0 != strcmp(l, kDummyLibName) && gPrevious) {
00180 result = gPrevious(c, l);
00181 }
00182 return result;
00183 }
00184
00185
00186
00187 struct CompareFirst {
00188 bool operator()(std::pair<std::string, std::string> const& iLHS,
00189 std::pair<std::string, std::string> const& iRHS) const{
00190 return iLHS.first > iRHS.first;
00191 }
00192 };
00193
00194 void registerTypes() {
00195 edmplugin::PluginManager* db = edmplugin::PluginManager::get();
00196
00197 typedef edmplugin::PluginManager::CategoryToInfos CatToInfos;
00198
00199 CatToInfos::const_iterator itFound = db->categoryToInfos().find("Capability");
00200
00201 if(itFound == db->categoryToInfos().end()) {
00202 return;
00203 }
00204
00205
00206
00207
00208
00209 typedef std::vector<std::pair<std::string, std::string> > ClassAndLibraries;
00210 ClassAndLibraries classes;
00211 classes.reserve(1000);
00212 std::string lastClass;
00213
00214
00215 std::map<std::string, std::string> specialsToLib;
00216 std::map<std::string, std::string> const& specials = cintToReflexSpecialCasesMap();
00217 for(auto const& special : specials) {
00218 specialsToLib[classNameForRoot(special.second)];
00219 }
00220 std::string const& cPrefix = dictionaryPlugInPrefix();
00221 for(auto const& info : itFound->second) {
00222 if (lastClass == info.name_) {
00223 continue;
00224 }
00225 lastClass = info.name_;
00226 if(cPrefix == lastClass.substr(0, cPrefix.size())) {
00227 std::string className = classNameForRoot(lastClass.c_str() + cPrefix.size());
00228 classes.emplace_back(className, info.loadable_.string());
00229 std::map<std::string, std::string>::iterator iFound = specialsToLib.find(className);
00230 if(iFound != specialsToLib.end()) {
00231
00232 iFound->second = info.loadable_.string();
00233 }
00234 }
00235 }
00236
00237
00238
00239 for(ClassAndLibraries::reverse_iterator itClass = classes.rbegin(), itClassEnd = classes.rend();
00240 itClass != itClassEnd;
00241 ++itClass) {
00242
00243 std::string const& className = itClass->first;
00244 std::string const& libraryName = itClass->second;
00245
00246 static std::string const toFind(":<");
00247 std::string::size_type pos = 0;
00248 while(std::string::npos != (pos = className.find_first_of(toFind, pos))) {
00249 if (className[pos] == '<') {break;}
00250 if (className.size() <= pos + 1 || className[pos + 1] != ':') {break;}
00251
00252 G__set_class_autoloading_table(const_cast<char*>(className.substr(0, pos).c_str()), const_cast<char*>(""));
00253
00254 pos += 2;
00255 }
00256 G__set_class_autoloading_table(const_cast<char*>(className.c_str()), const_cast<char*>(libraryName.c_str()));
00257
00258 }
00259
00260
00261 for(auto const& special : specials) {
00262 std::string const& name = special.second;
00263 std::string rootname = classNameForRoot(name);
00264
00265
00266 if(specialsToLib[rootname].size()) {
00267
00268 if(!isDictionaryLoaded(rootname) and
00269 (not edmplugin::PluginCapabilities::get()->tryToLoad(cPrefix + name))) {
00270 std::cout << "failed to load plugin for " << cPrefix + name << std::endl;
00271 continue;
00272 } else {
00273
00274 if(!isDictionaryLoaded(rootname)) {
00275 std::cout << "dictionary did not build " << name << std::endl;
00276 continue;
00277 }
00278 TClass* namedClass = TClass::GetClass(rootname.c_str());
00279 if(nullptr == namedClass) {
00280 std::cout << "failed to get TClass for " << name << std::endl;
00281 continue;
00282 }
00283 namedClass->Clone(special.first.c_str());
00284 std::string magictypedef("namespace edm { typedef ");
00285 magictypedef += rootname + " " + special.first + "; }";
00286
00287 gROOT->ProcessLine(magictypedef.c_str());
00288 }
00289 }
00290 }
00291 }
00292 }
00293
00294
00295
00296
00297 RootAutoLibraryLoader::RootAutoLibraryLoader() :
00298 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,27,6)
00299 classNameAttemptingToLoad_(nullptr),
00300 isInitializingCintex_(true) {
00301 #else
00302 classNameAttemptingToLoad_(nullptr) {
00303 #endif
00304 AssertHandler h;
00305 gROOT->AddClassGenerator(this);
00306 ROOT::Cintex::Cintex::Enable();
00307 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,27,6)
00308 isInitializingCintex_ =false;
00309 #endif
00310
00311 std::map<std::string, std::string>& specials = cintToReflexSpecialCasesMap();
00312 if(specials.empty()) {
00313 addWrapperOfVectorOfBuiltin(specials,"bool");
00314
00315 addWrapperOfVectorOfBuiltin(specials,"char");
00316 addWrapperOfVectorOfBuiltin(specials,"unsigned char");
00317 addWrapperOfVectorOfBuiltin(specials,"signed char");
00318 addWrapperOfVectorOfBuiltin(specials,"short");
00319 addWrapperOfVectorOfBuiltin(specials,"unsigned short");
00320 addWrapperOfVectorOfBuiltin(specials,"int");
00321 addWrapperOfVectorOfBuiltin(specials,"unsigned int");
00322 addWrapperOfVectorOfBuiltin(specials,"long");
00323 addWrapperOfVectorOfBuiltin(specials,"unsigned long");
00324 addWrapperOfVectorOfBuiltin(specials,"long long");
00325 addWrapperOfVectorOfBuiltin(specials,"unsigned long long");
00326
00327 addWrapperOfVectorOfBuiltin(specials,"float");
00328 addWrapperOfVectorOfBuiltin(specials,"double");
00329 }
00330
00331
00332 gPrevious = G__p_class_autoloading;
00333 G__set_class_autoloading_callback(&ALL_AutoLoadCallback);
00334 registerTypes();
00335 }
00336
00337
00338
00339
00340
00341 TClass*
00342 RootAutoLibraryLoader::GetClass(char const* classname, Bool_t load) {
00343 TClass* returnValue = nullptr;
00344 if(classNameAttemptingToLoad_ != nullptr && !strcmp(classname, classNameAttemptingToLoad_)) {
00345
00346
00347 std::string className(classname);
00348 std::string::size_type idx = className.find("basic_string<char>");
00349 if (idx != std::string::npos) {
00350 className.replace(idx, 18, std::string("string"));
00351
00352
00353 if(className.size() > idx + 6 && className[idx + 6] == ' ') {
00354 className.replace(idx + 6, 1, "");
00355 }
00356 classNameAttemptingToLoad_ = className.c_str();
00357 returnValue = gROOT->GetClass(className.c_str(), kTRUE);
00358 classNameAttemptingToLoad_ = classname;
00359 return returnValue;
00360 }
00361
00362
00363
00364 return nullptr;
00365 }
00366
00367 if (load) {
00368
00369
00370
00371
00372 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,27,6)
00373 if (not isInitializingCintex_ and loadLibraryForClass(classname)) {
00374 #else
00375 if (loadLibraryForClass(classname)) {
00376 #endif
00377
00378 classNameAttemptingToLoad_ = classname;
00379
00380
00381
00382
00383 returnValue = gROOT->GetClass(classname, kTRUE);
00384 classNameAttemptingToLoad_ = nullptr;
00385 }
00386 }
00387 return returnValue;
00388 }
00389
00390 TClass*
00391 RootAutoLibraryLoader::GetClass(type_info const& typeinfo, Bool_t load) {
00392
00393 TClass* returnValue = nullptr;
00394 if(load) {
00395 return GetClass(typeinfo.name(), load);
00396 }
00397 return returnValue;
00398 }
00399
00400 void
00401 RootAutoLibraryLoader::enable() {
00402
00403
00404 static RootAutoLibraryLoader s_loader;
00405 }
00406
00407 void
00408 RootAutoLibraryLoader::loadAll() {
00409
00410 enable();
00411
00412 edmplugin::PluginManager* db = edmplugin::PluginManager::get();
00413
00414 typedef edmplugin::PluginManager::CategoryToInfos CatToInfos;
00415
00416 CatToInfos::const_iterator itFound = db->categoryToInfos().find("Capability");
00417
00418 if(itFound == db->categoryToInfos().end()) {
00419 return;
00420 }
00421 std::string lastClass;
00422
00423
00424 RootLoadFileSentry sentry;
00425
00426 for(auto const& info : itFound->second) {
00427 if (lastClass == info.name_) {
00428 continue;
00429 }
00430
00431 lastClass = info.name_;
00432 edmplugin::PluginCapabilities::get()->load(lastClass);
00433
00434 }
00435 }
00436 }
00437
00438