OpenWalnut
1.4.0
|
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 "WModuleLoader.h" 00036 00037 WModuleLoader::WModuleLoader( ) 00038 { 00039 // initialize members 00040 } 00041 00042 WModuleLoader::~WModuleLoader() 00043 { 00044 // cleanup all the handles 00045 m_libs.clear(); 00046 } 00047 00048 void WModuleLoader::load( WSharedAssociativeContainer< std::set< boost::shared_ptr< WModule > > >::WriteTicket ticket, 00049 boost::filesystem::path dir, unsigned int level ) 00050 { 00051 for( boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator( dir ); 00052 i != boost::filesystem::directory_iterator(); ++i ) 00053 { 00054 // all modules need to begin with this 00055 std::string stem = i->path().stem().string(); 00056 00057 // we want to strip the search directory from the path 00058 std::string relPath = i->path().string(); 00059 relPath.erase( 0, dir.string().length() + 1 ); // NOTE: +1 because we want to remove the "/" too 00060 00061 // is it a lib? Use a regular expression to check this 00062 // NOTE:: the double \\ is needed to escape the escape char (to interpret the "dot" as dot and not as "any char". 00063 #ifdef __WIN32__ 00064 static const boost::regex CheckLibMMP( "^(lib)?(.*)\\" + WSharedLib::getSystemSuffix() +"$" ); 00065 #elif __APPLE__ 00066 static const boost::regex CheckLibMMP( "^(lib)?(.*)\\.[0-9]+\\.[0-9]+\\.[0-9]+\\" + WSharedLib::getSystemSuffix() + "$" ); 00067 #else 00068 static const boost::regex CheckLibMMP( "^(lib)?(.*)\\" + WSharedLib::getSystemSuffix() + "\\.[0-9]+\\.[0-9]+\\.[0-9]+$" ); 00069 #endif 00070 // this will contain the filename afterwards 00071 boost::smatch matches; 00072 std::string fn = i->path().filename().string(); 00073 bool matchLibName = boost::regex_match( fn, matches, CheckLibMMP ); 00074 std::string libBaseName = matchLibName ? std::string( matches[2] ) : ""; 00075 00076 if( !boost::filesystem::is_directory( *i ) && 00077 matchLibName && 00078 ( stem.compare( 0, getModulePrefix().length(), getModulePrefix() ) == 0 ) 00079 ) 00080 { 00081 try 00082 { 00083 // load lib 00084 boost::shared_ptr< WSharedLib > l( new WSharedLib( i->path() ) ); 00085 00086 bool isLoadableModule = false; 00087 bool isLoadableArbitrary = false; 00088 00089 // be nice. Do not fail if the module symbol does not exist 00090 if( l->existsFunction( W_LOADABLE_MODULE_SYMBOL ) ) 00091 { 00092 // get instantiation function 00093 W_LOADABLE_MODULE_SIGNATURE f; 00094 l->fetchFunction< W_LOADABLE_MODULE_SIGNATURE >( W_LOADABLE_MODULE_SYMBOL, f ); 00095 00096 isLoadableModule = true; 00097 00098 // get the first prototype 00099 WModuleList m; 00100 f( m ); 00101 00102 // could the prototype be created? 00103 if( m.empty() ) 00104 { 00105 continue; 00106 } 00107 else 00108 { 00109 // yes, add it to the list of prototypes 00110 for( WModuleList::const_iterator iter = m.begin(); iter != m.end(); ++iter ) 00111 { 00112 // which lib? 00113 ( *iter )->setLibPath( i->path() ); 00114 // we use the library name (excluding extension and optional lib prefix) as package name 00115 ( *iter )->setPackageName( libBaseName ); 00116 // resource path 00117 ( *iter )->setLocalPath( WPathHelper::getModuleResourcePath( i->path().parent_path(), ( *iter )->getPackageName() ) ); 00118 00119 // add module 00120 ticket->get().insert( *iter ); 00121 00122 // we need to keep a reference to the lib 00123 m_libs.push_back( l ); 00124 } 00125 00126 wlog::debug( "Module Loader" ) << "Loaded " << m.size() << " modules from " << relPath; 00127 } 00128 } 00129 00130 // do the same for the arbitrary register functionality 00131 // get instantiation function 00132 if( l->existsFunction( W_LOADABLE_REGISTERARBITRARY_SYMBOL ) ) 00133 { 00134 isLoadableArbitrary = true; 00135 00136 // store this temporarily. This is called later, after OW was completely initialized 00137 // put together the right path and call function 00138 m_arbitraryRegisterLibs.push_back( 00139 PostponedLoad( l, WPathHelper::getModuleResourcePath( i->path().parent_path(), libBaseName ) ) 00140 ); 00141 } 00142 // lib gets closed if l looses focus 00143 00144 if( !isLoadableModule && !isLoadableArbitrary ) 00145 { 00146 wlog::warn( "Module Loader" ) << "Library does neither contain a module nor another extension."; 00147 } 00148 } 00149 catch( const WException& e ) 00150 { 00151 WLogger::getLogger()->addLogMessage( "Load failed for module \"" + relPath + "\". " + e.what() + ". Ignoring.", 00152 "Module Loader", LL_ERROR ); 00153 } 00154 } 00155 else if( ( level <= 10 ) && // this sould be enough to tranverse the typical structure build/release/lib/openwalnut/MODULENAME (5 levels) 00156 boost::filesystem::is_directory( *i ) ) // this only traverses down one level 00157 { 00158 // if it a dir -> traverse down 00159 load( ticket, *i, level + 1 ); 00160 } 00161 } 00162 } 00163 00164 void WModuleLoader::load( WSharedAssociativeContainer< std::set< boost::shared_ptr< WModule > > >::WriteTicket ticket ) 00165 { 00166 std::vector< boost::filesystem::path > allPaths = WPathHelper::getAllModulePaths(); 00167 00168 // go through each of the paths 00169 for( std::vector< boost::filesystem::path >::const_iterator path = allPaths.begin(); path != allPaths.end(); ++path ) 00170 { 00171 WLogger::getLogger()->addLogMessage( "Searching modules in \"" + ( *path ).string() + "\".", "Module Loader", LL_INFO ); 00172 00173 // does the directory exist? 00174 if( !boost::filesystem::is_directory( *path ) || !boost::filesystem::exists( *path ) ) 00175 { 00176 WLogger::getLogger()->addLogMessage( "Searching modules in \"" + ( *path ).string() + 00177 "\" failed. It is not a directory or does not exist." + 00178 " Ignoring.", "Module Loader", LL_WARNING ); 00179 00180 continue; 00181 } 00182 00183 // directly search the path for libOWmodule_ files 00184 load( ticket, *path ); 00185 } 00186 } 00187 00188 void WModuleLoader::initializeExtensions() 00189 { 00190 typedef std::vector< PostponedLoad > Vec; 00191 for( Vec::const_iterator iter = m_arbitraryRegisterLibs.begin(); iter != m_arbitraryRegisterLibs.end(); ++iter ) 00192 { 00193 wlog::debug( "WModuleLoader" ) << "Initializing extensions of \"" << ( *iter ).m_lib->getLibraryName() << "\""; 00194 W_LOADABLE_REGISTERARBITRARY_SIGNATURE arbitraryRegister; 00195 ( *iter ).m_lib->fetchFunction< W_LOADABLE_REGISTERARBITRARY_SIGNATURE >( W_LOADABLE_REGISTERARBITRARY_SYMBOL, arbitraryRegister ); 00196 arbitraryRegister( ( *iter ).m_path ); 00197 } 00198 } 00199 00200 std::string WModuleLoader::getModulePrefix() 00201 { 00202 // all module file names need to have this prefix: 00203 return WSharedLib::getSystemPrefix(); 00204 } 00205