Logo 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. *
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 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
ThreadLocalStorage.h
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
TPluginManager::LoadHandlersFromEnv
void LoadHandlersFromEnv(TEnv *env)
Load plugin handlers specified in config file, like:
Definition: TPluginManager.cxx:350
TPluginHandler::CheckForExecPlugin
Bool_t CheckForExecPlugin(Int_t nargs)
Check that we can properly run ExecPlugin.
Definition: TPluginManager.cxx:269
TMethodCall.h