Field3D
PluginLoader.cpp
Go to the documentation of this file.
1 //----------------------------------------------------------------------------//
2 
3 /*
4  * Copyright (c) 2009 Sony Pictures Imageworks Inc
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the
17  * distribution. Neither the name of Sony Pictures Imageworks nor the
18  * names of its contributors may be used to endorse or promote
19  * products derived from this software without specific prior written
20  * permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
31  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33  * OF THE POSSIBILITY OF SUCH DAMAGE.
34  */
35 
36 //----------------------------------------------------------------------------//
37 
42 //----------------------------------------------------------------------------//
43 
44 #include <dlfcn.h>
45 #include <sys/types.h>
46 #include <dirent.h>
47 #include <stdlib.h>
48 #include <string>
49 #include <vector>
50 #include <stdio.h>
51 #include <errno.h>
52 #include <string.h>
53 
54 #include <boost/tokenizer.hpp>
55 
56 #include "ClassFactory.h"
57 #include "PluginLoader.h"
58 
59 //----------------------------------------------------------------------------//
60 
61 using namespace std;
62 
63 //----------------------------------------------------------------------------//
64 // Local namespace
65 //----------------------------------------------------------------------------//
66 
67 namespace {
68 
69  void tokenize(const std::string &str, const std::string &delimiters,
70  std::vector<std::string> &retItems)
71  {
72  typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
73  boost::char_separator<char> sep(delimiters.c_str());
74  Tokenizer tok(str, sep);
75  for (Tokenizer::iterator i = tok.begin(); i != tok.end(); ++i) {
76  retItems.push_back(*i);
77  }
78  }
79 
80 }
81 
82 //----------------------------------------------------------------------------//
83 
85 
86 //----------------------------------------------------------------------------//
87 // Static instances
88 //----------------------------------------------------------------------------//
89 
90 std::vector<std::string> PluginLoader::ms_pluginsLoaded;
91 
92 //----------------------------------------------------------------------------//
93 // PluginLoader implementations
94 //----------------------------------------------------------------------------//
95 
96 int filter(std::string &name)
97 {
98  std::string delimiters = ".";
99  std::vector <std::string> items;
100 
101  tokenize(name, delimiters, items);
102 
103  if (items.size() == 0) {
104  return 0;
105  }
106 
107  if (items[items.size() -1] == "so") {
108  return 1;
109  }
110 
111  return 0;
112 }
113 
114 //----------------------------------------------------------------------------//
115 
116 bool getDirSos(std::vector<std::string> &sos, std::string &dir)
117 {
118  struct dirent *dirent;
119 
120  const char *ds = dir.c_str();
121  DIR *dirfd = opendir(ds);
122  if (!dirfd) {
123  std::string er =
124  "Field3D_plugin loader: could not open directory " + dir + "\n";
125  //perror(er.c_str());
126  return false;
127  }
128 
129  dirent = readdir(dirfd);
130  while (dirent != NULL) {
131 
132  std::string name = dirent->d_name;
133 
134  if (filter(name)) {
135  name = dir + "/" + name;
136  sos.push_back(name);
137  }
138 
139  dirent = readdir(dirfd);
140  }
141 
142  closedir(dirfd);
143 
144  return true;
145 }
146 
147 //----------------------------------------------------------------------------//
148 
150 {
151 
152 }
153 
154 //----------------------------------------------------------------------------//
155 
157 {
158 
159 }
160 
161 //----------------------------------------------------------------------------//
162 
164 {
165  // Get environment variable
166  char *cptr = getenv("FIELD3D_DSO_PATH");
167  if (!cptr)
168  return;
169 
170  std::string path = cptr;
171 
172  // Split paths
173  std::vector<std::string> paths;
174  const std::string delimiters = ":";
175 
176  tokenize(path, delimiters, paths);
177 
178  // For each path
179  for (unsigned int i = 0; i < paths.size(); i++) {
180 
181  // List the contents of the directory
182  std::vector<std::string> sos;
183  if (!getDirSos(sos,paths[i])) {
184  continue;
185  }
186 
187  // Open each file
188  for (unsigned int j = 0; j < sos.size(); j++) {
189  std::string sofile = sos[j];
190 
191  //First check to see if a plugin of the same name has already been loaded
192  const std::string pathDelimiter = "/";
193  std::vector<std::string> pluginName;
194  tokenize(sofile, pathDelimiter, pluginName);
195 
196  bool pluginAlreadyLoaded = false;
197 
198  for (unsigned int i = 0; i < ms_pluginsLoaded.size(); i++) {
199  if (pluginName.size() > 0) {
200  if (ms_pluginsLoaded[i] == pluginName[pluginName.size() - 1]) {
201  //This plugin has been loaded so look for another one
202  //std::cout << ms_pluginsLoaded[i] << " is already loaded\n";
203  pluginAlreadyLoaded = true;
204  break;
205  }
206  }
207  }
208 
209  if (pluginAlreadyLoaded) {
210  continue;
211  }
212 
213  if (pluginName.size() > 0) {
214  std::string lastName = pluginName[pluginName.size() -1];
215  ms_pluginsLoaded.push_back(lastName);
216  }
217 
218 
219  // Attempt to load .so file
220  void *handle = dlopen(sofile.c_str(), RTLD_GLOBAL|RTLD_NOW);
221  if (!handle) {
222  std::cout <<
223  "Field3D Plugin loader: failed to load plugin: " << dlerror() << "\n";
224  continue;
225  }
226 
227  // Determine plugin type by looking for one of:
228  // registerField3DPlugin()
229 
230  int (*fptr)(ClassFactory &) = NULL;
231  fptr = (int (*)(ClassFactory&))
232  dlsym(handle,"registerField3DPlugin");
233  std::string msg = "Initialized Field3D Plugin " + sofile;
234 
235  char *dlsymError = dlerror();
236  if (!dlsymError) {
237  if (fptr) {
238  // Call the registration function
239  int res = (*fptr)(ClassFactory::singleton());
240  if (!res) {
242  "failed to init Field3D plugin " + sofile);
243  } else {
244  Msg::print(msg);
245  }
246  }
247  } else {
248  char *debugEnvVar = getenv("FIELD3D_DEBUG");
249  if (debugEnvVar) {
250  // debug env var exist, so print warning
252  "Field3D plugin loader: failed to load "
253  "the symbol registerField3DPlugin");
254  }
255  }
256  }
257  }
258 }
259 
260 //----------------------------------------------------------------------------//
261 
262 #if 0
263 
264 bool PluginLoader::getDso(char *cptr, const char *dso,
265  std::string &dsoPath)
266 {
267 
268  std::string path = cptr;
269 
270  // Split paths
271  std::vector<std::string> paths;
272  const std::string delimiters=":";
273 
274  Tokenize(path, paths, delimiters);
275 
276  // For each path
277  for (unsigned int i=0; i < paths.size(); i++) {
278  struct dirent *dirent;
279 
280  std::string dir = paths[i];
281  const char *ds = dir.c_str();
282  DIR *dirfd = opendir(ds);
283  if (!dirfd) {
284  continue;
285  }
286 
287  dirent = readdir(dirfd);
288  while (dirent != NULL) {
289 
290  std::string name = dirent->d_name;
291 
292  if (name == dso) {
293  dsoPath = dir + "/" + name;
294  closedir(dirfd);
295  return true;
296  }
297 
298  dirent = readdir(dirfd);
299  }
300  closedir(dirfd);
301  }
302 
303 
304  return false;
305 
306 }
307 
308 //----------------------------------------------------------------------------//
309 
310 bool PluginLoader::resolveGlobalsForPlugins(const char *dso) {
311 
312  // Get environment variable
313  char *cptr = getenv("HOUDINI_DSO_PATH");
314  if (!cptr)
315  return false;
316 
317  std::string sofile;
318  if (!getDso(cptr,dso,sofile)) {
319  std::string dsostring = dso;
320  Msg::print(dsostring + " is not in HOUDINI_DSO_PATH");
321  return false;
322  }
323 
324  void *handle = dlopen(sofile.c_str(), RTLD_GLOBAL|RTLD_NOW);
325 
326  if (!handle) {
327  std::cout << "Field3D Plugin loader: failed to load Houdini plugin: "
328  << sofile << " " << dlerror() << "\n";
329  return false;
330  }
331 
332 #if 0
333  Msg::print("---------------------------------------------------------");
334  Msg::print("Loaded " + sofile);
335  Msg::print("---------------------------------------------------------");
336 #endif
337 
338  return true;
339 
340 }
341 
342 #endif
343 
344 //----------------------------------------------------------------------------//
345 
347 
348 //----------------------------------------------------------------------------//
#define FIELD3D_NAMESPACE_SOURCE_CLOSE
Definition: ns.h:60
static void loadPlugins()
Checks all paths in $FIELD3D_DSO_PATH and loads the plugins it finds.
static ClassFactory & singleton()
}
void print(Severity severity, const std::string &message)
Sends the string to the assigned output, prefixing the message with the severity. ...
Definition: Log.cpp:62
int filter(std::string &name)
static std::vector< std::string > ms_pluginsLoaded
List of plugins loaded.
Definition: PluginLoader.h:96
PluginLoader()
Default constructor.
bool getDirSos(std::vector< std::string > &sos, std::string &dir)
Contains the PluginLoader class.
Contains the ClassFactory class for registering Field3D classes.
~PluginLoader()
Destructor.
#define FIELD3D_NAMESPACE_OPEN
Definition: ns.h:56