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