1 #include <cpPlugins/Interface/Plugins.h>
2 #include <cpPlugins/OS/DLLManager.h>
3 #include <cpPlugins/Interface/Dirent.h>
4 #include <cpExtensions/Utility.h>
6 // -------------------------------------------------------------------------
7 cpPlugins::Interface::Plugins::
8 Pointer cpPlugins::Interface::Plugins::
11 static Pointer singleton = NULL;
12 if( singleton.IsNull( ) )
13 singleton = new Self( );
17 // -------------------------------------------------------------------------
18 itk::LightObject::Pointer cpPlugins::Interface::Plugins::
19 CreateAnother( ) const
21 itk::LightObject::Pointer smartPtr;
26 // -------------------------------------------------------------------------
27 cpPlugins::Interface::Plugins::
28 Pointer cpPlugins::Interface::Plugins::
35 // -------------------------------------------------------------------------
36 cpPlugins::Interface::Plugins::
37 TStrings cpPlugins::Interface::Plugins::
42 auto i = this->m_Libraries.begin( ); i != this->m_Libraries.end( ); ++i
44 res.insert( i->first );
48 // -------------------------------------------------------------------------
49 cpPlugins::Interface::Plugins::
50 TStrings cpPlugins::Interface::Plugins::
54 for( auto i = this->m_Plugins.begin( ); i != this->m_Plugins.end( ); ++i )
55 res.insert( i->first );
59 // -------------------------------------------------------------------------
60 cpPlugins::Interface::Plugins::
61 TStrings cpPlugins::Interface::Plugins::
62 GetCategories( ) const
65 for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i )
66 res.insert( i->first );
70 // -------------------------------------------------------------------------
71 cpPlugins::Interface::Plugins::
72 TStrings cpPlugins::Interface::Plugins::
73 GetFilters( const std::string& category ) const
76 auto cIt = this->m_Filters.find( category );
77 if( cIt != this->m_Filters.end( ) )
78 for( auto i = cIt->second.begin( ); i != cIt->second.end( ); ++i )
79 res.insert( i->first );
83 // -------------------------------------------------------------------------
84 void cpPlugins::Interface::Plugins::
85 AddEnvironments( const std::string& new_environment )
87 std::vector< std::string > tokens;
88 cpExtensions::Tokenize( tokens, new_environment, cpPlugins_ENV_SEPARATOR );
89 for( auto i = tokens.begin( ); i != tokens.end( ); ++i )
91 std::stringstream dir;
92 dir << cpExtensions::CanonicalPath( *i );
93 if( dir.str( ) != "" )
95 if( !cpExtensions::IsPathSeparator( dir.str( ).back( ) ) )
96 dir << cpExtensions_PATH_SEPARATOR;
97 std::stringstream name;
98 name << dir.str( ) << cpPlugins_CONFIG;
99 std::ifstream check( name.str( ).c_str( ), std::ifstream::binary );
101 this->m_Paths.insert( dir.str( ) );
109 // -------------------------------------------------------------------------
110 void cpPlugins::Interface::Plugins::
113 std::stringstream all_errors;
114 for( auto d = this->m_Paths.begin( ); d != this->m_Paths.end( ); ++d )
116 std::stringstream name;
117 name << *d << cpPlugins_CONFIG;
119 if( cpExtensions::Read( buffer, name.str( ) ) )
121 std::istringstream input( buffer );
122 for( std::string line; std::getline( input, line ); )
124 std::vector< std::string > tokens;
125 cpExtensions::Tokenize( tokens, line, "@" );
126 std::string library_file = "";
127 if( tokens[ 0 ] == "local" )
129 cpExtensions::CanonicalPath(
130 *d + std::string( cpPlugins_LIB_PREFIX ) +
131 tokens[ 1 ] + std::string( cpPlugins_LIB_EXT )
133 else if( tokens[ 0 ] == "global" )
134 library_file = tokens[ 1 ];
136 if( library_file != "" )
138 std::string error = "";
139 void* hnd = cpPlugins::OS::DLLManager::Load( library_file, error );
141 this->m_Libraries[ library_file ] = hnd;
143 all_errors << " ; " << error;
154 if( all_errors.str( ) != "" )
155 throw std::runtime_error(
156 std::string( "Loading environment libraries errors: " ) +
161 // -------------------------------------------------------------------------
162 void cpPlugins::Interface::Plugins::
163 SaveEnvironments( const std::string& dir ) const
165 if( this->m_Paths.size( ) > 0 )
167 std::stringstream buffer;
168 auto i = this->m_Paths.begin( );
169 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
170 buffer << *i << std::endl;
172 std::stringstream fname;
174 if( !cpExtensions::IsPathSeparator( dir.back( ) ) )
175 fname << cpExtensions_PATH_SEPARATOR;
176 fname << cpPlugins_PATHS;
177 if( !cpExtensions::Write( buffer.str( ), fname.str( ) ) )
178 throw std::runtime_error( "Error writing environment file." );
181 throw std::runtime_error( "No paths to save." );
184 // -------------------------------------------------------------------------
185 void cpPlugins::Interface::Plugins::
186 OpenEnvironments( const std::string& dir )
188 std::stringstream fname;
190 if( !cpExtensions::IsPathSeparator( dir.back( ) ) )
191 fname << cpExtensions_PATH_SEPARATOR;
192 fname << cpPlugins_PATHS;
194 if( cpExtensions::Read( buffer, fname.str( ) ) )
196 std::istringstream input( buffer );
197 std::stringstream paths;
198 for( std::string line; std::getline( input, line ); )
199 paths << line << cpPlugins_ENV_SEPARATOR;
200 this->AddEnvironments( paths.str( ) );
203 throw std::runtime_error( "Error opening environment file." );
206 // -------------------------------------------------------------------------
207 void cpPlugins::Interface::Plugins::
208 LoadFile( const std::string& fname )
210 // Resolve canonical filename
211 std::string can_name = cpExtensions::CanonicalPath( fname );
213 throw std::runtime_error(
214 std::string( "Loading file: can't find library \"" ) +
218 if( this->m_Plugins.find( can_name ) != this->m_Plugins.end( ) )
222 std::string error = "";
223 void* hnd = cpPlugins::OS::DLLManager::Load( can_name, error );
225 throw std::runtime_error(
226 std::string( "Loading plugin library: " ) + error
230 typedef const char* ( *_TFunction )( );
231 _TFunction plugins_name_function = ( _TFunction )(
232 cpPlugins::OS::DLLManager::GetFunctionHandle( hnd, "cpPlugins_Name" )
234 if( plugins_name_function == NULL )
236 cpPlugins::OS::DLLManager::UnLoad( hnd );
237 throw std::runtime_error(
238 std::string( "Library \"" ) +
240 std::string( "\" not recognized as a cpPlugins library" )
244 std::string plugins_name = plugins_name_function( );
246 // Get loaded filters
247 _TFunction function = ( _TFunction )(
248 cpPlugins::OS::DLLManager::GetFunctionHandle( hnd, "cpPlugins_LoadedFilters" )
250 if( function == NULL )
252 cpPlugins::OS::DLLManager::UnLoad( hnd );
253 throw std::runtime_error(
254 std::string( "Library \"" ) +
256 std::string( "\" not recognized as a cpPlugins library" )
260 std::string descriptors = function( );
261 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
262 std::istringstream str( descriptors );
266 std::string value, category, name;
270 std::replace( value.begin( ), value.end( ), ':', ' ' );
271 std::istringstream value_str( value );
272 value_str >> category >> name;
274 // Check if the filter has been already loaded
276 auto fIt = this->m_Filters.find( category );
277 if( fIt != this->m_Filters.end( ) )
278 found = fIt->second.find( name ) != fIt->second.end( );
281 cpPlugins::OS::DLLManager::UnLoad( hnd );
282 throw std::runtime_error(
283 std::string( "Filter \"" ) +
284 category + std::string( "::" ) + name +
285 std::string( "\" already exists." )
290 // Get filter creator
291 TCreator creator = ( TCreator )(
292 cpPlugins::OS::DLLManager::GetFunctionHandle( hnd, category + "_" + name )
294 if( creator == NULL )
296 cpPlugins::OS::DLLManager::UnLoad( hnd );
297 throw std::runtime_error(
298 std::string( "Filter \"" ) +
299 category + std::string( "::" ) + name +
300 std::string( "\" does not have a valid creator." )
306 data.PluginName = plugins_name;
307 data.LibraryHandle = hnd;
308 data.Creator = creator;
309 filters[ category ][ name ] = data;
313 // Keep track of all loaded handlers
314 for( auto cIt = filters.begin( ); cIt != filters.end( ); ++cIt )
315 for( auto nIt = cIt->second.begin( ); nIt != cIt->second.end( ); ++nIt )
316 this->m_Filters[ cIt->first ][ nIt->first ] = nIt->second;
317 this->m_Plugins[ can_name ] = hnd;
320 // -------------------------------------------------------------------------
321 void cpPlugins::Interface::Plugins::
322 LoadPlugin( const std::string& pname )
324 std::stringstream fname;
325 fname << cpPlugins_LIB_PREFIX << pname << cpPlugins_LIB_EXT;
326 unsigned int count = 0;
327 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
329 std::stringstream dir;
331 if( !cpExtensions::IsPathSeparator( i->back( ) ) )
332 dir << cpExtensions_PATH_SEPARATOR;
336 this->LoadFile( dir.str( ) );
346 // Throw error, if any
347 if( count == this->m_Paths.size( ) )
348 throw std::runtime_error(
349 std::string( "Could not load plugin " ) +
350 std::string( "\"" ) + pname +
351 std::string( "\" from any registered path." )
355 // -------------------------------------------------------------------------
356 void cpPlugins::Interface::Plugins::
357 LoadDirectory( const std::string& dirname )
361 if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
363 while( ( ent = readdir( dir ) ) != NULL )
367 std::stringstream fname;
368 fname << dirname << cpExtensions_PATH_SEPARATOR << ent->d_name;
369 this->LoadFile( fname.str( ) );
377 throw std::runtime_error(
378 std::string( "Could not load directory " ) +
379 std::string( "\"" ) + dirname + std::string( "\"" )
383 // -------------------------------------------------------------------------
384 void cpPlugins::Interface::Plugins::
387 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
389 try { this->LoadDirectory( *i ); }
395 // -------------------------------------------------------------------------
396 cpPlugins::Interface::Plugins::TProcess::Pointer
397 cpPlugins::Interface::Plugins::
398 CreateProcessObject( const std::string& category, const std::string& name )
400 typedef cpPlugins::BaseObjects::ProcessObject::Pointer _Ptr;
402 auto cIt = this->m_Filters.find( category );
403 if( cIt != this->m_Filters.end( ) )
405 auto nIt = cIt->second.find( name );
406 if( nIt != cIt->second.end( ) )
408 o = reinterpret_cast< _Ptr* >( nIt->second.Creator( ) )->GetPointer( );
410 o->SetPluginName( nIt->second.PluginName );
418 // -------------------------------------------------------------------------
419 cpPlugins::Interface::Plugins::
423 char* p = std::getenv( cpPlugins_PATHS );
424 std::stringstream str;
426 str << p << cpPlugins_ENV_SEPARATOR;
428 this->AddEnvironments( str.str( ) );
430 // Try to read locally defined paths
431 std::vector< std::string > tokens;
432 cpExtensions::Tokenize( tokens, str.str( ), cpPlugins_ENV_SEPARATOR );
433 for( auto t = tokens.begin( ); t != tokens.end( ); ++t )
434 this->OpenEnvironments( *t );
437 // -------------------------------------------------------------------------
438 cpPlugins::Interface::Plugins::
443 // -------------------------------------------------------------------------
444 void cpPlugins::Interface::Plugins::
445 PrintSelf( std::ostream& os, itk::Indent indent ) const
448 os << indent << "----- PATHS -----" << std::endl;
449 auto paths = this->GetPaths( );
450 for( auto paIt = paths.begin( ); paIt != paths.end( ); ++paIt )
451 os << indent << *paIt << std::endl;
452 os << indent << std::endl << indent << "----- PLUGINS -----" << std::endl;
453 auto plugins = this->GetPlugins( );
454 for( auto plIt = plugins.begin( ); plIt != plugins.end( ); ++plIt )
455 os << indent << *plIt << std::endl;
456 os << indent << std::endl << indent << "----- FILTERS -----" << std::endl;
457 auto categories = this->GetCategories( );
458 for( auto cIt = categories.begin( ); cIt != categories.end( ); ++cIt )
460 os << indent << "** Category: " << *cIt << " **" << std::endl;
461 auto filters = this->GetFilters( *cIt );
462 for( auto fIt = filters.begin( ); fIt != filters.end( ); ++fIt )
463 os << indent << indent << indent << "Filter: " << *fIt << std::endl;