Logo ROOT   6.16/01
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
15This class implements a plugin library manager.
16
17It keeps track of a list of plugin handlers. A plugin handler knows which plugin
18library to load to get a specific class that is used to extend the
19functionality of a specific base class and how to create an object
20of this class. For example, to extend the base class TFile to be
21able to read RFIO files one needs to load the plugin library
22libRFIO.so which defines the TRFIOFile class. This loading should
23be triggered when a given URI contains a regular expression defined
24by the handler.
25
26Plugin handlers can be defined via macros in a list of plugin
27directories. With $ROOTSYS/etc/plugins the default top plugin
28directory specified in $ROOTSYS/etc/system.rootrc. Additional
29directories can be specified by adding them to the end of the list.
30Macros for identical plugin handlers in later directories will
31override previous ones (the inverse of normal search path behavior).
32The macros must have names like `<BaseClass>/PX0_<PluginClass>.C`,
33e.g.:
34
35 TFile/P10_TRFIOFile.C, TSQLServer/P20_TMySQLServer.C, etc.
36to allow easy sorting and grouping. If the BaseClass is in a
37namespace the directory must have the name NameSpace@@BaseClass as
38: is a reserved pathname character on some operating systems.
39Macros not beginning with 'P' and ending with ".C" are ignored.
40These 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~~~
48Plugin handlers can also be defined via resources in the .rootrc
49file. Although now deprecated this method still works for backward
50compatibility, 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~~~
57Where the + in front of Plugin.TSQLServer says that it extends the
58existing definition of TSQLServer, useful when there is more than
59one plugin that can extend the same base class. The "<constructor>"
60should be the constructor or a static method that generates an
61instance of the specified class. Global methods should start with
62"::" in their name, like "::CreateFitter()".
63Instead of being a shared library a plugin can also be a CINT
64script, so instead of libDialog.so one can have Dialog.C.
65The * is a placeholder in case there is no need for a URI to
66differentiate between different plugins for the same base class.
67For the default plugins see $ROOTSYS/etc/system.rootrc.
68
69Plugin 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~~~
75A list of currently defined handlers can be printed using:
76~~~ {.cpp}
77 gPluginMgr->Print(); // use option="a" to see ctors
78~~~
79The use of the plugin library manager removes all textual references
80to hard-coded class and library names and the resulting dependencies
81in the base classes. The plugin manager is used to extend a.o.
82TFile, 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
107TPluginManager *gPluginMgr; // main plugin manager created in TROOT
108
110
111static 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
121TPluginHandler::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("::")) {
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
164Bool_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.
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, "; "); // this method does not need to be reentrant
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
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 TString sbase = base;
459 if (sbase.Length())
460 sbase.ReplaceAll("::", "@@");
461
463
464 if (fBasesLoaded && fBasesLoaded->FindObject(sbase))
465 return;
466
468
469 // While waiting for the lock, another thread may
470 // have process the requested plugin.
471 if (fBasesLoaded && fBasesLoaded->FindObject(sbase))
472 return;
473
474 if (!fBasesLoaded) {
475 fBasesLoaded = new THashTable();
477 }
478 fBasesLoaded->Add(new TObjString(sbase));
479
481
482 TString plugindirs = gEnv->GetValue("Root.PluginPath", (char*)0);
483 if (plugindirs.Length() == 0) {
484 plugindirs = "plugins";
486 }
487#ifdef WIN32
488 TObjArray *dirs = plugindirs.Tokenize(";");
489#else
490 TObjArray *dirs = plugindirs.Tokenize(":");
491#endif
492 TString d;
493 for (Int_t i = 0; i < dirs->GetEntriesFast(); i++) {
494 d = ((TObjString*)dirs->At(i))->GetString();
495 // check if directory already scanned
496 Int_t skip = 0;
497 for (Int_t j = 0; j < i; j++) {
498 TString pd = ((TObjString*)dirs->At(j))->GetString();
499 if (pd == d) {
500 skip++;
501 break;
502 }
503 }
504 if (!skip) {
505 if (sbase != "") {
506 const char *p = gSystem->ConcatFileName(d, sbase);
508 delete [] p;
509 } else {
510 void *dirp = gSystem->OpenDirectory(d);
511 if (dirp) {
512 if (gDebug > 0)
513 Info("LoadHandlersFromPluginDirs", "%s", d.Data());
514 const char *f1;
515 while ((f1 = gSystem->GetDirEntry(dirp))) {
516 TString f = f1;
517 const char *p = gSystem->ConcatFileName(d, f);
520 delete [] p;
521 }
522 }
523 gSystem->FreeDirectory(dirp);
524 }
525 }
526 }
528 delete dirs;
529}
530
531////////////////////////////////////////////////////////////////////////////////
532/// Add plugin handler to the list of handlers. If there is already a
533/// handler defined for the same base and regexp it will be replaced.
534
535void TPluginManager::AddHandler(const char *base, const char *regexp,
536 const char *className, const char *pluginName,
537 const char *ctor, const char *origin)
538{
539 {
541 if (!fHandlers) {
542 fHandlers = new TList;
544 }
545 }
546 // make sure there is no previous handler for the same case
547 RemoveHandler(base, regexp);
548
549 if (TPH__IsReadingDirs())
550 origin = gInterpreter->GetCurrentMacroName();
551
552 TPluginHandler *h = new TPluginHandler(base, regexp, className,
553 pluginName, ctor, origin);
554 {
556 fHandlers->Add(h);
557 }
558}
559
560////////////////////////////////////////////////////////////////////////////////
561/// Remove handler for the specified base class and the specified
562/// regexp. If regexp=0 remove all handlers for the specified base.
563
564void TPluginManager::RemoveHandler(const char *base, const char *regexp)
565{
567 if (!fHandlers) return;
568
569 TIter next(fHandlers);
571
572 while ((h = (TPluginHandler*) next())) {
573 if (h->fBase == base) {
574 if (!regexp || h->fRegexp == regexp) {
576 delete h;
577 }
578 }
579 }
580}
581
582////////////////////////////////////////////////////////////////////////////////
583/// Returns the handler if there exists a handler for the specified URI.
584/// The uri can be 0 in which case the first matching plugin handler
585/// will be returned. Returns 0 in case handler is not found.
586
587TPluginHandler *TPluginManager::FindHandler(const char *base, const char *uri)
588{
590
592 TIter next(fHandlers);
594
595 while ((h = (TPluginHandler*) next())) {
596 if (h->CanHandle(base, uri)) {
597 if (gDebug > 0)
598 Info("FindHandler", "found plugin for %s", h->GetClass());
599 return h;
600 }
601 }
602
603 if (gDebug > 2) {
604 if (uri)
605 Info("FindHandler", "did not find plugin for class %s and uri %s", base, uri);
606 else
607 Info("FindHandler", "did not find plugin for class %s", base);
608 }
609
610 return 0;
611}
612
613////////////////////////////////////////////////////////////////////////////////
614/// Print list of registered plugin handlers. If option is "a" print
615/// also the ctor's that will be used.
616
618{
619 if (!fHandlers) return;
620
621 TIter next(fHandlers);
623 Int_t cnt = 0, cntmiss = 0;
624
625 Printf("=====================================================================");
626 Printf("Base Regexp Class Plugin");
627 Printf("=====================================================================");
628
629 while ((h = (TPluginHandler*) next())) {
630 cnt++;
631 h->Print(opt);
632 if (h->CheckPlugin() == -1)
633 cntmiss++;
634 }
635 Printf("=====================================================================");
636 Printf("%d plugin handlers registered", cnt);
637 Printf("[*] %d %s not available", cntmiss, cntmiss==1 ? "plugin" : "plugins");
638 Printf("=====================================================================\n");
639}
640
641////////////////////////////////////////////////////////////////////////////////
642/// Write in the specified directory the plugin macros. If plugin is specified
643/// and if it is a base class all macros for that base will be written. If it
644/// is a plugin class name, only that one macro will be written. If plugin
645/// is 0 all macros are written. Returns -1 if dir does not exist, 0 otherwise.
646
647Int_t TPluginManager::WritePluginMacros(const char *dir, const char *plugin) const
648{
649 const_cast<TPluginManager*>(this)->LoadHandlersFromPluginDirs();
650
651 if (!fHandlers) return 0;
652
653 TString d;
654 if (!dir || !dir[0])
655 d = ".";
656 else
657 d = dir;
658
660 Error("WritePluginMacros", "cannot write in directory %s", d.Data());
661 return -1;
662 }
663
664 TString base;
665 Int_t idx = 0;
666
667 TObjLink *lnk = fHandlers->FirstLink();
668 while (lnk) {
670 if (plugin && strcmp(plugin, h->fBase) && strcmp(plugin, h->fClass)) {
671 lnk = lnk->Next();
672 continue;
673 }
674 if (base != h->fBase) {
675 idx = 10;
676 base = h->fBase;
677 } else
678 idx += 10;
679 const char *dd = gSystem->ConcatFileName(d, h->fBase);
680 TString sdd = dd;
681 sdd.ReplaceAll("::", "@@");
682 delete [] dd;
684 if (gSystem->MakeDirectory(sdd) < 0) {
685 Error("WritePluginMacros", "cannot create directory %s", sdd.Data());
686 return -1;
687 }
688 }
689 TString fn;
690 fn.Form("P%03d_%s.C", idx, h->fClass.Data());
691 const char *fd = gSystem->ConcatFileName(sdd, fn);
692 FILE *f = fopen(fd, "w");
693 if (f) {
694 fprintf(f, "void P%03d_%s()\n{\n", idx, h->fClass.Data());
695 fprintf(f, " gPluginMgr->AddHandler(\"%s\", \"%s\", \"%s\",\n",
696 h->fBase.Data(), h->fRegexp.Data(), h->fClass.Data());
697 fprintf(f, " \"%s\", \"%s\");\n", h->fPlugin.Data(), h->fCtor.Data());
698
699 // check for different regexps cases for the same base + class and
700 // put them all in the same macro
701 TObjLink *lnk2 = lnk->Next();
702 while (lnk2) {
703 TPluginHandler *h2 = (TPluginHandler *) lnk2->GetObject();
704 if (h->fBase != h2->fBase || h->fClass != h2->fClass)
705 break;
706
707 fprintf(f, " gPluginMgr->AddHandler(\"%s\", \"%s\", \"%s\",\n",
708 h2->fBase.Data(), h2->fRegexp.Data(), h2->fClass.Data());
709 fprintf(f, " \"%s\", \"%s\");\n", h2->fPlugin.Data(), h2->fCtor.Data());
710
711 lnk = lnk2;
712 lnk2 = lnk2->Next();
713 }
714 fprintf(f, "}\n");
715 fclose(f);
716 }
717 delete [] fd;
718 lnk = lnk->Next();
719 }
720 return 0;
721}
722
723////////////////////////////////////////////////////////////////////////////////
724/// Write in the specified environment config file the plugin records. If
725/// plugin is specified and if it is a base class all records for that
726/// base will be written. If it is a plugin class name, only that one
727/// record will be written. If plugin is 0 all macros are written.
728/// If envFile is 0 or "" the records are written to stdout.
729/// Returns -1 if envFile cannot be created or opened, 0 otherwise.
730
731Int_t TPluginManager::WritePluginRecords(const char *envFile, const char *plugin) const
732{
733 const_cast<TPluginManager*>(this)->LoadHandlersFromPluginDirs();
734
735 if (!fHandlers) return 0;
736
737 FILE *fd;
738 if (!envFile || !envFile[0])
739 fd = stdout;
740 else
741 fd = fopen(envFile, "w+");
742
743 if (!fd) {
744 Error("WritePluginRecords", "error opening file %s", envFile);
745 return -1;
746 }
747
748 TString base, base2;
749 Int_t idx = 0;
750
751 TObjLink *lnk = fHandlers->FirstLink();
752 while (lnk) {
754 if (plugin && strcmp(plugin, h->fBase) && strcmp(plugin, h->fClass)) {
755 lnk = lnk->Next();
756 continue;
757 }
758 if (base != h->fBase) {
759 idx = 1;
760 base = h->fBase;
761 base2 = base;
762 base2.ReplaceAll("::", "@@");
763 } else
764 idx += 1;
765
766 if (idx == 1)
767 fprintf(fd, "Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h->fRegexp.Data(),
768 h->fClass.Data(), h->fPlugin.Data(), h->fCtor.Data());
769 else
770 fprintf(fd, "+Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h->fRegexp.Data(),
771 h->fClass.Data(), h->fPlugin.Data(), h->fCtor.Data());
772
773 // check for different regexps cases for the same base + class and
774 // put them all in the same macro
775 TObjLink *lnk2 = lnk->Next();
776 while (lnk2) {
777 TPluginHandler *h2 = (TPluginHandler *) lnk2->GetObject();
778 if (h->fBase != h2->fBase || h->fClass != h2->fClass)
779 break;
780
781 fprintf(fd, "+Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h2->fRegexp.Data(),
782 h2->fClass.Data(), h2->fPlugin.Data(), h2->fCtor.Data());
783
784 lnk = lnk2;
785 lnk2 = lnk2->Next();
786 }
787 lnk = lnk->Next();
788 }
789
790 if (envFile && envFile[0])
791 fclose(fd);
792
793 return 0;
794}
SVector< double, 2 > v
Definition: Dict.h:5
#define d(i)
Definition: RSha256.hxx:102
#define f(i)
Definition: RSha256.hxx:104
#define h(i)
Definition: RSha256.hxx:106
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
int Int_t
Definition: RtypesCore.h:41
const Bool_t kFALSE
Definition: RtypesCore.h:88
long Long_t
Definition: RtypesCore.h:50
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:363
R__EXTERN Int_t gDebug
Definition: Rtypes.h:90
@ kIsPublic
Definition: TDictionary.h:74
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
#define Printf
Definition: TGeoToOCC.h:18
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:40
#define gInterpreter
Definition: TInterpreter.h:538
static bool & TPH__IsReadingDirs()
TPluginManager * gPluginMgr
static TVirtualMutex * gPluginManagerMutex
#define gROOT
Definition: TROOT.h:410
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2465
@ kReadPermission
Definition: TSystem.h:48
@ kWritePermission
Definition: TSystem.h:47
R__EXTERN TSystem * gSystem
Definition: TSystem.h:540
#define R__LOCKGUARD2(mutex)
#define R__LOCKGUARD(mutex)
#define R__WRITE_LOCKGUARD(mutex)
#define R__READ_LOCKGUARD(mutex)
const char * proto
Definition: civetweb.c:16604
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
static TClass * LoadClass(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition: TClass.cxx:5511
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
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
Definition: TEnv.h:87
const char * GetName() const
Returns name of object.
Definition: TEnv.h:110
The TEnv class reads config files, by default named .rootrc.
Definition: TEnv.h:125
virtual Int_t GetValue(const char *name, Int_t dflt) const
Returns the integer value for a resource.
Definition: TEnv.cxx:491
THashList * GetTable() const
Definition: TEnv.h:141
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
Definition: TFunction.cxx:183
Int_t GetNargsOpt() const
Number of function optional (default) arguments.
Definition: TFunction.cxx:174
Int_t GetNargs() const
Number of function arguments.
Definition: TFunction.cxx:164
THashTable implements a hash table to store TObject's.
Definition: THashTable.h:35
void Add(TObject *obj)
Add object to the hash table.
Definition: THashTable.cxx:92
TObject * FindObject(const char *name) const
Find object using its name.
Definition: THashTable.cxx:238
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:818
virtual TObjLink * FirstLink() const
Definition: TList.h:108
Method or function calling interface.
Definition: TMethodCall.h:37
void Init(const TFunction *func)
Initialize the method invocation environment based on the TFunction object.
An array of TObjects.
Definition: TObjArray.h:37
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
Collectable string class.
Definition: TObjString.h:28
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:854
Int_t CheckPlugin() const
Check if the plugin library for this handler exits.
void Print(Option_t *opt="") const
Print info about the plugin handler.
TFunction * fMethod
ctor method call environment
AtomicInt_t fCanCall
ctor method or global function
Bool_t CanHandle(const char *base, const char *uri)
Check if regular expression appears in the URI, if so return kTRUE.
~TPluginHandler()
Cleanup plugin handler object.
Bool_t CheckForExecPlugin(Int_t nargs)
Check that we can properly run ExecPlugin.
Bool_t fIsMacro
if 1 fCallEnv is ok, -1 fCallEnv is not ok, 0 fCallEnv not setup yet.
void SetupCallEnv()
Setup ctor or static method call environment.
TMethodCall * fCallEnv
Int_t LoadPlugin()
Load the plugin library for this handler.
This class implements a plugin library manager.
void LoadHandlersFromPluginDirs(const char *base=0)
Load plugin handlers specified via macros in a list of plugin directories.
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.
~TPluginManager()
Clean up the plugin manager.
TPluginHandler * FindHandler(const char *base, const char *uri=0)
Returns the handler if there exists a handler for the specified URI.
void Print(Option_t *opt="") const
Print list of registered plugin handlers.
void LoadHandlersFromEnv(TEnv *env)
Load plugin handlers specified in config file, like:
void RemoveHandler(const char *base, const char *regexp=0)
Remove handler for the specified base class and the specified regexp.
THashTable * fBasesLoaded
void LoadHandlerMacros(const char *path)
Load all plugin macros from the specified path/base directory.
Int_t WritePluginMacros(const char *dir, const char *plugin=0) const
Write in the specified directory the plugin macros.
Int_t WritePluginRecords(const char *envFile, const char *plugin=0) const
Write in the specified environment config file the plugin records.
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
Definition: TROOT.cxx:3010
Regular expression class.
Definition: TRegexp.h:31
A sorted doubly linked list.
Definition: TSortedList.h:28
void Add(TObject *obj)
Add object in sorted list.
Definition: TSortedList.cxx:27
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2152
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1081
const char * Data() const
Definition: TString.h:364
Bool_t MaybeRegexp() const
Returns true if string contains one of the regexp characters "^$.[]*+?".
Definition: TString.cxx:897
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:687
@ kLeading
Definition: TString.h:262
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2172
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:610
Bool_t IsNull() const
Definition: TString.h:402
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2264
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition: TSystem.cxx:852
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition: TSystem.cxx:843
virtual TString SplitAclicMode(const char *filename, TString &mode, TString &args, TString &io) const
This method split a filename of the form:
Definition: TSystem.cxx:4160
virtual char * ConcatFileName(const char *dir, const char *name)
Concatenate a directory and a file name. User must delete returned string.
Definition: TSystem.cxx:1061
virtual int MakeDirectory(const char *name)
Make a directory.
Definition: TSystem.cxx:834
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition: TSystem.cxx:1071
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:1286
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition: TSystem.cxx:860
char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE)
Find a dynamic library called lib using the system search paths.
Definition: TSystem.cxx:2020
This class implements a mutex interface.
Definition: TVirtualMutex.h:34
TF1 * f1
Definition: legend1.C:11
R__EXTERN TVirtualRWMutex * gCoreMutex
static constexpr double s
const char * cnt
Definition: TXMLSetup.cxx:74