Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

PluginMgr.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2008 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: PluginMgr.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.31 $       $Date: 2008/03/27 19:36:44 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *  Plugin manager code, loads and registers static and dynamic 
00019  *  plugins, does version checks, etc.
00020  ***************************************************************************/
00021 
00022 #include "PluginMgr.h"
00023 #include "vmddlopen.h"
00024 #include "Inform.h"
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 
00028 #ifdef VMDSTATICPLUGINS
00029 #include "libmolfile_plugin.h"
00030 #endif
00031 
00032 extern "C" {
00033   typedef int (*initfunc)(void);
00034   typedef int (*regfunc)(void *, vmdplugin_register_cb);
00035   typedef int(* finifunc)(void);
00036 }
00037 
00038 // return true of a plugin is the same or older than ones we already have
00039 static int plugincmp(const vmdplugin_t *newp, const vmdplugin_t *oldp) {
00040   int issameorolder = 
00041          !strcmp(newp->type, oldp->type) && 
00042          !strcmp(newp->name, oldp->name) &&
00043          (newp->majorv <= oldp->majorv) &&           // only load new ones
00044          ((newp->majorv < oldp->majorv) ||           // only load new ones
00045           (newp->minorv <= oldp->minorv)) &&
00046          !strcmp(newp->author, oldp->author) &&
00047          (newp->is_reentrant == oldp->is_reentrant); // reentrant comes first
00048 
00049   return issameorolder;
00050 }
00051 
00052 PluginMgr::PluginMgr() {
00053 #ifdef VMDSTATICPLUGINS
00054   MOLFILE_INIT_ALL
00055 #endif
00056 }
00057 
00058 PluginMgr::~PluginMgr() {
00059   int i;
00060   for (i=0; i<handlelist.num(); i++) {
00061     void *ffunc = vmddlsym(handlelist[i], "vmdplugin_fini");
00062     if (ffunc) {
00063       ((finifunc)(ffunc))();
00064     }
00065     vmddlclose(handlelist[i]);
00066   }
00067 #ifdef VMDSTATICPLUGINS
00068   MOLFILE_FINI_ALL
00069 #endif
00070 }
00071 
00072 int PluginMgr::load_static_plugins() {
00073 #ifdef VMDSTATICPLUGINS
00074   num_in_library = 0;
00075   curpath = "statically linked.";
00076   MOLFILE_REGISTER_ALL(this, register_cb)
00077   return 1;
00078 #else
00079   return 0;
00080 #endif
00081 }
00082 
00083 
00084 int PluginMgr::register_cb(void *v, vmdplugin_t *plugin) {
00085   PluginMgr *self = (PluginMgr *)v;
00086 
00087   // check that the ABI version matches
00088   if (plugin->abiversion != vmdplugin_ABIVERSION) {
00089     msgWarn << "Rejecting plugin with incorrect ABI version: "
00090             << self->curpath << sendmsg;
00091     return -1;
00092   }
00093 
00094   // check that there are no null terms in the plugin
00095   if (!plugin->type || !plugin->name || !plugin->author) {
00096     msgWarn << "Rejecting plugin with NULL header values."
00097             << self->curpath << sendmsg;
00098     return -1;
00099   }
00100 
00101   // check new plugin against already-loaded plugins
00102   for (int i=0; i<self->pluginlist.num(); i++) {
00103     if (plugincmp(plugin, self->pluginlist[i])) {
00104       // don't add new plugin if we already have an identical or older version
00105       return 0;
00106     }
00107   }
00108 
00109   self->num_in_library++;
00110   self->pluginlist.append(plugin);
00111   return 0;
00112 }
00113  
00114 int PluginMgr::load_sharedlibrary_plugins(const char *fullpath) {
00115   // Open the dll; try to execute the init function.
00116   void *handle = vmddlopen(fullpath);
00117   if (!handle) {
00118     msgErr << "Unable to open dynamic library '" << fullpath << "'." << sendmsg;
00119     msgErr << vmddlerror() << sendmsg; 
00120     return -1;
00121   }
00122 
00123   if (handlelist.find(handle) >= 0) {
00124     msgWarn << "Already have a handle to the shared library " 
00125             << fullpath << "." << sendmsg;
00126     return 0;
00127   }
00128 
00129   void *ifunc = vmddlsym(handle, "vmdplugin_init");
00130   if (ifunc && ((initfunc)(ifunc))()) {
00131     msgErr << "vmdplugin_init() for " << fullpath 
00132            << " returned an error; plugin(s) not loaded." << sendmsg;
00133     vmddlclose(handle);
00134     return 0;
00135   }
00136   handlelist.append(handle);
00137    
00138   void *registerfunc = vmddlsym(handle, "vmdplugin_register");
00139   num_in_library = 0;
00140   curpath = fullpath;
00141   if (!registerfunc) {
00142     msgWarn << "Didn't find the register function in" << fullpath 
00143             << "; plugin(s) not loaded." << sendmsg;
00144   } else {
00145     // Load plugins from the library.
00146     ((regfunc)registerfunc)(this, register_cb);
00147   } 
00148   return num_in_library;
00149 }
00150 
00151 int PluginMgr::plugins(PluginList &pl, const char *type, const char *name) {
00152   int nfound = 0;
00153   for (int i=0; i<pluginlist.num(); i++) {
00154     vmdplugin_t *p = pluginlist[i]; 
00155     if (type && strcmp(p->type, type)) continue;
00156     if (name && strcmp(p->name, name)) continue;
00157     pl.append(p);
00158     nfound++;
00159   }
00160   return nfound;
00161 }
00162 
00163 #ifdef TEST_PLUGIN_MGR
00164 
00165 int main(int argc, char *argv[]) {
00166   PluginMgr *mgr = new PluginMgr;
00167   for (int i=1; i<argc; i++) {
00168     int rc = mgr->load_sharedlibrary_plugins(argv[i]);
00169     printf("Scanning plugin %s returned %d\n", argv[i], rc);
00170   }
00171   PluginList *pl = mgr->plugins();
00172   printf("found %d plugins\n", pl->num());
00173   for (int i=0; i<pl->num(); i++) {
00174     Plugin *p = (*pl)[i];
00175     printf("type: %s\nname: %s\nauthor: %s\n",
00176       p->type(), p->name(), p->author());
00177     printf("version %d%d\n", p->majorv(), p->minorv());
00178     printf("is%sreentrant\n", p->is_reentrant() ? " " : " not ");
00179   }
00180   delete pl;
00181   delete mgr;
00182   return 0;
00183 }
00184   
00185 #endif

Generated on Mon Oct 13 01:27:48 2008 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002