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