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 "Varargs.h"
83#include "TEnv.h"
84#include "TRegexp.h"
85#include "TROOT.h"
86#include "TSortedList.h"
87#include "THashList.h"
88#include "THashTable.h"
89#include "TClass.h"
90#include "TInterpreter.h"
91#include "TMethod.h"
92#include "TMethodArg.h"
93#include "TDataType.h"
94#include "TMethodCall.h"
95#include "TVirtualMutex.h"
96#include "TSystem.h"
97#include "TObjString.h"
98#include "TObjArray.h"
99#include "ThreadLocalStorage.h"
100
101#include <memory>
102
103TPluginManager *gPluginMgr; // main plugin manager created in TROOT
104
106
107static bool &TPH__IsReadingDirs() {
108 TTHREAD_TLS(bool) readingDirs (false);
109 return readingDirs;
110}
111
113
114////////////////////////////////////////////////////////////////////////////////
115/// Create a plugin handler. Called by TPluginManager.
116
117TPluginHandler::TPluginHandler(const char *base, const char *regexp,
118 const char *className, const char *pluginName,
119 const char *ctor, const char *origin):
120 fBase(base),
121 fRegexp(regexp),
122 fClass(className),
123 fPlugin(pluginName),
124 fCtor(ctor),
125 fOrigin(origin),
126 fCallEnv(0),
127 fMethod(0),
128 fCanCall(0),
129 fIsMacro(kFALSE),
130 fIsGlobal(kFALSE)
131{
132 TString aclicMode, arguments, io;
133 TString fname = gSystem->SplitAclicMode(fPlugin, aclicMode, arguments, io);
134 Bool_t validMacro = kFALSE;
135 if (fname.EndsWith(".C") || fname.EndsWith(".cxx") || fname.EndsWith(".cpp") ||
136 fname.EndsWith(".cc"))
137 validMacro = kTRUE;
138
139 if (validMacro && gROOT->LoadMacro(fPlugin, 0, kTRUE) == 0)
140 fIsMacro = kTRUE;
141
142 if (fCtor.BeginsWith("::")) {
145 }
146}
147
148////////////////////////////////////////////////////////////////////////////////
149/// Cleanup plugin handler object.
150
152{
153 delete fCallEnv;
154}
155
156////////////////////////////////////////////////////////////////////////////////
157/// Check if regular expression appears in the URI, if so return kTRUE.
158/// If URI = 0 always return kTRUE.
159
160Bool_t TPluginHandler::CanHandle(const char *base, const char *uri)
161{
162 if (fBase != base)
163 return kFALSE;
164
165 if (!uri || fRegexp == "*")
166 return kTRUE;
167
168 Bool_t wildcard = kFALSE;
169 if (!fRegexp.MaybeRegexp())
170 wildcard = kTRUE;
171
172 TRegexp re(fRegexp, wildcard);
173 TString ruri = uri;
174
175 if (ruri.Index(re) != kNPOS)
176 return kTRUE;
177 return kFALSE;
178}
179
180////////////////////////////////////////////////////////////////////////////////
181/// Setup ctor or static method call environment.
182
184{
185 int setCanCall = -1;
186
187 // Use a exit_scope guard, to insure that fCanCall is set (to the value of
188 // result) as the last action of this function before returning.
189
190 // When the standard supports it, we should use std::exit_code
191 // See N4189 for example.
192 // auto guard = make_exit_scope( [...]() { ... } );
193 using exit_scope = std::shared_ptr<void*>;
194 exit_scope guard(nullptr,
195 [this,&setCanCall](void *) { this->fCanCall = setCanCall; } );
196
197 // check if class exists
199 if (!cl && !fIsGlobal) {
200 Error("SetupCallEnv", "class %s not found in plugin %s", fClass.Data(),
201 fPlugin.Data());
202 return;
203 }
204
205 // split method and prototype strings
206 TString method = fCtor(0, fCtor.Index("("));
207 TString proto = fCtor(fCtor.Index("(")+1, fCtor.Index(")")-fCtor.Index("(")-1);
208
209 if (fIsGlobal) {
210 cl = 0;
211 fMethod = gROOT->GetGlobalFunctionWithPrototype(method, proto, kFALSE);
212 } else {
213 fMethod = cl->GetMethodWithPrototype(method, proto);
214 }
215
216 if (!fMethod) {
217 if (fIsGlobal)
218 Error("SetupCallEnv", "global function %s not found", method.Data());
219 else
220 Error("SetupCallEnv", "method %s not found in class %s", method.Data(),
221 fClass.Data());
222 return;
223 }
224
225 if (!fIsGlobal && !(fMethod->Property() & kIsPublic)) {
226 Error("SetupCallEnv", "method %s is not public", method.Data());
227 return;
228 }
229
230 fCallEnv = new TMethodCall;
232
233 setCanCall = 1;
234
235 return;
236}
237
238////////////////////////////////////////////////////////////////////////////////
239/// Check if the plugin library for this handler exits. Returns 0
240/// when it exists and -1 in case the plugin does not exist.
241
243{
244 if (fIsMacro) {
245 if (TClass::GetClass(fClass)) return 0;
246 return gROOT->LoadMacro(fPlugin, 0, kTRUE);
247 } else
248 return gROOT->LoadClass(fClass, fPlugin, kTRUE);
249}
250
251////////////////////////////////////////////////////////////////////////////////
252/// Load the plugin library for this handler. Returns 0 on successful loading
253/// and -1 in case the library does not exist or in case of error.
254
256{
257 if (fIsMacro) {
258 if (TClass::GetClass(fClass)) return 0;
259 return gROOT->LoadMacro(fPlugin);
260 } else {
261 // first call also loads dependent libraries declared via the rootmap file
262 if (TClass::LoadClass(fClass, /* silent = */ kFALSE)) return 0;
263 return gROOT->LoadClass(fClass, fPlugin);
264 }
265}
266
267////////////////////////////////////////////////////////////////////////////////
268/// Check that we can properly run ExecPlugin.
269
271{
272 if (fCtor.IsNull()) {
273 Error("ExecPlugin", "no ctor specified for this handler %s", fClass.Data());
274 return kFALSE;
275 }
276
277 if (fCanCall == 0) {
278 // Not initialized yet.
279 // SetupCallEnv is likely to require/take the interpreter lock.
280 // Grab it now to avoid dead-lock. In particular TPluginHandler::ExecPluginImpl
281 // takes the gInterpreterMutex and *then* call (indirectly) code that
282 // take the gPluginManagerMutex.
285
286 // Now check if another thread did not already do the work.
287 if (fCanCall == 0)
288 SetupCallEnv();
289 }
290
291 if (fCanCall == -1)
292 return kFALSE;
293
294 if (nargs < fMethod->GetNargs() - fMethod->GetNargsOpt() ||
295 nargs > fMethod->GetNargs()) {
296 Error("ExecPlugin", "nargs (%d) not consistent with expected number of arguments ([%d-%d])",
297 nargs, fMethod->GetNargs() - fMethod->GetNargsOpt(),
298 fMethod->GetNargs());
299 return kFALSE;
300 }
301
302 return kTRUE;
303}
304
305////////////////////////////////////////////////////////////////////////////////
306/// Print info about the plugin handler. If option is "a" print
307/// also the ctor's that will be used.
308
310{
311 const char *exist = "";
312 if (CheckPlugin() == -1)
313 exist = " [*]";
314
315 Printf("%-20s %-13s %-18s %s%s", fBase.Data(), fRegexp.Data(),
316 fClass.Data(), fPlugin.Data(), exist);
317 if (strchr(opt, 'a')) {
318 if (!exist[0]) {
319 TString lib = fPlugin;
320 if (!lib.BeginsWith("lib"))
321 lib = "lib" + lib;
322 char *path = gSystem->DynamicPathName(lib, kTRUE);
323 if (path) Printf(" [Lib: %s]", path);
324 delete [] path;
325 }
326 Printf(" [Ctor: %s]", fCtor.Data());
327 Printf(" [origin: %s]", fOrigin.Data());
328 }
329}
330
331
333
334////////////////////////////////////////////////////////////////////////////////
335/// Clean up the plugin manager.
336
338{
339 delete fHandlers;
340 delete fBasesLoaded;
341}
342
343////////////////////////////////////////////////////////////////////////////////
344/// Load plugin handlers specified in config file, like:
345/// ~~~ {.cpp}
346/// Plugin.TSQLServer: ^mysql: TMySQLServer MySQL "TMySQLServer(...)"
347/// +Plugin.TSQLServer: ^pgsql: TPgSQLServer PgSQL "TPgSQLServer(...)"
348/// ~~~
349/// The + allows the extension of an already defined resource (see TEnv).
350
352{
353 if (!env) return;
354
355 TIter next(env->GetTable());
356 TEnvRec *er;
357
358 while ((er = (TEnvRec*) next())) {
359 const char *s;
360 if ((s = strstr(er->GetName(), "Plugin."))) {
361 // use s, i.e. skip possible OS and application prefix to Plugin.
362 // so that GetValue() takes properly care of returning the value
363 // for the specified OS and/or application
364 const char *val = env->GetValue(s, (const char*)0);
365 if (val) {
366 Int_t cnt = 0;
367 char *v = StrDup(val);
368 s += 7;
369 while (1) {
370 TString regexp = strtok(!cnt ? v : 0, "; "); // this method does not need to be reentrant
371 if (regexp.IsNull()) break;
372 TString clss = strtok(0, "; ");
373 if (clss.IsNull()) break;
374 TString plugin = strtok(0, "; ");
375 if (plugin.IsNull()) break;
376 TString ctor = strtok(0, ";\"");
377 if (!ctor.Contains("("))
378 ctor = strtok(0, ";\"");
379 AddHandler(s, regexp, clss, plugin, ctor, "TEnv");
380 cnt++;
381 }
382 delete [] v;
383 }
384 }
385 }
386}
387
388////////////////////////////////////////////////////////////////////////////////
389/// Load all plugin macros from the specified path/base directory.
390
392{
393 void *dirp = gSystem->OpenDirectory(path);
394 if (dirp) {
395 if (gDebug > 0)
396 Info("LoadHandlerMacros", "%s", path);
397 TSortedList macros;
398 macros.SetOwner();
399 const char *f1;
400 while ((f1 = gSystem->GetDirEntry(dirp))) {
401 TString f = f1;
402 if (f[0] == 'P' && f.EndsWith(".C")) {
403 const char *p = gSystem->ConcatFileName(path, f);
405 macros.Add(new TObjString(p));
406 }
407 delete [] p;
408 }
409 }
410 // load macros in alphabetical order
411 TIter next(&macros);
412 TObjString *s;
413 while ((s = (TObjString*)next())) {
414 if (gDebug > 1)
415 Info("LoadHandlerMacros", " plugin macro: %s", s->String().Data());
416 Long_t res;
417 if ((res = gROOT->Macro(s->String(), 0, kFALSE)) < 0) {
418 Error("LoadHandlerMacros", "pluging macro %s returned %ld",
419 s->String().Data(), res);
420 }
421 }
422 }
423 gSystem->FreeDirectory(dirp);
424}
425
426////////////////////////////////////////////////////////////////////////////////
427/// Load plugin handlers specified via macros in a list of plugin
428/// directories. The `$ROOTSYS/etc/plugins` is the default top plugin directory
429/// specified in `$ROOTSYS/etc/system.rootrc`. The macros must have names
430/// like `<BaseClass>/PX0_<PluginClass>.C`, e.g. //`TSQLServer/P20_TMySQLServer.C`,
431/// to allow easy sorting and grouping. If the BaseClass is in a namespace
432/// the directory must have the name NameSpace@@BaseClass as : is a reserved
433/// pathname character on some operating systems. Macros not beginning with
434/// 'P' and ending with ".C" are ignored. If base is specified only plugin
435/// macros for that base class are loaded. The macros typically
436/// should look like:
437/// ~~~ {.cpp}
438/// void P10_TDCacheFile()
439/// {
440/// gPluginMgr->AddHandler("TFile", "^dcache", "TDCacheFile",
441/// "DCache", "TDCacheFile(const char*,Option_t*,const char*,Int_t)");
442/// }
443/// ~~~
444/// In general these macros should not cause side effects, by changing global
445/// ROOT state via, e.g. gSystem calls, etc. However, in specific cases
446/// this might be useful, e.g. adding a library search path, adding a specific
447/// dependency, check on some OS or ROOT capability or downloading
448/// of the plugin.
449
451{
452 TString sbase = base;
453 if (sbase.Length())
454 sbase.ReplaceAll("::", "@@");
455
457
458 if (fBasesLoaded && fBasesLoaded->FindObject(sbase))
459 return;
460
462
463 // While waiting for the lock, another thread may
464 // have process the requested plugin.
465 if (fBasesLoaded && fBasesLoaded->FindObject(sbase))
466 return;
467
468 if (!fBasesLoaded) {
469 fBasesLoaded = new THashTable();
471 }
472 fBasesLoaded->Add(new TObjString(sbase));
473
475
476 TString plugindirs = gEnv->GetValue("Root.PluginPath", (char*)0);
477 if (plugindirs.Length() == 0) {
478 plugindirs = "plugins";
480 }
481#ifdef WIN32
482 TObjArray *dirs = plugindirs.Tokenize(";");
483#else
484 TObjArray *dirs = plugindirs.Tokenize(":");
485#endif
486 TString d;
487 for (Int_t i = 0; i < dirs->GetEntriesFast(); i++) {
488 d = ((TObjString*)dirs->At(i))->GetString();
489 // check if directory already scanned
490 Int_t skip = 0;
491 for (Int_t j = 0; j < i; j++) {
492 TString pd = ((TObjString*)dirs->At(j))->GetString();
493 if (pd == d) {
494 skip++;
495 break;
496 }
497 }
498 if (!skip) {
499 if (sbase != "") {
500 const char *p = gSystem->ConcatFileName(d, sbase);
502 delete [] p;
503 } else {
504 void *dirp = gSystem->OpenDirectory(d);
505 if (dirp) {
506 if (gDebug > 0)
507 Info("LoadHandlersFromPluginDirs", "%s", d.Data());
508 const char *f1;
509 while ((f1 = gSystem->GetDirEntry(dirp))) {
510 TString f = f1;
511 const char *p = gSystem->ConcatFileName(d, f);
514 delete [] p;
515 }
516 }
517 gSystem->FreeDirectory(dirp);
518 }
519 }
520 }
522 delete dirs;
523}
524
525////////////////////////////////////////////////////////////////////////////////
526/// Add plugin handler to the list of handlers. If there is already a
527/// handler defined for the same base and regexp it will be replaced.
528
529void TPluginManager::AddHandler(const char *base, const char *regexp,
530 const char *className, const char *pluginName,
531 const char *ctor, const char *origin)
532{
533 {
535 if (!fHandlers) {
536 fHandlers = new TList;
538 }
539 }
540 // make sure there is no previous handler for the same case
541 RemoveHandler(base, regexp);
542
543 if (TPH__IsReadingDirs())
544 origin = gInterpreter->GetCurrentMacroName();
545
546 TPluginHandler *h = new TPluginHandler(base, regexp, className,
547 pluginName, ctor, origin);
548 {
550 fHandlers->Add(h);
551 }
552}
553
554////////////////////////////////////////////////////////////////////////////////
555/// Remove handler for the specified base class and the specified
556/// regexp. If regexp=0 remove all handlers for the specified base.
557
558void TPluginManager::RemoveHandler(const char *base, const char *regexp)
559{
561 if (!fHandlers) return;
562
563 TIter next(fHandlers);
565
566 while ((h = (TPluginHandler*) next())) {
567 if (h->fBase == base) {
568 if (!regexp || h->fRegexp == regexp) {
570 delete h;
571 }
572 }
573 }
574}
575
576////////////////////////////////////////////////////////////////////////////////
577/// Returns the handler if there exists a handler for the specified URI.
578/// The uri can be 0 in which case the first matching plugin handler
579/// will be returned. Returns 0 in case handler is not found.
580
581TPluginHandler *TPluginManager::FindHandler(const char *base, const char *uri)
582{
584
586 TIter next(fHandlers);
588
589 while ((h = (TPluginHandler*) next())) {
590 if (h->CanHandle(base, uri)) {
591 if (gDebug > 0)
592 Info("FindHandler", "found plugin for %s", h->GetClass());
593 return h;
594 }
595 }
596
597 if (gDebug > 2) {
598 if (uri)
599 Info("FindHandler", "did not find plugin for class %s and uri %s", base, uri);
600 else
601 Info("FindHandler", "did not find plugin for class %s", base);
602 }
603
604 return 0;
605}
606
607////////////////////////////////////////////////////////////////////////////////
608/// Print list of registered plugin handlers. If option is "a" print
609/// also the ctor's that will be used.
610
612{
613 if (!fHandlers) return;
614
615 TIter next(fHandlers);
617 Int_t cnt = 0, cntmiss = 0;
618
619 Printf("=====================================================================");
620 Printf("Base Regexp Class Plugin");
621 Printf("=====================================================================");
622
623 while ((h = (TPluginHandler*) next())) {
624 cnt++;
625 h->Print(opt);
626 if (h->CheckPlugin() == -1)
627 cntmiss++;
628 }
629 Printf("=====================================================================");
630 Printf("%d plugin handlers registered", cnt);
631 Printf("[*] %d %s not available", cntmiss, cntmiss==1 ? "plugin" : "plugins");
632 Printf("=====================================================================\n");
633}
634
635////////////////////////////////////////////////////////////////////////////////
636/// Write in the specified directory the plugin macros. If plugin is specified
637/// and if it is a base class all macros for that base will be written. If it
638/// is a plugin class name, only that one macro will be written. If plugin
639/// is 0 all macros are written. Returns -1 if dir does not exist, 0 otherwise.
640
641Int_t TPluginManager::WritePluginMacros(const char *dir, const char *plugin) const
642{
643 const_cast<TPluginManager*>(this)->LoadHandlersFromPluginDirs();
644
645 if (!fHandlers) return 0;
646
647 TString d;
648 if (!dir || !dir[0])
649 d = ".";
650 else
651 d = dir;
652
654 Error("WritePluginMacros", "cannot write in directory %s", d.Data());
655 return -1;
656 }
657
658 TString base;
659 Int_t idx = 0;
660
661 TObjLink *lnk = fHandlers->FirstLink();
662 while (lnk) {
664 if (plugin && strcmp(plugin, h->fBase) && strcmp(plugin, h->fClass)) {
665 lnk = lnk->Next();
666 continue;
667 }
668 if (base != h->fBase) {
669 idx = 10;
670 base = h->fBase;
671 } else
672 idx += 10;
673 const char *dd = gSystem->ConcatFileName(d, h->fBase);
674 TString sdd = dd;
675 sdd.ReplaceAll("::", "@@");
676 delete [] dd;
678 if (gSystem->MakeDirectory(sdd) < 0) {
679 Error("WritePluginMacros", "cannot create directory %s", sdd.Data());
680 return -1;
681 }
682 }
683 TString fn;
684 fn.Form("P%03d_%s.C", idx, h->fClass.Data());
685 const char *fd = gSystem->ConcatFileName(sdd, fn);
686 FILE *f = fopen(fd, "w");
687 if (f) {
688 fprintf(f, "void P%03d_%s()\n{\n", idx, h->fClass.Data());
689 fprintf(f, " gPluginMgr->AddHandler(\"%s\", \"%s\", \"%s\",\n",
690 h->fBase.Data(), h->fRegexp.Data(), h->fClass.Data());
691 fprintf(f, " \"%s\", \"%s\");\n", h->fPlugin.Data(), h->fCtor.Data());
692
693 // check for different regexps cases for the same base + class and
694 // put them all in the same macro
695 TObjLink *lnk2 = lnk->Next();
696 while (lnk2) {
697 TPluginHandler *h2 = (TPluginHandler *) lnk2->GetObject();
698 if (h->fBase != h2->fBase || h->fClass != h2->fClass)
699 break;
700
701 fprintf(f, " gPluginMgr->AddHandler(\"%s\", \"%s\", \"%s\",\n",
702 h2->fBase.Data(), h2->fRegexp.Data(), h2->fClass.Data());
703 fprintf(f, " \"%s\", \"%s\");\n", h2->fPlugin.Data(), h2->fCtor.Data());
704
705 lnk = lnk2;
706 lnk2 = lnk2->Next();
707 }
708 fprintf(f, "}\n");
709 fclose(f);
710 }
711 delete [] fd;
712 lnk = lnk->Next();
713 }
714 return 0;
715}
716
717////////////////////////////////////////////////////////////////////////////////
718/// Write in the specified environment config file the plugin records. If
719/// plugin is specified and if it is a base class all records for that
720/// base will be written. If it is a plugin class name, only that one
721/// record will be written. If plugin is 0 all macros are written.
722/// If envFile is 0 or "" the records are written to stdout.
723/// Returns -1 if envFile cannot be created or opened, 0 otherwise.
724
725Int_t TPluginManager::WritePluginRecords(const char *envFile, const char *plugin) const
726{
727 const_cast<TPluginManager*>(this)->LoadHandlersFromPluginDirs();
728
729 if (!fHandlers) return 0;
730
731 FILE *fd;
732 if (!envFile || !envFile[0])
733 fd = stdout;
734 else
735 fd = fopen(envFile, "w+");
736
737 if (!fd) {
738 Error("WritePluginRecords", "error opening file %s", envFile);
739 return -1;
740 }
741
742 TString base, base2;
743 Int_t idx = 0;
744
745 TObjLink *lnk = fHandlers->FirstLink();
746 while (lnk) {
748 if (plugin && strcmp(plugin, h->fBase) && strcmp(plugin, h->fClass)) {
749 lnk = lnk->Next();
750 continue;
751 }
752 if (base != h->fBase) {
753 idx = 1;
754 base = h->fBase;
755 base2 = base;
756 base2.ReplaceAll("::", "@@");
757 } else
758 idx += 1;
759
760 if (idx == 1)
761 fprintf(fd, "Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h->fRegexp.Data(),
762 h->fClass.Data(), h->fPlugin.Data(), h->fCtor.Data());
763 else
764 fprintf(fd, "+Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h->fRegexp.Data(),
765 h->fClass.Data(), h->fPlugin.Data(), h->fCtor.Data());
766
767 // check for different regexps cases for the same base + class and
768 // put them all in the same macro
769 TObjLink *lnk2 = lnk->Next();
770 while (lnk2) {
771 TPluginHandler *h2 = (TPluginHandler *) lnk2->GetObject();
772 if (h->fBase != h2->fBase || h->fClass != h2->fClass)
773 break;
774
775 fprintf(fd, "+Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h2->fRegexp.Data(),
776 h2->fClass.Data(), h2->fPlugin.Data(), h2->fCtor.Data());
777
778 lnk = lnk2;
779 lnk2 = lnk2->Next();
780 }
781 lnk = lnk->Next();
782 }
783
784 if (envFile && envFile[0])
785 fclose(fd);
786
787 return 0;
788}
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:113
const Bool_t kFALSE
Definition: RtypesCore.h:90
long Long_t
Definition: RtypesCore.h:52
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:117
const Bool_t kTRUE
Definition: RtypesCore.h:89
const char Option_t
Definition: RtypesCore.h:64
#define ClassImp(name)
Definition: Rtypes.h:361
@ kIsPublic
Definition: TDictionary.h:75
R__EXTERN TEnv * gEnv
Definition: TEnv.h:171
R__EXTERN TVirtualMutex * gInterpreterMutex
Definition: TInterpreter.h:41
#define gInterpreter
Definition: TInterpreter.h:556
static bool & TPH__IsReadingDirs()
TPluginManager * gPluginMgr
static TVirtualMutex * gPluginManagerMutex
#define gROOT
Definition: TROOT.h:406
void Printf(const char *fmt,...)
char * StrDup(const char *str)
Duplicate the string str.
Definition: TString.cxx:2490
@ kReadPermission
Definition: TSystem.h:46
@ kWritePermission
Definition: TSystem.h:45
R__EXTERN TSystem * gSystem
Definition: TSystem.h:556
#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:5712
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:2948
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:821
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:166
Collectable string class.
Definition: TObjString.h:28
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:891
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition: TObject.cxx:865
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:2939
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:2177
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1106
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:913
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:2197
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:2289
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:841
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition: TSystem.cxx:832
virtual TString SplitAclicMode(const char *filename, TString &mode, TString &args, TString &io) const
This method split a filename of the form:
Definition: TSystem.cxx:4220
virtual char * ConcatFileName(const char *dir, const char *name)
Concatenate a directory and a file name. User must delete returned string.
Definition: TSystem.cxx:1066
virtual int MakeDirectory(const char *name)
Make a directory.
Definition: TSystem.cxx:823
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition: TSystem.cxx:1076
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:1291
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition: TSystem.cxx:849
char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE)
Find a dynamic library called lib using the system search paths.
Definition: TSystem.cxx:2013
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