diff --git a/base/inc/TPluginManager.h b/base/inc/TPluginManager.h new file mode 100644 index 0000000000000000000000000000000000000000..82377513fd2c4e87471aef96238eda90c7a716dc --- /dev/null +++ b/base/inc/TPluginManager.h @@ -0,0 +1,113 @@ +// @(#)root/base:$Name:$:$Id:$ +// Author: Fons Rademakers 26/1/2002 + +/************************************************************************* + * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +#ifndef ROOT_TPluginManager +#define ROOT_TPluginManager + + +////////////////////////////////////////////////////////////////////////// +// // +// TPluginManager // +// // +// This class implements a plugin library manager. It keeps track of // +// a list of plugin handlers. A plugin handler knows which plugin // +// library to load to get a specific class that is used to extend the // +// functionality of a specific base class. For example, to extend the // +// base class TFile to be able to read RFIO files one needs to load // +// the plugin library libRFIO.so which defines the TRFIOFile class. // +// This loading should be triggered when a given URI contains a // +// regular expression defined by the handler. Handlers can be defined // +// for example as resources in the .rootrc file, e.g.: // +// // +// Plugin.TFile: ^rfio: TRFIOFile RFIO // +// Plugin.TSQLServer: ^mysql: TMySQLServer MySQL // +// +Plugin.TSQLServer: ^pgsql: TPgSQLServer PgSQL // +// // +// Plugin handlers can also be registered at run time, e.g.: // +// // +// gROOT->GetPluginManager()->AddHandler("TSQLServer", "^sapdb:", // +// "TSapDBServer", "SapDB"); // +// // +// A list of currently defined handlers can be printed using: // +// // +// gROOT->GetPluginManager()->Print(); // +// // +// The use of the plugin library manager removes all textual references // +// to hard-coded class and library names and the resulting dependencies // +// in the base classes. The plugin manager is used to extend a.o. // +// TFile, TSQLServer, TGrid, etc. functionality. // +// // +////////////////////////////////////////////////////////////////////////// + +#ifndef ROOT_TObject +#include "TObject.h" +#endif +#ifndef ROOT_TString +#include "TString.h" +#endif + +class TEnv; +class TList; +class TPluginManager; + + +class TPluginHandler : public TObject { + +friend class TPluginManager; + +private: + TString fBase; // base class which will be extended by plugin + TString fRegexp; // regular expression which must be matched in URI + TString fClass; // class to be loaded from plugin library + TString fPlugin; // plugin library which should contain fClass + + TPluginHandler() { } + TPluginHandler(const char *base, const char *regexp, + const char *className, const char *pluginName); + + ~TPluginHandler() { } + + const char *GetBase() const { return fBase; } + const char *GetRegexp() const { return fRegexp; } + const char *GetPlugin() const { return fPlugin; } + + Bool_t CanHandle(const char *base, const char *uri); + +public: + const char *GetClass() const { return fClass; } + Int_t LoadPlugin(); + + ClassDef(TPluginHandler,1) // Handler for plugin libraries +}; + + +class TPluginManager : public TObject { + +private: + TList *fHandlers; // list of plugin handlers + +public: + TPluginManager() { fHandlers = 0; } + ~TPluginManager(); + + void LoadHandlersFromEnv(TEnv *env); + void AddHandler(const char *base, const char *regexp, + const char *className, const char *pluginName); + void RemoveHandler(const char *base, const char *regexp = 0); + + TPluginHandler *FindHandler(const char *base, const char *uri); + + void Print(Option_t *opt = "") const; + + ClassDef(TPluginManager,1) // Manager for plugin handlers +}; + +#endif diff --git a/base/src/TPluginManager.cxx b/base/src/TPluginManager.cxx new file mode 100644 index 0000000000000000000000000000000000000000..cd255d50cdc301b01d45947127c5e8b191cf5182 --- /dev/null +++ b/base/src/TPluginManager.cxx @@ -0,0 +1,227 @@ +// @(#)root/base:$Name:$:$Id:$ +// Author: Fons Rademakers 26/1/2002 + +/************************************************************************* + * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers. * + * All rights reserved. * + * * + * For the licensing terms see $ROOTSYS/LICENSE. * + * For the list of contributors see $ROOTSYS/README/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +// // +// TPluginManager // +// // +// This class implements a plugin library manager. It keeps track of // +// a list of plugin handlers. A plugin handler knows which plugin // +// library to load to get a specific class that is used to extend the // +// functionality of a specific base class. For example, to extend the // +// base class TFile to be able to read RFIO files one needs to load // +// the plugin library libRFIO.so which defines the TRFIOFile class. // +// This loading should be triggered when a given URI contains a // +// regular expression defined by the handler. Handlers can be defined // +// for example as resources in the .rootrc file, e.g.: // +// // +// Plugin.TFile: ^rfio: TRFIOFile RFIO // +// Plugin.TSQLServer: ^mysql: TMySQLServer MySQL // +// +Plugin.TSQLServer: ^pgsql: TPgSQLServer PgSQL // +// // +// Plugin handlers can also be registered at run time, e.g.: // +// // +// gROOT->GetPluginManager()->AddHandler("TSQLServer", "^sapdb:", // +// "TSapDBServer", "SapDB"); // +// // +// A list of currently defined handlers can be printed using: // +// // +// gROOT->GetPluginManager()->Print(); // +// // +// The use of the plugin library manager removes all textual references // +// to hard-coded class and library names and the resulting dependencies // +// in the base classes. The plugin manager is used to extend a.o. // +// TFile, TSQLServer, TGrid, etc. functionality. // +// // +////////////////////////////////////////////////////////////////////////// + +#include "TPluginManager.h" +#include "TEnv.h" +#include "TRegexp.h" +#include "TROOT.h" +#include "TList.h" +#include "TOrdCollection.h" + +ClassImp(TPluginHandler) +ClassImp(TPluginManager) + + +//______________________________________________________________________________ +TPluginHandler::TPluginHandler(const char *base, const char *regexp, + const char *className, const char *pluginName) +{ + // Create a plugin handler. Called by TPluginManager. + + fBase = base; + fRegexp = regexp; + fClass = className; + fPlugin = pluginName; +} + +//______________________________________________________________________________ +Bool_t TPluginHandler::CanHandle(const char *base, const char *uri) +{ + // Check if regular expression appears in the URI, if so return kTRUE. + + if (fBase != base) + return kFALSE; + + TRegexp re(fRegexp, kFALSE); + TString ruri = uri; + + if (ruri.Index(re) != kNPOS) + return kTRUE; + return kFALSE; +} + +//______________________________________________________________________________ +Int_t TPluginHandler::LoadPlugin() +{ + // Load the plugin library for this handler. Returns 0 on successful loading + // and -1 in case the library does not exist or in case of error. + + return gROOT->LoadClass(fClass, fPlugin); +} + + +//______________________________________________________________________________ +TPluginManager::~TPluginManager() +{ + // Clean up the plugin manager. + + delete fHandlers; +} + +//______________________________________________________________________________ +void TPluginManager::LoadHandlersFromEnv(TEnv *env) +{ + // Load plugin handlers specified in config file, like: + // Plugin.TFile: ^rfio: TRFIOFile RFIO + // Plugin.TSQLServer: ^mysql: TMySQLServer MySQL + // +Plugin.TSQLServer: ^pgsql: TPgSQLServer PgSQL + // The + allows the extension of an already defined resource (see TEnv). + + if (!env) return; + + TIter next(env->GetTable()); + TEnvRec *er; + + while ((er = (TEnvRec*) next())) { + char *s; + if ((s = strstr(er->GetName(), "Plugin."))) { + const char *val = env->GetValue(er->GetName(), (const char*)0); + if (val) { + Int_t cnt = 0; + char *v = StrDup(val); + s += 7; + while (1) { + TString regexp = strtok(!cnt ? v : 0, ",; "); + if (regexp.IsNull()) break; + TString clss = strtok(0, ",; "); + if (clss.IsNull()) break; + TString plugin = strtok(0, ",; "); + if (plugin.IsNull()) break; + AddHandler(s, regexp, clss, plugin); + cnt++; + } + delete [] v; + } + } + } +} + +//______________________________________________________________________________ +void TPluginManager::AddHandler(const char *base, const char *regexp, + const char *className, const char *pluginName) +{ + // Add plugin handler to the list of handlers. If there is already a + // handler defined for the same base and regexp it will be replaced. + + if (!fHandlers) { + fHandlers = new TList; + fHandlers->IsOwner(); + } + + // make sure there is no previous handler for the same case + RemoveHandler(base, regexp); + + TPluginHandler *h = new TPluginHandler(base, regexp, className, pluginName); + fHandlers->Add(h); +} + +//______________________________________________________________________________ +void TPluginManager::RemoveHandler(const char *base, const char *regexp) +{ + // Remove handler for the specified base class and the specified + // regexp. If regexp=0 remove all handlers for the specified base. + + if (!fHandlers) return; + + TIter next(fHandlers); + TPluginHandler *h; + + while ((h = (TPluginHandler*) next())) { + if (h->fBase == base) { + if (!regexp || h->fRegexp == regexp) { + fHandlers->Remove(h); + delete h; + } + } + } +} + +//______________________________________________________________________________ +TPluginHandler *TPluginManager::FindHandler(const char *base, const char *uri) +{ + // Returns the handler if there exists a handler for the specified URI. + // Returns 0 in case handler is not found. + + if (!fHandlers) return kFALSE; + + TIter next(fHandlers); + TPluginHandler *h; + + while ((h = (TPluginHandler*) next())) { + if (h->CanHandle(base, uri)) { + if (gDebug > 0) + Printf("<TPluginManager::FindHandler>: found plugin for %s", + h->GetClass()); + return h; + } + } + + if (gDebug > 0) + Printf("<TPluginManager::FindHandler>: did not find plugin for handling %s", + uri); + + return 0; +} + +//______________________________________________________________________________ +void TPluginManager::Print(Option_t *) const +{ + // Print list of registered plugin handlers. + + if (!fHandlers) return; + + TIter next(fHandlers); + TPluginHandler *h; + + printf("=====================================================================\n"); + printf("Base Regexp Class Plugin\n"); + printf("=====================================================================\n"); + + while ((h = (TPluginHandler*) next())) { + printf("%-18s %-15s %-18s %s\n", h->fBase.Data(), h->fRegexp.Data(), + h->fClass.Data(), h->fPlugin.Data()); + } + printf("=====================================================================\n\n"); +}