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
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 SQLite files one needs to load the plugin library
22libRSQLite.so which defines the TRSQLiteServer class. This loading
23should be triggered when a given URI contains a regular expression
24defined by 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. TSQLServer/P20_TMySQLServer.C, to allow easy sorting and grouping.
34If the BaseClass is in a namespace the directory must have the name
35NameSpace@@BaseClass as `:` is a reserved pathname character on some
36operating systems. Macros not beginning with 'P' and ending with ".C"
37are 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~~~
45Plugin handlers can also be defined via resources in the .rootrc
46file. Although now deprecated this method still works for backward
47compatibility, 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~~~
53Where the + in front of Plugin.TSQLServer says that it extends the
54existing definition of TSQLServer, useful when there is more than
55one plugin that can extend the same base class. The "<constructor>"
56should be the constructor or a static method that generates an
57instance of the specified class. Global methods should start with
58"::" in their name, like "::CreateFitter()".
59Instead of being a shared library a plugin can also be a CINT
60script, so instead of libDialog.so one can have Dialog.C.
61The * is a placeholder in case there is no need for a URI to
62differentiate between different plugins for the same base class.
63For the default plugins see $ROOTSYS/etc/system.rootrc.
64
65Plugin 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~~~
71A list of currently defined handlers can be printed using:
72~~~ {.cpp}
73 gPluginMgr->Print(); // use option="a" to see ctors
74~~~
75The use of the plugin library manager removes all textual references
76to hard-coded class and library names and the resulting dependencies
77in the base classes. The plugin manager is used to extend a.o.
78TFile, 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
102TPluginManager *gPluginMgr; // main plugin manager created in TROOT
103
105
106static 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
116TPluginHandler::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(nullptr),
126 fMethod(nullptr),
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, nullptr, kTRUE) == 0)
139 fIsMacro = kTRUE;
140
141 if (fCtor.BeginsWith("::")) {
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
159Bool_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 = nullptr;
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, nullptr, 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*)nullptr);
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 : nullptr, "; "); // this method does not need to be reentrant
370 if (regexp.IsNull()) break;
371 TString clss = strtok(nullptr, "; ");
372 if (clss.IsNull()) break;
373 TString plugin = strtok(nullptr, "; ");
374 if (plugin.IsNull()) break;
375 TString ctor = strtok(nullptr, ";\"");
376 if (!ctor.Contains("("))
377 ctor = strtok(nullptr, ";\"");
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
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 Longptr_t res;
416 if ((res = gROOT->Macro(s->String(), nullptr, 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*)nullptr);
476 if (plugindirs.Length() == 0) {
477 plugindirs = "plugins";
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);
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
528void 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;
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
557void TPluginManager::RemoveHandler(const char *base, const char *regexp)
558{
560 if (!fHandlers) return;
561
562 TIter next(fHandlers);
564
565 while ((h = (TPluginHandler*) next())) {
566 if (h->fBase == base) {
567 if (!regexp || h->fRegexp == regexp) {
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
580TPluginHandler *TPluginManager::FindHandler(const char *base, const char *uri)
581{
583
585 TIter next(fHandlers);
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 nullptr;
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);
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
640Int_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
724Int_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}
int Int_t
Definition: CPyCppyy.h:43
Cppyy::TCppType_t fClass
#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:124
long Longptr_t
Definition: RtypesCore.h:82
const Bool_t kFALSE
Definition: RtypesCore.h:101
bool Bool_t
Definition: RtypesCore.h:63
const Bool_t kTRUE
Definition: RtypesCore.h:100
const char Option_t
Definition: RtypesCore.h:66
#define ClassImp(name)
Definition: Rtypes.h:364
@ kIsPublic
Definition: TDictionary.h:75
R__EXTERN TEnv * gEnv
Definition: TEnv.h:170
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:44
#define gInterpreter
Definition: TInterpreter.h:560
static bool & TPH__IsReadingDirs()
TPluginManager * gPluginMgr
static TVirtualMutex * gPluginManagerMutex
Int_t gDebug
Definition: TROOT.cxx:589
#define gROOT
Definition: TROOT.h:404
void Printf(const char *fmt,...)
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2515
@ kReadPermission
Definition: TSystem.h:47
@ kWritePermission
Definition: TSystem.h:46
R__EXTERN TSystem * gSystem
Definition: TSystem.h:559
#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
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
static TClass * LoadClass(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition: TClass.cxx:5742
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:2955
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
Definition: TEnv.h:86
const char * GetName() const
Returns name of object.
Definition: TEnv.h:109
The TEnv class reads config files, by default named .rootrc.
Definition: TEnv.h:124
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:140
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
Definition: TFunction.cxx:184
Int_t GetNargsOpt() const
Number of function optional (default) arguments.
Definition: TFunction.cxx:175
Int_t GetNargs() const
Number of function arguments.
Definition: TFunction.cxx:165
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 TObjLink * FirstLink() const
Definition: TList.h:108
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * Remove(TObject *obj)
Remove object from the list.
Definition: TList.cxx:822
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:166
Collectable string class.
Definition: TObjString.h:28
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:893
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:867
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:2950
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:136
Ssiz_t Length() const
Definition: TString.h:410
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2202
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1131
Bool_t MaybeRegexp() const
Returns true if string contains one of the regexp characters "^$.[]*+?".
Definition: TString.cxx:937
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:692
@ kLeading
Definition: TString.h:267
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition: TString.cxx:2222
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:615
const char * Data() const
Definition: TString.h:369
Bool_t IsNull() const
Definition: TString.h:407
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition: TString.cxx:2314
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:624
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:639
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition: TSystem.cxx:846
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition: TSystem.cxx:837
virtual TString SplitAclicMode(const char *filename, TString &mode, TString &args, TString &io) const
This method split a filename of the form:
Definition: TSystem.cxx:4241
virtual char * ConcatFileName(const char *dir, const char *name)
Concatenate a directory and a file name. User must delete returned string.
Definition: TSystem.cxx:1071
virtual int MakeDirectory(const char *name)
Make a directory.
Definition: TSystem.cxx:828
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition: TSystem.cxx:1081
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:1296
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition: TSystem.cxx:854
char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE)
Find a dynamic library called lib using the system search paths.
Definition: TSystem.cxx:2018
This class implements a mutex interface.
Definition: TVirtualMutex.h:32
TF1 * f1
Definition: legend1.C:11
R__EXTERN TVirtualRWMutex * gCoreMutex
static constexpr double s
const char * cnt
Definition: TXMLSetup.cxx:75