PageRenderTime 23ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/googleclient/third_party/fcollada/files/FUtils/FUPluginManager.cpp

http://o3d.googlecode.com/
C++ | 232 lines | 182 code | 23 blank | 27 comment | 83 complexity | 1a915a6d115b217c02a185d42d3ea4c3 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.0, LGPL-3.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, BSD-3-Clause, GPL-2.0, Apache-2.0, MIT, CPL-1.0
  1. /*
  2. Copyright (C) 2005-2007 Feeling Software Inc.
  3. Portions of the code are:
  4. Copyright (C) 2005-2007 Sony Computer Entertainment America
  5. MIT License: http://www.opensource.org/licenses/mit-license.php
  6. */
  7. #include "StdAfx.h"
  8. #include "FUPlugin.h"
  9. #include "FUPluginManager.h"
  10. #include "FUFileManager.h"
  11. #ifdef WIN32
  12. #include <io.h>
  13. #if defined(UNICODE)
  14. #define ffinddata _wfinddata_t
  15. #define ffindfirst _wfindfirst
  16. #define ffindclose _findclose
  17. #define ffindnext _wfindnext
  18. #else // UNICODE
  19. #define ffinddata _finddata_t
  20. #define ffindfirst _findfirst
  21. #define ffindclose _findclose
  22. #define ffindnext _findnext
  23. #endif
  24. #elif defined(__APPLE__) || defined(LINUX)
  25. #include <dlfcn.h>
  26. #include <dirent.h>
  27. #endif //WIN32
  28. //
  29. // FUPlugin
  30. //
  31. ImplementObjectType(FUPlugin);
  32. //
  33. // FUPluginManager
  34. //
  35. FUPluginManager::FUPluginManager(const fchar* _filter)
  36. {
  37. fstring applicationFolderName = FUFileManager::GetApplicationFolderName();
  38. LoadPluginsInFolderName(applicationFolderName, _filter);
  39. fstring moduleFolderName = FUFileManager::GetModuleFolderName();
  40. if (!moduleFolderName.empty() && !IsEquivalent(moduleFolderName, applicationFolderName))
  41. {
  42. LoadPluginsInFolderName(moduleFolderName, _filter);
  43. }
  44. }
  45. void FUPluginManager::LoadPluginsInFolderName(const fstring& folderName, const fchar* _filter)
  46. {
  47. // Append the wanted extension for the plugins.
  48. FUStringBuilder pluginFolder(folderName);
  49. fchar lastChar = folderName[pluginFolder.length() - 1];
  50. if (lastChar != '\\' && lastChar != '/') pluginFolder.append((fchar) '/');
  51. pluginFolder.append(FC("Plugins/"));
  52. pluginFolderName = pluginFolder.ToString();
  53. if (_filter == NULL || _filter[0] == 0) _filter = FC("*.*");
  54. do
  55. {
  56. const fchar* nextFilter = fstrchr(_filter, '|');
  57. fstring filter(_filter);
  58. if (nextFilter != NULL)
  59. {
  60. filter.erase(nextFilter - _filter);
  61. ++nextFilter; // skip the pipe.
  62. }
  63. _filter = nextFilter;
  64. // Windows-only for now.
  65. #if defined(WIN32)
  66. size_t filterLength = filter.length();
  67. // Iterate over all the filtered files within the given folder.
  68. ffinddata folderIterator;
  69. fstring searchString = pluginFolderName + filter;
  70. intptr_t folderHandle = ffindfirst(searchString.c_str(), &folderIterator);
  71. if (folderHandle != -1L)
  72. {
  73. int32 isDone = FALSE;
  74. while (isDone == FALSE)
  75. {
  76. bool keep = false;
  77. PluginLibrary* library = new PluginLibrary();
  78. library->filename = pluginFolderName + folderIterator.name;
  79. // work around for wildcards and 3 letter extensions that pick up 3+ letter extensions
  80. // e.g. "dir *.fvp" in command prompt on a directory with "a.fvp", "a.fvpa", and "a.dll" returns
  81. // "a.fvp" and "a.fvpa"
  82. bool checkModule = true;
  83. if (filterLength > 3)
  84. {
  85. if ((filter.at(filterLength-4) == FC('.')) && (filter.at(filterLength-3) != FC('*')) &&
  86. (filter.at(filterLength-2) != FC('*')) && (filter.at(filterLength-1) != FC('*')))
  87. {
  88. size_t filepathLength = fstrlen(folderIterator.name);
  89. checkModule = (folderIterator.name[filepathLength-4] == filter.at(filterLength-4)) &&
  90. (folderIterator.name[filepathLength-3] == filter.at(filterLength-3)) &&
  91. (folderIterator.name[filepathLength-2] == filter.at(filterLength-2)) &&
  92. (folderIterator.name[filepathLength-1] == filter.at(filterLength-1));
  93. }
  94. }
  95. library->module = LoadLibrary(library->filename.c_str());
  96. if (checkModule && (library->module != NULL))
  97. {
  98. // Retrieve the necessary callbacks
  99. library->getPluginCount = (GetPluginCount) GetProcAddress(library->module, "GetPluginCount");
  100. library->getPluginType = (GetPluginType) GetProcAddress(library->module, "GetPluginType");
  101. library->createPlugin = (CreatePlugin) GetProcAddress(library->module, "CreatePlugin");
  102. keep = library->createPlugin != NULL && library->getPluginType != NULL && library->getPluginCount != NULL;
  103. }
  104. // This is a valid library.
  105. if (keep) loadedLibraries.push_back(library);
  106. else { SAFE_DELETE(library); }
  107. isDone = ffindnext(folderHandle, &folderIterator);
  108. }
  109. ffindclose(folderHandle);
  110. }
  111. #elif defined(__APPLE__) || defined(LINUX)
  112. fm::string s_filter = TO_STRING(filter);
  113. if (s_filter.length() > 0 && s_filter.front() == '*') s_filter.erase(0, 1);
  114. if (s_filter.length() > 0 && s_filter.back() == '*') s_filter.pop_back();
  115. DIR* directory = opendir(TO_STRING(pluginFolderName).c_str());
  116. if (directory == NULL) continue;
  117. dirent* directoryEntry;
  118. while ((directoryEntry = readdir(directory)) != NULL)
  119. {
  120. if (directoryEntry->d_type == DT_DIR) continue; // skip sub-folders.
  121. if (strstr((const char*) directoryEntry->d_name, s_filter.c_str()) != NULL)
  122. {
  123. // We have a match.
  124. bool keep = false;
  125. PluginLibrary* library = new PluginLibrary();
  126. library->filename = pluginFolderName + TO_FSTRING((const char*) directoryEntry->d_name);
  127. fm::string libraryModuleFilename = TO_STRING(library->filename);
  128. DEBUG_OUT("Found dynamic library: %s\n", libraryModuleFilename.c_str());
  129. library->module = dlopen(libraryModuleFilename.c_str(), RTLD_NOW);
  130. if (library->module != NULL)
  131. {
  132. // Retrieve the necessary callbacks
  133. library->getPluginCount = (GetPluginCount) dlsym(library->module, "GetPluginCount");
  134. library->getPluginType = (GetPluginType) dlsym(library->module, "GetPluginType");
  135. library->createPlugin = (CreatePlugin) dlsym(library->module, "CreatePlugin");
  136. keep = library->createPlugin != NULL && library->getPluginType != NULL && library->getPluginCount != NULL;
  137. }
  138. // This is a valid library.
  139. if (keep) loadedLibraries.push_back(library);
  140. else { SAFE_DELETE(library); }
  141. }
  142. }
  143. closedir(directory);
  144. #endif // WIN32
  145. } while (_filter != NULL);
  146. }
  147. FUPluginManager::~FUPluginManager()
  148. {
  149. UnloadPlugins();
  150. FUAssert(loadedPlugins.empty(), return);
  151. // Detach all the plugin libraries.
  152. for (PluginLibraryList::iterator it = loadedLibraries.begin(); it != loadedLibraries.end(); ++it)
  153. {
  154. #if defined(WIN32)
  155. if ((*it)->module != NULL) FreeLibrary((*it)->module);
  156. #elif defined(LINUX) || defined(__APPLE__)
  157. if ((*it)->module != NULL) dlclose((*it)->module);
  158. #endif // WIN32
  159. }
  160. CLEAR_POINTER_VECTOR(loadedLibraries);
  161. }
  162. void FUPluginManager::LoadPlugins(const FUObjectType& pluginType)
  163. {
  164. for (PluginLibraryList::iterator it = loadedLibraries.begin(); it != loadedLibraries.end(); ++it)
  165. {
  166. #ifndef _DEBUG
  167. try
  168. #endif // _DEBUG
  169. {
  170. DEBUG_OUT("Loading plug-in: %s\n", TO_STRING((*it)->filename).c_str());
  171. FUAssert((*it)->createPlugin != NULL && (*it)->getPluginType != NULL && (*it)->getPluginCount != NULL, continue);
  172. uint32 pluginCount = (*((*it)->getPluginCount))();
  173. for (uint32 i = 0; i < pluginCount; ++i)
  174. {
  175. // Retrieve the types of all the plug-ins within this library.
  176. // Compare them against the wanted types and create the wanted plug-ins.
  177. const FUObjectType* type = (*((*it)->getPluginType))(i);
  178. if (type->Includes(pluginType))
  179. {
  180. FUPlugin* plugin = (*((*it)->createPlugin))(i);
  181. if (plugin == NULL) continue;
  182. loadedPlugins.push_back(plugin);
  183. }
  184. }
  185. }
  186. #ifndef _DEBUG
  187. catch (...)
  188. {
  189. fm::string _filename = TO_STRING((*it)->filename);
  190. ERROR_OUT("Unhandled exception when loading plugin: %s.", _filename.c_str());
  191. }
  192. #endif // _DEBUG
  193. }
  194. }
  195. void FUPluginManager::AddPluginLibrary(FUPluginManager::GetPluginCount fnGetPluginCount, FUPluginManager::GetPluginType fnGetPluginType, FUPluginManager::CreatePlugin fnCreatePlugin)
  196. {
  197. PluginLibrary* library = new PluginLibrary();
  198. library->getPluginCount = fnGetPluginCount;
  199. library->getPluginType = fnGetPluginType;
  200. library->createPlugin = fnCreatePlugin;
  201. library->filename.clear();
  202. library->module = NULL;
  203. loadedLibraries.push_back(library);
  204. }
  205. void FUPluginManager::UnloadPlugins()
  206. {
  207. loadedPlugins.clear();
  208. }