Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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#include <sstream>
102
103TPluginManager *gPluginMgr; // main plugin manager created in TROOT
104
105static bool &TPH__IsReadingDirs() {
106 TTHREAD_TLS(bool) readingDirs (false);
107 return readingDirs;
108}
109
111
112////////////////////////////////////////////////////////////////////////////////
113/// Create a plugin handler. Called by TPluginManager.
114
115TPluginHandler::TPluginHandler(const char *base, const char *regexp, const char *className, const char *pluginName,
116 const char *ctor, const char *origin)
117 : fBase(base),
118 fRegexp(regexp),
119 fClass(className),
120 fPlugin(pluginName),
121 fCtor(ctor),
122 fOrigin(origin),
123 fCallEnv(nullptr),
124 fMethod(nullptr),
125 fCanCall(0),
126 fIsMacro(kFALSE),
127 fIsGlobal(kFALSE),
128 fLoadStatus(-1)
129{
130 TString aclicMode, arguments, io;
131 TString fname = gSystem->SplitAclicMode(fPlugin, aclicMode, arguments, io);
132 Bool_t validMacro = kFALSE;
133 if (fname.EndsWith(".C") || fname.EndsWith(".cxx") || fname.EndsWith(".cpp") ||
134 fname.EndsWith(".cc"))
135 validMacro = kTRUE;
136
137 if (validMacro && gROOT->LoadMacro(fPlugin, nullptr, kTRUE) == 0)
138 fIsMacro = kTRUE;
139
140 if (fCtor.BeginsWith("::")) {
143 }
144}
145
146////////////////////////////////////////////////////////////////////////////////
147/// Cleanup plugin handler object.
148
150{
151 delete fCallEnv;
152}
153
154////////////////////////////////////////////////////////////////////////////////
155/// Check if regular expression appears in the URI, if so return kTRUE.
156/// If URI = 0 always return kTRUE.
157
158Bool_t TPluginHandler::CanHandle(const char *base, const char *uri)
159{
160 if (fBase != base)
161 return kFALSE;
162
163 if (!uri || fRegexp == "*")
164 return kTRUE;
165
166 Bool_t wildcard = kFALSE;
167 if (!fRegexp.MaybeRegexp())
168 wildcard = kTRUE;
169
170 TRegexp re(fRegexp, wildcard);
171 TString ruri = uri;
172
173 if (ruri.Index(re) != kNPOS)
174 return kTRUE;
175 return kFALSE;
176}
177
178////////////////////////////////////////////////////////////////////////////////
179/// Setup ctor or static method call environment.
180
182{
183 int setCanCall = -1;
184
185 // Use a exit_scope guard, to insure that fCanCall is set (to the value of
186 // result) as the last action of this function before returning.
187
188 // When the standard supports it, we should use std::exit_code
189 // See N4189 for example.
190 // auto guard = make_exit_scope( [...]() { ... } );
191 using exit_scope = std::shared_ptr<void*>;
192 exit_scope guard(nullptr,
193 [this,&setCanCall](void *) { this->fCanCall = setCanCall; } );
194
195 // check if class exists
197 if (!cl && !fIsGlobal) {
198 Error("SetupCallEnv", "class %s not found in plugin %s", fClass.Data(),
199 fPlugin.Data());
200 return;
201 }
202
203 // split method and prototype strings
204 TString method = fCtor(0, fCtor.Index("("));
205 TString proto = fCtor(fCtor.Index("(")+1, fCtor.Index(")")-fCtor.Index("(")-1);
206
207 if (fIsGlobal) {
208 cl = nullptr;
209 fMethod = gROOT->GetGlobalFunctionWithPrototype(method, proto, kFALSE);
210 } else {
211 fMethod = cl->GetMethodWithPrototype(method, proto);
212 }
213
214 if (!fMethod) {
215 if (fIsGlobal)
216 Error("SetupCallEnv", "global function %s not found", method.Data());
217 else
218 Error("SetupCallEnv", "method %s not found in class %s", method.Data(),
219 fClass.Data());
220 return;
221 }
222
223 if (!fIsGlobal && !(fMethod->Property() & kIsPublic)) {
224 Error("SetupCallEnv", "method %s is not public", method.Data());
225 return;
226 }
227
228 fCallEnv = new TMethodCall;
230
231 // cache argument types for fast comparison
232 fArgTupleClasses.clear();
233
234 std::stringstream typelist;
235 for (int iarg = 0; iarg < fMethod->GetNargs(); ++iarg) {
236 if (iarg > 0) {
237 typelist << ", ";
238 }
239 const TMethodArg *arg = static_cast<const TMethodArg *>(fMethod->GetListOfMethodArgs()->At(iarg));
241
242 std::stringstream tupletype;
243 tupletype << "std::tuple<" << typelist.str() << ">";
244 const TClass *tupleclass = TClass::GetClass(tupletype.str().c_str());
245 if (!tupleclass) {
246 Error("SetupCallEnv", "couldn't get TClass for tuple of argument types %s", tupletype.str().c_str());
247 }
248 fArgTupleClasses.push_back(tupleclass);
249 }
250
251 setCanCall = 1;
252
253 return;
254}
255
256////////////////////////////////////////////////////////////////////////////////
257/// Check if the plugin library for this handler exits. Returns 0
258/// when it exists and -1 in case the plugin does not exist.
259
261{
262 if (fIsMacro) {
263 if (TClass::GetClass(fClass)) return 0;
264 return gROOT->LoadMacro(fPlugin, nullptr, kTRUE);
265 } else
266 return gROOT->LoadClass(fClass, fPlugin, kTRUE);
267}
268
269////////////////////////////////////////////////////////////////////////////////
270/// Load the plugin library for this handler. Sets status to 0 on successful loading
271/// and -1 in case the library does not exist or in case of error.
273{
274 if (fIsMacro) {
276 fLoadStatus = 0;
277 else
278 fLoadStatus = gROOT->LoadMacro(fPlugin);
279 } else {
280 // first call also loads dependent libraries declared via the rootmap file
281 if (TClass::LoadClass(fClass, /* silent = */ kFALSE))
282 fLoadStatus = 0;
283 else
284 fLoadStatus = gROOT->LoadClass(fClass, fPlugin);
285 }
286}
287
288////////////////////////////////////////////////////////////////////////////////
289/// Load the plugin library for this handler. Returns 0 on successful loading
290/// and -1 in case the library does not exist or in case of error.
292{
293 // call once and cache the result to reduce lock contention
294 std::call_once(fLoadStatusFlag, &TPluginHandler::LoadPluginImpl, this);
295 return fLoadStatus;
296}
297
298////////////////////////////////////////////////////////////////////////////////
299/// Check that we can properly run ExecPlugin.
300
302{
303 if (fCtor.IsNull()) {
304 Error("ExecPlugin", "no ctor specified for this handler %s", fClass.Data());
305 return kFALSE;
306 }
307
308 if (fCanCall == 0) {
309 // Not initialized yet.
310 // SetupCallEnv is likely to require/take the interpreter lock.
311 // Grab it now to avoid dead-lock. In particular TPluginHandler::ExecPluginImpl
312 // takes the gInterpreterMutex and *then* call (indirectly) code that
313 // take the lock in fHandlers.
315
316 // Now check if another thread did not already do the work.
317 if (fCanCall == 0)
318 SetupCallEnv();
319 }
320
321 if (fCanCall == -1)
322 return kFALSE;
323
324 if (nargs < fMethod->GetNargs() - fMethod->GetNargsOpt() ||
325 nargs > fMethod->GetNargs()) {
326 Error("ExecPlugin", "nargs (%d) not consistent with expected number of arguments ([%d-%d])",
327 nargs, fMethod->GetNargs() - fMethod->GetNargsOpt(),
328 fMethod->GetNargs());
329 return kFALSE;
330 }
331
332 return kTRUE;
333}
334
335////////////////////////////////////////////////////////////////////////////////
336/// Print info about the plugin handler. If option is "a" print
337/// also the ctor's that will be used.
338
340{
341 const char *exist = "";
342 if (CheckPlugin() == -1)
343 exist = " [*]";
344
345 Printf("%-20s %-13s %-18s %s%s", fBase.Data(), fRegexp.Data(),
346 fClass.Data(), fPlugin.Data(), exist);
347 if (strchr(opt, 'a')) {
348 if (!exist[0]) {
349 TString lib = fPlugin;
350 if (!lib.BeginsWith("lib"))
351 lib = "lib" + lib;
352 char *path = gSystem->DynamicPathName(lib, kTRUE);
353 if (path) Printf(" [Lib: %s]", path);
354 delete [] path;
355 }
356 Printf(" [Ctor: %s]", fCtor.Data());
357 Printf(" [origin: %s]", fOrigin.Data());
358 }
359}
360
361
363
364////////////////////////////////////////////////////////////////////////////////
365/// Constructor
366TPluginManager::TPluginManager() : fHandlers(new TList()), fBasesLoaded(nullptr), fReadingDirs(kFALSE)
367{
370}
371
372////////////////////////////////////////////////////////////////////////////////
373/// Clean up the plugin manager.
374
376{
377 delete fHandlers;
378 delete fBasesLoaded;
379}
380
381////////////////////////////////////////////////////////////////////////////////
382/// Load plugin handlers specified in config file, like:
383/// ~~~ {.cpp}
384/// Plugin.TSQLServer: ^mysql: TMySQLServer MySQL "TMySQLServer(...)"
385/// +Plugin.TSQLServer: ^pgsql: TPgSQLServer PgSQL "TPgSQLServer(...)"
386/// ~~~
387/// The + allows the extension of an already defined resource (see TEnv).
388
390{
391 if (!env) return;
392
393 TIter next(env->GetTable());
394 TEnvRec *er;
395
396 while ((er = (TEnvRec*) next())) {
397 const char *s;
398 if ((s = strstr(er->GetName(), "Plugin."))) {
399 // use s, i.e. skip possible OS and application prefix to Plugin.
400 // so that GetValue() takes properly care of returning the value
401 // for the specified OS and/or application
402 const char *val = env->GetValue(s, (const char*)nullptr);
403 if (val) {
404 Int_t cnt = 0;
405 char *v = StrDup(val);
406 s += 7;
407 while (1) {
408 TString regexp = strtok(!cnt ? v : nullptr, "; "); // this method does not need to be reentrant
409 if (regexp.IsNull()) break;
410 TString clss = strtok(nullptr, "; ");
411 if (clss.IsNull()) break;
412 TString plugin = strtok(nullptr, "; ");
413 if (plugin.IsNull()) break;
414 TString ctor = strtok(nullptr, ";\"");
415 if (!ctor.Contains("("))
416 ctor = strtok(nullptr, ";\"");
417 AddHandler(s, regexp, clss, plugin, ctor, "TEnv");
418 cnt++;
419 }
420 delete [] v;
421 }
422 }
423 }
424}
425
426////////////////////////////////////////////////////////////////////////////////
427/// Load all plugin macros from the specified path/base directory.
428
430{
431 void *dirp = gSystem->OpenDirectory(path);
432 if (dirp) {
433 if (gDebug > 0)
434 Info("LoadHandlerMacros", "%s", path);
435 TSortedList macros;
436 macros.SetOwner();
437 const char *f1;
438 while ((f1 = gSystem->GetDirEntry(dirp))) {
439 TString f = f1;
440 if (f[0] == 'P' && f.EndsWith(".C")) {
441 const char *p = gSystem->ConcatFileName(path, f);
443 macros.Add(new TObjString(p));
444 }
445 delete [] p;
446 }
447 }
448 // load macros in alphabetical order
449 TIter next(&macros);
450 TObjString *s;
451 while ((s = (TObjString*)next())) {
452 if (gDebug > 1)
453 Info("LoadHandlerMacros", " plugin macro: %s", s->String().Data());
454 Longptr_t res;
455 if ((res = gROOT->Macro(s->String(), nullptr, kFALSE)) < 0) {
456 Error("LoadHandlerMacros", "pluging macro %s returned %ld",
457 s->String().Data(), res);
458 }
459 }
460 }
461 gSystem->FreeDirectory(dirp);
462}
463
464////////////////////////////////////////////////////////////////////////////////
465/// Load plugin handlers specified via macros in a list of plugin
466/// directories. The `$ROOTSYS/etc/plugins` is the default top plugin directory
467/// specified in `$ROOTSYS/etc/system.rootrc`. The macros must have names
468/// like `<BaseClass>/PX0_<PluginClass>.C`, e.g. //`TSQLServer/P20_TMySQLServer.C`,
469/// to allow easy sorting and grouping. If the BaseClass is in a namespace
470/// the directory must have the name NameSpace@@BaseClass as : is a reserved
471/// pathname character on some operating systems. Macros not beginning with
472/// 'P' and ending with ".C" are ignored. If base is specified only plugin
473/// macros for that base class are loaded. The macros typically
474/// should look like:
475/// ~~~ {.cpp}
476/// void P10_TDCacheFile()
477/// {
478/// gPluginMgr->AddHandler("TFile", "^dcache", "TDCacheFile",
479/// "DCache", "TDCacheFile(const char*,Option_t*,const char*,Int_t)");
480/// }
481/// ~~~
482/// In general these macros should not cause side effects, by changing global
483/// ROOT state via, e.g. gSystem calls, etc. However, in specific cases
484/// this might be useful, e.g. adding a library search path, adding a specific
485/// dependency, check on some OS or ROOT capability or downloading
486/// of the plugin.
487
489{
490 TString sbase = base;
491 if (sbase.Length())
492 sbase.ReplaceAll("::", "@@");
493
495
496 if (fBasesLoaded && fBasesLoaded->FindObject(sbase))
497 return;
498
500
501 // While waiting for the lock, another thread may
502 // have process the requested plugin.
503 if (fBasesLoaded && fBasesLoaded->FindObject(sbase))
504 return;
505
506 if (!fBasesLoaded) {
507 fBasesLoaded = new THashTable();
509 }
510 fBasesLoaded->Add(new TObjString(sbase));
511
513
514 TString plugindirs = gEnv->GetValue("Root.PluginPath", (char*)nullptr);
515 if (plugindirs.Length() == 0) {
516 plugindirs = "plugins";
518 }
519#ifdef WIN32
520 TObjArray *dirs = plugindirs.Tokenize(";");
521#else
522 TObjArray *dirs = plugindirs.Tokenize(":");
523#endif
524 TString d;
525 for (Int_t i = 0; i < dirs->GetEntriesFast(); i++) {
526 d = ((TObjString*)dirs->At(i))->GetString();
527 // check if directory already scanned
528 Int_t skip = 0;
529 for (Int_t j = 0; j < i; j++) {
530 TString pd = ((TObjString*)dirs->At(j))->GetString();
531 if (pd == d) {
532 skip++;
533 break;
534 }
535 }
536 if (!skip) {
537 if (sbase != "") {
538 const char *p = gSystem->ConcatFileName(d, sbase);
540 delete [] p;
541 } else {
542 void *dirp = gSystem->OpenDirectory(d);
543 if (dirp) {
544 if (gDebug > 0)
545 Info("LoadHandlersFromPluginDirs", "%s", d.Data());
546 const char *f1;
547 while ((f1 = gSystem->GetDirEntry(dirp))) {
548 TString f = f1;
549 const char *p = gSystem->ConcatFileName(d, f);
552 delete [] p;
553 }
554 }
555 gSystem->FreeDirectory(dirp);
556 }
557 }
558 }
560 delete dirs;
561}
562
563////////////////////////////////////////////////////////////////////////////////
564/// Add plugin handler to the list of handlers. If there is already a
565/// handler defined for the same base and regexp it will be replaced.
566
567void TPluginManager::AddHandler(const char *base, const char *regexp,
568 const char *className, const char *pluginName,
569 const char *ctor, const char *origin)
570{
571 // make sure there is no previous handler for the same case
572 RemoveHandler(base, regexp);
573
574 if (TPH__IsReadingDirs())
575 origin = gInterpreter->GetCurrentMacroName();
576
577 TPluginHandler *h = new TPluginHandler(base, regexp, className,
578 pluginName, ctor, origin);
579 fHandlers->Add(h);
580}
581
582////////////////////////////////////////////////////////////////////////////////
583/// Remove handler for the specified base class and the specified
584/// regexp. If regexp=0 remove all handlers for the specified base.
585
586void TPluginManager::RemoveHandler(const char *base, const char *regexp)
587{
588 TIter next(fHandlers);
590
591 while ((h = (TPluginHandler*) next())) {
592 if (h->fBase == base) {
593 if (!regexp || h->fRegexp == regexp) {
595 delete h;
596 }
597 }
598 }
599}
600
601////////////////////////////////////////////////////////////////////////////////
602/// Returns the handler if there exists a handler for the specified URI.
603/// The uri can be 0 in which case the first matching plugin handler
604/// will be returned. Returns 0 in case handler is not found.
605
606TPluginHandler *TPluginManager::FindHandler(const char *base, const char *uri)
607{
609
610 TIter next(fHandlers);
612
613 while ((h = (TPluginHandler*) next())) {
614 if (h->CanHandle(base, uri)) {
615 if (gDebug > 0)
616 Info("FindHandler", "found plugin for %s", h->GetClass());
617 return h;
618 }
619 }
620
621 if (gDebug > 2) {
622 if (uri)
623 Info("FindHandler", "did not find plugin for class %s and uri %s", base, uri);
624 else
625 Info("FindHandler", "did not find plugin for class %s", base);
626 }
627
628 return nullptr;
629}
630
631////////////////////////////////////////////////////////////////////////////////
632/// Print list of registered plugin handlers. If option is "a" print
633/// also the ctor's that will be used.
634
636{
637 TIter next(fHandlers);
639 Int_t cnt = 0, cntmiss = 0;
640
641 Printf("=====================================================================");
642 Printf("Base Regexp Class Plugin");
643 Printf("=====================================================================");
644
645 while ((h = (TPluginHandler*) next())) {
646 cnt++;
647 h->Print(opt);
648 if (h->CheckPlugin() == -1)
649 cntmiss++;
650 }
651 Printf("=====================================================================");
652 Printf("%d plugin handlers registered", cnt);
653 Printf("[*] %d %s not available", cntmiss, cntmiss==1 ? "plugin" : "plugins");
654 Printf("=====================================================================\n");
655}
656
657////////////////////////////////////////////////////////////////////////////////
658/// Write in the specified directory the plugin macros. If plugin is specified
659/// and if it is a base class all macros for that base will be written. If it
660/// is a plugin class name, only that one macro will be written. If plugin
661/// is 0 all macros are written. Returns -1 if dir does not exist, 0 otherwise.
662
663Int_t TPluginManager::WritePluginMacros(const char *dir, const char *plugin) const
664{
665 const_cast<TPluginManager*>(this)->LoadHandlersFromPluginDirs();
666
667 TString d;
668 if (!dir || !dir[0])
669 d = ".";
670 else
671 d = dir;
672
674 Error("WritePluginMacros", "cannot write in directory %s", d.Data());
675 return -1;
676 }
677
678 TString base;
679 Int_t idx = 0;
680
681 TObjLink *lnk = fHandlers->FirstLink();
682 while (lnk) {
684 if (plugin && strcmp(plugin, h->fBase) && strcmp(plugin, h->fClass)) {
685 lnk = lnk->Next();
686 continue;
687 }
688 if (base != h->fBase) {
689 idx = 10;
690 base = h->fBase;
691 } else
692 idx += 10;
693 const char *dd = gSystem->ConcatFileName(d, h->fBase);
694 TString sdd = dd;
695 sdd.ReplaceAll("::", "@@");
696 delete [] dd;
698 if (gSystem->MakeDirectory(sdd) < 0) {
699 Error("WritePluginMacros", "cannot create directory %s", sdd.Data());
700 return -1;
701 }
702 }
703 TString fn;
704 fn.Form("P%03d_%s.C", idx, h->fClass.Data());
705 const char *fd = gSystem->ConcatFileName(sdd, fn);
706 FILE *f = fopen(fd, "w");
707 if (f) {
708 fprintf(f, "void P%03d_%s()\n{\n", idx, h->fClass.Data());
709 fprintf(f, " gPluginMgr->AddHandler(\"%s\", \"%s\", \"%s\",\n",
710 h->fBase.Data(), h->fRegexp.Data(), h->fClass.Data());
711 fprintf(f, " \"%s\", \"%s\");\n", h->fPlugin.Data(), h->fCtor.Data());
712
713 // check for different regexps cases for the same base + class and
714 // put them all in the same macro
715 TObjLink *lnk2 = lnk->Next();
716 while (lnk2) {
717 TPluginHandler *h2 = (TPluginHandler *) lnk2->GetObject();
718 if (h->fBase != h2->fBase || h->fClass != h2->fClass)
719 break;
720
721 fprintf(f, " gPluginMgr->AddHandler(\"%s\", \"%s\", \"%s\",\n",
722 h2->fBase.Data(), h2->fRegexp.Data(), h2->fClass.Data());
723 fprintf(f, " \"%s\", \"%s\");\n", h2->fPlugin.Data(), h2->fCtor.Data());
724
725 lnk = lnk2;
726 lnk2 = lnk2->Next();
727 }
728 fprintf(f, "}\n");
729 fclose(f);
730 }
731 delete [] fd;
732 lnk = lnk->Next();
733 }
734 return 0;
735}
736
737////////////////////////////////////////////////////////////////////////////////
738/// Write in the specified environment config file the plugin records. If
739/// plugin is specified and if it is a base class all records for that
740/// base will be written. If it is a plugin class name, only that one
741/// record will be written. If plugin is 0 all macros are written.
742/// If envFile is 0 or "" the records are written to stdout.
743/// Returns -1 if envFile cannot be created or opened, 0 otherwise.
744
745Int_t TPluginManager::WritePluginRecords(const char *envFile, const char *plugin) const
746{
747 const_cast<TPluginManager*>(this)->LoadHandlersFromPluginDirs();
748
749 FILE *fd;
750 if (!envFile || !envFile[0])
751 fd = stdout;
752 else
753 fd = fopen(envFile, "w+");
754
755 if (!fd) {
756 Error("WritePluginRecords", "error opening file %s", envFile);
757 return -1;
758 }
759
760 TString base, base2;
761 Int_t idx = 0;
762
763 TObjLink *lnk = fHandlers->FirstLink();
764 while (lnk) {
766 if (plugin && strcmp(plugin, h->fBase) && strcmp(plugin, h->fClass)) {
767 lnk = lnk->Next();
768 continue;
769 }
770 if (base != h->fBase) {
771 idx = 1;
772 base = h->fBase;
773 base2 = base;
774 base2.ReplaceAll("::", "@@");
775 } else
776 idx += 1;
777
778 if (idx == 1)
779 fprintf(fd, "Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h->fRegexp.Data(),
780 h->fClass.Data(), h->fPlugin.Data(), h->fCtor.Data());
781 else
782 fprintf(fd, "+Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h->fRegexp.Data(),
783 h->fClass.Data(), h->fPlugin.Data(), h->fCtor.Data());
784
785 // check for different regexps cases for the same base + class and
786 // put them all in the same macro
787 TObjLink *lnk2 = lnk->Next();
788 while (lnk2) {
789 TPluginHandler *h2 = (TPluginHandler *) lnk2->GetObject();
790 if (h->fBase != h2->fBase || h->fClass != h2->fClass)
791 break;
792
793 fprintf(fd, "+Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h2->fRegexp.Data(),
794 h2->fClass.Data(), h2->fPlugin.Data(), h2->fCtor.Data());
795
796 lnk = lnk2;
797 lnk2 = lnk2->Next();
798 }
799 lnk = lnk->Next();
800 }
801
802 if (envFile && envFile[0])
803 fclose(fd);
804
805 return 0;
806}
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
const Bool_t kTRUE
Definition RtypesCore.h:100
const char Option_t
Definition RtypesCore.h:66
#define ClassImp(name)
Definition Rtypes.h:377
@ kIsPublic
Definition TDictionary.h:75
R__EXTERN TEnv * gEnv
Definition TEnv.h:170
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t Atom_t typelist
R__EXTERN TVirtualMutex * gInterpreterMutex
#define gInterpreter
static bool & TPH__IsReadingDirs()
TPluginManager * gPluginMgr
Int_t gDebug
Definition TROOT.cxx:585
#define gROOT
Definition TROOT.h:406
void Printf(const char *fmt,...)
Formats a string in a circular formatting buffer and prints the string.
Definition TString.cxx:2482
char * StrDup(const char *str)
Duplicate the string str.
Definition TString.cxx:2536
@ kReadPermission
Definition TSystem.h:47
@ kWritePermission
Definition TSystem.h:46
R__EXTERN TSystem * gSystem
Definition TSystem.h:560
#define R__LOCKGUARD(mutex)
#define R__WRITE_LOCKGUARD(mutex)
#define R__READ_LOCKGUARD(mutex)
const char * proto
Definition civetweb.c:17536
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:81
static TClass * LoadClass(const char *requestedname, Bool_t silent)
Helper function used by TClass::GetClass().
Definition TClass.cxx:5749
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:2968
virtual bool UseRWLock(Bool_t enable=true)
Set this collection to use a RW lock upon access, making it thread safe.
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 override
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 override
Get property description word. For meaning of bits see EProperty.
Int_t GetNargsOpt() const
Number of function optional (default) arguments.
Int_t GetNargs() const
Number of function arguments.
TList * GetListOfMethodArgs()
Return list containing the TMethodArgs of a TFunction.
THashTable implements a hash table to store TObject's.
Definition THashTable.h:35
void Add(TObject *obj) override
Add object to the hash table.
TObject * FindObject(const char *name) const override
Find object using its name.
A doubly linked list.
Definition TList.h:38
void Add(TObject *obj) override
Definition TList.h:81
TObject * Remove(TObject *obj) override
Remove object from the list.
Definition TList.cxx:822
virtual TObjLink * FirstLink() const
Definition TList.h:102
TObject * At(Int_t idx) const override
Returns the object at position idx. Returns 0 if idx is out of range.
Definition TList.cxx:357
Each ROOT method (see TMethod) has a linked list of its arguments.
Definition TMethodArg.h:36
std::string GetTypeNormalizedName() const
Get the normalized name of the return type.
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:31
Int_t GetEntriesFast() const
Definition TObjArray.h:58
TObject * At(Int_t idx) const override
Definition TObjArray.h:164
Collectable string class.
Definition TObjString.h:28
TString & String()
Definition TObjString.h:48
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:970
virtual void Info(const char *method, const char *msgfmt,...) const
Issue info message.
Definition TObject.cxx:944
Int_t CheckPlugin() const
Check if the plugin library for this handler exits.
TFunction * fMethod
ctor method call environment
AtomicInt_t fCanCall
cached TClass pointers for fast comparison
std::vector< const TClass * > fArgTupleClasses
ctor method or global function
void Print(Option_t *opt="") const override
Print info about the plugin handler.
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.
void LoadPluginImpl()
Load the plugin library for this handler.
TMethodCall * fCallEnv
Int_t LoadPlugin()
Load the plugin library for this handler.
std::once_flag fLoadStatusFlag
This class implements a plugin library manager.
Int_t WritePluginMacros(const char *dir, const char *plugin=nullptr) const
Write in the specified directory the plugin macros.
void AddHandler(const char *base, const char *regexp, const char *className, const char *pluginName, const char *ctor=nullptr, const char *origin=nullptr)
Add plugin handler to the list of handlers.
void Print(Option_t *opt="") const override
Print list of registered plugin handlers.
~TPluginManager()
Clean up the plugin manager.
void RemoveHandler(const char *base, const char *regexp=nullptr)
Remove handler for the specified base class and the specified regexp.
void LoadHandlersFromEnv(TEnv *env)
Load plugin handlers specified in config file, like:
THashTable * fBasesLoaded
void LoadHandlerMacros(const char *path)
Load all plugin macros from the specified path/base directory.
Int_t WritePluginRecords(const char *envFile, const char *plugin=nullptr) const
Write in the specified environment config file the plugin records.
TPluginHandler * FindHandler(const char *base, const char *uri=nullptr)
Returns the handler if there exists a handler for the specified URI.
TPluginManager()
Constructor.
void LoadHandlersFromPluginDirs(const char *base=nullptr)
Load plugin handlers specified via macros in a list of plugin directories.
static const TString & GetEtcDir()
Get the sysconfig directory in the installation. Static utility function.
Definition TROOT.cxx:2980
Regular expression class.
Definition TRegexp.h:31
A sorted doubly linked list.
Definition TSortedList.h:28
void Add(TObject *obj) override
Add object in sorted list.
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:421
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition TString.cxx:2223
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1152
const char * Data() const
Definition TString.h:380
Bool_t MaybeRegexp() const
Returns true if string contains one of the regexp characters "^$.[]*+?".
Definition TString.cxx:946
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition TString.h:704
@ kLeading
Definition TString.h:278
TObjArray * Tokenize(const TString &delim) const
This function is used to isolate sequential tokens in a TString.
Definition TString.cxx:2243
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:627
Bool_t IsNull() const
Definition TString.h:418
void Form(const char *fmt,...)
Formats a string using a printf style format descriptor.
Definition TString.cxx:2335
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition TString.h:636
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition TString.h:651
virtual void FreeDirectory(void *dirp)
Free a directory.
Definition TSystem.cxx:848
virtual void * OpenDirectory(const char *name)
Open a directory. Returns 0 if directory does not exist.
Definition TSystem.cxx:839
virtual TString SplitAclicMode(const char *filename, TString &mode, TString &args, TString &io) const
This method split a filename of the form:
Definition TSystem.cxx:4251
virtual char * ConcatFileName(const char *dir, const char *name)
Concatenate a directory and a file name. User must delete returned string.
Definition TSystem.cxx:1074
virtual int MakeDirectory(const char *name)
Make a directory.
Definition TSystem.cxx:830
virtual const char * PrependPathName(const char *dir, TString &name)
Concatenate a directory and a file name.
Definition TSystem.cxx:1084
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:1299
virtual const char * GetDirEntry(void *dirp)
Get a directory entry. Returns 0 if no more entries.
Definition TSystem.cxx:856
char * DynamicPathName(const char *lib, Bool_t quiet=kFALSE)
Find a dynamic library called lib using the system search paths.
Definition TSystem.cxx:2021
TF1 * f1
Definition legend1.C:11
R__EXTERN TVirtualRWMutex * gCoreMutex