OpenWalnut  1.2.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
WModuleLoader.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <set>
26 #include <string>
27 #include <vector>
28 
29 #include <boost/regex.hpp>
30 
31 #include "../common/WIOTools.h"
32 #include "../common/WPathHelper.h"
33 #include "../common/WSharedLib.h"
34 
35 #include "WKernel.h"
36 
37 #include "WModuleLoader.h"
38 
40 {
41  // initialize members
42 }
43 
45 {
46  // cleanup all the handles
47  m_libs.clear();
48 }
49 
50 void WModuleLoader::load( WSharedAssociativeContainer< std::set< boost::shared_ptr< WModule > > >::WriteTicket ticket,
51  boost::filesystem::path dir, unsigned int level )
52 {
53  for( boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator( dir );
54  i != boost::filesystem::directory_iterator(); ++i )
55  {
56  // all modules need to begin with this
57  std::string suffix = getSuffix( i->leaf() );
58  std::string stem = i->path().stem();
59 
60 #ifdef _MSC_VER
61  std::string supposedFilename = getModulePrefix() + '_' + i->path().parent_path().filename()
62 #ifdef _DEBUG
63  + 'd'
64 #endif
66  std::string isFileName = i->path().filename();
67 #endif // _MSC_VER
68 
69  // we want to strip the search directory from the path
70  std::string relPath = i->path().file_string();
71  relPath.erase( 0, dir.file_string().length() + 1 ); // NOTE: +1 because we want to remove the "/" too
72 
73  // is it a lib? Use a regular expression to check this
74  // NOTE:: the double \\ is needed to escape the escape char
75  #ifdef __WIN32__
76  static const boost::regex CheckLibMMP( "^.*\\" + WSharedLib::getSystemSuffix() +"$" );
77  #elif __APPLE__
78  static const boost::regex CheckLibMMP( "^.*\\.[0-9]+\\.[0-9]+\\.[0-9]+\\" + WSharedLib::getSystemSuffix() + "$" );
79  #else
80  static const boost::regex CheckLibMMP( "^.*\\" + WSharedLib::getSystemSuffix() + "\\.[0-9]+\\.[0-9]+\\.[0-9]+$" );
81  #endif
82  boost::smatch matches;
83 
84  if( !boost::filesystem::is_directory( *i ) &&
85  ( boost::regex_match( i->path().string(), matches, CheckLibMMP ) ) &&
86  ( stem.compare( 0, getModulePrefix().length(), getModulePrefix() ) == 0 )
87 #ifdef _MSC_VER
88  && supposedFilename == isFileName
89 #endif
90  )
91  {
92  try
93  {
94  // load lib
95  boost::shared_ptr< WSharedLib > l = boost::shared_ptr< WSharedLib >( new WSharedLib( i->path() ) );
96 
97  // get instantiation function
98  W_LOADABLE_MODULE_SIGNATURE f;
99  l->fetchFunction< W_LOADABLE_MODULE_SIGNATURE >( W_LOADABLE_MODULE_SYMBOL, f );
100 
101  // get the first prototype
102  WModuleList m;
103  f( m );
104 
105  // could the prototype be created?
106  if( m.empty() )
107  {
108  WLogger::getLogger()->addLogMessage( "Load failed for module \"" + relPath + "\". Could not create any " +
109  "prototype instance.", "Module Loader", LL_ERROR );
110  continue;
111  }
112  else
113  {
114  // yes, add it to the list of prototypes
115  for( WModuleList::const_iterator iter = m.begin(); iter != m.end(); ++iter )
116  {
117  ( *iter )->setLocalPath( i->path().parent_path() );
118  ticket->get().insert( *iter );
119  m_libs.push_back( l );
120  }
121 
122  wlog::debug( "Module Loader" ) << "Loaded " << m.size() << " modules from " << relPath;
123  }
124 
125  // lib gets closed if l looses focus
126  }
127  catch( const WException& e )
128  {
129  WLogger::getLogger()->addLogMessage( "Load failed for module \"" + relPath + "\". " + e.what() + ". Ignoring.",
130  "Module Loader", LL_ERROR );
131  }
132  }
133  else if( ( level == 0 ) && boost::filesystem::is_directory( *i ) ) // this only traverses down one level
134  {
135  // if it a dir -> traverse down
136  load( ticket, *i, level + 1 );
137  }
138  }
139 }
140 
141 void WModuleLoader::load( WSharedAssociativeContainer< std::set< boost::shared_ptr< WModule > > >::WriteTicket ticket )
142 {
143  std::vector< boost::filesystem::path > allPaths = WPathHelper::getAllModulePaths();
144 
145  // go through each of the paths
146  for( std::vector< boost::filesystem::path >::const_iterator path = allPaths.begin(); path != allPaths.end(); ++path )
147  {
148  WLogger::getLogger()->addLogMessage( "Searching modules in \"" + ( *path ).file_string() + "\".", "Module Loader", LL_INFO );
149 
150  // does the directory exist?
151  if( !boost::filesystem::is_directory( *path ) || !boost::filesystem::exists( *path ) )
152  {
153  WLogger::getLogger()->addLogMessage( "Searching modules in \"" + ( *path ).file_string() +
154  "\" failed. It is not a directory or does not exist." +
155  " Ignoring.", "Module Loader", LL_WARNING );
156 
157  continue;
158  }
159 
160  // directly search the path for libOWmodule_ files
161  load( ticket, *path );
162  }
163 }
164 
166 {
167  // all module file names need to have this prefix:
169 }
170