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