1 #include <cpPlugins/Interface.h>
2 #include <cpPlugins/Utilities.h>
3 #include <cpPlugins/DLLManager.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->AddEnvironments( str.str( ) );
19 // -------------------------------------------------------------------------
20 cpPlugins::Interface::
25 // -------------------------------------------------------------------------
26 const cpPlugins::Interface::
27 TStrings& cpPlugins::Interface::
30 return( this->m_Paths );
33 // -------------------------------------------------------------------------
34 cpPlugins::Interface::
35 TStrings cpPlugins::Interface::
40 auto i = this->m_Libraries.begin( ); i != this->m_Libraries.end( ); ++i
42 res.insert( i->first );
46 // -------------------------------------------------------------------------
47 cpPlugins::Interface::
48 TStrings cpPlugins::Interface::
52 for( auto i = this->m_Plugins.begin( ); i != this->m_Plugins.end( ); ++i )
53 res.insert( i->first );
57 // -------------------------------------------------------------------------
58 cpPlugins::Interface::
59 TStrings cpPlugins::Interface::
60 GetCategories( ) const
63 for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i )
64 res.insert( i->first );
68 // -------------------------------------------------------------------------
69 cpPlugins::Interface::
70 TStrings cpPlugins::Interface::
71 GetFilters( const std::string& category ) const
74 auto cIt = this->m_Filters.find( category );
75 if( cIt != this->m_Filters.end( ) )
76 for( auto i = cIt->second.begin( ); i != cIt->second.end( ); ++i )
77 res.insert( i->first );
81 // -------------------------------------------------------------------------
82 void cpPlugins::Interface::
83 AddEnvironments( const std::string& new_environment )
85 std::vector< std::string > tokens;
86 cpPlugins::TokenizeString( tokens, new_environment, cpPlugins_SEPARATOR );
87 for( auto i = tokens.begin( ); i != tokens.end( ); ++i )
89 std::stringstream dir;
90 dir << cpPlugins::CanonicalPath( *i );
91 if( dir.str( ) != "" )
93 if( !cpPlugins::IsPathSeparator( dir.str( ).back( ) ) )
94 dir << cpPlugins_PATH_SEPARATOR;
95 std::stringstream name;
96 name << dir.str( ) << cpPlugins_CONFIG;
97 std::ifstream check( name.str( ).c_str( ), std::ifstream::binary );
99 this->m_Paths.insert( dir.str( ) );
107 // -------------------------------------------------------------------------
108 void cpPlugins::Interface::
111 std::stringstream all_errors;
112 for( auto d = this->m_Paths.begin( ); d != this->m_Paths.end( ); ++d )
114 std::stringstream name;
115 name << *d << cpPlugins_CONFIG;
117 if( cpPlugins::ReadFileIntoBuffer( buffer, name.str( ) ) )
119 std::istringstream input( buffer );
120 for( std::string line; std::getline( input, line ); )
122 std::vector< std::string > tokens;
123 cpPlugins::TokenizeString( tokens, line, "@" );
124 std::string library_file = "";
125 if( tokens[ 0 ] == "local" )
127 cpPlugins::CanonicalPath(
128 *d + std::string( cpPlugins_LIB_PREFIX ) +
129 tokens[ 1 ] + std::string( "." ) +
130 std::string( cpPlugins_LIB_EXT )
132 else if( tokens[ 0 ] == "global" )
133 library_file = tokens[ 1 ];
135 if( library_file != "" )
137 std::string error = "";
138 void* hnd = cpPlugins::DLLManager::Load( library_file, error );
140 this->m_Libraries[ library_file ] = hnd;
142 all_errors << " ; " << error;
153 if( all_errors.str( ) != "" )
154 throw std::runtime_error(
155 std::string( "Loading environment libraries errors: " ) +
160 // -------------------------------------------------------------------------
161 void cpPlugins::Interface::
162 SaveEnvironments( const std::string& dir ) const
164 if( this->m_Paths.size( ) > 0 )
166 std::stringstream buffer;
167 auto i = this->m_Paths.begin( );
168 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
169 buffer << *i << std::endl;
171 std::stringstream fname;
173 if( !cpPlugins::IsPathSeparator( dir.back( ) ) )
174 fname << cpPlugins_PATH_SEPARATOR;
175 fname << cpPlugins_PATHS;
176 if( !cpPlugins::WriteBufferToFile( buffer.str( ), fname.str( ) ) )
177 throw std::runtime_error( "Error writing environment file." );
180 throw std::runtime_error( "No paths to save." );
183 // -------------------------------------------------------------------------
184 void cpPlugins::Interface::
185 OpenEnvironments( const std::string& dir )
187 std::stringstream fname;
189 if( !cpPlugins::IsPathSeparator( dir.back( ) ) )
190 fname << cpPlugins_PATH_SEPARATOR;
191 fname << cpPlugins_PATHS;
193 if( cpPlugins::ReadFileIntoBuffer( buffer, fname.str( ) ) )
195 std::istringstream input( buffer );
196 std::stringstream paths;
197 for( std::string line; std::getline( input, line ); )
198 paths << line << cpPlugins_SEPARATOR;
199 this->AddEnvironments( paths.str( ) );
202 throw std::runtime_error( "Error opening environment file." );
205 // -------------------------------------------------------------------------
206 void cpPlugins::Interface::
207 LoadFile( const std::string& fname )
209 // Resolve canonical filename
210 std::string can_name = cpPlugins::CanonicalPath( fname );
212 throw std::runtime_error(
213 std::string( "Loading file: can't find library \"" ) +
217 if( this->m_Plugins.find( can_name ) != this->m_Plugins.end( ) )
221 std::string error = "";
222 void* hnd = cpPlugins::DLLManager::Load( can_name, error );
224 throw std::runtime_error(
225 std::string( "Loading plugin library: " ) + error
229 typedef const char* ( *_TFunction )( );
230 _TFunction plugins_name_function = ( _TFunction )(
231 cpPlugins::DLLManager::GetFunctionHandle( hnd, "cpPlugins_Name" )
233 if( plugins_name_function == NULL )
235 cpPlugins::DLLManager::UnLoad( hnd );
236 throw std::runtime_error(
237 std::string( "Library \"" ) +
239 std::string( "\" not recognized as a cpPlugins library" )
243 std::string plugins_name = plugins_name_function( );
245 // Get loaded filters
246 _TFunction function = ( _TFunction )(
247 cpPlugins::DLLManager::GetFunctionHandle( hnd, "cpPlugins_LoadedFilters" )
249 if( function == NULL )
251 cpPlugins::DLLManager::UnLoad( hnd );
252 throw std::runtime_error(
253 std::string( "Library \"" ) +
255 std::string( "\" not recognized as a cpPlugins library" )
259 std::string descriptors = function( );
260 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
261 std::istringstream str( descriptors );
265 std::string value, category, name;
269 std::replace( value.begin( ), value.end( ), ':', ' ' );
270 std::istringstream value_str( value );
271 value_str >> category >> name;
273 // Check if the filter has been already loaded
275 auto fIt = this->m_Filters.find( category );
276 if( fIt != this->m_Filters.end( ) )
277 found = fIt->second.find( name ) != fIt->second.end( );
280 cpPlugins::DLLManager::UnLoad( hnd );
281 throw std::runtime_error(
282 std::string( "Filter \"" ) +
283 category + std::string( "::" ) + name +
284 std::string( "\" already exists." )
289 // Get filter creator
290 TCreator creator = ( TCreator )(
291 cpPlugins::DLLManager::GetFunctionHandle( hnd, category + "_" + name )
293 if( creator == NULL )
295 cpPlugins::DLLManager::UnLoad( hnd );
296 throw std::runtime_error(
297 std::string( "Filter \"" ) +
298 category + std::string( "::" ) + name +
299 std::string( "\" does not have a valid creator." )
305 data.PluginName = plugins_name;
306 data.LibraryHandle = hnd;
307 data.Creator = creator;
308 filters[ category ][ name ] = data;
312 // Keep track of all loaded handlers
313 for( auto cIt = filters.begin( ); cIt != filters.end( ); ++cIt )
314 for( auto nIt = cIt->second.begin( ); nIt != cIt->second.end( ); ++nIt )
315 this->m_Filters[ cIt->first ][ nIt->first ] = nIt->second;
316 this->m_Plugins[ can_name ] = hnd;
319 // -------------------------------------------------------------------------
320 void cpPlugins::Interface::
321 LoadPlugin( const std::string& pname )
323 std::stringstream fname;
324 fname << cpPlugins_LIB_PREFIX << pname << "." << cpPlugins_LIB_EXT;
325 unsigned int count = 0;
326 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
328 std::stringstream dir;
330 if( !cpPlugins::IsPathSeparator( i->back( ) ) )
331 dir << cpPlugins_PATH_SEPARATOR;
335 this->LoadFile( dir.str( ) );
345 // Throw error, if any
346 if( count == this->m_Paths.size( ) )
347 throw std::runtime_error(
348 std::string( "Could not load plugin " ) +
349 std::string( "\"" ) + pname +
350 std::string( "\" from any registered path." )
354 // -------------------------------------------------------------------------
355 void cpPlugins::Interface::
356 LoadDirectory( const std::string& dirname )
360 if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
362 while( ( ent = readdir( dir ) ) != NULL )
366 std::stringstream fname;
367 fname << dirname << cpPlugins_PATH_SEPARATOR << ent->d_name;
368 this->LoadFile( fname.str( ) );
376 throw std::runtime_error(
377 std::string( "Could not load directory " ) +
378 std::string( "\"" ) + dirname + std::string( "\"" )
382 // -------------------------------------------------------------------------
383 void cpPlugins::Interface::
386 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
388 try { this->LoadDirectory( *i ); }
394 // -------------------------------------------------------------------------
395 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
396 CreateProcessObject( const std::string& category, const std::string& name )
398 typedef cpPlugins::ProcessObject::Pointer _Ptr;
400 auto cIt = this->m_Filters.find( category );
401 if( cIt != this->m_Filters.end( ) )
403 auto nIt = cIt->second.find( name );
404 if( nIt != cIt->second.end( ) )
406 o = reinterpret_cast< _Ptr* >( nIt->second.Creator( ) )->GetPointer( );
408 o->SetPluginName( nIt->second.PluginName );