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