1 #include <cpPlugins/Interface.h>
2 #include <cpPlugins/Utilities.h>
3 #include <cpPlugins/LoadDynamicLibrariesFunctions.h>
4 #include <cpPlugins/dirent.h>
7 // -------------------------------------------------------------------------
11 char* p = std::getenv( cpPlugins_PATHS );
12 std::stringstream str;
14 str << p << cpPlugins_SEPARATOR;
16 this->UpdateEnvironments( str.str( ) );
19 // -------------------------------------------------------------------------
20 cpPlugins::Interface::
25 // -------------------------------------------------------------------------
26 const std::set< std::string >& cpPlugins::Interface::
29 return( this->m_Paths );
32 // -------------------------------------------------------------------------
33 std::set< std::string > cpPlugins::Interface::
36 std::set< std::string > res;
38 auto i = this->m_Libraries.begin( ); i != this->m_Libraries.end( ); ++i
40 res.insert( i->first );
44 // -------------------------------------------------------------------------
45 std::set< std::string > cpPlugins::Interface::
48 std::set< std::string > res;
49 for( auto i = this->m_Plugins.begin( ); i != this->m_Plugins.end( ); ++i )
50 res.insert( i->first );
54 // -------------------------------------------------------------------------
55 std::set< std::string > cpPlugins::Interface::
56 GetCategories( ) const
58 std::set< std::string > res;
59 for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i )
60 res.insert( i->first );
64 // -------------------------------------------------------------------------
65 std::set< std::string > cpPlugins::Interface::
66 GetFilters( const std::string& category ) const
68 std::set< std::string > res;
69 auto cIt = this->m_Filters.find( category );
70 if( cIt != this->m_Filters.end( ) )
72 for( auto i = cIt->second.begin( ); i != cIt->second.end( ); ++i )
73 res.insert( i->first );
79 // -------------------------------------------------------------------------
80 void cpPlugins::Interface::
81 UpdateEnvironments( const std::string& new_environment )
83 std::vector< std::string > tokens;
84 cpPlugins::TokenizeString( tokens, new_environment, cpPlugins_SEPARATOR );
85 for( auto i = tokens.begin( ); i != tokens.end( ); ++i )
87 std::string dir = cpPlugins::CanonicalPath( *i );
89 this->m_Paths.insert( dir );
94 // -------------------------------------------------------------------------
95 void cpPlugins::Interface::
98 std::stringstream all_errors;
99 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
101 std::stringstream dir;
103 if( !cpPlugins::IsPathSeparator( i->back( ) ) )
104 dir << cpPlugins_PATH_SEPARATOR;
105 std::string fname = dir.str( ) + std::string( cpPlugins_CONFIG );
106 std::string config_file;
107 if( cpPlugins::ReadFileIntoBuffer( config_file, fname ) )
109 std::istringstream input( config_file );
110 for( std::string line; std::getline( input, line ); )
112 std::vector< std::string > tokens;
113 cpPlugins::TokenizeString( tokens, line, "@" );
114 std::string library_file = "";
115 if( tokens[ 0 ] == "local" )
117 cpPlugins::CanonicalPath(
119 std::string( cpPlugins_LIB_PREFIX ) +
122 std::string( cpPlugins_LIB_EXT )
124 else if( tokens[ 0 ] == "global" )
125 library_file = tokens[ 1 ];
127 if( library_file != "" )
129 std::string error = "";
130 void* hnd = cpPlugins::DLLManager::Load( library_file, error );
132 this->m_Libraries[ library_file ] = hnd;
134 all_errors << " ; " << error;
145 if( all_errors.str( ) != "" )
146 throw std::runtime_error(
147 std::string( "Loading environment libraries errors: " ) +
152 // -------------------------------------------------------------------------
153 void cpPlugins::Interface::
154 SaveEnvironments( const std::string& dir ) const
156 if( this->m_Paths.size( ) > 0 )
158 std::stringstream buffer;
159 auto i = this->m_Paths.begin( );
160 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
161 buffer << *i << std::endl;
163 std::stringstream fname;
165 if( cpPlugins::IsPathSeparator( dir.back( ) ) )
166 fname << cpPlugins_PATH_SEPARATOR;
167 fname << cpPlugins_CONFIG;
168 if( !( cpPlugins::WriteBufferToFile( buffer.str( ), fname.str( ) ) ) )
169 throw std::runtime_error( "Error writing environment file." );
172 throw std::runtime_error( "No paths to save." );
175 // -------------------------------------------------------------------------
176 void cpPlugins::Interface::
177 OpenEnvironments( const std::string& dir )
179 std::stringstream fname;
181 if( cpPlugins::IsPathSeparator( dir.back( ) ) )
182 fname << cpPlugins_PATH_SEPARATOR;
183 fname << cpPlugins_CONFIG;
185 if( cpPlugins::ReadFileIntoBuffer( buffer, fname.str( ) ) )
187 std::istringstream input( buffer );
188 for( std::string line; std::getline( input, line ); )
189 this->m_Paths.insert( cpPlugins::CanonicalPath( line ) );
192 throw std::runtime_error( "Error opening environment file." );
195 // -------------------------------------------------------------------------
196 void cpPlugins::Interface::
197 LoadFile( const std::string& fname )
199 // Resolve canonical filename
200 std::string can_name = cpPlugins::CanonicalPath( fname );
202 throw std::runtime_error(
203 std::string( "Loading file: can't find library \"" ) +
207 if( this->m_Plugins.find( can_name ) != this->m_Plugins.end( ) )
211 std::string error = "";
212 void* hnd = cpPlugins::DLLManager::Load( can_name, error );
214 throw std::runtime_error(
215 std::string( "Loading plugin library: " ) + error
219 typedef const char* ( *_TFunction )( );
220 _TFunction plugins_name_function = ( _TFunction )(
221 cpPlugins::DLLManager::GetFunctionHandle( hnd, "cpPlugins_Name" )
223 if( plugins_name_function == NULL )
225 cpPlugins::DLLManager::UnLoad( hnd );
226 throw std::runtime_error(
227 std::string( "Library \"" ) +
229 std::string( "\" not recognized as a cpPlugins library" )
233 std::string plugins_name = plugins_name_function( );
235 // Get loaded filters
236 _TFunction function = ( _TFunction )(
237 cpPlugins::DLLManager::GetFunctionHandle( hnd, "cpPlugins_LoadedFilters" )
239 if( function == NULL )
241 cpPlugins::DLLManager::UnLoad( hnd );
242 throw std::runtime_error(
243 std::string( "Library \"" ) +
245 std::string( "\" not recognized as a cpPlugins library" )
249 std::string descriptors = function( );
250 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
251 std::istringstream str( descriptors );
255 std::string value, category, name;
259 std::replace( value.begin( ), value.end( ), ':', ' ' );
260 std::istringstream value_str( value );
261 value_str >> category >> name;
263 // Check if the filter has been already loaded
265 auto fIt = this->m_Filters.find( category );
266 if( fIt != this->m_Filters.end( ) )
267 found = fIt->second.find( name ) != fIt->second.end( );
270 cpPlugins::DLLManager::UnLoad( hnd );
271 throw std::runtime_error(
272 std::string( "Filter \"" ) +
273 category + std::string( "::" ) + name +
274 std::string( "\" already exists." )
279 // Get filter creator
280 TCreator creator = ( TCreator )(
281 cpPlugins::DLLManager::GetFunctionHandle( hnd, category + "_" + name )
283 if( creator == NULL )
285 cpPlugins::DLLManager::UnLoad( hnd );
286 throw std::runtime_error(
287 std::string( "Filter \"" ) +
288 category + std::string( "::" ) + name +
289 std::string( "\" does not have a valid creator." )
295 data.PluginName = plugins_name;
296 data.LibraryHandle = hnd;
297 data.Creator = creator;
298 filters[ category ][ name ] = data;
302 // Keep track of all loaded handlers
303 for( auto cIt = filters.begin( ); cIt != filters.end( ); ++cIt )
304 for( auto nIt = cIt->second.begin( ); nIt != cIt->second.end( ); ++nIt )
305 this->m_Filters[ cIt->first ][ nIt->first ] = nIt->second;
306 this->m_Plugins[ can_name ] = hnd;
309 // -------------------------------------------------------------------------
310 void cpPlugins::Interface::
311 LoadPlugin( const std::string& pname )
313 std::stringstream fname;
314 fname << cpPlugins_LIB_PREFIX << pname << "." << cpPlugins_LIB_EXT;
315 unsigned int count = 0;
316 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
318 std::stringstream dir;
320 if( !cpPlugins::IsPathSeparator( i->back( ) ) )
321 dir << cpPlugins_PATH_SEPARATOR;
325 this->LoadFile( dir.str( ) );
335 // Throw error, if any
336 if( count == this->m_Paths.size( ) )
337 throw std::runtime_error(
338 std::string( "Could not load plugin " ) +
339 std::string( "\"" ) + pname +
340 std::string( "\" from any registered path." )
344 // -------------------------------------------------------------------------
345 void cpPlugins::Interface::
346 LoadDirectory( const std::string& dirname )
350 if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
352 while( ( ent = readdir( dir ) ) != NULL )
356 std::stringstream fname;
357 fname << dirname << cpPlugins_PATH_SEPARATOR << ent->d_name;
358 this->LoadFile( fname.str( ) );
366 throw std::runtime_error(
367 std::string( "Could not load directory " ) +
368 std::string( "\"" ) + dirname + std::string( "\"" )
372 // -------------------------------------------------------------------------
373 void cpPlugins::Interface::
376 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
380 this->LoadDirectory( *i );
389 // -------------------------------------------------------------------------
390 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
391 CreateProcessObject( const std::string& category, const std::string& name )
393 typedef cpPlugins::ProcessObject::Pointer _Ptr;
395 auto cIt = this->m_Filters.find( category );
396 if( cIt != this->m_Filters.end( ) )
398 auto nIt = cIt->second.find( name );
399 if( nIt != cIt->second.end( ) )
401 o = reinterpret_cast< _Ptr* >( nIt->second.Creator( ) )->GetPointer( );
403 o->SetPluginName( nIt->second.PluginName );