OpenWalnut 1.2.5
|
00001 //--------------------------------------------------------------------------- 00002 // 00003 // Project: OpenWalnut ( http://www.openwalnut.org ) 00004 // 00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS 00006 // For more information see http://www.openwalnut.org/copying 00007 // 00008 // This file is part of OpenWalnut. 00009 // 00010 // OpenWalnut is free software: you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as published by 00012 // the Free Software Foundation, either version 3 of the License, or 00013 // (at your option) any later version. 00014 // 00015 // OpenWalnut is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 // GNU Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public License 00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>. 00022 // 00023 //--------------------------------------------------------------------------- 00024 00025 #include <set> 00026 #include <string> 00027 #include <vector> 00028 00029 #include <boost/regex.hpp> 00030 00031 #include "../common/WIOTools.h" 00032 #include "../common/WPathHelper.h" 00033 #include "../common/WSharedLib.h" 00034 00035 #include "WKernel.h" 00036 00037 #include "WModuleLoader.h" 00038 00039 WModuleLoader::WModuleLoader( ) 00040 { 00041 // initialize members 00042 } 00043 00044 WModuleLoader::~WModuleLoader() 00045 { 00046 // cleanup all the handles 00047 m_libs.clear(); 00048 } 00049 00050 void WModuleLoader::load( WSharedAssociativeContainer< std::set< boost::shared_ptr< WModule > > >::WriteTicket ticket, 00051 boost::filesystem::path dir, unsigned int level ) 00052 { 00053 for( boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator( dir ); 00054 i != boost::filesystem::directory_iterator(); ++i ) 00055 { 00056 // all modules need to begin with this 00057 std::string suffix = getSuffix( i->leaf() ); 00058 std::string stem = i->path().stem(); 00059 00060 #ifdef _MSC_VER 00061 std::string supposedFilename = getModulePrefix() + '_' + i->path().parent_path().filename() 00062 #ifdef _DEBUG 00063 + 'd' 00064 #endif 00065 + WSharedLib::getSystemSuffix(); 00066 std::string isFileName = i->path().filename(); 00067 #endif // _MSC_VER 00068 00069 // we want to strip the search directory from the path 00070 std::string relPath = i->path().file_string(); 00071 relPath.erase( 0, dir.file_string().length() + 1 ); // NOTE: +1 because we want to remove the "/" too 00072 00073 // is it a lib? Use a regular expression to check this 00074 // NOTE:: the double \\ is needed to escape the escape char 00075 #ifdef __WIN32__ 00076 static const boost::regex CheckLibMMP( "^.*\\" + WSharedLib::getSystemSuffix() +"$" ); 00077 #elif __APPLE__ 00078 static const boost::regex CheckLibMMP( "^.*\\.[0-9]+\\.[0-9]+\\.[0-9]+\\" + WSharedLib::getSystemSuffix() + "$" ); 00079 #else 00080 static const boost::regex CheckLibMMP( "^.*\\" + WSharedLib::getSystemSuffix() + "\\.[0-9]+\\.[0-9]+\\.[0-9]+$" ); 00081 #endif 00082 boost::smatch matches; 00083 00084 if( !boost::filesystem::is_directory( *i ) && 00085 ( boost::regex_match( i->path().string(), matches, CheckLibMMP ) ) && 00086 ( stem.compare( 0, getModulePrefix().length(), getModulePrefix() ) == 0 ) 00087 #ifdef _MSC_VER 00088 && supposedFilename == isFileName 00089 #endif 00090 ) 00091 { 00092 try 00093 { 00094 // load lib 00095 boost::shared_ptr< WSharedLib > l = boost::shared_ptr< WSharedLib >( new WSharedLib( i->path() ) ); 00096 00097 // get instantiation function 00098 W_LOADABLE_MODULE_SIGNATURE f; 00099 l->fetchFunction< W_LOADABLE_MODULE_SIGNATURE >( W_LOADABLE_MODULE_SYMBOL, f ); 00100 00101 // get the first prototype 00102 WModuleList m; 00103 f( m ); 00104 00105 // could the prototype be created? 00106 if( m.empty() ) 00107 { 00108 WLogger::getLogger()->addLogMessage( "Load failed for module \"" + relPath + "\". Could not create any " + 00109 "prototype instance.", "Module Loader", LL_ERROR ); 00110 continue; 00111 } 00112 else 00113 { 00114 // yes, add it to the list of prototypes 00115 for( WModuleList::const_iterator iter = m.begin(); iter != m.end(); ++iter ) 00116 { 00117 ( *iter )->setLocalPath( i->path().parent_path() ); 00118 ticket->get().insert( *iter ); 00119 m_libs.push_back( l ); 00120 } 00121 00122 wlog::debug( "Module Loader" ) << "Loaded " << m.size() << " modules from " << relPath; 00123 } 00124 00125 // lib gets closed if l looses focus 00126 } 00127 catch( const WException& e ) 00128 { 00129 WLogger::getLogger()->addLogMessage( "Load failed for module \"" + relPath + "\". " + e.what() + ". Ignoring.", 00130 "Module Loader", LL_ERROR ); 00131 } 00132 } 00133 else if( ( level == 0 ) && boost::filesystem::is_directory( *i ) ) // this only traverses down one level 00134 { 00135 // if it a dir -> traverse down 00136 load( ticket, *i, level + 1 ); 00137 } 00138 } 00139 } 00140 00141 void WModuleLoader::load( WSharedAssociativeContainer< std::set< boost::shared_ptr< WModule > > >::WriteTicket ticket ) 00142 { 00143 std::vector< boost::filesystem::path > allPaths = WPathHelper::getAllModulePaths(); 00144 00145 // go through each of the paths 00146 for( std::vector< boost::filesystem::path >::const_iterator path = allPaths.begin(); path != allPaths.end(); ++path ) 00147 { 00148 WLogger::getLogger()->addLogMessage( "Searching modules in \"" + ( *path ).file_string() + "\".", "Module Loader", LL_INFO ); 00149 00150 // does the directory exist? 00151 if( !boost::filesystem::is_directory( *path ) || !boost::filesystem::exists( *path ) ) 00152 { 00153 WLogger::getLogger()->addLogMessage( "Searching modules in \"" + ( *path ).file_string() + 00154 "\" failed. It is not a directory or does not exist." + 00155 " Ignoring.", "Module Loader", LL_WARNING ); 00156 00157 continue; 00158 } 00159 00160 // directly search the path for libOWmodule_ files 00161 load( ticket, *path ); 00162 } 00163 } 00164 00165 std::string WModuleLoader::getModulePrefix() 00166 { 00167 // all module file names need to have this prefix: 00168 return WSharedLib::getSystemPrefix(); 00169 } 00170