]> Creatis software - cpPlugins.git/blobdiff - lib/cpPlugins/Interface/Plugins.cxx
debug finished
[cpPlugins.git] / lib / cpPlugins / Interface / Plugins.cxx
index 260172e467c41e1b0d93ca5a1d0d6d419189aaa7..9da2f70e9d31b54fa3233a41eff6fcb9af64250d 100644 (file)
@@ -1,18 +1,20 @@
 #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 );
 }
 
 // -------------------------------------------------------------------------
@@ -20,7 +22,7 @@ itk::LightObject::Pointer cpPlugins::Interface::Plugins::
 CreateAnother( ) const
 {
   itk::LightObject::Pointer smartPtr;
-  smartPtr = NULL;
+  smartPtr = Self::m_Singleton;
   return( smartPtr );
 }
 
@@ -29,413 +31,174 @@ cpPlugins::Interface::Plugins::
 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;
@@ -448,39 +211,10 @@ Plugins( )
   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$