1 #include <cpPlugins/Interface.h>
2 #include <cpPlugins/Utilities.h>
3 #include <cpPlugins/LoadDynamicLibrariesFunctions.h>
4 #include <cpPlugins/dirent.h>
7 // -------------------------------------------------------------------------
11 char* p = std::getenv( cpPlugins_PATHS );
12 std::stringstream str;
14 str << p << cpPlugins_SEPARATOR;
16 this->UpdateEnvironments( str.str( ) );
19 // -------------------------------------------------------------------------
20 cpPlugins::Interface::
25 // -------------------------------------------------------------------------
26 const std::set< std::string >& cpPlugins::Interface::
29 return( this->m_Paths );
32 // -------------------------------------------------------------------------
33 std::set< std::string > cpPlugins::Interface::
36 std::set< std::string > res;
38 auto i = this->m_Libraries.begin( ); i != this->m_Libraries.end( ); ++i
40 res.insert( i->first );
44 // -------------------------------------------------------------------------
45 std::set< std::string > cpPlugins::Interface::
48 std::set< std::string > res;
49 for( auto i = this->m_Plugins.begin( ); i != this->m_Plugins.end( ); ++i )
50 res.insert( i->first );
54 // -------------------------------------------------------------------------
55 std::set< std::string > cpPlugins::Interface::
56 GetCategories( ) const
58 std::set< std::string > res;
59 for( auto i = this->m_Filters.begin( ); i != this->m_Filters.end( ); ++i )
60 res.insert( i->first );
64 // -------------------------------------------------------------------------
65 std::set< std::string > cpPlugins::Interface::
66 GetFilters( const std::string& category ) const
68 std::set< std::string > res;
69 auto cIt = this->m_Filters.find( category );
70 if( cIt != this->m_Filters.end( ) )
72 for( auto i = cIt->second.begin( ); i != cIt->second.end( ); ++i )
73 res.insert( i->first );
79 // -------------------------------------------------------------------------
80 void cpPlugins::Interface::
81 UpdateEnvironments( const std::string& new_environment )
83 std::vector< std::string > tokens;
84 cpPlugins::TokenizeString( tokens, new_environment, cpPlugins_SEPARATOR );
85 for( auto i = tokens.begin( ); i != tokens.end( ); ++i )
87 std::string dir = cpPlugins::CanonicalPath( *i );
89 this->m_Paths.insert( dir );
94 // -------------------------------------------------------------------------
95 void cpPlugins::Interface::
98 std::stringstream all_errors;
99 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
101 std::stringstream dir;
103 if( !cpPlugins::IsPathSeparator( i->back( ) ) )
104 dir << cpPlugins_PATH_SEPARATOR;
105 std::string config_file;
107 cpPlugins::ReadFileIntoBuffer(
109 cpPlugins::CanonicalPath(
110 dir.str( ) + std::string( cpPlugins_CONFIG )
115 std::istringstream input( config_file );
116 for( std::string line; std::getline( input, line ); )
118 std::vector< std::string > tokens;
119 cpPlugins::TokenizeString( tokens, line, "@" );
120 std::string library_file = "";
121 if( tokens[ 0 ] == "local" )
123 cpPlugins::CanonicalPath(
125 std::string( cpPlugins_LIB_PREFIX ) +
128 std::string( cpPlugins_LIB_EXT )
130 else if( tokens[ 0 ] == "global" )
131 library_file = tokens[ 1 ];
133 if( library_file != "" )
135 std::string error = "";
136 void* hnd = cpPlugins::DLLManager::Load( library_file, error );
138 this->m_Libraries[ library_file ] = hnd;
140 all_errors << " ; " << error;
151 if( all_errors.str( ) != "" )
152 throw std::runtime_error(
153 std::string( "Loading environment libraries errors: " ) +
158 // -------------------------------------------------------------------------
159 void cpPlugins::Interface::
160 LoadFile( const std::string& fname )
162 // Resolve canonical filename
163 std::string can_name = cpPlugins::CanonicalPath( fname );
165 throw std::runtime_error(
166 std::string( "Loading file: can't find library \"" ) +
170 if( this->m_Plugins.find( can_name ) != this->m_Plugins.end( ) )
174 std::string error = "";
175 void* hnd = cpPlugins::DLLManager::Load( can_name, error );
177 throw std::runtime_error(
178 std::string( "Loading plugin library: " ) + error
182 typedef const char* ( *_TFunction )( );
183 _TFunction plugins_name_function = ( _TFunction )(
184 cpPlugins::DLLManager::GetFunctionHandle( hnd, "cpPlugins_Name" )
186 if( plugins_name_function == NULL )
188 cpPlugins::DLLManager::UnLoad( hnd );
189 throw std::runtime_error(
190 std::string( "Library \"" ) +
192 std::string( "\" not recognized as a cpPlugins library" )
196 std::string plugins_name = plugins_name_function( );
198 // Get loaded filters
199 _TFunction function = ( _TFunction )(
200 cpPlugins::DLLManager::GetFunctionHandle( hnd, "cpPlugins_LoadedFilters" )
202 if( function == NULL )
204 cpPlugins::DLLManager::UnLoad( hnd );
205 throw std::runtime_error(
206 std::string( "Library \"" ) +
208 std::string( "\" not recognized as a cpPlugins library" )
212 std::string descriptors = function( );
213 std::replace( descriptors.begin( ), descriptors.end( ), ';', ' ' );
214 std::istringstream str( descriptors );
218 std::string value, category, name;
222 std::replace( value.begin( ), value.end( ), ':', ' ' );
223 std::istringstream value_str( value );
224 value_str >> category >> name;
226 // Check if the filter has been already loaded
228 auto fIt = this->m_Filters.find( category );
229 if( fIt != this->m_Filters.end( ) )
230 found = fIt->second.find( name ) != fIt->second.end( );
233 cpPlugins::DLLManager::UnLoad( hnd );
234 throw std::runtime_error(
235 std::string( "Filter \"" ) +
236 category + std::string( "::" ) + name +
237 std::string( "\" already exists." )
242 // Get filter creator
243 TCreator creator = ( TCreator )(
244 cpPlugins::DLLManager::GetFunctionHandle( hnd, category + "_" + name )
246 if( creator == NULL )
248 cpPlugins::DLLManager::UnLoad( hnd );
249 throw std::runtime_error(
250 std::string( "Filter \"" ) +
251 category + std::string( "::" ) + name +
252 std::string( "\" does not have a valid creator." )
258 data.PluginName = plugins_name;
259 data.LibraryHandle = hnd;
260 data.Creator = creator;
261 filters[ category ][ name ] = data;
265 // Keep track of all loaded handlers
266 for( auto cIt = filters.begin( ); cIt != filters.end( ); ++cIt )
267 for( auto nIt = cIt->second.begin( ); nIt != cIt->second.end( ); ++nIt )
268 this->m_Filters[ cIt->first ][ nIt->first ] = nIt->second;
269 this->m_Plugins[ can_name ] = hnd;
272 // -------------------------------------------------------------------------
273 void cpPlugins::Interface::
274 LoadPlugin( const std::string& pname )
276 std::stringstream fname;
277 fname << cpPlugins_LIB_PREFIX << pname << "." << cpPlugins_LIB_EXT;
278 unsigned int count = 0;
279 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
281 std::stringstream dir;
283 if( !cpPlugins::IsPathSeparator( i->back( ) ) )
284 dir << cpPlugins_PATH_SEPARATOR;
288 this->LoadFile( dir.str( ) );
298 // Throw error, if any
299 if( count == this->m_Paths.size( ) )
300 throw std::runtime_error(
301 std::string( "Could not load plugin " ) +
302 std::string( "\"" ) + pname +
303 std::string( "\" from any registered path." )
307 // -------------------------------------------------------------------------
308 void cpPlugins::Interface::
309 LoadDirectory( const std::string& dirname )
313 if( ( dir = opendir( dirname.c_str( ) ) ) != NULL )
315 while( ( ent = readdir( dir ) ) != NULL )
319 std::stringstream fname;
320 fname << dirname << cpPlugins_PATH_SEPARATOR << ent->d_name;
321 this->LoadFile( fname.str( ) );
329 throw std::runtime_error(
330 std::string( "Could not load directory " ) +
331 std::string( "\"" ) + dirname + std::string( "\"" )
335 // -------------------------------------------------------------------------
336 void cpPlugins::Interface::
339 for( auto i = this->m_Paths.begin( ); i != this->m_Paths.end( ); ++i )
343 this->LoadDirectory( *i );
352 // -------------------------------------------------------------------------
353 cpPlugins::ProcessObject::Pointer cpPlugins::Interface::
354 CreateProcessObject( const std::string& category, const std::string& name )
356 typedef cpPlugins::ProcessObject::Pointer _Ptr;
358 auto cIt = this->m_Filters.find( category );
359 if( cIt != this->m_Filters.end( ) )
361 auto nIt = cIt->second.find( name );
362 if( nIt != cIt->second.end( ) )
364 o = reinterpret_cast< _Ptr* >( nIt->second.Creator( ) )->GetPointer( );
366 o->SetPluginName( nIt->second.PluginName );