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