TPluginManager.cxx

Go to the documentation of this file.
00001 // @(#)root/base:$Id: TPluginManager.cxx 38073 2011-02-15 11:48:06Z rdm $
00002 // Author: Fons Rademakers   26/1/2002
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2002, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TPluginManager                                                       //
00015 //                                                                      //
00016 // This class implements a plugin library manager. It keeps track of    //
00017 // a list of plugin handlers. A plugin handler knows which plugin       //
00018 // library to load to get a specific class that is used to extend the   //
00019 // functionality of a specific base class and how to create an object   //
00020 // of this class. For example, to extend the base class TFile to be     //
00021 // able to read RFIO files one needs to load the plugin library         //
00022 // libRFIO.so which defines the TRFIOFile class. This loading should    //
00023 // be triggered when a given URI contains a regular expression defined  //
00024 // by the handler.                                                      //
00025 // Plugin handlers can be defined via macros in a list of plugin        //
00026 // directories. With $ROOTSYS/etc/plugins the default top plugin        //
00027 // directory specified in $ROOTSYS/etc/system.rootrc. Additional        //
00028 // directories can be specified by adding them to the end of the list.  //
00029 // Macros for identical plugin handlers in later directories will       //
00030 // override previous ones (the inverse of normal search path behavior). //
00031 // The macros must have names like <BaseClass>/PX0_<PluginClass>.C,     //
00032 // e.g.:                                                                //
00033 //    TFile/P10_TRFIOFile.C, TSQLServer/P20_TMySQLServer.C, etc.        //
00034 // to allow easy sorting and grouping. If the BaseClass is in a         //
00035 // namespace the directory must have the name NameSpace@@BaseClass as   //
00036 // : is a reserved pathname character on some operating systems.        //
00037 // Macros not beginning with 'P' and ending with ".C" are ignored.      //
00038 // These macros typically look like:                                    //
00039 //                                                                      //
00040 //   void P10_TDCacheFile()                                             //
00041 //   {                                                                  //
00042 //       gPluginMgr->AddHandler("TFile", "^dcache", "TDCacheFile",      //
00043 //          "DCache", "TDCacheFile(const char*,Option_t*)");            //
00044 //   }                                                                  //
00045 //                                                                      //
00046 // Plugin handlers can also be defined via resources in the .rootrc     //
00047 // file. Although now deprecated this method still works for backward   //
00048 // compatibility, e.g.:                                                 //
00049 //                                                                      //
00050 //   Plugin.TFile:       ^rfio:   TRFIOFile    RFIO   "<constructor>"   //
00051 //   Plugin.TSQLServer:  ^mysql:  TMySQLServer MySQL  "<constructor>"   //
00052 //   +Plugin.TSQLServer: ^pgsql:  TPgSQLServer PgSQL  "<constructor>"   //
00053 //   Plugin.TVirtualFitter: *     TFitter      Minuit "TFitter(Int_t)"  //
00054 //                                                                      //
00055 // Where the + in front of Plugin.TSQLServer says that it extends the   //
00056 // existing definition of TSQLServer, useful when there is more than    //
00057 // one plugin that can extend the same base class. The "<constructor>"  //
00058 // should be the constructor or a static method that generates an       //
00059 // instance of the specified class. Global methods should start with    //
00060 // "::" in their name, like "::CreateFitter()".                         //
00061 // Instead of being a shared library a plugin can also be a CINT        //
00062 // script, so instead of libDialog.so one can have Dialog.C.            //
00063 // The * is a placeholder in case there is no need for a URI to         //
00064 // differentiate between different plugins for the same base class.     //
00065 // For the default plugins see $ROOTSYS/etc/system.rootrc.              //
00066 //                                                                      //
00067 // Plugin handlers can also be registered at run time, e.g.:            //
00068 //                                                                      //
00069 //   gPluginMgr->AddHandler("TSQLServer", "^sapdb:",                    //
00070 //                          "TSapDBServer", "SapDB",                    //
00071 //             "TSapDBServer(const char*,const char*, const char*)");   //
00072 //                                                                      //
00073 // A list of currently defined handlers can be printed using:           //
00074 //                                                                      //
00075 //   gPluginMgr->Print(); // use option="a" to see ctors                //
00076 //                                                                      //
00077 // The use of the plugin library manager removes all textual references //
00078 // to hard-coded class and library names and the resulting dependencies //
00079 // in the base classes. The plugin manager is used to extend a.o.       //
00080 // TFile, TSQLServer, TGrid, etc. functionality.                        //
00081 //                                                                      //
00082 //////////////////////////////////////////////////////////////////////////
00083 
00084 #include "TPluginManager.h"
00085 #include "Varargs.h"
00086 #include "TEnv.h"
00087 #include "TRegexp.h"
00088 #include "TROOT.h"
00089 #include "TSortedList.h"
00090 #include "THashList.h"
00091 #include "THashTable.h"
00092 #include "Varargs.h"
00093 #include "TClass.h"
00094 #include "TInterpreter.h"
00095 #include "TMethod.h"
00096 #include "TMethodArg.h"
00097 #include "TDataType.h"
00098 #include "TMethodCall.h"
00099 #include "TVirtualMutex.h"
00100 #include "TSystem.h"
00101 #include "TObjString.h"
00102 
00103 
00104 TPluginManager *gPluginMgr;   // main plugin manager created in TROOT
00105 
00106 
00107 ClassImp(TPluginHandler)
00108 
00109 //______________________________________________________________________________
00110 TPluginHandler::TPluginHandler(const char *base, const char *regexp,
00111                                const char *className, const char *pluginName,
00112                                const char *ctor, const char *origin):
00113    fBase(base),
00114    fRegexp(regexp),
00115    fClass(className),
00116    fPlugin(pluginName),
00117    fCtor(ctor),
00118    fOrigin(origin),
00119    fCallEnv(0),
00120    fMethod(0),
00121    fCanCall(0),
00122    fIsMacro(kFALSE),
00123    fIsGlobal(kFALSE)
00124 {
00125    // Create a plugin handler. Called by TPluginManager.
00126 
00127    if (fPlugin.EndsWith(".C") && gROOT->LoadMacro(fPlugin, 0, kTRUE) == 0)
00128       fIsMacro = kTRUE;
00129 
00130    if (fCtor.Contains("::")) {
00131       fIsGlobal = kTRUE;
00132       fCtor = fCtor.Strip(TString::kLeading, ':');
00133    }
00134 }
00135 
00136 //______________________________________________________________________________
00137 TPluginHandler::~TPluginHandler()
00138 {
00139    // Cleanup plugin handler object.
00140 
00141    delete fCallEnv;
00142 }
00143 
00144 //______________________________________________________________________________
00145 Bool_t TPluginHandler::CanHandle(const char *base, const char *uri)
00146 {
00147    // Check if regular expression appears in the URI, if so return kTRUE.
00148    // If URI = 0 always return kTRUE.
00149 
00150    if (fBase != base)
00151       return kFALSE;
00152 
00153    if (!uri || fRegexp == "*")
00154       return kTRUE;
00155 
00156    Bool_t wildcard = kFALSE;
00157    if (!fRegexp.MaybeRegexp())
00158       wildcard = kTRUE;
00159 
00160    TRegexp re(fRegexp, wildcard);
00161    TString ruri = uri;
00162 
00163    if (ruri.Index(re) != kNPOS)
00164       return kTRUE;
00165    return kFALSE;
00166 }
00167 
00168 //______________________________________________________________________________
00169 void TPluginHandler::SetupCallEnv()
00170 {
00171    // Setup ctor or static method call environment.
00172 
00173    fCanCall = -1;
00174 
00175    // check if class exists
00176    TClass *cl = TClass::GetClass(fClass);
00177    if (!cl && !fIsGlobal) {
00178       Error("SetupCallEnv", "class %s not found in plugin %s", fClass.Data(),
00179             fPlugin.Data());
00180       return;
00181    }
00182 
00183    // split method and prototype strings
00184    TString method = fCtor(0, fCtor.Index("("));
00185    TString proto  = fCtor(fCtor.Index("(")+1, fCtor.Index(")")-fCtor.Index("(")-1);
00186 
00187    if (fIsGlobal) {
00188       cl = 0;
00189       fMethod = gROOT->GetGlobalFunctionWithPrototype(method, proto, kTRUE);
00190    } else {
00191       fMethod = cl->GetMethodWithPrototype(method, proto);
00192    }
00193 
00194    if (!fMethod) {
00195       if (fIsGlobal)
00196          Error("SetupCallEnv", "global function %s not found", method.Data());
00197       else
00198          Error("SetupCallEnv", "method %s not found in class %s", method.Data(),
00199                fClass.Data());
00200       return;
00201    }
00202 
00203    if (!fIsGlobal && !(fMethod->Property() & kIsPublic)) {
00204       Error("SetupCallEnv", "method %s is not public", method.Data());
00205       return;
00206    }
00207 
00208    fCallEnv = new TMethodCall;
00209    fCallEnv->InitWithPrototype(cl, method, proto);
00210 
00211    fCanCall = 1;
00212 
00213    return;
00214 }
00215 
00216 //______________________________________________________________________________
00217 Int_t TPluginHandler::CheckPlugin() const
00218 {
00219    // Check if the plugin library for this handler exits. Returns 0
00220    // when it exists and -1 in case the plugin does not exist.
00221 
00222    if (fIsMacro) {
00223       if (TClass::GetClass(fClass)) return 0;
00224       return gROOT->LoadMacro(fPlugin, 0, kTRUE);
00225    } else
00226       return gROOT->LoadClass(fClass, fPlugin, kTRUE);
00227 }
00228 
00229 //______________________________________________________________________________
00230 Int_t TPluginHandler::LoadPlugin()
00231 {
00232    // Load the plugin library for this handler. Returns 0 on successful loading
00233    // and -1 in case the library does not exist or in case of error.
00234 
00235    if (fIsMacro) {
00236       if (TClass::GetClass(fClass)) return 0;
00237       return gROOT->LoadMacro(fPlugin);
00238    } else {
00239       // first call also loads dependent libraries declared via the rootmap file
00240       if (gROOT->LoadClass(fClass)) return 0;
00241       return gROOT->LoadClass(fClass, fPlugin);
00242    }
00243 }
00244 
00245 //______________________________________________________________________________
00246 Long_t TPluginHandler::ExecPlugin(Int_t va_(nargs), ...)
00247 {
00248    // Execute ctor for this plugin and return pointer to object of specific
00249    // class. User must cast the returned long to the correct class.
00250    // This method accepts a variable number of arguments to be passed
00251    // to the ctor, where nargs is the number of arguments, followed
00252    // by nargs arguments. Returns 0 in case of error.
00253 
00254    if (fCtor.IsNull()) {
00255       Error("ExecPlugin", "no ctor specified for this handler %s", fClass.Data());
00256       return 0;
00257    }
00258 
00259    if (!fCallEnv && !fCanCall)
00260       SetupCallEnv();
00261 
00262    if (fCanCall == -1)
00263       return 0;
00264 
00265    if (nargs < fMethod->GetNargs() - fMethod->GetNargsOpt() ||
00266        nargs > fMethod->GetNargs()) {
00267       Error("ExecPlugin", "nargs (%d) not consistent with expected number of arguments ([%d-%d])",
00268             nargs, fMethod->GetNargs() - fMethod->GetNargsOpt(),
00269             fMethod->GetNargs());
00270       return 0;
00271    }
00272 
00273    R__LOCKGUARD2(gCINTMutex);
00274 
00275    fCallEnv->ResetParam();
00276 
00277    if (nargs > 0) {
00278       TIter next(fMethod->GetListOfMethodArgs());
00279       TMethodArg *arg;
00280 
00281       va_list ap;
00282       va_start(ap, va_(nargs));
00283 
00284       for (int i = 0; i < nargs; i++) {
00285          arg = (TMethodArg*) next();
00286          TString type = arg->GetFullTypeName();
00287          TDataType *dt = gROOT->GetType(type);
00288          if (dt)
00289             type = dt->GetFullTypeName();
00290          if (arg->Property() & (kIsPointer | kIsArray | kIsReference))
00291             fCallEnv->SetParam((Long_t) va_arg(ap, void*));
00292          else if (type == "bool")
00293             fCallEnv->SetParam((Long_t) va_arg(ap, int));  // bool is promoted to int
00294          else if (type == "char" || type == "unsigned char")
00295             fCallEnv->SetParam((Long_t) va_arg(ap, int));  // char is promoted to int
00296          else if (type == "short" || type == "unsigned short")
00297             fCallEnv->SetParam((Long_t) va_arg(ap, int));  // short is promoted to int
00298          else if (type == "int" || type == "unsigned int")
00299             fCallEnv->SetParam((Long_t) va_arg(ap, int));
00300          else if (type == "long" || type == "unsigned long")
00301             fCallEnv->SetParam((Long_t) va_arg(ap, long));
00302          else if (type == "long long")
00303             fCallEnv->SetParam((Long64_t) va_arg(ap, Long64_t));
00304          else if (type == "unsigned long long")
00305             fCallEnv->SetParam((ULong64_t) va_arg(ap, ULong64_t));
00306          else if (type == "float")
00307             fCallEnv->SetParam((Double_t) va_arg(ap, double));  // float is promoted to double
00308          else if (type == "double")
00309             fCallEnv->SetParam((Double_t) va_arg(ap, double));
00310       }
00311 
00312       va_end(ap);
00313    }
00314 
00315    Long_t ret;
00316    fCallEnv->Execute(ret);
00317 
00318    return ret;
00319 }
00320 
00321 //______________________________________________________________________________
00322 void TPluginHandler::Print(Option_t *opt) const
00323 {
00324    // Print info about the plugin handler. If option is "a" print
00325    // also the ctor's that will be used.
00326 
00327    const char *exist = "";
00328    if (CheckPlugin() == -1)
00329       exist = " [*]";
00330 
00331    Printf("%-20s %-13s %-18s %s%s", fBase.Data(), fRegexp.Data(),
00332           fClass.Data(), fPlugin.Data(), exist);
00333    if (strchr(opt, 'a')) {
00334       if (strlen(exist) == 0) {
00335          TString lib = fPlugin;
00336          if (!lib.BeginsWith("lib"))
00337             lib = "lib" + lib;
00338          char *path = gSystem->DynamicPathName(lib, kTRUE);
00339          if (path) Printf("  [Lib:  %s]", path);
00340          delete [] path;
00341       }
00342       Printf("  [Ctor: %s]", fCtor.Data());
00343       Printf("  [origin: %s]", fOrigin.Data());
00344    }
00345 }
00346 
00347 
00348 ClassImp(TPluginManager)
00349 
00350 //______________________________________________________________________________
00351 TPluginManager::~TPluginManager()
00352 {
00353    // Clean up the plugin manager.
00354 
00355    delete fHandlers;
00356    delete fBasesLoaded;
00357 }
00358 
00359 //______________________________________________________________________________
00360 void TPluginManager::LoadHandlersFromEnv(TEnv *env)
00361 {
00362    // Load plugin handlers specified in config file, like:
00363    //    Plugin.TFile:       ^rfio:    TRFIOFile      RFIO  "TRFIOFile(...)"
00364    //    Plugin.TSQLServer:  ^mysql:   TMySQLServer   MySQL "TMySQLServer(...)"
00365    //    +Plugin.TSQLServer: ^pgsql:   TPgSQLServer   PgSQL "TPgSQLServer(...)"
00366    // The + allows the extension of an already defined resource (see TEnv).
00367 
00368    if (!env) return;
00369 
00370    TIter next(env->GetTable());
00371    TEnvRec *er;
00372 
00373    while ((er = (TEnvRec*) next())) {
00374       const char *s;
00375       if ((s = strstr(er->GetName(), "Plugin."))) {
00376          // use s, i.e. skip possible OS and application prefix to Plugin.
00377          // so that GetValue() takes properly care of returning the value
00378          // for the specified OS and/or application
00379          const char *val = env->GetValue(s, (const char*)0);
00380          if (val) {
00381             Int_t cnt = 0;
00382             char *v = StrDup(val);
00383             s += 7;
00384             while (1) {
00385                TString regexp = strtok(!cnt ? v : 0, "; ");
00386                if (regexp.IsNull()) break;
00387                TString clss   = strtok(0, "; ");
00388                if (clss.IsNull()) break;
00389                TString plugin = strtok(0, "; ");
00390                if (plugin.IsNull()) break;
00391                TString ctor = strtok(0, ";\"");
00392                if (!ctor.Contains("("))
00393                   ctor = strtok(0, ";\"");
00394                AddHandler(s, regexp, clss, plugin, ctor, "TEnv");
00395                cnt++;
00396             }
00397             delete [] v;
00398          }
00399       }
00400    }
00401 }
00402 
00403 //______________________________________________________________________________
00404 void TPluginManager::LoadHandlerMacros(const char *path)
00405 {
00406    // Load all plugin macros from the specified path/base directory.
00407 
00408    void *dirp = gSystem->OpenDirectory(path);
00409    if (dirp) {
00410       if (gDebug > 0)
00411          Info("LoadHandlerMacros", "%s", path);
00412       TSortedList macros;
00413       macros.SetOwner();
00414       const char *f1;
00415       while ((f1 = gSystem->GetDirEntry(dirp))) {
00416          TString f = f1;
00417          if (f[0] == 'P' && f.EndsWith(".C")) {
00418             const char *p = gSystem->ConcatFileName(path, f);
00419             if (!gSystem->AccessPathName(p, kReadPermission)) {
00420                macros.Add(new TObjString(p));
00421             }
00422             delete [] p;
00423          }
00424       }
00425       // load macros in alphabetical order
00426       TIter next(&macros);
00427       TObjString *s;
00428       while ((s = (TObjString*)next())) {
00429          if (gDebug > 1)
00430             Info("LoadHandlerMacros", "   plugin macro: %s", s->String().Data());
00431          Long_t res;
00432          if ((res = gROOT->Macro(s->String(), 0, kFALSE)) < 0) {
00433             Error("LoadHandlerMacros", "pluging macro %s returned %ld",
00434                   s->String().Data(), res);
00435          }
00436       }
00437    }
00438    gSystem->FreeDirectory(dirp);
00439 }
00440 
00441 //______________________________________________________________________________
00442 void TPluginManager::LoadHandlersFromPluginDirs(const char *base)
00443 {
00444    // Load plugin handlers specified via macros in a list of plugin
00445    // directories. The $ROOTSYS/etc/plugins is the default top plugin directory
00446    // specified in $ROOTSYS/etc/system.rootrc. The macros must have names
00447    // like <BaseClass>/PX0_<PluginClass>.C, e.g.:
00448    //    TFile/P10_TRFIOFile.C, TSQLServer/P20_TMySQLServer.C, etc.
00449    // to allow easy sorting and grouping. If the BaseClass is in a namespace
00450    // the directory must have the name NameSpace@@BaseClass as : is a reserved
00451    // pathname character on some operating systems. Macros not beginning with
00452    // 'P' and ending with ".C" are ignored. If base is specified only plugin
00453    // macros for that base class are loaded. The macros typically
00454    // should look like:
00455    //   void P10_TDCacheFile()
00456    //   {
00457    //       gPluginMgr->AddHandler("TFile", "^dcache", "TDCacheFile",
00458    //          "DCache", "TDCacheFile(const char*,Option_t*,const char*,Int_t)");
00459    //   }
00460    // In general these macros should not cause side effects, by changing global
00461    // ROOT state via, e.g. gSystem calls, etc. However, in specific cases
00462    // this might be useful, e.g. adding a library search path, adding a specific
00463    // dependency, check on some OS or ROOT capability or downloading
00464    // of the plugin.
00465 
00466    if (!fBasesLoaded) {
00467       fBasesLoaded = new THashTable();
00468       fBasesLoaded->SetOwner();
00469    }
00470    TString sbase = base;
00471    if (sbase != "") {
00472       sbase.ReplaceAll("::", "@@");
00473       if (fBasesLoaded->FindObject(sbase))
00474          return;
00475       fBasesLoaded->Add(new TObjString(sbase));
00476    }
00477 
00478    fReadingDirs = kTRUE;
00479 
00480    TString plugindirs = gEnv->GetValue("Root.PluginPath", (char*)0);
00481 #ifdef WIN32
00482    TObjArray *dirs = plugindirs.Tokenize(";");
00483 #else
00484    TObjArray *dirs = plugindirs.Tokenize(":");
00485 #endif
00486    TString d;
00487    for (Int_t i = 0; i < dirs->GetEntriesFast(); i++) {
00488       d = ((TObjString*)dirs->At(i))->GetString();
00489       // check if directory already scanned
00490       Int_t skip = 0;
00491       for (Int_t j = 0; j < i; j++) {
00492          TString pd = ((TObjString*)dirs->At(j))->GetString();
00493          if (pd == d) {
00494             skip++;
00495             break;
00496          }
00497       }
00498       if (!skip) {
00499          if (sbase != "") {
00500             const char *p = gSystem->ConcatFileName(d, sbase);
00501             LoadHandlerMacros(p);
00502             delete [] p;
00503          } else {
00504             void *dirp = gSystem->OpenDirectory(d);
00505             if (dirp) {
00506                if (gDebug > 0)
00507                   Info("LoadHandlersFromPluginDirs", "%s", d.Data());
00508                const char *f1;
00509                while ((f1 = gSystem->GetDirEntry(dirp))) {
00510                   TString f = f1;
00511                   const char *p = gSystem->ConcatFileName(d, f);
00512                   LoadHandlerMacros(p);
00513                   fBasesLoaded->Add(new TObjString(f));
00514                   delete [] p;
00515                }
00516             }
00517             gSystem->FreeDirectory(dirp);
00518          }
00519       }
00520    }
00521 
00522    delete dirs;
00523    fReadingDirs = kFALSE;
00524 }
00525 
00526 //______________________________________________________________________________
00527 void TPluginManager::AddHandler(const char *base, const char *regexp,
00528                                 const char *className, const char *pluginName,
00529                                 const char *ctor, const char *origin)
00530 {
00531    // Add plugin handler to the list of handlers. If there is already a
00532    // handler defined for the same base and regexp it will be replaced.
00533 
00534    if (!fHandlers) {
00535       fHandlers = new TList;
00536       fHandlers->SetOwner();
00537    }
00538 
00539    // make sure there is no previous handler for the same case
00540    RemoveHandler(base, regexp);
00541 
00542    if (fReadingDirs)
00543       origin = gInterpreter->GetCurrentMacroName();
00544 
00545    TPluginHandler *h = new TPluginHandler(base, regexp, className,
00546                                           pluginName, ctor, origin);
00547    fHandlers->Add(h);
00548 }
00549 
00550 //______________________________________________________________________________
00551 void TPluginManager::RemoveHandler(const char *base, const char *regexp)
00552 {
00553    // Remove handler for the specified base class and the specified
00554    // regexp. If regexp=0 remove all handlers for the specified base.
00555 
00556    if (!fHandlers) return;
00557 
00558    TIter next(fHandlers);
00559    TPluginHandler *h;
00560 
00561    while ((h = (TPluginHandler*) next())) {
00562       if (h->fBase == base) {
00563          if (!regexp || h->fRegexp == regexp) {
00564             fHandlers->Remove(h);
00565             delete h;
00566          }
00567       }
00568    }
00569 }
00570 
00571 //______________________________________________________________________________
00572 TPluginHandler *TPluginManager::FindHandler(const char *base, const char *uri)
00573 {
00574    // Returns the handler if there exists a handler for the specified URI.
00575    // The uri can be 0 in which case the first matching plugin handler
00576    // will be returned. Returns 0 in case handler is not found.
00577 
00578    LoadHandlersFromPluginDirs(base);
00579 
00580    TIter next(fHandlers);
00581    TPluginHandler *h;
00582 
00583    while ((h = (TPluginHandler*) next())) {
00584       if (h->CanHandle(base, uri)) {
00585          if (gDebug > 0)
00586             Info("FindHandler", "found plugin for %s", h->GetClass());
00587          return h;
00588       }
00589    }
00590 
00591    if (gDebug > 2) {
00592       if (uri)
00593          Info("FindHandler", "did not find plugin for class %s and uri %s", base, uri);
00594       else
00595          Info("FindHandler", "did not find plugin for class %s", base);
00596    }
00597 
00598    return 0;
00599 }
00600 
00601 //______________________________________________________________________________
00602 void TPluginManager::Print(Option_t *opt) const
00603 {
00604    // Print list of registered plugin handlers. If option is "a" print
00605    // also the ctor's that will be used.
00606 
00607    if (!fHandlers) return;
00608 
00609    TIter next(fHandlers);
00610    TPluginHandler *h;
00611    Int_t cnt = 0, cntmiss = 0;
00612 
00613    Printf("=====================================================================");
00614    Printf("Base                 Regexp        Class              Plugin");
00615    Printf("=====================================================================");
00616 
00617    while ((h = (TPluginHandler*) next())) {
00618       cnt++;
00619       h->Print(opt);
00620       if (h->CheckPlugin() == -1)
00621          cntmiss++;
00622    }
00623    Printf("=====================================================================");
00624    Printf("%d plugin handlers registered", cnt);
00625    Printf("[*] %d %s not available", cntmiss, cntmiss==1 ? "plugin" : "plugins");
00626    Printf("=====================================================================\n");
00627 }
00628 
00629 //______________________________________________________________________________
00630 Int_t TPluginManager::WritePluginMacros(const char *dir, const char *plugin) const
00631 {
00632    // Write in the specified directory the plugin macros. If plugin is specified
00633    // and if it is a base class all macros for that base will be written. If it
00634    // is a plugin class name, only that one macro will be written. If plugin
00635    // is 0 all macros are written. Returns -1 if dir does not exist, 0 otherwise.
00636 
00637    const_cast<TPluginManager*>(this)->LoadHandlersFromPluginDirs();
00638 
00639    if (!fHandlers) return 0;
00640 
00641    TString d;
00642    if (!dir || !dir[0])
00643       d = ".";
00644    else
00645       d = dir;
00646 
00647    if (gSystem->AccessPathName(d, kWritePermission)) {
00648       Error("WritePluginMacros", "cannot write in directory %s", d.Data());
00649       return -1;
00650    }
00651 
00652    TString base;
00653    Int_t   idx = 0;
00654 
00655    TObjLink *lnk = fHandlers->FirstLink();
00656    while (lnk) {
00657       TPluginHandler *h = (TPluginHandler *) lnk->GetObject();
00658       if (plugin && strcmp(plugin, h->fBase) && strcmp(plugin, h->fClass)) {
00659          lnk = lnk->Next();
00660          continue;
00661       }
00662       if (base != h->fBase) {
00663          idx = 10;
00664          base = h->fBase;
00665       } else
00666          idx += 10;
00667       const char *dd = gSystem->ConcatFileName(d, h->fBase);
00668       TString sdd = dd;
00669       sdd.ReplaceAll("::", "@@");
00670       delete [] dd;
00671       if (gSystem->AccessPathName(sdd, kWritePermission)) {
00672          if (gSystem->MakeDirectory(sdd) < 0) {
00673             Error("WritePluginMacros", "cannot create directory %s", sdd.Data());
00674             return -1;
00675          }
00676       }
00677       TString fn;
00678       fn.Form("P%03d_%s.C", idx, h->fClass.Data());
00679       const char *fd = gSystem->ConcatFileName(sdd, fn);
00680       FILE *f = fopen(fd, "w");
00681       fprintf(f, "void P%03d_%s()\n{\n", idx, h->fClass.Data());
00682       fprintf(f, "   gPluginMgr->AddHandler(\"%s\", \"%s\", \"%s\",\n",
00683               h->fBase.Data(), h->fRegexp.Data(), h->fClass.Data());
00684       fprintf(f, "      \"%s\", \"%s\");\n", h->fPlugin.Data(), h->fCtor.Data());
00685 
00686       // check for different regexps cases for the same base + class and
00687       // put them all in the same macro
00688       TObjLink *lnk2 = lnk->Next();
00689       while (lnk2) {
00690          TPluginHandler *h2 = (TPluginHandler *) lnk2->GetObject();
00691          if (h->fBase != h2->fBase || h->fClass != h2->fClass)
00692             break;
00693 
00694          fprintf(f, "   gPluginMgr->AddHandler(\"%s\", \"%s\", \"%s\",\n",
00695                  h2->fBase.Data(), h2->fRegexp.Data(), h2->fClass.Data());
00696          fprintf(f, "      \"%s\", \"%s\");\n", h2->fPlugin.Data(), h2->fCtor.Data());
00697 
00698          lnk  = lnk2;
00699          lnk2 = lnk2->Next();
00700       }
00701       fprintf(f, "}\n");
00702       fclose(f);
00703       delete [] fd;
00704       lnk = lnk->Next();
00705    }
00706    return 0;
00707 }
00708 
00709 //______________________________________________________________________________
00710 Int_t TPluginManager::WritePluginRecords(const char *envFile, const char *plugin) const
00711 {
00712    // Write in the specified environment config file the plugin records. If
00713    // plugin is specified and if it is a base class all records for that
00714    // base will be written. If it is a plugin class name, only that one
00715    // record will be written. If plugin is 0 all macros are written.
00716    // If envFile is 0 or "" the records are written to stdout.
00717    // Returns -1 if envFile cannot be created or opened, 0 otherwise.
00718 
00719    const_cast<TPluginManager*>(this)->LoadHandlersFromPluginDirs();
00720 
00721    if (!fHandlers) return 0;
00722 
00723    FILE *fd;
00724    if (!envFile || !envFile[0])
00725       fd = stdout;
00726    else
00727       fd = fopen(envFile, "w+");
00728 
00729    if (!fd) {
00730       Error("WritePluginRecords", "error opening file %s", envFile);
00731       return -1;
00732    }
00733 
00734    TString base, base2;
00735    Int_t   idx = 0;
00736 
00737    TObjLink *lnk = fHandlers->FirstLink();
00738    while (lnk) {
00739       TPluginHandler *h = (TPluginHandler *) lnk->GetObject();
00740       if (plugin && strcmp(plugin, h->fBase) && strcmp(plugin, h->fClass)) {
00741          lnk = lnk->Next();
00742          continue;
00743       }
00744       if (base != h->fBase) {
00745          idx = 1;
00746          base = h->fBase;
00747          base2 = base;
00748          base2.ReplaceAll("::", "@@");
00749       } else
00750          idx += 1;
00751 
00752       if (idx == 1)
00753          fprintf(fd, "Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h->fRegexp.Data(),
00754                  h->fClass.Data(), h->fPlugin.Data(), h->fCtor.Data());
00755       else
00756          fprintf(fd, "+Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h->fRegexp.Data(),
00757                  h->fClass.Data(), h->fPlugin.Data(), h->fCtor.Data());
00758 
00759       // check for different regexps cases for the same base + class and
00760       // put them all in the same macro
00761       TObjLink *lnk2 = lnk->Next();
00762       while (lnk2) {
00763          TPluginHandler *h2 = (TPluginHandler *) lnk2->GetObject();
00764          if (h->fBase != h2->fBase || h->fClass != h2->fClass)
00765             break;
00766 
00767          fprintf(fd, "+Plugin.%s: %s %s %s \"%s\"\n", base2.Data(), h2->fRegexp.Data(),
00768                  h2->fClass.Data(), h2->fPlugin.Data(), h2->fCtor.Data());
00769 
00770          lnk  = lnk2;
00771          lnk2 = lnk2->Next();
00772       }
00773       lnk = lnk->Next();
00774    }
00775 
00776    if (envFile && envFile[0])
00777       fclose(fd);
00778 
00779    return 0;
00780 }

Generated on Tue Jul 5 14:11:21 2011 for ROOT_528-00b_version by  doxygen 1.5.1