ROOT   Reference Guide
TPluginManager.cxx
Go to the documentation of this file.
1 // @(#)root/base:$Id$
2 // Author: Fons Rademakers 26/1/2002
3
4 /*************************************************************************
5  * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. * 9 * For the list of contributors see$ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11
12 /** \class TPluginManager
13 \ingroup Base
14
15 This class implements a plugin library manager.
16
17 It keeps track of a list of plugin handlers. A plugin handler knows which plugin
18 library to load to get a specific class that is used to extend the
19 functionality of a specific base class and how to create an object
20 of this class. For example, to extend the base class TFile to be
21 able to read SQLite files one needs to load the plugin library
22 libRSQLite.so which defines the TRSQLiteServer class. This loading
23 should be triggered when a given URI contains a regular expression
24 defined by the handler.
25
26 Plugin handlers can be defined via macros in a list of plugin
27 directories. With $ROOTSYS/etc/plugins the default top plugin 28 directory specified in$ROOTSYS/etc/system.rootrc. Additional
29 directories can be specified by adding them to the end of the list.
30 Macros for identical plugin handlers in later directories will
31 override previous ones (the inverse of normal search path behavior).
32 The macros must have names like <BaseClass>/PX0_<PluginClass>.C,
33 e.g. TSQLServer/P20_TMySQLServer.C, to allow easy sorting and grouping.
34 If the BaseClass is in a namespace the directory must have the name
35 NameSpace@@BaseClass as : is a reserved pathname character on some
36 operating systems. Macros not beginning with 'P' and ending with ".C"
37 are ignored. These macros typically look like:
38 ~~~ {.cpp}
39  void P10_TDCacheFile()
40  {
41  gPluginMgr->AddHandler("TFile", "^dcache", "TDCacheFile",
42  "DCache", "TDCacheFile(const char*,Option_t*)");
43  }
44 ~~~
45 Plugin handlers can also be defined via resources in the .rootrc
46 file. Although now deprecated this method still works for backward
47 compatibility, e.g.:
48 ~~~ {.cpp}
49  Plugin.TSQLServer: ^mysql: TMySQLServer MySQL "<constructor>"
50  +Plugin.TSQLServer: ^pgsql: TPgSQLServer PgSQL "<constructor>"
51  Plugin.TVirtualFitter: * TFitter Minuit "TFitter(Int_t)"
52 ~~~
53 Where the + in front of Plugin.TSQLServer says that it extends the
54 existing definition of TSQLServer, useful when there is more than
55 one plugin that can extend the same base class. The "<constructor>"
56 should be the constructor or a static method that generates an
57 instance of the specified class. Global methods should start with
58 "::" in their name, like "::CreateFitter()".
59 Instead of being a shared library a plugin can also be a CINT
60 script, so instead of libDialog.so one can have Dialog.C.
61 The * is a placeholder in case there is no need for a URI to
62 differentiate between different plugins for the same base class.
63 For the default plugins see $ROOTSYS/etc/system.rootrc. 64 65 Plugin handlers can also be registered at run time, e.g.: 66 ~~~ {.cpp} 67 gPluginMgr->AddHandler("TSQLServer", "^sqlite:", 68 "TSQLiteServer", "RSQLite", 69 "TSQLiteServer(const char*,const char*,const char*)"); 70 ~~~ 71 A list of currently defined handlers can be printed using: 72 ~~~ {.cpp} 73 gPluginMgr->Print(); // use option="a" to see ctors 74 ~~~ 75 The use of the plugin library manager removes all textual references 76 to hard-coded class and library names and the resulting dependencies 77 in the base classes. The plugin manager is used to extend a.o. 78 TFile, TSQLServer, TGrid, etc. functionality. 79 */ 80 81 #include "TPluginManager.h" 82 #include "TEnv.h" 83 #include "TRegexp.h" 84 #include "TROOT.h" 85 #include "TSortedList.h" 86 #include "THashList.h" 87 #include "THashTable.h" 88 #include "TClass.h" 89 #include "TInterpreter.h" 90 #include "TMethod.h" 91 #include "TMethodArg.h" 92 #include "TDataType.h" 93 #include "TMethodCall.h" 94 #include "TVirtualMutex.h" 95 #include "TSystem.h" 96 #include "TObjString.h" 97 #include "TObjArray.h" 98 #include "ThreadLocalStorage.h" 99 100 #include <memory> 101 102 TPluginManager *gPluginMgr; // main plugin manager created in TROOT 103 105 106 static bool &TPH__IsReadingDirs() { 107 TTHREAD_TLS(bool) readingDirs (false); 108 return readingDirs; 109 } 110 112 113 //////////////////////////////////////////////////////////////////////////////// 114 /// Create a plugin handler. Called by TPluginManager. 115 116 TPluginHandler::TPluginHandler(const char *base, const char *regexp, 117 const char *className, const char *pluginName, 118 const char *ctor, const char *origin): 119 fBase(base), 120 fRegexp(regexp), 121 fClass(className), 122 fPlugin(pluginName), 123 fCtor(ctor), 124 fOrigin(origin), 125 fCallEnv(0), 126 fMethod(0), 127 fCanCall(0), 128 fIsMacro(kFALSE), 129 fIsGlobal(kFALSE) 130 { 131 TString aclicMode, arguments, io; 132 TString fname = gSystem->SplitAclicMode(fPlugin, aclicMode, arguments, io); 133 Bool_t validMacro = kFALSE; 134 if (fname.EndsWith(".C") || fname.EndsWith(".cxx") || fname.EndsWith(".cpp") || 135 fname.EndsWith(".cc")) 136 validMacro = kTRUE; 137 138 if (validMacro && gROOT->LoadMacro(fPlugin, 0, kTRUE) == 0) 139 fIsMacro = kTRUE; 140 141 if (fCtor.BeginsWith("::")) { 142 fIsGlobal = kTRUE; 144 } 145 } 146 147 //////////////////////////////////////////////////////////////////////////////// 148 /// Cleanup plugin handler object. 149 151 { 152 delete fCallEnv; 153 } 154 155 //////////////////////////////////////////////////////////////////////////////// 156 /// Check if regular expression appears in the URI, if so return kTRUE. 157 /// If URI = 0 always return kTRUE. 158 159 Bool_t TPluginHandler::CanHandle(const char *base, const char *uri) 160 { 161 if (fBase != base) 162 return kFALSE; 163 164 if (!uri || fRegexp == "*") 165 return kTRUE; 166 167 Bool_t wildcard = kFALSE; 168 if (!fRegexp.MaybeRegexp()) 169 wildcard = kTRUE; 170 171 TRegexp re(fRegexp, wildcard); 172 TString ruri = uri; 173 174 if (ruri.Index(re) != kNPOS) 175 return kTRUE; 176 return kFALSE; 177 } 178 179 //////////////////////////////////////////////////////////////////////////////// 180 /// Setup ctor or static method call environment. 181 183 { 184 int setCanCall = -1; 185 186 // Use a exit_scope guard, to insure that fCanCall is set (to the value of 187 // result) as the last action of this function before returning. 188 189 // When the standard supports it, we should use std::exit_code 190 // See N4189 for example. 191 // auto guard = make_exit_scope( [...]() { ... } ); 192 using exit_scope = std::shared_ptr<void*>; 193 exit_scope guard(nullptr, 194 [this,&setCanCall](void *) { this->fCanCall = setCanCall; } ); 195 196 // check if class exists 198 if (!cl && !fIsGlobal) { 199 Error("SetupCallEnv", "class %s not found in plugin %s", fClass.Data(), 200 fPlugin.Data()); 201 return; 202 } 203 204 // split method and prototype strings 205 TString method = fCtor(0, fCtor.Index("(")); 206 TString proto = fCtor(fCtor.Index("(")+1, fCtor.Index(")")-fCtor.Index("(")-1); 207 208 if (fIsGlobal) { 209 cl = 0; 210 fMethod = gROOT->GetGlobalFunctionWithPrototype(method, proto, kFALSE); 211 } else { 212 fMethod = cl->GetMethodWithPrototype(method, proto); 213 } 214 215 if (!fMethod) { 216 if (fIsGlobal) 217 Error("SetupCallEnv", "global function %s not found", method.Data()); 218 else 219 Error("SetupCallEnv", "method %s not found in class %s", method.Data(), 220 fClass.Data()); 221 return; 222 } 223 224 if (!fIsGlobal && !(fMethod->Property() & kIsPublic)) { 225 Error("SetupCallEnv", "method %s is not public", method.Data()); 226 return; 227 } 228 229 fCallEnv = new TMethodCall; 231 232 setCanCall = 1; 233 234 return; 235 } 236 237 //////////////////////////////////////////////////////////////////////////////// 238 /// Check if the plugin library for this handler exits. Returns 0 239 /// when it exists and -1 in case the plugin does not exist. 240 242 { 243 if (fIsMacro) { 244 if (TClass::GetClass(fClass)) return 0; 245 return gROOT->LoadMacro(fPlugin, 0, kTRUE); 246 } else 247 return gROOT->LoadClass(fClass, fPlugin, kTRUE); 248 } 249 250 //////////////////////////////////////////////////////////////////////////////// 251 /// Load the plugin library for this handler. Returns 0 on successful loading 252 /// and -1 in case the library does not exist or in case of error. 253 255 { 256 if (fIsMacro) { 257 if (TClass::GetClass(fClass)) return 0; 258 return gROOT->LoadMacro(fPlugin); 259 } else { 260 // first call also loads dependent libraries declared via the rootmap file 261 if (TClass::LoadClass(fClass, /* silent = */ kFALSE)) return 0; 262 return gROOT->LoadClass(fClass, fPlugin); 263 } 264 } 265 266 //////////////////////////////////////////////////////////////////////////////// 267 /// Check that we can properly run ExecPlugin. 268 270 { 271 if (fCtor.IsNull()) { 272 Error("ExecPlugin", "no ctor specified for this handler %s", fClass.Data()); 273 return kFALSE; 274 } 275 276 if (fCanCall == 0) { 277 // Not initialized yet. 278 // SetupCallEnv is likely to require/take the interpreter lock. 279 // Grab it now to avoid dead-lock. In particular TPluginHandler::ExecPluginImpl 280 // takes the gInterpreterMutex and *then* call (indirectly) code that 281 // take the gPluginManagerMutex. 284 285 // Now check if another thread did not already do the work. 286 if (fCanCall == 0) 287 SetupCallEnv(); 288 } 289 290 if (fCanCall == -1) 291 return kFALSE; 292 293 if (nargs < fMethod->GetNargs() - fMethod->GetNargsOpt() || 294 nargs > fMethod->GetNargs()) { 295 Error("ExecPlugin", "nargs (%d) not consistent with expected number of arguments ([%d-%d])", 296 nargs, fMethod->GetNargs() - fMethod->GetNargsOpt(), 297 fMethod->GetNargs()); 298 return kFALSE; 299 } 300 301 return kTRUE; 302 } 303 304 //////////////////////////////////////////////////////////////////////////////// 305 /// Print info about the plugin handler. If option is "a" print 306 /// also the ctor's that will be used. 307 309 { 310 const char *exist = ""; 311 if (CheckPlugin() == -1) 312 exist = " [*]"; 313 314 Printf("%-20s %-13s %-18s %s%s", fBase.Data(), fRegexp.Data(), 315 fClass.Data(), fPlugin.Data(), exist); 316 if (strchr(opt, 'a')) { 317 if (!exist[0]) { 318 TString lib = fPlugin; 319 if (!lib.BeginsWith("lib")) 320 lib = "lib" + lib; 321 char *path = gSystem->DynamicPathName(lib, kTRUE); 322 if (path) Printf(" [Lib: %s]", path); 323 delete [] path; 324 } 325 Printf(" [Ctor: %s]", fCtor.Data()); 326 Printf(" [origin: %s]", fOrigin.Data()); 327 } 328 } 329 330 332 333 //////////////////////////////////////////////////////////////////////////////// 334 /// Clean up the plugin manager. 335 337 { 338 delete fHandlers; 339 delete fBasesLoaded; 340 } 341 342 //////////////////////////////////////////////////////////////////////////////// 343 /// Load plugin handlers specified in config file, like: 344 /// ~~~ {.cpp} 345 /// Plugin.TSQLServer: ^mysql: TMySQLServer MySQL "TMySQLServer(...)" 346 /// +Plugin.TSQLServer: ^pgsql: TPgSQLServer PgSQL "TPgSQLServer(...)" 347 /// ~~~ 348 /// The + allows the extension of an already defined resource (see TEnv). 349 351 { 352 if (!env) return; 353 354 TIter next(env->GetTable()); 355 TEnvRec *er; 356 357 while ((er = (TEnvRec*) next())) { 358 const char *s; 359 if ((s = strstr(er->GetName(), "Plugin."))) { 360 // use s, i.e. skip possible OS and application prefix to Plugin. 361 // so that GetValue() takes properly care of returning the value 362 // for the specified OS and/or application 363 const char *val = env->GetValue(s, (const char*)0); 364 if (val) { 365 Int_t cnt = 0; 366 char *v = StrDup(val); 367 s += 7; 368 while (1) { 369 TString regexp = strtok(!cnt ? v : 0, "; "); // this method does not need to be reentrant 370 if (regexp.IsNull()) break; 371 TString clss = strtok(0, "; "); 372 if (clss.IsNull()) break; 373 TString plugin = strtok(0, "; "); 374 if (plugin.IsNull()) break; 375 TString ctor = strtok(0, ";\""); 376 if (!ctor.Contains("(")) 377 ctor = strtok(0, ";\""); 378 AddHandler(s, regexp, clss, plugin, ctor, "TEnv"); 379 cnt++; 380 } 381 delete [] v; 382 } 383 } 384 } 385 } 386 387 //////////////////////////////////////////////////////////////////////////////// 388 /// Load all plugin macros from the specified path/base directory. 389 390 void TPluginManager::LoadHandlerMacros(const char *path) 391 { 392 void *dirp = gSystem->OpenDirectory(path); 393 if (dirp) { 394 if (gDebug > 0) 395 Info("LoadHandlerMacros", "%s", path); 396 TSortedList macros; 397 macros.SetOwner(); 398 const char *f1; 399 while ((f1 = gSystem->GetDirEntry(dirp))) { 400 TString f = f1; 401 if (f[0] == 'P' && f.EndsWith(".C")) { 402 const char *p = gSystem->ConcatFileName(path, f); 404 macros.Add(new TObjString(p)); 405 } 406 delete [] p; 407 } 408 } 409 // load macros in alphabetical order 410 TIter next(&macros); 411 TObjString *s; 412 while ((s = (TObjString*)next())) { 413 if (gDebug > 1) 414 Info("LoadHandlerMacros", " plugin macro: %s", s->String().Data()); 415 Long_t res; 416 if ((res = gROOT->Macro(s->String(), 0, kFALSE)) < 0) { 417 Error("LoadHandlerMacros", "pluging macro %s returned %ld", 418 s->String().Data(), res); 419 } 420 } 421 } 422 gSystem->FreeDirectory(dirp); 423 } 424 425 //////////////////////////////////////////////////////////////////////////////// 426 /// Load plugin handlers specified via macros in a list of plugin 427 /// directories. The $ROOTSYS/etc/plugins is the default top plugin directory
428 /// specified in $ROOTSYS/etc/system.rootrc. The macros must have names 429 /// like <BaseClass>/PX0_<PluginClass>.C, e.g. //TSQLServer/P20_TMySQLServer.C, 430 /// to allow easy sorting and grouping. If the BaseClass is in a namespace 431 /// the directory must have the name NameSpace@@BaseClass as : is a reserved 432 /// pathname character on some operating systems. Macros not beginning with 433 /// 'P' and ending with ".C" are ignored. If base is specified only plugin 434 /// macros for that base class are loaded. The macros typically 435 /// should look like: 436 /// ~~~ {.cpp} 437 /// void P10_TDCacheFile() 438 /// { 439 /// gPluginMgr->AddHandler("TFile", "^dcache", "TDCacheFile", 440 /// "DCache", "TDCacheFile(const char*,Option_t*,const char*,Int_t)"); 441 /// } 442 /// ~~~ 443 /// In general these macros should not cause side effects, by changing global 444 /// ROOT state via, e.g. gSystem calls, etc. However, in specific cases 445 /// this might be useful, e.g. adding a library search path, adding a specific 446 /// dependency, check on some OS or ROOT capability or downloading 447 /// of the plugin. 448 450 { 451 TString sbase = base; 452 if (sbase.Length()) 453 sbase.ReplaceAll("::", "@@"); 454 456 457 if (fBasesLoaded && fBasesLoaded->FindObject(sbase)) 458 return; 459 461 462 // While waiting for the lock, another thread may 463 // have process the requested plugin. 464 if (fBasesLoaded && fBasesLoaded->FindObject(sbase)) 465 return; 466 467 if (!fBasesLoaded) { 468 fBasesLoaded = new THashTable(); 470 } 471 fBasesLoaded->Add(new TObjString(sbase)); 472 474 475 TString plugindirs = gEnv->GetValue("Root.PluginPath", (char*)0); 476 if (plugindirs.Length() == 0) { 477 plugindirs = "plugins"; 478 gSystem->PrependPathName(TROOT::GetEtcDir(), plugindirs); 479 } 480 #ifdef WIN32 481 TObjArray *dirs = plugindirs.Tokenize(";"); 482 #else 483 TObjArray *dirs = plugindirs.Tokenize(":"); 484 #endif 485 TString d; 486 for (Int_t i = 0; i < dirs->GetEntriesFast(); i++) { 487 d = ((TObjString*)dirs->At(i))->GetString(); 488 // check if directory already scanned 489 Int_t skip = 0; 490 for (Int_t j = 0; j < i; j++) { 491 TString pd = ((TObjString*)dirs->At(j))->GetString(); 492 if (pd == d) { 493 skip++; 494 break; 495 } 496 } 497 if (!skip) { 498 if (sbase != "") { 499 const char *p = gSystem->ConcatFileName(d, sbase); 501 delete [] p; 502 } else { 503 void *dirp = gSystem->OpenDirectory(d); 504 if (dirp) { 505 if (gDebug > 0) 506 Info("LoadHandlersFromPluginDirs", "%s", d.Data()); 507 const char *f1; 508 while ((f1 = gSystem->GetDirEntry(dirp))) { 509 TString f = f1; 510 const char *p = gSystem->ConcatFileName(d, f); 512 fBasesLoaded->Add(new TObjString(f)); 513 delete [] p; 514 } 515 } 516 gSystem->FreeDirectory(dirp); 517 } 518 } 519 } 521 delete dirs; 522 } 523 524 //////////////////////////////////////////////////////////////////////////////// 525 /// Add plugin handler to the list of handlers. If there is already a 526 /// handler defined for the same base and regexp it will be replaced. 527 528 void TPluginManager::AddHandler(const char *base, const char *regexp, 529 const char *className, const char *pluginName, 530 const char *ctor, const char *origin) 531 { 532 { 534 if (!fHandlers) { 535 fHandlers = new TList; 536 fHandlers->SetOwner(); 537 } 538 } 539 // make sure there is no previous handler for the same case 540 RemoveHandler(base, regexp); 541 542 if (TPH__IsReadingDirs()) 543 origin = gInterpreter->GetCurrentMacroName(); 544 545 TPluginHandler *h = new TPluginHandler(base, regexp, className, 546 pluginName, ctor, origin); 547 { 549 fHandlers->Add(h); 550 } 551 } 552 553 //////////////////////////////////////////////////////////////////////////////// 554 /// Remove handler for the specified base class and the specified 555 /// regexp. If regexp=0 remove all handlers for the specified base. 556 557 void TPluginManager::RemoveHandler(const char *base, const char *regexp) 558 { 560 if (!fHandlers) return; 561 562 TIter next(fHandlers); 563 TPluginHandler *h; 564 565 while ((h = (TPluginHandler*) next())) { 566 if (h->fBase == base) { 567 if (!regexp || h->fRegexp == regexp) { 568 fHandlers->Remove(h); 569 delete h; 570 } 571 } 572 } 573 } 574 575 //////////////////////////////////////////////////////////////////////////////// 576 /// Returns the handler if there exists a handler for the specified URI. 577 /// The uri can be 0 in which case the first matching plugin handler 578 /// will be returned. Returns 0 in case handler is not found. 579 580 TPluginHandler *TPluginManager::FindHandler(const char *base, const char *uri) 581 { 583 585 TIter next(fHandlers); 586 TPluginHandler *h; 587 588 while ((h = (TPluginHandler*) next())) { 589 if (h->CanHandle(base, uri)) { 590 if (gDebug > 0) 591 Info("FindHandler", "found plugin for %s", h->GetClass()); 592 return h; 593 } 594 } 595 596 if (gDebug > 2) { 597 if (uri) 598 Info("FindHandler", "did not find plugin for class %s and uri %s", base, uri); 599 else 600 Info("FindHandler", "did not find plugin for class %s", base); 601 } 602 603 return 0; 604 } 605 606 //////////////////////////////////////////////////////////////////////////////// 607 /// Print list of registered plugin handlers. If option is "a" print 608 /// also the ctor's that will be used. 609 611 { 612 if (!fHandlers) return; 613 614 TIter next(fHandlers); 615 TPluginHandler *h; 616 Int_t cnt = 0, cntmiss = 0; 617 618 Printf("====================================================================="); 619 Printf("Base Regexp Class Plugin"); 620 Printf("====================================================================="); 621 622 while ((h = (TPluginHandler*) next())) { 623 cnt++; 624 h->Print(opt); 625 if (h->CheckPlugin() == -1) 626 cntmiss++; 627 } 628 Printf("====================================================================="); 629 Printf("%d plugin handlers registered", cnt); 630 Printf("[*] %d %s not available", cntmiss, cntmiss==1 ? "plugin" : "plugins"); 631 Printf("=====================================================================\n"); 632 } 633 634 //////////////////////////////////////////////////////////////////////////////// 635 /// Write in the specified directory the plugin macros. If plugin is specified 636 /// and if it is a base class all macros for that base will be written. If it 637 /// is a plugin class name, only that one macro will be written. If plugin 638 /// is 0 all macros are written. Returns -1 if dir does not exist, 0 otherwise. 639 640 Int_t TPluginManager::WritePluginMacros(const char *dir, const char *plugin) const 641 { 642 const_cast<TPluginManager*>(this)->LoadHandlersFromPluginDirs(); 643 644 if (!fHandlers) return 0; 645 646 TString d; 647 if (!dir || !dir[0]) 648 d = "."; 649 else 650 d = dir; 651 653 Error("WritePluginMacros", "cannot write in directory %s", d.Data()); 654 return -1; 655 } 656 657 TString base; 658 Int_t idx = 0; 659 660 TObjLink *lnk = fHandlers->FirstLink(); 661 while (lnk) { 663 if (plugin && strcmp(plugin, h->fBase) && strcmp(plugin, h->fClass)) { 664 lnk = lnk->Next(); 665 continue; 666 } 667 if (base != h->fBase) { 668 idx = 10; 669 base = h->fBase; 670 } else 671 idx += 10; 672 const char *dd = gSystem->ConcatFileName(d, h->fBase); 673 TString sdd = dd; 674 sdd.ReplaceAll("::", "@@"); 675 delete [] dd; 677 if (gSystem->MakeDirectory(sdd) < 0) { 678 Error("WritePluginMacros", "cannot create directory %s", sdd.Data()); 679 return -1; 680 } 681 } 682 TString fn; 683 fn.Form("P%03d_%s.C", idx, h->fClass.Data()); 684 const char *fd = gSystem->ConcatFileName(sdd, fn); 685 FILE *f = fopen(fd, "w"); 686 if (f) { 687 fprintf(f, "void P%03d_%s()\n{\n", idx, h->fClass.Data()); 688 fprintf(f, " gPluginMgr->AddHandler(\"%s\", \"%s\", \"%s\",\n", 689 h->fBase.Data(), h->fRegexp.Data(), h->fClass.Data()); 690 fprintf(f, " \"%s\", \"%s\");\n", h->fPlugin.Data(), h->fCtor.Data()); 691 692 // check for different regexps cases for the same base + class and 693 // put them all in the same macro 694 TObjLink *lnk2 = lnk->Next(); 695 while (lnk2) { 696 TPluginHandler *h2 = (TPluginHandler *) lnk2->GetObject(); 697 if (h->fBase != h2->fBase || h->fClass != h2->fClass) 698 break; 699 700 fprintf(f, " gPluginMgr->AddHandler(\"%s\", \"%s\", \"%s\",\n", 701 h2->fBase.Data(), h2->fRegexp.Data(), h2->fClass.Data()); 702 fprintf(f, " \"%s\", \"%s\");\n", h2->fPlugin.Data(), h2->fCtor.Data()); 703 704 lnk = lnk2; 705 lnk2 = lnk2->Next(); 706 } 707 fprintf(f, "}\n"); 708 fclose(f); 709 } 710 delete [] fd; 711 lnk = lnk->Next(); 712 } 713 return 0; 714 } 715 716 //////////////////////////////////////////////////////////////////////////////// 717 /// Write in the specified environment config file the plugin records. If 718 /// plugin is specified and if it is a base class all records for that 719 /// base will be written. If it is a plugin class name, only that one 720 /// record will be written. If plugin is 0 all macros are written. 721 /// If envFile is 0 or "" the records are written to stdout. 722 /// Returns -1 if envFile cannot be created or opened, 0 otherwise. 723 724 Int_t TPluginManager::WritePluginRecords(const char *envFile, const char *plugin) const 725 { 726 const_cast<TPluginManager*>(this)->LoadHandlersFromPluginDirs(); 727 728 if (!fHandlers) return 0; 729 730 FILE *fd; 731 if (!envFile || !envFile[0]) 732 fd = stdout; 733 else 734 fd = fopen(envFile, "w+"); 735 736 if (!fd) { 737 Error("WritePluginRecords", "error opening file %s", envFile); 738 return -1; 739 } 740 741 TString base, base2; 742 Int_t idx = 0; 743 744 TObjLink *lnk = fHandlers->FirstLink(); 745 while (lnk) { 747 if (plugin && strcmp(plugin, h->fBase) && strcmp(plugin, h->fClass)) { 748 lnk = lnk->Next(); 749 continue; 750 } 751 if (base != h->fBase) { 752 idx = 1; 753 base = h->fBase; 754 base2 = base; 755 base2.ReplaceAll("::", "@@"); 756 } else 757 idx += 1; 758 759 if (idx == 1) 760 fprintf(fd, "Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h->fRegexp.Data(), 761 h->fClass.Data(), h->fPlugin.Data(), h->fCtor.Data()); 762 else 763 fprintf(fd, "+Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h->fRegexp.Data(), 764 h->fClass.Data(), h->fPlugin.Data(), h->fCtor.Data()); 765 766 // check for different regexps cases for the same base + class and 767 // put them all in the same macro 768 TObjLink *lnk2 = lnk->Next(); 769 while (lnk2) { 770 TPluginHandler *h2 = (TPluginHandler *) lnk2->GetObject(); 771 if (h->fBase != h2->fBase || h->fClass != h2->fClass) 772 break; 773 774 fprintf(fd, "+Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h2->fRegexp.Data(), 775 h2->fClass.Data(), h2->fPlugin.Data(), h2->fCtor.Data()); 776 777 lnk = lnk2; 778 lnk2 = lnk2->Next(); 779 } 780 lnk = lnk->Next(); 781 } 782 783 if (envFile && envFile[0]) 784 fclose(fd); 785 786 return 0; 787 } gPluginMgr TPluginManager * gPluginMgr Definition: TPluginManager.cxx:102 kTRUE const Bool_t kTRUE Definition: RtypesCore.h:91 TPluginHandler::fCanCall AtomicInt_t fCanCall ctor method or global function Definition: TPluginManager.h:116 TPluginManager Definition: TPluginManager.h:181 TEnvRec::GetName const char * GetName() const Returns name of object. Definition: TEnv.h:110 TObjArray Definition: TObjArray.h:37 f #define f(i) Definition: RSha256.hxx:122 TPluginManager::fBasesLoaded THashTable * fBasesLoaded Definition: TPluginManager.h:185 TPluginHandler::TPluginHandler TPluginHandler() Definition: TPluginManager.h:120 R__READ_LOCKGUARD #define R__READ_LOCKGUARD(mutex) Definition: TVirtualRWMutex.h:148 THashTable::Add void Add(TObject *obj) Add object to the hash table. Definition: THashTable.cxx:92 TString::Strip TSubString Strip(EStripType s=kTrailing, char c=' ') const Return a substring of self stripped at beginning and/or end. Definition: TString.cxx:1106 kNPOS const Ssiz_t kNPOS Definition: RtypesCore.h:115 TPH__IsReadingDirs static bool & TPH__IsReadingDirs() Definition: TPluginManager.cxx:106 TPluginHandler::SetupCallEnv void SetupCallEnv() Setup ctor or static method call environment. Definition: TPluginManager.cxx:182 TPluginHandler::fIsMacro Bool_t fIsMacro if 1 fCallEnv is ok, -1 fCallEnv is not ok, 0 fCallEnv not setup yet. Definition: TPluginManager.h:117 gEnv R__EXTERN TEnv * gEnv Definition: TEnv.h:171 TString::Data const char * Data() const Definition: TString.h:369 TSystem::FreeDirectory virtual void FreeDirectory(void *dirp) Free a directory. Definition: TSystem.cxx:844 ClassImp #define ClassImp(name) Definition: Rtypes.h:364 TObjString.h TMethod.h TObject::Info virtual void Info(const char *method, const char *msgfmt,...) const Issue info message. Definition: TObject.cxx:864 TObject::Error virtual void Error(const char *method, const char *msgfmt,...) const Issue error message. Definition: TObject.cxx:890 TCollection::SetOwner virtual void SetOwner(Bool_t enable=kTRUE) Set whether this collection is the owner (enable==true) of its content. Definition: TCollection.cxx:746 TPluginHandler::Print void Print(Option_t *opt="") const Print info about the plugin handler. Definition: TPluginManager.cxx:308 TSystem::DynamicPathName char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE) Find a dynamic library called lib using the system search paths. Definition: TSystem.cxx:2015 gInterpreter #define gInterpreter Definition: TInterpreter.h:558 TClass::LoadClass static TClass * LoadClass(const char *requestedname, Bool_t silent) Helper function used by TClass::GetClass(). Definition: TClass.cxx:5563 TPluginManager::WritePluginMacros Int_t WritePluginMacros(const char *dir, const char *plugin=0) const Write in the specified directory the plugin macros. Definition: TPluginManager.cxx:640 TGeant4Unit::s static constexpr double s Definition: TGeant4SystemOfUnits.h:168 TPluginHandler::fCtor TString fCtor Definition: TPluginManager.h:112 TVirtualMutex Definition: TVirtualMutex.h:32 TString::Contains Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const Definition: TString.h:624 TString::EndsWith Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const Return true if string ends with the specified string. Definition: TString.cxx:2177 TString::Length Ssiz_t Length() const Definition: TString.h:410 TSystem::MakeDirectory virtual int MakeDirectory(const char *name) Make a directory. Definition: TSystem.cxx:826 TMethodCall::Init void Init(const TFunction *func) Initialize the method invocation environment based on the TFunction object. Definition: TMethodCall.cxx:223 TPluginHandler::CanHandle Bool_t CanHandle(const char *base, const char *uri) Check if regular expression appears in the URI, if so return kTRUE. Definition: TPluginManager.cxx:159 TClass.h TEnv::GetValue virtual Int_t GetValue(const char *name, Int_t dflt) const Returns the integer value for a resource. Definition: TEnv.cxx:492 ROOT::gCoreMutex R__EXTERN TVirtualRWMutex * gCoreMutex Definition: TVirtualRWMutex.h:38 TPluginHandler::fMethod TFunction * fMethod ctor method call environment Definition: TPluginManager.h:115 TSystem::PrependPathName virtual const char * PrependPathName(const char *dir, TString &name) Concatenate a directory and a file name. Definition: TSystem.cxx:1079 TObjArray::At TObject * At(Int_t idx) const Definition: TObjArray.h:166 TEnv.h TString Definition: TString.h:136 TSystem::AccessPathName virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists) Returns FALSE if one can access a file using the specified access mode. Definition: TSystem.cxx:1294 TPluginManager::~TPluginManager ~TPluginManager() Clean up the plugin manager. Definition: TPluginManager.cxx:336 v @ v Definition: rootcling_impl.cxx:3635 bool TString::ReplaceAll TString & ReplaceAll(const TString &s1, const TString &s2) Definition: TString.h:692 TSystem::SplitAclicMode virtual TString SplitAclicMode(const char *filename, TString &mode, TString &args, TString &io) const This method split a filename of the form: Definition: TSystem.cxx:4265 TEnvRec Definition: TEnv.h:87 TROOT.h TPluginManager::LoadHandlerMacros void LoadHandlerMacros(const char *path) Load all plugin macros from the specified path/base directory. Definition: TPluginManager.cxx:390 TSortedList.h TObjString Definition: TObjString.h:28 TPluginHandler Definition: TPluginManager.h:101 TRegexp.h TString::Form void Form(const char *fmt,...) Formats a string using a printf style format descriptor. Definition: TString.cxx:2289 TDataType.h TPluginHandler::fOrigin TString fOrigin Definition: TPluginManager.h:113 TFunction::GetNargsOpt Int_t GetNargsOpt() const Number of function optional (default) arguments. Definition: TFunction.cxx:175 TString::Tokenize TObjArray * Tokenize(const TString &delim) const This function is used to isolate sequential tokens in a TString. Definition: TString.cxx:2197 Option_t const typedef char Option_t Definition: RtypesCore.h:66 TPluginHandler::fClass TString fClass Definition: TPluginManager.h:110 TPluginManager::LoadHandlersFromPluginDirs void LoadHandlersFromPluginDirs(const char *base=0) Load plugin handlers specified via macros in a list of plugin directories. Definition: TPluginManager.cxx:449 TFunction::Property Long_t Property() const Get property description word. For meaning of bits see EProperty. Definition: TFunction.cxx:184 TPluginHandler::~TPluginHandler ~TPluginHandler() Cleanup plugin handler object. Definition: TPluginManager.cxx:150 TList::FirstLink virtual TObjLink * FirstLink() const Definition: TList.h:108 TSystem.h THashTable Definition: THashTable.h:35 gInterpreterMutex R__EXTERN TVirtualMutex * gInterpreterMutex Definition: TInterpreter.h:43 h #define h(i) Definition: RSha256.hxx:124 TSortedList Definition: TSortedList.h:28 kWritePermission @ kWritePermission Definition: TSystem.h:46 TObjArray::GetEntriesFast Int_t GetEntriesFast() const Definition: TObjArray.h:64 TPluginHandler::fIsGlobal Bool_t fIsGlobal Definition: TPluginManager.h:118 THashTable::FindObject TObject * FindObject(const char *name) const Find object using its name. Definition: THashTable.cxx:238 kFALSE const Bool_t kFALSE Definition: RtypesCore.h:92 gDebug R__EXTERN Int_t gDebug Definition: RtypesCore.h:119 Long_t long Long_t Definition: RtypesCore.h:54 TPluginManager::AddHandler void AddHandler(const char *base, const char *regexp, const char *className, const char *pluginName, const char *ctor=0, const char *origin=0) Add plugin handler to the list of handlers. Definition: TPluginManager.cxx:528 StrDup char * StrDup(const char *str) Duplicate the string str. Definition: TString.cxx:2490 TPluginHandler::fRegexp TString fRegexp Definition: TPluginManager.h:109 R__LOCKGUARD #define R__LOCKGUARD(mutex) Definition: TVirtualMutex.h:104 TString::BeginsWith Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const Definition: TString.h:615 TPluginHandler::fCallEnv TMethodCall * fCallEnv Definition: TPluginManager.h:114 TClass::GetClass static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE) Static method returning pointer to TClass of the specified class name. Definition: TClass.cxx:2925 TPluginManager::FindHandler TPluginHandler * FindHandler(const char *base, const char *uri=0) Returns the handler if there exists a handler for the specified URI. Definition: TPluginManager.cxx:580 TFunction::GetNargs Int_t GetNargs() const Number of function arguments. Definition: TFunction.cxx:165 TVirtualMutex.h fClass Cppyy::TCppType_t fClass Definition: DeclareConverters.h:259 TRegexp Definition: TRegexp.h:31 THashList.h TString::Index Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const Definition: TString.h:639 TROOT::GetEtcDir static const TString & GetEtcDir() Get the sysconfig directory in the installation. Static utility function. Definition: TROOT.cxx:2956 Printf void Printf(const char *fmt,...) gSystem R__EXTERN TSystem * gSystem Definition: TSystem.h:559 R__LOCKGUARD2 #define R__LOCKGUARD2(mutex) Definition: TVirtualMutex.h:106 proto const char * proto Definition: civetweb.c:16604 TPluginHandler::LoadPlugin Int_t LoadPlugin() Load the plugin library for this handler. Definition: TPluginManager.cxx:254 f1 TF1 * f1 Definition: legend1.C:11 TString::IsNull Bool_t IsNull() const Definition: TString.h:407 TSystem::OpenDirectory virtual void * OpenDirectory(const char *name) Open a directory. Returns 0 if directory does not exist. Definition: TSystem.cxx:835 TPluginManager.h TObjArray.h TList::Remove virtual TObject * Remove(TObject *obj) Remove object from the list. Definition: TList.cxx:821 TInterpreter.h TSortedList::Add void Add(TObject *obj) Add object in sorted list. Definition: TSortedList.cxx:27 TClass Definition: TClass.h:80 TEnv Definition: TEnv.h:125 gPluginManagerMutex static TVirtualMutex * gPluginManagerMutex Definition: TPluginManager.cxx:104 TList::Add virtual void Add(TObject *obj) Definition: TList.h:87 TPluginHandler::fBase TString fBase Definition: TPluginManager.h:108 TSystem::GetDirEntry virtual const char * GetDirEntry(void *dirp) Get a directory entry. Returns 0 if no more entries. Definition: TSystem.cxx:852 kIsPublic @ kIsPublic Definition: TDictionary.h:74 d #define d(i) Definition: RSha256.hxx:120 TSystem::ConcatFileName virtual char * ConcatFileName(const char *dir, const char *name) Concatenate a directory and a file name. User must delete returned string. Definition: TSystem.cxx:1069 TPluginHandler::CheckPlugin Int_t CheckPlugin() const Check if the plugin library for this handler exits. Definition: TPluginManager.cxx:241 TIter Definition: TCollection.h:233 TString::kLeading @ kLeading Definition: TString.h:267 TPluginHandler::fPlugin TString fPlugin Definition: TPluginManager.h:111 TMethodCall Definition: TMethodCall.h:37 TPluginManager::fHandlers TList * fHandlers Definition: TPluginManager.h:184 TPluginManager::WritePluginRecords Int_t WritePluginRecords(const char *envFile, const char *plugin=0) const Write in the specified environment config file the plugin records. Definition: TPluginManager.cxx:724 xmlio::cnt const char * cnt Definition: TXMLSetup.cxx:81 TMethodArg.h R__WRITE_LOCKGUARD #define R__WRITE_LOCKGUARD(mutex) Definition: TVirtualRWMutex.h:151 kReadPermission @ kReadPermission Definition: TSystem.h:47 TEnv::GetTable THashList * GetTable() const Definition: TEnv.h:141 TString::MaybeRegexp Bool_t MaybeRegexp() const Returns true if string contains one of the regexp characters "^$.[]*+?".
Definition: TString.cxx:913
TPluginManager::RemoveHandler
void RemoveHandler(const char *base, const char *regexp=0)
Remove handler for the specified base class and the specified regexp.
Definition: TPluginManager.cxx:557
TList
Definition: TList.h:44
TPluginManager::Print
void Print(Option_t *opt="") const
Print list of registered plugin handlers.
Definition: TPluginManager.cxx:610
gROOT
#define gROOT
Definition: TROOT.h:406
int
THashTable.h