RunTimeLibraryLoader.cxx
Go to the documentation of this file.00001 #include "RunTimeLibraryLoader.hxx"
00002
00003 #include <iostream>
00004 #include <cstdlib>
00005 #include <dirent.h>
00006 #ifdef WIN32
00007 # include "CLAM_windows.h"
00008 #else
00009 # include <dlfcn.h>
00010 #endif
00011
00012 #include <fstream>
00013
00014 #include "ProcessingFactory.hxx"
00015
00016 static bool debug = false;
00017
00018
00019 void RunTimeLibraryLoader::ReLoad()
00020 {
00021 CLAM::ProcessingFactory& factory = CLAM::ProcessingFactory::GetInstance();
00022 std::list<std::string> usedLibraries=GetUsedLibraries();
00023 std::list<std::string>::const_iterator itLibraries;
00024
00025 for (itLibraries=usedLibraries.begin();itLibraries!=usedLibraries.end();itLibraries++)
00026 {
00027 CLAM::ProcessingFactory::Keys keys;
00028 keys=factory.GetKeys("library",(*itLibraries));
00029 CLAM::ProcessingFactory::Keys::const_iterator itKeys;
00030
00031 for(itKeys=keys.begin();itKeys!=keys.end();itKeys++)
00032 {
00033 factory.DeleteCreator(*itKeys);
00034 }
00035 if (needReleaseHandlerOnReload())
00036 {
00037 void * handle=GetLibraryHandler(*itLibraries);
00038 ReleaseLibraryHandler(handle,(*itLibraries));
00039 }
00040 }
00041 Load();
00042 }
00043
00044 std::list<std::string> RunTimeLibraryLoader::GetUsedLibraries()
00045 {
00046 CLAM::ProcessingFactory& factory = CLAM::ProcessingFactory::GetInstance();
00047 std::list<std::string> usedLibraries;
00048 CLAM::ProcessingFactory::Values librariesValues=factory.GetSetOfValues("library");
00049 CLAM::ProcessingFactory::Values::const_iterator itLibraries;
00050 for (itLibraries=librariesValues.begin();itLibraries!=librariesValues.end();itLibraries++)
00051 {
00052 const std::string & path=getPathFromFullFileName(*itLibraries);
00053 if (IsOnPath(path))
00054 usedLibraries.push_back(*itLibraries);
00055 }
00056 return usedLibraries;
00057 }
00058
00059 bool RunTimeLibraryLoader::IsOnPath(const std::string & path) const
00060 {
00061 std::string paths = GetPaths();
00062 std::vector <std::string> environmentPaths = SplitPathVariable(paths);
00063 for (unsigned i=0; i<environmentPaths.size(); i++)
00064 {
00065 if (environmentPaths[i]==path)
00066 return true;
00067 }
00068 return false;
00069 }
00070
00071 void RunTimeLibraryLoader::Load() const
00072 {
00073 std::string path = GetPaths();
00074
00075 std::vector <std::string> environmentPaths = SplitPathVariable(path);
00076 for (unsigned i=0; i<environmentPaths.size(); i++)
00077 {
00078 debug && std::cout << "RunTimeLibraryLoader: Scanning for libraries in " << environmentPaths[i] << std::endl;
00079 LoadLibrariesFromPath(environmentPaths[i]);
00080 }
00081 }
00082 void RunTimeLibraryLoader::LoadLibrariesFromPath(const std::string & path) const
00083 {
00084 DIR* dir = opendir(path.c_str());
00085 if (!dir) return;
00086 while ( struct dirent * dirEntry = readdir(dir) )
00087 {
00088 std::string pluginFilename(dirEntry->d_name);
00089 if(pluginFilename == "." || pluginFilename == "..")
00090 continue;
00091 debug && std::cout << "RunTimeLibraryLoader: Found file " << pluginFilename << std::endl;
00092 std::string pluginFullFilename(path + std::string("/") + pluginFilename);
00093 void * handle = FullyLoadLibrary(pluginFullFilename);
00094
00095
00096 if (handle == NULL)
00097 {
00098 std::cout << "Error loading: " << pluginFullFilename
00099 << " reason: " << LibraryLoadError()
00100 << std::endl;
00101 }
00102
00103 SetupLibrary( handle, pluginFullFilename );
00104 }
00105 closedir(dir);
00106 }
00107
00108
00109 void * RunTimeLibraryLoader::FullyLoadLibrary(const std::string & libraryPath)
00110 {
00111 #ifdef WIN32
00112
00113
00114 return LoadLibrary(libraryPath.c_str());
00115 #else
00116 return dlopen( libraryPath.c_str(), RTLD_NOW);
00117 #endif
00118 }
00119
00120
00121 void * RunTimeLibraryLoader::LazyLoadLibrary(const std::string & libraryPath)
00122 {
00123 #ifdef WIN32
00124
00125 return 0;
00126 #else
00127 return dlopen( libraryPath.c_str(), RTLD_LAZY);
00128 #endif
00129 }
00130
00131
00132 void * RunTimeLibraryLoader::GetSymbol(void * libraryHandler, const std::string & symbolName)
00133 {
00134 #ifdef WIN32
00135 return (void*) GetProcAddress((HMODULE)libraryHandler, symbolName.c_str());
00136 #else
00137 return dlsym(libraryHandler, symbolName.c_str());
00138 #endif
00139 }
00140
00141
00142 void * RunTimeLibraryLoader::GetLibraryHandler(const std::string & libraryPath) const
00143 {
00144 #ifdef WIN32 //TODO: does windows have an equivalent method to have the handler?
00145 return 0;
00146 #else
00147 return dlopen (libraryPath.c_str(), RTLD_NOLOAD);
00148 #endif
00149 }
00150
00151
00152
00153 bool RunTimeLibraryLoader::ReleaseLibraryHandler(void* handle, const std::string pluginFullFilename)
00154 {
00155 if (!handle)
00156 {
00157 std::cout<<"Cannot release an empty handle!"<<std::endl;
00158 return true;
00159 }
00160 #ifdef WIN32
00161 return !FreeLibrary((HMODULE)handle);
00162 #else
00163 return dlclose(handle);
00164 #endif
00165 }
00166
00167 const std::string RunTimeLibraryLoader::LibraryLoadError()
00168 {
00169 #ifdef WIN32
00170 LPVOID lpMsgBuf;
00171 FormatMessage(
00172 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
00173 NULL,
00174 GetLastError(),
00175 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00176 (LPTSTR) &lpMsgBuf,
00177 0, NULL );
00178 std::string message((char*)lpMsgBuf);
00179 LocalFree(lpMsgBuf);
00180 return message;
00181 #else
00182 return dlerror();
00183 #endif
00184 }
00185
00186 const std::string RunTimeLibraryLoader::FileOfSymbol (void * symbolAddress)
00187 {
00188 #ifdef WIN32
00189 char pluginpath[1024];
00190 HMODULE module;
00191 GetModuleHandleExA(
00192 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
00193 (char *)symbolAddress,
00194 &module);
00195 GetModuleFileNameA(module, pluginpath, 1024);
00196 FreeLibrary(module);
00197 return pluginpath;
00198 #else
00199 Dl_info info;
00200 int ok=dladdr(symbolAddress,&info);
00201 if (ok)
00202 return info.dli_fname;
00203 #endif
00204 return "";
00205 }
00206
00207 std::vector<std::string> RunTimeLibraryLoader::SplitPathVariable(const std::string & pathVariable) const
00208 {
00209 std::string content=pathVariable;
00210 std::vector<std::string> result;
00211 while (!content.empty())
00212 {
00213 size_t separatorPos = content.find(pathSeparator());
00214 if (separatorPos == std::string::npos)
00215 {
00216 result.push_back(content);
00217 break;
00218 }
00219 result.push_back(content.substr(0, separatorPos));
00220 content = content.substr(separatorPos+1);
00221 }
00222 return result;
00223 }
00224
00225 const std::string RunTimeLibraryLoader::GetPaths() const
00226 {
00227 const char * envPath = getenv(pathEnvironmentVar());
00228 const char * envHome = getenv("HOME");
00229 std::string path = envPath ? envPath : "";
00230 if (envHome)
00231 {
00232 path += std::string(path.empty()? "":pathSeparator()) + envHome + homePath();
00233 }
00234
00235 for (const char ** standardPath=standardPaths(); *standardPath; standardPath++)
00236 path += std::string(path.empty()? "":pathSeparator()) + *standardPath;
00237 return path;
00238 }
00239
00240
00241 const std::string RunTimeLibraryLoader::CompletePathFor(const std::string & subpathAndName) const
00242 {
00243 std::string paths=GetPaths();
00244 std::vector <std::string> environmentPaths = SplitPathVariable(paths);
00245 for (unsigned i=0; i<environmentPaths.size(); i++)
00246 {
00247
00248 std::string fileName = subpathAndName.substr( subpathAndName.rfind("/")+1);
00249
00250 std::string testDir = environmentPaths[i] + "/" + subpathAndName.substr(0, subpathAndName.size()-fileName.size());
00251
00252 DIR* dir = opendir(testDir.c_str());
00253 if (not dir)
00254 continue;
00255 closedir(dir);
00256
00257 std::fstream fin;
00258 std::string completeFileName=testDir+fileName;
00259 fin.open(completeFileName.c_str(),std::ios::in);
00260 if (not fin.is_open())
00261 continue;
00262 fin.close();
00263 return completeFileName;
00264 }
00265 return "";
00266 }