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         // iterate on used libraries
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                 // iterate on used creators of the library
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         // for each path, load libraries
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                 // TODO: throw exception and have catch in main()
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 //              SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
00113 //                      SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX );
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 //      TODO: if windows allow it, add here a lazy load
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 //TODO: the name argument will be used to check on the plugins map 
00152 // returns false on success, true on fail
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         // add standardPath to the env path string (i.e. path1:path2)
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                 // get file name:
00248                 std::string fileName = subpathAndName.substr( subpathAndName.rfind("/")+1); 
00249                 // testDir= root_path + subpath:
00250                 std::string testDir = environmentPaths[i] + "/" + subpathAndName.substr(0, subpathAndName.size()-fileName.size());
00251                 // check if directory exists:
00252                 DIR* dir = opendir(testDir.c_str());
00253                 if (not dir) 
00254                         continue; // directory doesn't match, skip
00255                 closedir(dir);
00256                 // check if file exists:
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; // file doesn't exist, skip
00262                 fin.close();
00263                 return completeFileName;
00264         }
00265         return "";
00266 }
Generated by  doxygen 1.6.3