Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TPluginManager.h
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 #ifndef ROOT_TPluginManager
13 #define ROOT_TPluginManager
14 
15 
16 //////////////////////////////////////////////////////////////////////////
17 // //
18 // TPluginManager //
19 // //
20 // This class implements a plugin library manager. It keeps track of //
21 // a list of plugin handlers. A plugin handler knows which plugin //
22 // library to load to get a specific class that is used to extend the //
23 // functionality of a specific base class and how to create an object //
24 // of this class. For example, to extend the base class TFile to be //
25 // able to read SQLite files one needs to load the plugin library //
26 // libRSQLite.so which defines the TSQLiteServer class. This loading //
27 // should be triggered when a given URI contains a regular expression //
28 // defined by the handler. //
29 // Plugin handlers can be defined via macros in a list of plugin //
30 // directories. With $ROOTSYS/etc/plugins the default top plugin //
31 // directory specified in $ROOTSYS/etc/system.rootrc. Additional //
32 // directories can be specified by adding them to the end of the list. //
33 // Macros for identical plugin handlers in later directories will //
34 // override previous ones (the inverse of normal search path behavior). //
35 // The macros must have names like <BaseClass>/PX0_<PluginClass>.C, //
36 // e.g.: //
37 // TSQLServer/P20_TMySQLServer.C, etc. //
38 // to allow easy sorting and grouping. If the BaseClass is in a //
39 // namespace the directory must have the name NameSpace@@BaseClass as //
40 // : is a reserved pathname character on some operating systems. //
41 // Macros not beginning with 'P' and ending with ".C" are ignored. //
42 // These macros typically look like: //
43 // //
44 // void P10_TDCacheFile() //
45 // { //
46 // gPluginMgr->AddHandler("TFile", "^dcache", "TDCacheFile", //
47 // "DCache", "TDCacheFile(const char*,Option_t*)"); //
48 // } //
49 // //
50 // Plugin handlers can also be defined via resources in the .rootrc //
51 // file. Although now deprecated this method still works for backward //
52 // compatibility, e.g.: //
53 // //
54 // Plugin.TSQLServer: ^mysql: TMySQLServer MySQL "<constructor>" //
55 // +Plugin.TSQLServer: ^pgsql: TPgSQLServer PgSQL "<constructor>" //
56 // Plugin.TVirtualFitter: * TFitter Minuit "TFitter(Int_t)" //
57 // //
58 // Where the + in front of Plugin.TSQLServer says that it extends the //
59 // existing definition of TSQLServer, useful when there is more than //
60 // one plugin that can extend the same base class. The "<constructor>" //
61 // should be the constructor or a static method that generates an //
62 // instance of the specified class. Global methods should start with //
63 // "::" in their name, like "::CreateFitter()". //
64 // Instead of being a shared library a plugin can also be a CINT //
65 // script, so instead of libDialog.so one can have Dialog.C. //
66 // The * is a placeholder in case there is no need for a URI to //
67 // differentiate between different plugins for the same base class. //
68 // For the default plugins see $ROOTSYS/etc/system.rootrc. //
69 // //
70 // Plugin handlers can also be registered at run time, e.g.: //
71 // //
72 // gPluginMgr->AddHandler("TSQLServer", "^sqlite:", //
73 // "TSQLiteServer", "RSQLite", //
74 // "TSQLiteServer(const char*,const char*,const char*)"); //
75 // //
76 // A list of currently defined handlers can be printed using: //
77 // //
78 // gPluginMgr->Print(); // use option="a" to see ctors //
79 // //
80 // The use of the plugin library manager removes all textual references //
81 // to hard-coded class and library names and the resulting dependencies //
82 // in the base classes. The plugin manager is used to extend a.o. //
83 // TFile, TSQLServer, TGrid, etc. functionality. //
84 // //
85 //////////////////////////////////////////////////////////////////////////
86 
87 #include "TObject.h"
88 #include "TString.h"
89 #include "TMethodCall.h"
90 #include "TVirtualMutex.h"
91 #include "TInterpreter.h"
92 
93 class TEnv;
94 class TList;
95 class THashTable;
96 class TFunction;
97 class TMethodCall;
98 class TPluginManager;
99 
100 #include <atomic>
101 
102 class TPluginHandler : public TObject {
103 
104 friend class TPluginManager;
105 
106 private:
107  using AtomicInt_t = std::atomic<Int_t>;
108 
109  TString fBase; // base class which will be extended by plugin
110  TString fRegexp; // regular expression which must be matched in URI
111  TString fClass; // class to be loaded from plugin library
112  TString fPlugin; // plugin library which should contain fClass
113  TString fCtor; // ctor used to instantiate object of fClass
114  TString fOrigin; // origin of plugin handler definition
115  TMethodCall *fCallEnv; //!ctor method call environment
116  TFunction *fMethod; //!ctor method or global function
117  AtomicInt_t fCanCall; //!if 1 fCallEnv is ok, -1 fCallEnv is not ok, 0 fCallEnv not setup yet.
118  Bool_t fIsMacro; // plugin is a macro and not a library
119  Bool_t fIsGlobal; // plugin ctor is a global function
120 
121  TPluginHandler() :
122  fBase(), fRegexp(), fClass(), fPlugin(), fCtor(), fOrigin(),
123  fCallEnv(0), fMethod(0), fCanCall(0), fIsMacro(kTRUE), fIsGlobal(kTRUE) { }
124  TPluginHandler(const char *base, const char *regexp,
125  const char *className, const char *pluginName,
126  const char *ctor, const char *origin);
127  TPluginHandler(const TPluginHandler&); // not implemented
128  TPluginHandler& operator=(const TPluginHandler&); // not implemented
129 
130  ~TPluginHandler();
131 
132  const char *GetBase() const { return fBase; }
133  const char *GetRegexp() const { return fRegexp; }
134  const char *GetPlugin() const { return fPlugin; }
135  const char *GetCtor() const { return fCtor; }
136  const char *GetOrigin() const { return fOrigin; }
137 
138  Bool_t CanHandle(const char *base, const char *uri);
139  void SetupCallEnv();
140 
141  Bool_t CheckForExecPlugin(Int_t nargs);
142 
143 public:
144  const char *GetClass() const { return fClass; }
145  Int_t CheckPlugin() const;
146  Int_t LoadPlugin();
147 
148  template <typename... T> Long_t ExecPluginImpl(const T&... params)
149  {
150  auto nargs = sizeof...(params);
151  if (!CheckForExecPlugin(nargs)) return 0;
152 
153  // The fCallEnv object is shared, since the PluginHandler is a global
154  // resource ... and both SetParams and Execute ends up taking the lock
155  // individually anyway ...
156 
157  R__LOCKGUARD(gInterpreterMutex);
158  fCallEnv->SetParams(params...);
159 
160  Long_t ret;
161  fCallEnv->Execute(ret);
162 
163  return ret;
164  }
165 
166  template <typename... T> Long_t ExecPlugin(int nargs, const T&... params)
167  {
168  // For backward compatibility.
169  if ((gDebug > 1) && (nargs != (int)sizeof...(params))) {
170  Warning("ExecPlugin","Announced number of args different from the real number of argument passed %d vs %lu",
171  nargs, (unsigned long)sizeof...(params) );
172  }
173  return ExecPluginImpl(params...);
174  }
175 
176  void Print(Option_t *opt = "") const;
177 
178  ClassDef(TPluginHandler,3) // Handler for plugin libraries
179 };
180 
181 
182 class TPluginManager : public TObject {
183 
184 private:
185  TList *fHandlers; // list of plugin handlers
186  THashTable *fBasesLoaded; //! table of base classes already checked or loaded
187  Bool_t fReadingDirs; //! true if we are running LoadHandlersFromPluginDirs
188 
189  TPluginManager(const TPluginManager& pm); // not implemented
190  TPluginManager& operator=(const TPluginManager& pm); // not implemented
191  void LoadHandlerMacros(const char *path);
192 
193 public:
194  TPluginManager() : fHandlers(0), fBasesLoaded(0), fReadingDirs(kFALSE) { }
195  ~TPluginManager();
196 
197  void LoadHandlersFromEnv(TEnv *env);
198  void LoadHandlersFromPluginDirs(const char *base = 0);
199  void AddHandler(const char *base, const char *regexp,
200  const char *className, const char *pluginName,
201  const char *ctor = 0, const char *origin = 0);
202  void RemoveHandler(const char *base, const char *regexp = 0);
203 
204  TPluginHandler *FindHandler(const char *base, const char *uri = 0);
205 
206  void Print(Option_t *opt = "") const;
207  Int_t WritePluginMacros(const char *dir, const char *plugin = 0) const;
208  Int_t WritePluginRecords(const char *envFile, const char *plugin = 0) const;
209 
210  ClassDef(TPluginManager,1) // Manager for plugin handlers
211 };
212 
213 R__EXTERN TPluginManager *gPluginMgr;
214 
215 #endif