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/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 #include "FWCore/Utilities/interface/TypeWithDict.h"
00031
00032 #include "Cintex/Cintex.h"
00033 #include "TClass.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 std::string const& cPrefix = dictionaryPlugInPrefix();
00105
00106 try {
00107
00108 RootLoadFileSentry sentry;
00109 if(edmplugin::PluginCapabilities::get()->tryToLoad(cPrefix + classname)) {
00110 TypeWithDict t(TypeWithDict::byName(classname));
00111 if(!t.isComplete()) {
00112
00113
00114
00115 return false;
00116 }
00117 } else {
00118
00119 std::string name = root::stdNamespaceAdder(classname);
00120
00121 if (not edmplugin::PluginCapabilities::get()->tryToLoad(cPrefix + name)) {
00122
00123 return false;
00124 }
00125 TypeWithDict t(TypeWithDict::byName(name));
00126 if (!bool(t)) {
00127 TypeWithDict t2(TypeWithDict::byName(name));
00128 if (!bool(t2)) {
00129
00130 return false;
00131 }
00132 }
00133 }
00134 } catch(cms::Exception& e) {
00135
00136 return false;
00137 }
00138
00139 return true;
00140 }
00141
00142
00143
00144 int ALL_AutoLoadCallback(char* c, char* l) {
00145
00146
00147 if(0 == c || 0 == l || l[0] == 0) {
00148 return 0;
00149 }
00150 ULong_t varp = G__getgvp();
00151 G__setgvp((long)G__PVOID);
00152 int result = loadLibraryForClass(c) ? 1:0;
00153 G__setgvp(varp);
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 if(!result && 0 != strcmp(l, kDummyLibName) && gPrevious) {
00164 result = gPrevious(c, l);
00165 }
00166 return result;
00167 }
00168
00169 std::string
00170 classNameForRoot(std::string const& iCapName) {
00171
00172 static boost::regex const ex("std::");
00173 std::string const to("");
00174
00175 return regex_replace(iCapName, ex, to, boost::match_default | boost::format_sed);
00176 }
00177
00178
00179
00180 struct CompareFirst {
00181 bool operator()(std::pair<std::string, std::string> const& iLHS,
00182 std::pair<std::string, std::string> const& iRHS) const{
00183 return iLHS.first > iRHS.first;
00184 }
00185 };
00186
00187 void registerTypes() {
00188 edmplugin::PluginManager* db = edmplugin::PluginManager::get();
00189
00190 typedef edmplugin::PluginManager::CategoryToInfos CatToInfos;
00191
00192 CatToInfos::const_iterator itFound = db->categoryToInfos().find("Capability");
00193
00194 if(itFound == db->categoryToInfos().end()) {
00195 return;
00196 }
00197
00198
00199
00200
00201
00202 typedef std::vector<std::pair<std::string, std::string> > ClassAndLibraries;
00203 ClassAndLibraries classes;
00204 classes.reserve(1000);
00205 std::string lastClass;
00206
00207
00208 std::map<std::string, std::string> specialsToLib;
00209 std::map<std::string, std::string> const& specials = cintToReflexSpecialCasesMap();
00210 for(std::map<std::string, std::string>::const_iterator itSpecial = specials.begin();
00211 itSpecial != specials.end();
00212 ++itSpecial) {
00213 specialsToLib[classNameForRoot(itSpecial->second)];
00214 }
00215 std::string const& cPrefix = dictionaryPlugInPrefix();
00216 for (edmplugin::PluginManager::Infos::const_iterator itInfo = itFound->second.begin(),
00217 itInfoEnd = itFound->second.end();
00218 itInfo != itInfoEnd; ++itInfo) {
00219 if (lastClass == itInfo->name_) {
00220 continue;
00221 }
00222 lastClass = itInfo->name_;
00223 if(cPrefix == lastClass.substr(0, cPrefix.size())) {
00224 std::string className = classNameForRoot(lastClass.c_str() + cPrefix.size());
00225 classes.push_back(std::pair<std::string, std::string>(className, itInfo->loadable_.string()));
00226 std::map<std::string, std::string>::iterator itFound = specialsToLib.find(className);
00227 if(itFound != specialsToLib.end()) {
00228
00229 itFound->second = itInfo->loadable_.string();
00230 }
00231 }
00232 }
00233
00234
00235
00236 for(ClassAndLibraries::reverse_iterator itClass = classes.rbegin(), itClassEnd = classes.rend();
00237 itClass != itClassEnd;
00238 ++itClass) {
00239
00240 std::string const& className = itClass->first;
00241 std::string const& libraryName = itClass->second;
00242
00243 static std::string const toFind(":<");
00244 std::string::size_type pos = 0;
00245 while(std::string::npos != (pos = className.find_first_of(toFind, pos))) {
00246 if (className[pos] == '<') {break;}
00247 if (className.size() <= pos + 1 || className[pos + 1] != ':') {break;}
00248
00249 G__set_class_autoloading_table(const_cast<char*>(className.substr(0, pos).c_str()), const_cast<char*>(""));
00250
00251 pos += 2;
00252 }
00253 G__set_class_autoloading_table(const_cast<char*>(className.c_str()), const_cast<char*>(libraryName.c_str()));
00254
00255 }
00256
00257
00258 for(std::map<std::string, std::string>::const_iterator itSpecial = specials.begin();
00259 itSpecial != specials.end();
00260 ++itSpecial) {
00261
00262
00263 if(specialsToLib[classNameForRoot(itSpecial->second)].size()) {
00264
00265 std::string name = itSpecial->second;
00266 TypeWithDict t(TypeWithDict::byName(name));
00267
00268 if(!bool(t) 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 TypeWithDict t(TypeWithDict::byName(name));
00275 if(!bool(t)) {
00276 std::cout << "dictionary did not build " << name << std::endl;
00277 continue;
00278 }
00279 TClass* namedClass = TClass::GetClass(t.typeInfo());
00280 if(0 == namedClass) {
00281 std::cout << "failed to get TClass by typeid for " << name << std::endl;
00282 continue;
00283 }
00284 namedClass->Clone(itSpecial->first.c_str());
00285 std::string magictypedef("namespace edm { typedef ");
00286 magictypedef += classNameForRoot(name) + " " + itSpecial->first + "; }";
00287
00288 gROOT->ProcessLine(magictypedef.c_str());
00289 }
00290 }
00291 }
00292 }
00293 }
00294
00295
00296
00297
00298 RootAutoLibraryLoader::RootAutoLibraryLoader() :
00299 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,27,6)
00300 classNameAttemptingToLoad_(0),
00301 isInitializingCintex_(true) {
00302 #else
00303 classNameAttemptingToLoad_(0) {
00304 #endif
00305 AssertHandler h;
00306 gROOT->AddClassGenerator(this);
00307 ROOT::Cintex::Cintex::Enable();
00308 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,27,6)
00309 isInitializingCintex_ =false;
00310 #endif
00311
00312 std::map<std::string, std::string>& specials = cintToReflexSpecialCasesMap();
00313 if(specials.empty()) {
00314 addWrapperOfVectorOfBuiltin(specials,"bool");
00315
00316 addWrapperOfVectorOfBuiltin(specials,"char");
00317 addWrapperOfVectorOfBuiltin(specials,"unsigned char");
00318 addWrapperOfVectorOfBuiltin(specials,"signed char");
00319 addWrapperOfVectorOfBuiltin(specials,"short");
00320 addWrapperOfVectorOfBuiltin(specials,"unsigned short");
00321 addWrapperOfVectorOfBuiltin(specials,"int");
00322 addWrapperOfVectorOfBuiltin(specials,"unsigned int");
00323 addWrapperOfVectorOfBuiltin(specials,"long");
00324 addWrapperOfVectorOfBuiltin(specials,"unsigned long");
00325 addWrapperOfVectorOfBuiltin(specials,"long long");
00326 addWrapperOfVectorOfBuiltin(specials,"unsigned long long");
00327
00328 addWrapperOfVectorOfBuiltin(specials,"float");
00329 addWrapperOfVectorOfBuiltin(specials,"double");
00330 }
00331
00332
00333 gPrevious = G__p_class_autoloading;
00334 G__set_class_autoloading_callback(&ALL_AutoLoadCallback);
00335 registerTypes();
00336 }
00337
00338
00339
00340
00341
00342 TClass*
00343 RootAutoLibraryLoader::GetClass(char const* classname, Bool_t load) {
00344 TClass* returnValue = 0;
00345 if(classNameAttemptingToLoad_ != 0 && !strcmp(classname, classNameAttemptingToLoad_)) {
00346
00347
00348 std::string className(classname);
00349 std::string::size_type idx = className.find("basic_string<char>");
00350 if (idx != std::string::npos) {
00351 className.replace(idx, 18, std::string("string"));
00352
00353
00354 if(className.size() > idx + 6 && className[idx + 6] == ' ') {
00355 className.replace(idx + 6, 1, "");
00356 }
00357 classNameAttemptingToLoad_ = className.c_str();
00358 returnValue = gROOT->GetClass(className.c_str(), kTRUE);
00359 classNameAttemptingToLoad_ = classname;
00360 return returnValue;
00361 }
00362
00363
00364
00365 return 0;
00366 }
00367
00368 if (load) {
00369
00370
00371
00372
00373 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,27,6)
00374 if (not isInitializingCintex_ and loadLibraryForClass(classname)) {
00375 #else
00376 if (loadLibraryForClass(classname)) {
00377 #endif
00378
00379 classNameAttemptingToLoad_ = classname;
00380
00381
00382
00383
00384 returnValue = gROOT->GetClass(classname, kTRUE);
00385 classNameAttemptingToLoad_ = 0;
00386 }
00387 }
00388 return returnValue;
00389 }
00390
00391 TClass*
00392 RootAutoLibraryLoader::GetClass(type_info const& typeinfo, Bool_t load) {
00393
00394 TClass* returnValue = 0;
00395 if(load) {
00396 return GetClass(typeinfo.name(), load);
00397 }
00398 return returnValue;
00399 }
00400
00401 void
00402 RootAutoLibraryLoader::enable() {
00403
00404
00405 static RootAutoLibraryLoader s_loader;
00406 }
00407
00408 void
00409 RootAutoLibraryLoader::loadAll() {
00410
00411 enable();
00412
00413 edmplugin::PluginManager* db = edmplugin::PluginManager::get();
00414
00415 typedef edmplugin::PluginManager::CategoryToInfos CatToInfos;
00416
00417 CatToInfos::const_iterator itFound = db->categoryToInfos().find("Capability");
00418
00419 if(itFound == db->categoryToInfos().end()) {
00420 return;
00421 }
00422 std::string lastClass;
00423
00424
00425 RootLoadFileSentry sentry;
00426
00427 for (edmplugin::PluginManager::Infos::const_iterator itInfo = itFound->second.begin(),
00428 itInfoEnd = itFound->second.end();
00429 itInfo != itInfoEnd; ++itInfo) {
00430 if (lastClass == itInfo->name_) {
00431 continue;
00432 }
00433
00434 lastClass = itInfo->name_;
00435 edmplugin::PluginCapabilities::get()->load(lastClass);
00436
00437 }
00438 }
00439 }
00440
00441