// @(#)root/base:$Name:  $:$Id: TPluginManager.cxx,v 1.5 2002/02/23 10:35:56 brun Exp $
// 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::CheckPlugin()
{
   // Check if the plugin library for this handler exits. Returns 0 on
   // when it exists and -1 in case the library does not exist.

   return gROOT->LoadClass(fClass, fPlugin, kTRUE);
}

//______________________________________________________________________________
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())) {
      const 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 0;

   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              Pluginn");
   printf("=====================================================================n");

   while ((h = (TPluginHandler*) next())) {
      const char *exist = "";
      if (h->CheckPlugin() == -1)
         exist = " [*]";
      printf("%-18s %-15s %-18s %s%sn", h->fBase.Data(), h->fRegexp.Data(),
             h->fClass.Data(), h->fPlugin.Data(), exist);
   }
   printf("=====================================================================n");
   printf("[*] plugin not availablen");
   printf("=====================================================================n\n");
}


ROOT page - Class index - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.