1 #include <cpPlugins/Interface/Plugins.h>
2 #include <cpPlugins/OS/DLLManager.h>
3 #include <cpPlugins/OS/DirContents.h>
4 #include <cpPlugins/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& env )
87 std::vector< std::string > directories;
88 cpPlugins::Tokenize( directories, env, cpPlugins_ENV_SEPARATOR );
89 for( auto dir = directories.begin( ); dir != directories.end( ); ++dir )
90 this->m_Paths.insert( cpPlugins::CanonicalPath( *dir ) );
93 // -------------------------------------------------------------------------
94 void cpPlugins::Interface::Plugins::
97 std::set< std::string > libs;
98 for( auto d = this->m_Paths.begin( ); d != this->m_Paths.end( ); ++d )
100 std::stringstream fname;
101 fname << *d << cpPlugins_PATH_SEPARATOR << cpPlugins_CONFIG;
103 if( cpPlugins::Read( buffer, fname.str( ) ) )
105 std::istringstream input( buffer );
106 for( std::string line; std::getline( input, line ); )
108 auto pos = line.find( "*" );
109 if( pos != std::string::npos )
111 std::string dname, fname;
112 cpPlugins::OS::SplitPath( dname, fname, line );
113 auto files = cpPlugins::OS::LoadDirContents( dname, false, fname );
114 for( auto fIt = files.begin( ); fIt != files.end( ); ++fIt )
126 for( auto l = libs.begin( ); l != libs.end( ); ++l )
128 std::string lib = cpPlugins::CanonicalPath( *l );
131 if( this->m_Libraries.find( lib ) == this->m_Libraries.end( ) )
133 std::string error = "";
134 void* hnd = cpPlugins::OS::DLLManager::Load( lib, error );
136 this->m_Libraries[ lib ] = hnd;
145 // -------------------------------------------------------------------------
146 void cpPlugins::Interface::Plugins::
147 LoadPaths( const std::string& dir )
149 std::stringstream fname, envs;
151 if( !cpPlugins::IsPathSeparator( dir.back( ) ) )
152 fname << cpPlugins_PATH_SEPARATOR;
153 fname << cpPlugins_PATHS;
155 if( cpPlugins::Read( buffer, fname.str( ) ) )
157 std::istringstream input( buffer );
158 for( std::string line; std::getline( input, line ); )
159 envs << line << cpPlugins_ENV_SEPARATOR;
162 if( envs.str( ).size( ) > 0 )
163 this->AddEnvironments( envs.str( ) );
166 // -------------------------------------------------------------------------
167 void cpPlugins::Interface::Plugins::
168 SavePaths( const std::string& dir ) const
170 std::stringstream buffer;
171 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
172 buffer << *i << std::endl;
174 std::stringstream fname;
176 if( !cpPlugins::IsPathSeparator( dir.back( ) ) )
177 fname << cpPlugins_PATH_SEPARATOR;
178 fname << cpPlugins_PATHS;
179 if( !cpPlugins::Write( buffer.str( ), fname.str( ) ) )
180 throw std::runtime_error( "Error writing environment file." );
183 // -------------------------------------------------------------------------
184 void cpPlugins::Interface::Plugins::
185 LoadFile( const std::string& fname )
187 // Resolve canonical filename
188 std::string can_name = cpPlugins::CanonicalPath( fname );
190 throw std::runtime_error(
191 std::string( "Loading file: can't find library \"" ) +
195 if( this->m_Plugins.find( can_name ) != this->m_Plugins.end( ) )
199 std::string error = "";
200 void* hnd = cpPlugins::OS::DLLManager::Load( can_name, error );
202 throw std::runtime_error(
203 std::string( "Loading plugin library: " ) + error
207 typedef const char* ( *_TFunction )( );
208 _TFunction plugins_name_function = ( _TFunction )(
209 cpPlugins::OS::DLLManager::GetFunctionHandle( hnd, "cpPlugins_Name" )
211 if( plugins_name_function == NULL )
213 cpPlugins::OS::DLLManager::UnLoad( hnd );
214 throw std::runtime_error(
215 std::string( "Library \"" ) +
217 std::string( "\" not recognized as a cpPlugins library" )
221 std::string plugins_name = plugins_name_function( );
223 // Get loaded filters
224 _TFunction function = ( _TFunction )(
225 cpPlugins::OS::DLLManager::GetFunctionHandle( hnd, "cpPlugins_LoadedFilters" )
227 if( function == NULL )
229 cpPlugins::OS::DLLManager::UnLoad( hnd );
230 throw std::runtime_error(
231 std::string( "Library \"" ) +
233 std::string( "\" not recognized as a cpPlugins library" )
237 std::string descriptors = function( );
238 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
239 std::istringstream str( descriptors );
243 std::string value, category, name;
247 std::replace( value.begin( ), value.end( ), ':', ' ' );
248 std::istringstream value_str( value );
249 value_str >> category >> name;
251 // Check if the filter has been already loaded
253 auto fIt = this->m_Filters.find( category );
254 if( fIt != this->m_Filters.end( ) )
255 found = fIt->second.find( name ) != fIt->second.end( );
258 cpPlugins::OS::DLLManager::UnLoad( hnd );
259 throw std::runtime_error(
260 std::string( "Filter \"" ) +
261 category + std::string( "::" ) + name +
262 std::string( "\" already exists." )
267 // Get filter creator
268 TCreator creator = ( TCreator )(
269 cpPlugins::OS::DLLManager::GetFunctionHandle(
270 hnd, category + "_" + name
273 if( creator == NULL )
275 cpPlugins::OS::DLLManager::UnLoad( hnd );
276 throw std::runtime_error(
277 std::string( "Filter \"" ) +
278 category + std::string( "::" ) + name +
279 std::string( "\" does not have a valid creator." )
285 data.PluginName = plugins_name;
286 data.LibraryHandle = hnd;
287 data.Creator = creator;
288 filters[ category ][ name ] = data;
292 // Keep track of all loaded handlers
293 for( auto cIt = filters.begin( ); cIt != filters.end( ); ++cIt )
294 for( auto nIt = cIt->second.begin( ); nIt != cIt->second.end( ); ++nIt )
295 this->m_Filters[ cIt->first ][ nIt->first ] = nIt->second;
296 this->m_Plugins[ can_name ] = hnd;
299 // -------------------------------------------------------------------------
300 void cpPlugins::Interface::Plugins::
301 LoadPlugin( const std::string& pname )
303 std::stringstream fname;
304 fname << cpPlugins_LIB_PREFIX << pname << cpPlugins_LIB_EXT;
305 unsigned int count = 0;
306 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
308 std::stringstream dir;
310 if( !cpPlugins::IsPathSeparator( i->back( ) ) )
311 dir << cpPlugins_PATH_SEPARATOR;
315 this->LoadFile( dir.str( ) );
325 // Throw error, if any
326 if( count == this->m_Paths.size( ) )
327 throw std::runtime_error(
328 std::string( "Could not load plugin " ) +
329 std::string( "\"" ) + pname +
330 std::string( "\" from any registered path." )
334 // -------------------------------------------------------------------------
335 void cpPlugins::Interface::Plugins::
336 LoadDirectory( const std::string& dirname )
338 std::stringstream pat;
339 pat << "*" << cpPlugins_LIB_EXT;
340 auto libs = cpPlugins::OS::LoadDirContents( dirname, false, pat.str( ) );
341 for( auto lIt = libs.begin( ); lIt != libs.end( ); ++lIt )
345 this->LoadFile( *lIt );
352 // -------------------------------------------------------------------------
353 void cpPlugins::Interface::Plugins::
356 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
358 try { this->LoadDirectory( *i ); }
364 // -------------------------------------------------------------------------
365 cpPlugins::Interface::Plugins::TProcess::Pointer
366 cpPlugins::Interface::Plugins::
367 CreateProcessObject( const std::string& category, const std::string& name )
369 typedef cpPlugins::BaseObjects::ProcessObject::Pointer _Ptr;
371 auto cIt = this->m_Filters.find( category );
372 if( cIt != this->m_Filters.end( ) )
374 auto nIt = cIt->second.find( name );
375 if( nIt != cIt->second.end( ) )
377 o = reinterpret_cast< _Ptr* >( nIt->second.Creator( ) )->GetPointer( );
379 o->SetPluginName( nIt->second.PluginName );
387 // -------------------------------------------------------------------------
388 cpPlugins::Interface::Plugins::
392 #ifdef cpPlugins_OS_Windows
395 _dupenv_s( &p, &size, cpPlugins_PATHS );
396 #else // cpPlugins_OS_Windows
397 char* p = std::getenv( cpPlugins_PATHS );
398 #endif // cpPlugins_OS_Windows
399 std::stringstream str;
401 str << p << cpPlugins_ENV_SEPARATOR;
403 this->AddEnvironments( str.str( ) );
406 // -------------------------------------------------------------------------
407 cpPlugins::Interface::Plugins::
412 // -------------------------------------------------------------------------
413 void cpPlugins::Interface::Plugins::
414 PrintSelf( std::ostream& os, itk::Indent indent ) const
417 os << indent << "----- PATHS -----" << std::endl;
418 auto paths = this->GetPaths( );
419 for( auto paIt = paths.begin( ); paIt != paths.end( ); ++paIt )
420 os << indent << *paIt << std::endl;
421 os << indent << std::endl << indent << "----- PLUGINS -----" << std::endl;
422 auto plugins = this->GetPlugins( );
423 for( auto plIt = plugins.begin( ); plIt != plugins.end( ); ++plIt )
424 os << indent << *plIt << std::endl;
425 os << indent << std::endl << indent << "----- FILTERS -----" << std::endl;
426 auto categories = this->GetCategories( );
427 for( auto cIt = categories.begin( ); cIt != categories.end( ); ++cIt )
429 os << indent << "** Category: " << *cIt << " **" << std::endl;
430 auto filters = this->GetFilters( *cIt );
431 for( auto fIt = filters.begin( ); fIt != filters.end( ); ++fIt )
432 os << indent << indent << indent << "Filter: " << *fIt << std::endl;