Field3D
PluginLoader.cpp
Go to the documentation of this file.
00001 //----------------------------------------------------------------------------//
00002 
00003 /*
00004  * Copyright (c) 2009 Sony Pictures Imageworks Inc
00005  *
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  *
00012  * Redistributions of source code must retain the above copyright
00013  * notice, this list of conditions and the following disclaimer.
00014  * Redistributions in binary form must reproduce the above copyright
00015  * notice, this list of conditions and the following disclaimer in the
00016  * documentation and/or other materials provided with the
00017  * distribution.  Neither the name of Sony Pictures Imageworks nor the
00018  * names of its contributors may be used to endorse or promote
00019  * products derived from this software without specific prior written
00020  * permission.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
00026  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00028  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00029  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00030  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00031  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
00033  * OF THE POSSIBILITY OF SUCH DAMAGE.
00034  */
00035 
00036 //----------------------------------------------------------------------------//
00037 
00042 //----------------------------------------------------------------------------//
00043 
00044 #include <dlfcn.h>
00045 #include <sys/types.h>
00046 #include <dirent.h>
00047 #include <stdlib.h>
00048 #include <string>
00049 #include <vector>
00050 #include <stdio.h>
00051 #include <errno.h>
00052 #include <string.h>
00053 
00054 #include <boost/tokenizer.hpp>
00055 
00056 #include "ClassFactory.h"
00057 #include "PluginLoader.h"
00058 
00059 //----------------------------------------------------------------------------//
00060 
00061 using namespace std;
00062 
00063 //----------------------------------------------------------------------------//
00064 // Local namespace
00065 //----------------------------------------------------------------------------//
00066 
00067 namespace {
00068 
00069   void tokenize(const std::string &str, const std::string &delimiters, 
00070                 std::vector<std::string> &retItems)
00071   {
00072     typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
00073     boost::char_separator<char> sep(delimiters.c_str());
00074     Tokenizer tok(str, sep);
00075     for (Tokenizer::iterator i = tok.begin(); i != tok.end(); ++i) {
00076       retItems.push_back(*i);
00077     }
00078   }
00079 
00080 }
00081 
00082 //----------------------------------------------------------------------------//
00083 
00084 FIELD3D_NAMESPACE_OPEN
00085   
00086 //----------------------------------------------------------------------------//
00087 // Static instances
00088 //----------------------------------------------------------------------------//
00089 
00090 std::vector<std::string> PluginLoader::ms_pluginsLoaded;
00091 
00092 //----------------------------------------------------------------------------//
00093 // PluginLoader implementations
00094 //----------------------------------------------------------------------------//
00095 
00096 int filter(std::string &name) 
00097 {
00098   std::string delimiters = ".";
00099   std::vector <std::string> items;
00100   
00101   tokenize(name, delimiters, items);
00102 
00103   if (items.size() == 0) {
00104     return 0;
00105   }
00106   
00107   if (items[items.size() -1] == "so") {
00108     return 1;
00109   }
00110 
00111   return 0;
00112 }
00113 
00114 //----------------------------------------------------------------------------//
00115 
00116 bool getDirSos(std::vector<std::string> &sos, std::string &dir) 
00117 {
00118   struct dirent *dirent;
00119 
00120   const char *ds = dir.c_str();
00121   DIR *dirfd = opendir(ds);
00122   if (!dirfd) {
00123     std::string er =
00124       "Field3D_plugin loader: could not open directory " + dir + "\n"; 
00125     //perror(er.c_str());
00126     return false;
00127   }
00128   
00129   dirent = readdir(dirfd);
00130   while (dirent != NULL) {
00131 
00132     std::string name = dirent->d_name;
00133 
00134     if (filter(name)) {
00135       name = dir + "/" + name;
00136       sos.push_back(name);
00137     }
00138 
00139     dirent = readdir(dirfd);
00140   }
00141 
00142   closedir(dirfd);
00143   
00144   return true;
00145 }
00146 
00147 //----------------------------------------------------------------------------//
00148 
00149 PluginLoader::PluginLoader()
00150 {
00151 
00152 }
00153 
00154 //----------------------------------------------------------------------------//
00155 
00156 PluginLoader::~PluginLoader()
00157 {
00158 
00159 }
00160 
00161 //----------------------------------------------------------------------------//
00162 
00163 void PluginLoader::loadPlugins()
00164 {
00165   // Get environment variable
00166   char *cptr = getenv("FIELD3D_DSO_PATH");
00167   if (!cptr)
00168     return;
00169 
00170   std::string path = cptr;
00171   
00172   // Split paths
00173   std::vector<std::string> paths;
00174   const std::string delimiters = ":";
00175   
00176   tokenize(path, delimiters, paths);
00177 
00178   // For each path
00179   for (unsigned int i = 0; i < paths.size(); i++) {
00180 
00181     // List the contents of the directory
00182     std::vector<std::string> sos;
00183     if (!getDirSos(sos,paths[i])) {
00184       continue;
00185     }
00186     
00187     // Open each file
00188     for (unsigned int j = 0; j < sos.size(); j++) {
00189       std::string sofile = sos[j];
00190       
00191       //First check to see if a plugin of the same name has already been loaded
00192       const std::string pathDelimiter = "/";
00193       std::vector<std::string> pluginName;
00194       tokenize(sofile, pathDelimiter, pluginName);
00195 
00196       bool pluginAlreadyLoaded = false;
00197 
00198       for (unsigned int i = 0; i < ms_pluginsLoaded.size(); i++) {
00199         if (pluginName.size() > 0) {
00200           if (ms_pluginsLoaded[i] == pluginName[pluginName.size() - 1]) {
00201             //This plugin has been loaded so look for another one
00202             //std::cout << ms_pluginsLoaded[i] << " is already loaded\n";
00203             pluginAlreadyLoaded = true;
00204             break;
00205           } 
00206         }
00207       }
00208     
00209       if (pluginAlreadyLoaded) {
00210         continue;
00211       }
00212       
00213       if (pluginName.size() > 0) {
00214         std::string lastName = pluginName[pluginName.size() -1];
00215         ms_pluginsLoaded.push_back(lastName);
00216       }
00217       
00218 
00219       // Attempt to load .so file
00220       void *handle = dlopen(sofile.c_str(), RTLD_GLOBAL|RTLD_NOW);
00221       if (!handle) {
00222         std::cout <<
00223           "Field3D Plugin loader: failed to load plugin: " << dlerror() << "\n";
00224         continue;
00225       }
00226 
00227       // Determine plugin type by looking for one of:
00228       //   registerField3DPlugin()
00229 
00230       int (*fptr)(ClassFactory &) = NULL;
00231       fptr = (int (*)(ClassFactory&))
00232         dlsym(handle,"registerField3DPlugin");
00233       std::string msg = "Initialized Field3D Plugin " + sofile;
00234 
00235       char *dlsymError = dlerror();
00236       if (!dlsymError) {
00237         if (fptr) {
00238           // Call the registration function
00239           int res = (*fptr)(ClassFactory::singleton());
00240           if (!res) {
00241             Msg::print(Msg::SevWarning,
00242                       "failed to init Field3D plugin " + sofile);
00243           } else {
00244             Msg::print(msg);
00245           }
00246         }
00247       } else {
00248         char *debugEnvVar = getenv("FIELD3D_DEBUG");
00249         if (debugEnvVar) {
00250           // debug env var exist, so print warning
00251           Msg::print(Msg::SevWarning,
00252                      "Field3D plugin loader: failed to load "
00253                      "the symbol registerField3DPlugin");
00254         }
00255       }
00256     }
00257   }
00258 }
00259 
00260 //----------------------------------------------------------------------------//
00261 
00262 #if 0
00263 
00264 bool PluginLoader::getDso(char *cptr, const char *dso,
00265                           std::string &dsoPath) 
00266 {
00267 
00268   std::string path = cptr;
00269   
00270   // Split paths
00271   std::vector<std::string> paths;
00272   const std::string delimiters=":";
00273 
00274   Tokenize(path, paths, delimiters);
00275   
00276   // For each path
00277   for (unsigned int i=0; i < paths.size(); i++) {
00278     struct dirent *dirent;
00279 
00280     std::string dir = paths[i];
00281     const char *ds = dir.c_str();
00282     DIR *dirfd = opendir(ds);
00283     if (!dirfd) {
00284       continue;
00285     }
00286   
00287     dirent = readdir(dirfd);
00288     while (dirent != NULL) {
00289 
00290       std::string name = dirent->d_name;
00291 
00292       if (name  == dso) {
00293         dsoPath = dir + "/" + name;
00294         closedir(dirfd);
00295         return true;
00296       }
00297 
00298       dirent = readdir(dirfd);
00299     }
00300     closedir(dirfd);
00301   }
00302 
00303   
00304   return false;
00305   
00306 }  
00307 
00308 //----------------------------------------------------------------------------//
00309 
00310 bool PluginLoader::resolveGlobalsForPlugins(const char *dso) {
00311 
00312   // Get environment variable
00313   char *cptr  = getenv("HOUDINI_DSO_PATH");
00314   if (!cptr)
00315     return false;
00316 
00317   std::string sofile;
00318   if (!getDso(cptr,dso,sofile)) {
00319     std::string dsostring = dso;
00320     Msg::print(dsostring + " is not in HOUDINI_DSO_PATH");
00321     return false;
00322   }
00323   
00324   void *handle = dlopen(sofile.c_str(), RTLD_GLOBAL|RTLD_NOW);
00325 
00326   if (!handle) {
00327     std::cout << "Field3D Plugin loader: failed to load Houdini plugin: "
00328               << sofile << " " << dlerror() << "\n";
00329     return false;
00330   }
00331 
00332 #if 0 
00333   Msg::print("---------------------------------------------------------");
00334   Msg::print("Loaded " + sofile);
00335   Msg::print("---------------------------------------------------------");
00336 #endif
00337   
00338   return true;
00339 
00340 }
00341 
00342 #endif
00343 
00344 //----------------------------------------------------------------------------//
00345 
00346 FIELD3D_NAMESPACE_SOURCE_CLOSE
00347 
00348 //----------------------------------------------------------------------------//