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