#include <cpPlugins/Interface/Plugins.h>
#include <cpPlugins/OS/DLLManager.h>
-#include <cpPlugins/Interface/Dirent.h>
-#include <cpExtensions/Utility.h>
-#include <regex>
+#include <cpPlugins/OS/DirContents.h>
+#include <cpPlugins/Utility.h>
+
+// -------------------------------------------------------------------------
+cpPlugins::Interface::Plugins::Pointer
+cpPlugins::Interface::Plugins::m_Singleton = NULL;
// -------------------------------------------------------------------------
cpPlugins::Interface::Plugins::
Pointer cpPlugins::Interface::Plugins::
New( )
{
- static Pointer singleton = NULL;
- if( singleton.IsNull( ) )
- singleton = new Self( );
- return( singleton );
+ if( Self::m_Singleton.IsNull( ) )
+ Self::m_Singleton = new Self( );
+ return( Self::m_Singleton );
}
// -------------------------------------------------------------------------
CreateAnother( ) const
{
itk::LightObject::Pointer smartPtr;
- smartPtr = NULL;
+ smartPtr = Self::m_Singleton;
return( smartPtr );
}
Pointer cpPlugins::Interface::Plugins::
Clone( ) const
{
- Pointer r = NULL;
- return( r );
+ return( Self::m_Singleton );
}
// -------------------------------------------------------------------------
-cpPlugins::Interface::Plugins::
-TStrings cpPlugins::Interface::Plugins::
-GetLibraries( ) const
+const cpPlugins::Interface::Plugins::
+TFilters& cpPlugins::Interface::Plugins::
+GetFilters( ) const
{
- TStrings res;
- for(
- auto i = this->m_Libraries.begin( ); i != this->m_Libraries.end( ); ++i
- )
- res.insert( i->first );
- return( res );
+ return( this->m_Filters );
}
// -------------------------------------------------------------------------
-cpPlugins::Interface::Plugins::
-TStrings cpPlugins::Interface::Plugins::
-GetPlugins( ) const
+void cpPlugins::Interface::Plugins::
+LoadPluginsFile( const std::string& libname )
{
- TStrings res;
- for( auto i = this->m_Plugins.begin( ); i != this->m_Plugins.end( ); ++i )
- res.insert( i->first );
- return( res );
+ std::map< std::string, std::set< std::string > > filters;
+ cpPlugins::OS::DLLManager::GetPluginsLibraryContents( filters, libname );
+ THandlers zero( NULL, NULL );
+ for( auto i : filters )
+ for( auto j : i.second )
+ this->m_Filters[ i.first ][ j ] = TLibData( libname, zero );
}
// -------------------------------------------------------------------------
-cpPlugins::Interface::Plugins::
-TStrings cpPlugins::Interface::Plugins::
-GetCategories( ) const
+void cpPlugins::Interface::Plugins::
+LoadPluginsDirectory( const std::string& dir )
{
- TStrings res;
- for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i )
- res.insert( i->first );
- return( res );
-}
+ // Create a globbing pattern
+ std::stringstream glob;
+ glob << cpPlugins_LIB_PREFIX << "*" << cpPlugins_LIB_EXT;
-// -------------------------------------------------------------------------
-cpPlugins::Interface::Plugins::
-TStrings cpPlugins::Interface::Plugins::
-GetFilters( const std::string& category ) const
-{
- TStrings res;
- auto cIt = this->m_Filters.find( category );
- if( cIt != this->m_Filters.end( ) )
- for( auto i = cIt->second.begin( ); i != cIt->second.end( ); ++i )
- res.insert( i->first );
- return( res );
+ // Get possible shared libraries
+ std::set< std::string > files =
+ cpPlugins::OS::LoadDirContents( dir, false, glob.str( ) );
+ this->m_PluginsPaths.insert( dir );
+ for( auto f : files )
+ try { this->LoadPluginsFile( f ); } catch( ... ) { }
}
// -------------------------------------------------------------------------
void cpPlugins::Interface::Plugins::
-AddEnvironments( const std::string& env )
+GuessPlugins( )
{
- std::vector< std::string > directories;
- cpExtensions::Tokenize( directories, env, cpPlugins_ENV_SEPARATOR );
- for( auto dir = directories.begin( ); dir != directories.end( ); ++dir )
- this->m_Paths.insert( cpExtensions::CanonicalPath( *dir ) );
-}
+ // Create a globbing pattern
+ std::stringstream glob;
+ glob << cpPlugins_LIB_PREFIX << "*" << cpPlugins_LIB_EXT;
-// -------------------------------------------------------------------------
-void cpPlugins::Interface::Plugins::
-LoadEnvironments( )
-{
- std::set< std::string > libs;
- for( auto d = this->m_Paths.begin( ); d != this->m_Paths.end( ); ++d )
+ // Update paths and get possible shared libraries
+ this->_ReadPluginsPathsVariable( );
+ for( auto dir : this->m_PluginsPaths )
{
- std::stringstream fname;
- fname << *d << cpPlugins_PATH_SEPARATOR << cpPlugins_CONFIG;
- std::string buffer;
- if( cpExtensions::Read( buffer, fname.str( ) ) )
- {
- std::istringstream input( buffer );
- for( std::string line; std::getline( input, line ); )
- {
- std::vector< std::string > tokens;
- cpExtensions::Tokenize( tokens, line, "|" );
- if( tokens.size( ) == 2 )
- {
- std::string pth = tokens[ 0 ];
- std::string lib = tokens[ 1 ];
- if( lib.find( "*" ) != std::string::npos )
- {
- std::string ext( cpPlugins_LIB_EXT );
- DIR* dir;
- struct dirent* ent;
- if( ( dir = opendir( pth.c_str( ) ) ) != NULL )
- {
- while( ( ent = readdir( dir ) ) != NULL )
- {
- std::string fname( ent->d_name );
- long pos = long( fname.size( ) ) - long( ext.size( ) );
- if( pos > 0 )
- {
- if( fname.substr( pos ) == ext )
- {
- std::regex re( lib );
-std::smatch match;
-if( std::regex_search( fname, match, re ) && match.size( ) >= 1 )
- {
- std::stringstream str;
- str
- << pth << cpPlugins_PATH_SEPARATOR << fname;
- libs.insert( str.str( ) );
- } // fi
-
- } // fi
-
- } // fi
-
- } // elihw
- closedir( dir );
-
- } // fi
- }
- else
- {
- std::stringstream str;
- str
- << pth << cpPlugins_PATH_SEPARATOR << cpPlugins_LIB_PREFIX
- << lib << cpPlugins_LIB_EXT;
- libs.insert( str.str( ) );
-
- } // fi
-
- } // fi
-
- } // rof
-
- } // fi
-
- } // rof
- for( auto l = libs.begin( ); l != libs.end( ); ++l )
- {
- std::string lib = cpExtensions::CanonicalPath( *l );
- if( lib != "" )
- {
- if( this->m_Libraries.find( lib ) == this->m_Libraries.end( ) )
-{
- std::string error = "";
- void* hnd = cpPlugins::OS::DLLManager::Load( lib, error );
- if( hnd != NULL )
- this->m_Libraries[ lib ] = hnd;
-
-} // fi
-
- } // fi
+ std::set< std::string > files =
+ cpPlugins::OS::LoadDirContents( dir, false, glob.str( ) );
+ for( auto f : files )
+ try { this->LoadPluginsFile( f ); } catch( ... ) { }
} // rof
}
// -------------------------------------------------------------------------
void cpPlugins::Interface::Plugins::
-LoadPaths( const std::string& dir )
+GuessEnvironment( const std::string& dir )
{
- std::stringstream fname, envs;
- fname << dir;
- if( !cpExtensions::IsPathSeparator( dir.back( ) ) )
- fname << cpExtensions_PATH_SEPARATOR;
- fname << cpPlugins_PATHS;
- std::string buffer;
- if( cpExtensions::Read( buffer, fname.str( ) ) )
- {
- std::istringstream input( buffer );
- for( std::string line; std::getline( input, line ); )
- envs << line << cpPlugins_ENV_SEPARATOR;
+ std::stringstream fname;
+ fname << dir << cpPlugins_PATH_SEPARATOR << cpPlugins_PATHS;
+ std::string buffer;
+ if( cpPlugins::Read( buffer, fname.str( ) ) )
+ {
+ std::istringstream input( buffer );
+ for( std::string line; std::getline( input, line ); )
+ this->m_PluginsPaths.insert( cpPlugins::CanonicalPath( line ) );
- } // fi
- if( envs.str( ).size( ) > 0 )
- this->AddEnvironments( envs.str( ) );
+ } // fi
}
// -------------------------------------------------------------------------
-void cpPlugins::Interface::Plugins::
-SavePaths( const std::string& dir ) const
+bool cpPlugins::Interface::Plugins::
+SaveEnvironment( const std::string& dir )
{
std::stringstream buffer;
- for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
- buffer << *i << std::endl;
-
+ for( auto p : this->m_PluginsPaths )
+ buffer << p << std::endl;
std::stringstream fname;
- fname << dir;
- if( !cpExtensions::IsPathSeparator( dir.back( ) ) )
- fname << cpExtensions_PATH_SEPARATOR;
- fname << cpPlugins_PATHS;
- if( !cpExtensions::Write( buffer.str( ), fname.str( ) ) )
- throw std::runtime_error( "Error writing environment file." );
+ fname << dir << cpPlugins_PATH_SEPARATOR << cpPlugins_PATHS;
+ return( cpPlugins::Write( buffer.str( ), fname.str( ) ) );
}
// -------------------------------------------------------------------------
-void cpPlugins::Interface::Plugins::
-LoadFile( const std::string& fname )
+cpPlugins::BaseObjects::ProcessObject::Pointer
+cpPlugins::Interface::Plugins::
+CreateFilter( const std::string& category, const std::string& name )
{
- // Resolve canonical filename
- std::string can_name = cpExtensions::CanonicalPath( fname );
- if( can_name == "" )
- throw std::runtime_error(
- std::string( "Loading file: can't find library \"" ) +
- fname +
- std::string( "\"" )
- );
- if( this->m_Plugins.find( can_name ) != this->m_Plugins.end( ) )
- return;
-
- // Load the library
- std::string error = "";
- void* hnd = cpPlugins::OS::DLLManager::Load( can_name, error );
- if( hnd == NULL )
- throw std::runtime_error(
- std::string( "Loading plugin library: " ) + error
- );
-
- // Get plugins name
- typedef const char* ( *_TFunction )( );
- _TFunction plugins_name_function = ( _TFunction )(
- cpPlugins::OS::DLLManager::GetFunctionHandle( hnd, "cpPlugins_Name" )
- );
- if( plugins_name_function == NULL )
+ typedef void* ( *_TCreator )( );
+ typedef cpPlugins::BaseObjects::ProcessObject::Pointer _TPtr;
+ _TPtr o = NULL;
+ auto cat = this->m_Filters.find( category );
+ if( cat != this->m_Filters.end( ) )
{
- cpPlugins::OS::DLLManager::UnLoad( hnd );
- throw std::runtime_error(
- std::string( "Library \"" ) +
- can_name +
- std::string( "\" not recognized as a cpPlugins library" )
- );
-
- } // fi
- std::string plugins_name = plugins_name_function( );
+ auto nam = cat->second.find( name );
+ if( nam != cat->second.end( ) )
+ {
+ void* l_hnd = nam->second.second.first;
+ void* f_hnd = nam->second.second.second;
+ if( l_hnd == NULL )
+ {
+ l_hnd = cpPlugins::OS::DLLManager::LoadPlugins( nam->second.first );
+ nam->second.second.first = l_hnd;
- // Get loaded filters
- _TFunction function = ( _TFunction )(
- cpPlugins::OS::DLLManager::GetFunctionHandle( hnd, "cpPlugins_LoadedFilters" )
- );
- if( function == NULL )
- {
- cpPlugins::OS::DLLManager::UnLoad( hnd );
- throw std::runtime_error(
- std::string( "Library \"" ) +
- can_name +
- std::string( "\" not recognized as a cpPlugins library" )
- );
+ } // fi
+ if( f_hnd == NULL )
+ {
+ f_hnd =
+ cpPlugins::OS::DLLManager::LoadCreator( l_hnd, category, name );
+ nam->second.second.second = f_hnd;
- } // fi
- std::string descriptors = function( );
- std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
- std::istringstream str( descriptors );
- TFilters filters;
- while( str )
- {
- std::string value, category, name;
- str >> value;
- if( value == "" )
- continue;
- std::replace( value.begin( ), value.end( ), ':', ' ' );
- std::istringstream value_str( value );
- value_str >> category >> name;
+ } // fi
+ _TCreator creator = reinterpret_cast< _TCreator >( f_hnd );
+ if( creator != NULL )
+ {
+ void* a = creator( );
+ o = reinterpret_cast< _TPtr* >( a )->GetPointer( );
+ o->SetName( name );
+ o->SetPluginName( nam->second.first );
- // Check if the filter has been already loaded
- bool found = false;
- auto fIt = this->m_Filters.find( category );
- if( fIt != this->m_Filters.end( ) )
- found = fIt->second.find( name ) != fIt->second.end( );
- if( found )
- {
- cpPlugins::OS::DLLManager::UnLoad( hnd );
- throw std::runtime_error(
- std::string( "Filter \"" ) +
- category + std::string( "::" ) + name +
- std::string( "\" already exists." )
- );
+ } // fi
} // fi
- // Get filter creator
- TCreator creator = ( TCreator )(
- cpPlugins::OS::DLLManager::GetFunctionHandle( hnd, category + "_" + name )
+ } // fi
+ if( o.IsNull( ) )
+ throw std::runtime_error(
+ std::string( "Could not create a valid ProcessObject of type \"" ) +
+ category + std::string( ":" ) +
+ name + std::string( "\"" )
);
- if( creator == NULL )
- {
- cpPlugins::OS::DLLManager::UnLoad( hnd );
- throw std::runtime_error(
- std::string( "Filter \"" ) +
- category + std::string( "::" ) + name +
- std::string( "\" does not have a valid creator." )
- );
-
- } // fi
-
- TCreatorData data;
- data.PluginName = plugins_name;
- data.LibraryHandle = hnd;
- data.Creator = creator;
- filters[ category ][ name ] = data;
-
- } // elihw
-
- // Keep track of all loaded handlers
- for( auto cIt = filters.begin( ); cIt != filters.end( ); ++cIt )
- for( auto nIt = cIt->second.begin( ); nIt != cIt->second.end( ); ++nIt )
- this->m_Filters[ cIt->first ][ nIt->first ] = nIt->second;
- this->m_Plugins[ can_name ] = hnd;
+ return( o );
}
// -------------------------------------------------------------------------
-void cpPlugins::Interface::Plugins::
-LoadPlugin( const std::string& pname )
+cpPlugins::Interface::Plugins::
+Plugins( )
+ : Superclass( )
{
- std::stringstream fname;
- fname << cpPlugins_LIB_PREFIX << pname << cpPlugins_LIB_EXT;
- unsigned int count = 0;
- for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
- {
- std::stringstream dir;
- dir << *i;
- if( !cpExtensions::IsPathSeparator( i->back( ) ) )
- dir << cpExtensions_PATH_SEPARATOR;
- dir << fname.str( );
- try
- {
- this->LoadFile( dir.str( ) );
- }
- catch( ... )
- {
- count++;
-
- } // yrt
-
- } // rof
-
- // Throw error, if any
- if( count == this->m_Paths.size( ) )
- throw std::runtime_error(
- std::string( "Could not load plugin " ) +
- std::string( "\"" ) + pname +
- std::string( "\" from any registered path." )
- );
+ cpPlugins::OS::DLLManager::TeaseLoadedLibraries( );
}
// -------------------------------------------------------------------------
-void cpPlugins::Interface::Plugins::
-LoadDirectory( const std::string& dirname )
+cpPlugins::Interface::Plugins::
+~Plugins( )
{
- DIR* dir;
- struct dirent* ent;
- if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
- {
- while( ( ent = readdir( dir ) ) != NULL )
- {
- try
- {
- std::stringstream fname;
- fname << dirname << cpExtensions_PATH_SEPARATOR << ent->d_name;
- this->LoadFile( fname.str( ) );
- }
- catch( ... ) { }
-
- } // elihw
- closedir( dir );
- }
- else
- throw std::runtime_error(
- std::string( "Could not load directory " ) +
- std::string( "\"" ) + dirname + std::string( "\"" )
- );
}
// -------------------------------------------------------------------------
void cpPlugins::Interface::Plugins::
-GuessPlugins( )
+PrintSelf( std::ostream& os, itk::Indent indent ) const
{
- for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
+ for( auto i : this->m_Filters )
{
- try { this->LoadDirectory( *i ); }
- catch( ... ) { }
+ os << indent << "+ " << i.first << std::endl;
+ for( auto j : i.second )
+ os << indent << "|----> " << j.first << std::endl;
} // rof
}
// -------------------------------------------------------------------------
-cpPlugins::Interface::Plugins::TProcess::Pointer
-cpPlugins::Interface::Plugins::
-CreateProcessObject( const std::string& category, const std::string& name )
-{
- typedef cpPlugins::BaseObjects::ProcessObject::Pointer _Ptr;
- _Ptr o = NULL;
- auto cIt = this->m_Filters.find( category );
- if( cIt != this->m_Filters.end( ) )
- {
- auto nIt = cIt->second.find( name );
- if( nIt != cIt->second.end( ) )
- {
- o = reinterpret_cast< _Ptr* >( nIt->second.Creator( ) )->GetPointer( );
- o->SetName( name );
- o->SetPluginName( nIt->second.PluginName );
-
- } // fi
-
- } // fi
- return( o );
-}
-
-// -------------------------------------------------------------------------
-cpPlugins::Interface::Plugins::
-Plugins( )
- : Superclass( )
+void cpPlugins::Interface::Plugins::
+_ReadPluginsPathsVariable( )
{
#ifdef cpPlugins_OS_Windows
char* p;
if( p != NULL )
str << p << cpPlugins_ENV_SEPARATOR;
str << ".";
- this->AddEnvironments( str.str( ) );
-}
-
-// -------------------------------------------------------------------------
-cpPlugins::Interface::Plugins::
-~Plugins( )
-{
-}
-
-// -------------------------------------------------------------------------
-void cpPlugins::Interface::Plugins::
-PrintSelf( std::ostream& os, itk::Indent indent ) const
-{
- // Show data
- os << indent << "----- PATHS -----" << std::endl;
- auto paths = this->GetPaths( );
- for( auto paIt = paths.begin( ); paIt != paths.end( ); ++paIt )
- os << indent << *paIt << std::endl;
- os << indent << std::endl << indent << "----- PLUGINS -----" << std::endl;
- auto plugins = this->GetPlugins( );
- for( auto plIt = plugins.begin( ); plIt != plugins.end( ); ++plIt )
- os << indent << *plIt << std::endl;
- os << indent << std::endl << indent << "----- FILTERS -----" << std::endl;
- auto categories = this->GetCategories( );
- for( auto cIt = categories.begin( ); cIt != categories.end( ); ++cIt )
- {
- os << indent << "** Category: " << *cIt << " **" << std::endl;
- auto filters = this->GetFilters( *cIt );
- for( auto fIt = filters.begin( ); fIt != filters.end( ); ++fIt )
- os << indent << indent << indent << "Filter: " << *fIt << std::endl;
-
- } // rof
-
+ std::vector< std::string > tokens;
+ cpPlugins::Tokenize( tokens, str.str( ), cpPlugins_ENV_SEPARATOR );
+ for( auto dir : tokens )
+ this->m_PluginsPaths.insert( cpPlugins::CanonicalPath( dir ) );
}
// eof - $RCSfile$