1 #include <cpPlugins/Interface/Plugins.h>
2 #include <cpPlugins/OS/DLLManager.h>
3 #include <cpPlugins/Interface/Dirent.h>
4 #include <cpExtensions/Utility.h>
7 // -------------------------------------------------------------------------
8 cpPlugins::Interface::Plugins::
9 Pointer cpPlugins::Interface::Plugins::
12 static Pointer singleton = NULL;
13 if( singleton.IsNull( ) )
14 singleton = new Self( );
18 // -------------------------------------------------------------------------
19 itk::LightObject::Pointer cpPlugins::Interface::Plugins::
20 CreateAnother( ) const
22 itk::LightObject::Pointer smartPtr;
27 // -------------------------------------------------------------------------
28 cpPlugins::Interface::Plugins::
29 Pointer cpPlugins::Interface::Plugins::
36 // -------------------------------------------------------------------------
37 cpPlugins::Interface::Plugins::
38 TStrings cpPlugins::Interface::Plugins::
43 auto i = this->m_Libraries.begin( ); i != this->m_Libraries.end( ); ++i
45 res.insert( i->first );
49 // -------------------------------------------------------------------------
50 cpPlugins::Interface::Plugins::
51 TStrings cpPlugins::Interface::Plugins::
55 for( auto i = this->m_Plugins.begin( ); i != this->m_Plugins.end( ); ++i )
56 res.insert( i->first );
60 // -------------------------------------------------------------------------
61 cpPlugins::Interface::Plugins::
62 TStrings cpPlugins::Interface::Plugins::
63 GetCategories( ) const
66 for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i )
67 res.insert( i->first );
71 // -------------------------------------------------------------------------
72 cpPlugins::Interface::Plugins::
73 TStrings cpPlugins::Interface::Plugins::
74 GetFilters( const std::string& category ) const
77 auto cIt = this->m_Filters.find( category );
78 if( cIt != this->m_Filters.end( ) )
79 for( auto i = cIt->second.begin( ); i != cIt->second.end( ); ++i )
80 res.insert( i->first );
84 // -------------------------------------------------------------------------
85 void cpPlugins::Interface::Plugins::
86 AddEnvironments( const std::string& env )
88 std::vector< std::string > directories;
89 cpExtensions::Tokenize( directories, env, cpPlugins_ENV_SEPARATOR );
90 for( auto dir = directories.begin( ); dir != directories.end( ); ++dir )
91 this->m_Paths.insert( cpExtensions::CanonicalPath( *dir ) );
94 // -------------------------------------------------------------------------
95 void cpPlugins::Interface::Plugins::
98 std::set< std::string > libs;
99 for( auto d = this->m_Paths.begin( ); d != this->m_Paths.end( ); ++d )
101 std::stringstream fname;
102 fname << *d << cpPlugins_PATH_SEPARATOR << cpPlugins_CONFIG;
104 if( cpExtensions::Read( buffer, fname.str( ) ) )
106 std::istringstream input( buffer );
107 for( std::string line; std::getline( input, line ); )
109 std::vector< std::string > tokens;
110 cpExtensions::Tokenize( tokens, line, "|" );
111 if( tokens.size( ) == 2 )
113 std::string pth = tokens[ 0 ];
114 std::string lib = tokens[ 1 ];
115 if( lib.find( "*" ) != std::string::npos )
117 std::string ext( cpPlugins_LIB_EXT );
120 if( ( dir = opendir( pth.c_str( ) ) ) != NULL )
122 while( ( ent = readdir( dir ) ) != NULL )
124 std::string fname( ent->d_name );
125 long pos = long( fname.size( ) ) - long( ext.size( ) );
128 if( fname.substr( pos ) == ext )
130 std::regex re( lib );
132 if( std::regex_search( fname, match, re ) && match.size( ) >= 1 )
134 std::stringstream str;
136 << pth << cpPlugins_PATH_SEPARATOR << fname;
137 libs.insert( str.str( ) );
151 std::stringstream str;
153 << pth << cpPlugins_PATH_SEPARATOR << cpPlugins_LIB_PREFIX
154 << lib << cpPlugins_LIB_EXT;
155 libs.insert( str.str( ) );
166 for( auto l = libs.begin( ); l != libs.end( ); ++l )
168 std::string lib = cpExtensions::CanonicalPath( *l );
171 if( this->m_Libraries.find( lib ) == this->m_Libraries.end( ) )
173 std::string error = "";
174 void* hnd = cpPlugins::OS::DLLManager::Load( lib, error );
176 this->m_Libraries[ lib ] = hnd;
185 // -------------------------------------------------------------------------
186 void cpPlugins::Interface::Plugins::
187 LoadPaths( const std::string& dir )
189 std::stringstream fname, envs;
191 if( !cpExtensions::IsPathSeparator( dir.back( ) ) )
192 fname << cpExtensions_PATH_SEPARATOR;
193 fname << cpPlugins_PATHS;
195 if( cpExtensions::Read( buffer, fname.str( ) ) )
197 std::istringstream input( buffer );
198 for( std::string line; std::getline( input, line ); )
199 envs << line << cpPlugins_ENV_SEPARATOR;
202 if( envs.str( ).size( ) > 0 )
203 this->AddEnvironments( envs.str( ) );
206 // -------------------------------------------------------------------------
207 void cpPlugins::Interface::Plugins::
208 SavePaths( const std::string& dir ) const
210 std::stringstream buffer;
211 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
212 buffer << *i << std::endl;
214 std::stringstream fname;
216 if( !cpExtensions::IsPathSeparator( dir.back( ) ) )
217 fname << cpExtensions_PATH_SEPARATOR;
218 fname << cpPlugins_PATHS;
219 if( !cpExtensions::Write( buffer.str( ), fname.str( ) ) )
220 throw std::runtime_error( "Error writing environment file." );
223 // -------------------------------------------------------------------------
224 void cpPlugins::Interface::Plugins::
225 LoadFile( const std::string& fname )
227 // Resolve canonical filename
228 std::string can_name = cpExtensions::CanonicalPath( fname );
230 throw std::runtime_error(
231 std::string( "Loading file: can't find library \"" ) +
235 if( this->m_Plugins.find( can_name ) != this->m_Plugins.end( ) )
239 std::string error = "";
240 void* hnd = cpPlugins::OS::DLLManager::Load( can_name, error );
242 throw std::runtime_error(
243 std::string( "Loading plugin library: " ) + error
247 typedef const char* ( *_TFunction )( );
248 _TFunction plugins_name_function = ( _TFunction )(
249 cpPlugins::OS::DLLManager::GetFunctionHandle( hnd, "cpPlugins_Name" )
251 if( plugins_name_function == NULL )
253 cpPlugins::OS::DLLManager::UnLoad( hnd );
254 throw std::runtime_error(
255 std::string( "Library \"" ) +
257 std::string( "\" not recognized as a cpPlugins library" )
261 std::string plugins_name = plugins_name_function( );
263 // Get loaded filters
264 _TFunction function = ( _TFunction )(
265 cpPlugins::OS::DLLManager::GetFunctionHandle( hnd, "cpPlugins_LoadedFilters" )
267 if( function == NULL )
269 cpPlugins::OS::DLLManager::UnLoad( hnd );
270 throw std::runtime_error(
271 std::string( "Library \"" ) +
273 std::string( "\" not recognized as a cpPlugins library" )
277 std::string descriptors = function( );
278 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
279 std::istringstream str( descriptors );
283 std::string value, category, name;
287 std::replace( value.begin( ), value.end( ), ':', ' ' );
288 std::istringstream value_str( value );
289 value_str >> category >> name;
291 // Check if the filter has been already loaded
293 auto fIt = this->m_Filters.find( category );
294 if( fIt != this->m_Filters.end( ) )
295 found = fIt->second.find( name ) != fIt->second.end( );
298 cpPlugins::OS::DLLManager::UnLoad( hnd );
299 throw std::runtime_error(
300 std::string( "Filter \"" ) +
301 category + std::string( "::" ) + name +
302 std::string( "\" already exists." )
307 // Get filter creator
308 TCreator creator = ( TCreator )(
309 cpPlugins::OS::DLLManager::GetFunctionHandle( hnd, category + "_" + name )
311 if( creator == NULL )
313 cpPlugins::OS::DLLManager::UnLoad( hnd );
314 throw std::runtime_error(
315 std::string( "Filter \"" ) +
316 category + std::string( "::" ) + name +
317 std::string( "\" does not have a valid creator." )
323 data.PluginName = plugins_name;
324 data.LibraryHandle = hnd;
325 data.Creator = creator;
326 filters[ category ][ name ] = data;
330 // Keep track of all loaded handlers
331 for( auto cIt = filters.begin( ); cIt != filters.end( ); ++cIt )
332 for( auto nIt = cIt->second.begin( ); nIt != cIt->second.end( ); ++nIt )
333 this->m_Filters[ cIt->first ][ nIt->first ] = nIt->second;
334 this->m_Plugins[ can_name ] = hnd;
337 // -------------------------------------------------------------------------
338 void cpPlugins::Interface::Plugins::
339 LoadPlugin( const std::string& pname )
341 std::stringstream fname;
342 fname << cpPlugins_LIB_PREFIX << pname << cpPlugins_LIB_EXT;
343 unsigned int count = 0;
344 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
346 std::stringstream dir;
348 if( !cpExtensions::IsPathSeparator( i->back( ) ) )
349 dir << cpExtensions_PATH_SEPARATOR;
353 this->LoadFile( dir.str( ) );
363 // Throw error, if any
364 if( count == this->m_Paths.size( ) )
365 throw std::runtime_error(
366 std::string( "Could not load plugin " ) +
367 std::string( "\"" ) + pname +
368 std::string( "\" from any registered path." )
372 // -------------------------------------------------------------------------
373 void cpPlugins::Interface::Plugins::
374 LoadDirectory( const std::string& dirname )
378 if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
380 while( ( ent = readdir( dir ) ) != NULL )
384 std::stringstream fname;
385 fname << dirname << cpExtensions_PATH_SEPARATOR << ent->d_name;
386 this->LoadFile( fname.str( ) );
394 throw std::runtime_error(
395 std::string( "Could not load directory " ) +
396 std::string( "\"" ) + dirname + std::string( "\"" )
400 // -------------------------------------------------------------------------
401 void cpPlugins::Interface::Plugins::
404 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
406 try { this->LoadDirectory( *i ); }
412 // -------------------------------------------------------------------------
413 cpPlugins::Interface::Plugins::TProcess::Pointer
414 cpPlugins::Interface::Plugins::
415 CreateProcessObject( const std::string& category, const std::string& name )
417 typedef cpPlugins::BaseObjects::ProcessObject::Pointer _Ptr;
419 auto cIt = this->m_Filters.find( category );
420 if( cIt != this->m_Filters.end( ) )
422 auto nIt = cIt->second.find( name );
423 if( nIt != cIt->second.end( ) )
425 o = reinterpret_cast< _Ptr* >( nIt->second.Creator( ) )->GetPointer( );
427 o->SetPluginName( nIt->second.PluginName );
435 // -------------------------------------------------------------------------
436 cpPlugins::Interface::Plugins::
440 #ifdef cpPlugins_OS_Windows
443 _dupenv_s( &p, &size, cpPlugins_PATHS );
444 #else // cpPlugins_OS_Windows
445 char* p = std::getenv( cpPlugins_PATHS );
446 #endif // cpPlugins_OS_Windows
447 std::stringstream str;
449 str << p << cpPlugins_ENV_SEPARATOR;
451 this->AddEnvironments( str.str( ) );
454 // -------------------------------------------------------------------------
455 cpPlugins::Interface::Plugins::
460 // -------------------------------------------------------------------------
461 void cpPlugins::Interface::Plugins::
462 PrintSelf( std::ostream& os, itk::Indent indent ) const
465 os << indent << "----- PATHS -----" << std::endl;
466 auto paths = this->GetPaths( );
467 for( auto paIt = paths.begin( ); paIt != paths.end( ); ++paIt )
468 os << indent << *paIt << std::endl;
469 os << indent << std::endl << indent << "----- PLUGINS -----" << std::endl;
470 auto plugins = this->GetPlugins( );
471 for( auto plIt = plugins.begin( ); plIt != plugins.end( ); ++plIt )
472 os << indent << *plIt << std::endl;
473 os << indent << std::endl << indent << "----- FILTERS -----" << std::endl;
474 auto categories = this->GetCategories( );
475 for( auto cIt = categories.begin( ); cIt != categories.end( ); ++cIt )
477 os << indent << "** Category: " << *cIt << " **" << std::endl;
478 auto filters = this->GetFilters( *cIt );
479 for( auto fIt = filters.begin( ); fIt != filters.end( ); ++fIt )
480 os << indent << indent << indent << "Filter: " << *fIt << std::endl;