OpenWalnut 1.3.1
|
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 stem = i->path().stem().string(); 00058 00059 // we want to strip the search directory from the path 00060 std::string relPath = i->path().string(); 00061 relPath.erase( 0, dir.string().length() + 1 ); // NOTE: +1 because we want to remove the "/" too 00062 00063 // is it a lib? Use a regular expression to check this 00064 // NOTE:: the double \\ is needed to escape the escape char (to interpret the "dot" as dot and not as "any char". 00065 #ifdef __WIN32__ 00066 static const boost::regex CheckLibMMP( "^(lib)?(.*)\\" + WSharedLib::getSystemSuffix() +"$" ); 00067 #elif __APPLE__ 00068 static const boost::regex CheckLibMMP( "^(lib)?(.*)\\.[0-9]+\\.[0-9]+\\.[0-9]+\\" + WSharedLib::getSystemSuffix() + "$" ); 00069 #else 00070 static const boost::regex CheckLibMMP( "^(lib)?(.*)\\" + WSharedLib::getSystemSuffix() + "\\.[0-9]+\\.[0-9]+\\.[0-9]+$" ); 00071 #endif 00072 // this will contain the filename afterwards 00073 boost::smatch matches; 00074 bool matchLibName = boost::regex_match( i->path().filename().string(), matches, CheckLibMMP ); 00075 std::string libBaseName = matchLibName ? std::string( matches[2] ) : ""; 00076 00077 if( !boost::filesystem::is_directory( *i ) && 00078 matchLibName && 00079 ( stem.compare( 0, getModulePrefix().length(), getModulePrefix() ) == 0 ) 00080 ) 00081 { 00082 try 00083 { 00084 // load lib 00085 boost::shared_ptr< WSharedLib > l = boost::shared_ptr< WSharedLib >( new WSharedLib( i->path() ) ); 00086 00087 // get instantiation function 00088 W_LOADABLE_MODULE_SIGNATURE f; 00089 l->fetchFunction< W_LOADABLE_MODULE_SIGNATURE >( W_LOADABLE_MODULE_SYMBOL, f ); 00090 00091 // get the first prototype 00092 WModuleList m; 00093 f( m ); 00094 00095 // could the prototype be created? 00096 if( m.empty() ) 00097 { 00098 WLogger::getLogger()->addLogMessage( "Load failed for module \"" + relPath + "\". Could not create any " + 00099 "prototype instance.", "Module Loader", LL_ERROR ); 00100 continue; 00101 } 00102 else 00103 { 00104 // yes, add it to the list of prototypes 00105 for( WModuleList::const_iterator iter = m.begin(); iter != m.end(); ++iter ) 00106 { 00107 // which lib? 00108 ( *iter )->setLibPath( i->path() ); 00109 // we use the library name (excluding extension and optional lib prefix) as package name 00110 ( *iter )->setPackageName( libBaseName ); 00111 // resource path 00112 ( *iter )->setLocalPath( WPathHelper::getModuleResourcePath( i->path().parent_path(), ( *iter )->getPackageName() ) ); 00113 00114 // add module 00115 ticket->get().insert( *iter ); 00116 00117 // we need to keep a reference to the lib 00118 m_libs.push_back( l ); 00119 } 00120 00121 wlog::debug( "Module Loader" ) << "Loaded " << m.size() << " modules from " << relPath; 00122 } 00123 00124 // lib gets closed if l looses focus 00125 } 00126 catch( const WException& e ) 00127 { 00128 WLogger::getLogger()->addLogMessage( "Load failed for module \"" + relPath + "\". " + e.what() + ". Ignoring.", 00129 "Module Loader", LL_ERROR ); 00130 } 00131 } 00132 else if( ( level <= 10 ) && // this sould be enough to tranverse the typical structure build/release/lib/openwalnut/MODULENAME (5 levels) 00133 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 ).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 ).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