#include "TPluginManager.h"
#include "Varargs.h"
#include "TEnv.h"
#include "TRegexp.h"
#include "TROOT.h"
#include "TSortedList.h"
#include "THashList.h"
#include "THashTable.h"
#include "Varargs.h"
#include "TClass.h"
#include "TInterpreter.h"
#include "TMethod.h"
#include "TMethodArg.h"
#include "TDataType.h"
#include "TMethodCall.h"
#include "TVirtualMutex.h"
#include "TSystem.h"
#include "TObjString.h"
TPluginManager *gPluginMgr;   
ClassImp(TPluginHandler)
TPluginHandler::TPluginHandler(const char *base, const char *regexp,
                               const char *className, const char *pluginName,
                               const char *ctor, const char *origin)
{
   
   fBase     = base;
   fRegexp   = regexp;
   fClass    = className;
   fPlugin   = pluginName;
   fCtor     = ctor;
   fOrigin   = origin;
   fCallEnv  = 0;
   fCanCall  = 0;
   fIsMacro  = kFALSE;
   fIsGlobal = kFALSE;
   if (gROOT->LoadMacro(pluginName, 0, kTRUE) == 0)
      fIsMacro = kTRUE;
   if (fCtor.Contains("::")) {
      fIsGlobal = kTRUE;
      fCtor = fCtor.Strip(TString::kLeading, ':');
   }
}
TPluginHandler::~TPluginHandler()
{
   
   delete fCallEnv;
}
Bool_t TPluginHandler::CanHandle(const char *base, const char *uri)
{
   
   
   if (fBase != base)
      return kFALSE;
   if (!uri || fRegexp == "*")
      return kTRUE;
   Bool_t wildcard = kFALSE;
   if (!fRegexp.MaybeRegexp())
      wildcard = kTRUE;
   TRegexp re(fRegexp, wildcard);
   TString ruri = uri;
   if (ruri.Index(re) != kNPOS)
      return kTRUE;
   return kFALSE;
}
void TPluginHandler::SetupCallEnv()
{
   
   fCanCall = -1;
   
   TClass *cl = TClass::GetClass(fClass);
   if (!cl && !fIsGlobal) {
      Error("SetupCallEnv", "class %s not found in plugin %s", fClass.Data(),
            fPlugin.Data());
      return;
   }
   
   TString method = fCtor(0, fCtor.Index("("));
   TString proto  = fCtor(fCtor.Index("(")+1, fCtor.Index(")")-fCtor.Index("(")-1);
   if (fIsGlobal) {
      cl = 0;
      fMethod = gROOT->GetGlobalFunctionWithPrototype(method, proto, kTRUE);
   } else {
      fMethod = cl->GetMethodWithPrototype(method, proto);
   }
   if (!fMethod) {
      if (fIsGlobal)
         Error("SetupCallEnv", "global function %s not found", method.Data());
      else
         Error("SetupCallEnv", "method %s not found in class %s", method.Data(),
               fClass.Data());
      return;
   }
   if (!fIsGlobal && !(fMethod->Property() & kIsPublic)) {
      Error("SetupCallEnv", "method %s is not public", method.Data());
      return;
   }
   fCallEnv = new TMethodCall;
   fCallEnv->InitWithPrototype(cl, method, proto);
   fCanCall = 1;
   return;
}
Int_t TPluginHandler::CheckPlugin()
{
   
   
   if (fIsMacro) {
      if (TClass::GetClass(fClass)) return 0;
      return gROOT->LoadMacro(fPlugin, 0, kTRUE);
   } else
      return gROOT->LoadClass(fClass, fPlugin, kTRUE);
}
Int_t TPluginHandler::LoadPlugin()
{
   
   
   if (fIsMacro) {
      if (TClass::GetClass(fClass)) return 0;
      return gROOT->LoadMacro(fPlugin);
   } else {
      
      if (gROOT->LoadClass(fClass)) return 0;
      return gROOT->LoadClass(fClass, fPlugin);
   }
}
Long_t TPluginHandler::ExecPlugin(Int_t va_(nargs), ...)
{
   
   
   
   
   
   if (fCtor.IsNull()) {
      Error("ExecPlugin", "no ctor specified for this handler %s", fClass.Data());
      return 0;
   }
   if (!fCallEnv && !fCanCall)
      SetupCallEnv();
   if (fCanCall == -1)
      return 0;
   if (nargs < fMethod->GetNargs() - fMethod->GetNargsOpt() ||
       nargs > fMethod->GetNargs()) {
      Error("ExecPlugin", "nargs (%d) not consistent with expected number of arguments ([%d-%d])",
            nargs, fMethod->GetNargs() - fMethod->GetNargsOpt(),
            fMethod->GetNargs());
      return 0;
   }
   R__LOCKGUARD2(gCINTMutex);
   fCallEnv->ResetParam();
   if (nargs > 0) {
      TIter next(fMethod->GetListOfMethodArgs());
      TMethodArg *arg;
      va_list ap;
      va_start(ap, va_(nargs));
      for (int i = 0; i < nargs; i++) {
         arg = (TMethodArg*) next();
         TString type = arg->GetFullTypeName();
         TDataType *dt = gROOT->GetType(type);
         if (dt)
            type = dt->GetFullTypeName();
         if (arg->Property() & (kIsPointer | kIsArray | kIsReference))
            fCallEnv->SetParam((Long_t) va_arg(ap, void*));
         else if (type == "bool")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));  
         else if (type == "char" || type == "unsigned char")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));  
         else if (type == "short" || type == "unsigned short")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));  
         else if (type == "int" || type == "unsigned int")
            fCallEnv->SetParam((Long_t) va_arg(ap, int));
         else if (type == "long" || type == "unsigned long")
            fCallEnv->SetParam((Long_t) va_arg(ap, long));
         else if (type == "long long")
            fCallEnv->SetParam((Long64_t) va_arg(ap, Long64_t));
         else if (type == "unsigned long long")
            fCallEnv->SetParam((ULong64_t) va_arg(ap, ULong64_t));
         else if (type == "float")
            fCallEnv->SetParam((Double_t) va_arg(ap, double));  
         else if (type == "double")
            fCallEnv->SetParam((Double_t) va_arg(ap, double));
      }
      va_end(ap);
   }
   Long_t ret;
   fCallEnv->Execute(ret);
   return ret;
}
ClassImp(TPluginManager)
TPluginManager::~TPluginManager()
{
   
   delete fHandlers;
   delete fBasesLoaded;
}
void TPluginManager::LoadHandlersFromEnv(TEnv *env)
{
   
   
   
   
   
   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(s, (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;
               TString ctor = strtok(0, ";\"");
               if (!ctor.Contains("("))
                  ctor = strtok(0, ";\"");
               AddHandler(s, regexp, clss, plugin, ctor, "TEnv");
               cnt++;
            }
            delete [] v;
         }
      }
   }
}
void TPluginManager::LoadHandlerMacros(const char *path)
{
   
   void *dirp = gSystem->OpenDirectory(path);
   if (dirp) {
      if (gDebug > 0)
         Info("LoadHandlerMacros", "%s", path);
      TSortedList macros;
      macros.SetOwner();
      const char *f1;
      while ((f1 = gSystem->GetDirEntry(dirp))) {
         TString f = f1;
         if (f[0] == 'P' && f.EndsWith(".C")) {
            const char *p = gSystem->ConcatFileName(path, f);
            if (!gSystem->AccessPathName(p, kReadPermission)) {
               macros.Add(new TObjString(p));
            }
            delete [] p;
         }
      }
      
      TIter next(¯os);
      TObjString *s;
      while ((s = (TObjString*)next())) {
         if (gDebug > 1)
            Info("LoadHandlerMacros", "   plugin macro: %s", s->String().Data());
         Long_t res;
         if ((res = gROOT->Macro(s->String(), 0, kFALSE)) < 0) {
            Error("LoadHandlerMacros", "pluging macro %s returned %ld",
                  s->String().Data(), res);
         }
      }
   }
   gSystem->FreeDirectory(dirp);
}
void TPluginManager::LoadHandlersFromPluginDirs(const char *base)
{
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   
   if (!fBasesLoaded) {
      fBasesLoaded = new THashTable();
      fBasesLoaded->SetOwner();
   }
   TString sbase = base;
   if (sbase != "") {
      sbase.ReplaceAll("::", "@@");
      if (fBasesLoaded->FindObject(sbase))
         return;
      fBasesLoaded->Add(new TObjString(sbase));
   }
   fReadingDirs = kTRUE;
   TString plugindirs = gEnv->GetValue("Root.PluginPath", (char*)0);
#ifdef WIN32
   TObjArray *dirs = plugindirs.Tokenize(";");
#else
   TObjArray *dirs = plugindirs.Tokenize(":");
#endif
   TString d;
   for (Int_t i = 0; i < dirs->GetEntriesFast(); i++) {
      d = ((TObjString*)dirs->At(i))->GetString();
      
      Int_t skip = 0;
      for (Int_t j = 0; j < i; j++) {
         TString pd = ((TObjString*)dirs->At(j))->GetString();
         if (pd == d) {
            skip++;
            break;
         }
      }
      if (!skip) {
         if (sbase != "") {
            const char *p = gSystem->ConcatFileName(d, sbase);
            LoadHandlerMacros(p);
            delete [] p;
         } else {
            void *dirp = gSystem->OpenDirectory(d);
            if (dirp) {
               if (gDebug > 0)
                  Info("LoadHandlersFromPluginDirs", "%s", d.Data());
               const char *f1;
               while ((f1 = gSystem->GetDirEntry(dirp))) {
                  TString f = f1;
                  const char *p = gSystem->ConcatFileName(d, f);
                  LoadHandlerMacros(p);
                  fBasesLoaded->Add(new TObjString(f));
                  delete [] p;
               }
            }
            gSystem->FreeDirectory(dirp);
         }
      }
   }
   delete dirs;
   fReadingDirs = kFALSE;
}
void TPluginManager::AddHandler(const char *base, const char *regexp,
                                const char *className, const char *pluginName,
                                const char *ctor, const char *origin)
{
   
   
   if (!fHandlers) {
      fHandlers = new TList;
      fHandlers->SetOwner();
   }
   
   RemoveHandler(base, regexp);
   if (fReadingDirs)
      origin = gInterpreter->GetCurrentMacroName();
   TPluginHandler *h = new TPluginHandler(base, regexp, className,
                                          pluginName, ctor, origin);
   fHandlers->Add(h);
}
void TPluginManager::RemoveHandler(const char *base, const char *regexp)
{
   
   
   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)
{
   
   
   
   LoadHandlersFromPluginDirs(base);
   TIter next(fHandlers);
   TPluginHandler *h;
   while ((h = (TPluginHandler*) next())) {
      if (h->CanHandle(base, uri)) {
         if (gDebug > 0)
            Info("FindHandler", "found plugin for %s", h->GetClass());
         return h;
      }
   }
   if (gDebug > 2) {
      if (uri)
         Info("FindHandler", "did not find plugin for class %s and uri %s", base, uri);
      else
         Info("FindHandler", "did not find plugin for class %s", base);
   }
   return 0;
}
void TPluginManager::Print(Option_t *opt) const
{
   
   
   if (!fHandlers) return;
   TIter next(fHandlers);
   TPluginHandler *h;
   Int_t cnt = 0, cntmiss = 0;
   Printf("=====================================================================");
   Printf("Base                 Regexp        Class              Plugin");
   Printf("=====================================================================");
   while ((h = (TPluginHandler*) next())) {
      cnt++;
      const char *exist = "";
      if (h->CheckPlugin() == -1) {
         exist = " [*]";
         cntmiss++;
      }
      Printf("%-20s %-13s %-18s %s%s", h->fBase.Data(), h->fRegexp.Data(),
             h->fClass.Data(), h->fPlugin.Data(), exist);
      if (strchr(opt, 'a')) {
         if (strlen(exist) == 0) {
            TString lib = h->fPlugin;
            if (!lib.BeginsWith("lib"))
               lib = "lib" + lib;
            char *path = gSystem->DynamicPathName(lib, kTRUE);
            if (path) Printf("  [Lib:  %s]", path);
            delete [] path;
         }
         Printf("  [Ctor: %s]", h->fCtor.Data());
         Printf("  [origin: %s]", h->fOrigin.Data());
      }
   }
   Printf("=====================================================================");
   Printf("%d plugin handlers registered", cnt);
   Printf("[*] %d %s not available", cntmiss, cntmiss==1 ? "plugin" : "plugins");
   Printf("=====================================================================\n");
}
Int_t TPluginManager::WritePluginMacros(const char *dir, const char *plugin) const
{
   
   
   
   
   const_cast<TPluginManager*>(this)->LoadHandlersFromPluginDirs();
   if (!fHandlers) return 0;
   TString d;
   if (!dir || !dir[0])
      d = ".";
   else
      d = dir;
   if (gSystem->AccessPathName(d, kWritePermission)) {
      Error("WritePluginMacros", "cannot write in directory %s", d.Data());
      return -1;
   }
   TString base;
   Int_t   idx = 0;
   TObjLink *lnk = fHandlers->FirstLink();
   while (lnk) {
      TPluginHandler *h = (TPluginHandler *) lnk->GetObject();
      if (plugin && strcmp(plugin, h->fBase) && strcmp(plugin, h->fClass)) {
         lnk = lnk->Next();
         continue;
      }
      if (base != h->fBase) {
         idx = 10;
         base = h->fBase;
      } else
         idx += 10;
      const char *dd = gSystem->ConcatFileName(d, h->fBase);
      TString sdd = dd;
      sdd.ReplaceAll("::", "@@");
      delete [] dd;
      if (gSystem->AccessPathName(sdd, kWritePermission)) {
         if (gSystem->MakeDirectory(sdd) < 0) {
            Error("WritePluginMacros", "cannot create directory %s", sdd.Data());
            return -1;
         }
      }
      TString fn;
      fn.Form("P%03d_%s.C", idx, h->fClass.Data());
      const char *fd = gSystem->ConcatFileName(sdd, fn);
      FILE *f = fopen(fd, "w");
      fprintf(f, "void P%03d_%s()\n{\n", idx, h->fClass.Data());
      fprintf(f, "   gPluginMgr->AddHandler(\"%s\", \"%s\", \"%s\",\n",
              h->fBase.Data(), h->fRegexp.Data(), h->fClass.Data());
      fprintf(f, "      \"%s\", \"%s\");\n", h->fPlugin.Data(), h->fCtor.Data());
      
      
      TObjLink *lnk2 = lnk->Next();
      while (lnk2) {
         TPluginHandler *h2 = (TPluginHandler *) lnk2->GetObject();
         if (h->fBase != h2->fBase || h->fClass != h2->fClass)
            break;
         fprintf(f, "   gPluginMgr->AddHandler(\"%s\", \"%s\", \"%s\",\n",
                 h2->fBase.Data(), h2->fRegexp.Data(), h2->fClass.Data());
         fprintf(f, "      \"%s\", \"%s\");\n", h2->fPlugin.Data(), h2->fCtor.Data());
         lnk  = lnk2;
         lnk2 = lnk2->Next();
      }
      fprintf(f, "}\n");
      fclose(f);
      delete [] fd;
      lnk = lnk->Next();
   }
   return 0;
}
Last change: Wed Jun 25 08:50:43 2008
Last generated: 2008-06-25 08:50
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.