OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends
WModuleLoader.cpp
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 
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends