]> Creatis software - cpPlugins.git/blob - lib/cpPlugins/Interface/Interface.cxx
...
[cpPlugins.git] / lib / cpPlugins / Interface / Interface.cxx
1 #include <cpPlugins/Interface/Interface.h>
2 #include <cpPlugins/Interface/ProcessObjectProvider.h>
3 #include <algorithm>
4 #include <cstdlib>
5 #include <fstream>
6 #include <sstream>
7 #include <Pluma/Pluma.hpp>
8
9 #ifdef _WIN32
10 #  define PLUGIN_PREFIX ""
11 #  define PLUGIN_EXT ".dll"
12 #else // Linux
13 #  define PLUGIN_PREFIX "lib"
14 #  define PLUGIN_EXT ".so"
15 #endif // _WIN32
16 #define PLUGIN_CONFIG_FILE "plugins.cfg"
17
18 namespace cpPlugins
19 {
20   namespace Interface
21   {
22     struct PathSeparator
23     {
24       bool operator()( char c ) const
25         {
26 #ifdef _WIN32
27           return( c == '\\' || c == '/' );
28 #else // Linux like
29           return( c == '/' );
30 #endif // _WIN32
31         }
32     };
33
34   } // ecapseman
35
36 } // ecapseman
37
38 // -------------------------------------------------------------------------
39 std::string cpPlugins_Interface_CanonicalPath( const std::string& path )
40 {
41 #ifdef _WIN32
42   TCHAR  buffer[ 4096 ] = TEXT( "" );
43   TCHAR** lppPart = { NULL };
44   GetFullPathName( path.c_str( ), 4096, buffer, lppPart );
45   return( std::string( buffer ) );
46 #else // Linux like
47   return( std::string( realpath( path.c_str( ), NULL ) ) );
48 #endif // _WIN32
49 }
50
51 // -------------------------------------------------------------------------
52 cpPlugins::Interface::Interface::
53 Interface( )
54 {
55   this->m_Pluma = new pluma::Pluma( );
56   this->m_Pluma->acceptProviderType< ProcessObjectProvider >( );
57 }
58
59 // -------------------------------------------------------------------------
60 cpPlugins::Interface::Interface::
61 ~Interface( )
62 {
63   this->UnloadAll( );
64   delete this->m_Pluma;
65 }
66
67 // -------------------------------------------------------------------------
68 bool cpPlugins::Interface::Interface::
69 LoadDefaultConfiguration( const std::string& path )
70 {
71   std::ifstream file( PLUGIN_CONFIG_FILE );
72   if( file )
73   {
74     char buffer[ 1000 ];
75     while( file.getline( buffer, 1000 ) )
76     {
77       // std::string line( buffer );
78       std::istringstream line( buffer );
79       std::string name, folder;
80       std::getline( line, name, '@' );
81       std::getline( line, folder, '@' );
82       std::stringstream path;
83       path << folder << "/" << PLUGIN_PREFIX << name << PLUGIN_EXT;
84       this->Load( path.str( ) );
85
86     } // elihw
87
88     file.close( );
89     return( true );
90   }
91   else
92     return( false );
93 }
94
95 // -------------------------------------------------------------------------
96 bool cpPlugins::Interface::Interface::
97 SaveDefaultConfiguration( const std::string& path )
98 {
99   std::ofstream file( PLUGIN_CONFIG_FILE );
100   if( file )
101   {
102     auto pIt = this->m_LoadedPlugins.begin( );
103     for( ; pIt != this->m_LoadedPlugins.end( ); ++pIt )
104     {
105       auto fIt = pIt->second.begin( );
106       for( ; fIt != pIt->second.end( ); ++fIt )
107         file << *fIt << "@" << pIt->first << std::endl;
108
109     } // rof
110     file.close( );
111     return( true );
112   }
113   else
114     return( false );
115 }
116
117 // -------------------------------------------------------------------------
118 cpPlugins::Interface::Interface::
119 TClasses& cpPlugins::Interface::Interface::
120 GetClasses( )
121 {
122   return( this->m_Classes );
123 }
124
125 // -------------------------------------------------------------------------
126 const cpPlugins::Interface::Interface::
127 TClasses& cpPlugins::Interface::Interface::
128 GetClasses( ) const
129 {
130   return( this->m_Classes );
131 }
132
133 // -------------------------------------------------------------------------
134 cpPlugins::Interface::Interface::
135 TLoadedPlugins& cpPlugins::Interface::Interface::
136 GetLoadedPlugins( )
137 {
138   return( this->m_LoadedPlugins );
139 }
140
141 // -------------------------------------------------------------------------
142 const cpPlugins::Interface::Interface::
143 TLoadedPlugins& cpPlugins::Interface::Interface::
144 GetLoadedPlugins( ) const
145 {
146   return( this->m_LoadedPlugins );
147 }
148
149 // -------------------------------------------------------------------------
150 cpPlugins::Interface::ProcessObject::Pointer
151 cpPlugins::Interface::Interface::
152 CreateObject( const std::string& name ) const
153 {
154   cpPlugins::Interface::ProcessObject::Pointer po = NULL;
155   auto catIt = this->m_Classes.begin( );
156   while( catIt != this->m_Classes.end( ) )
157   {
158     auto classIt = catIt->second.find( name );
159     if( classIt != catIt->second.end( ) )
160     {
161       ProcessObjectProvider* provider =
162         dynamic_cast< ProcessObjectProvider* >(
163           this->m_Providers[ classIt->second ]
164           );
165       if( provider != NULL )
166         po = provider->create( );
167       catIt = this->m_Classes.end( );
168     }
169     else
170       catIt++;
171
172   } // elihw
173
174   return( po );
175 }
176
177 // -------------------------------------------------------------------------
178 bool cpPlugins::Interface::Interface::
179 Load( const std::string& path )
180 {
181   bool ret = true;
182   try
183   {
184     ret = this->m_Pluma->load( path );
185     if( ret )
186     {
187       std::string folder, name;
188       Self::_SepFName( path, folder, name );
189       this->m_LoadedPlugins[ folder ].push_back( name );
190       this->_LoadClasses( );
191
192     } // fi
193   }
194   catch( ... )
195   {
196     ret = false;
197
198   } // yrt
199   return( ret );
200 }
201
202 // -------------------------------------------------------------------------
203 bool cpPlugins::Interface::Interface::
204 Load( const std::string& folder, const std::string& name )
205 {
206   std::string real_folder = folder;
207   PathSeparator sep;
208   if( sep( folder[ folder.size( ) - 1 ] ) )
209     real_folder = folder.substr( 0, folder.size( ) - 1 );
210   real_folder = cpPlugins_Interface_CanonicalPath( real_folder );
211
212   bool ret = true;
213   try
214   {
215     ret = this->m_Pluma->load( real_folder, name );
216     if( ret )
217     {
218       // Update loaded plugins
219       std::string prefix( PLUGIN_PREFIX );
220       std::string ext( PLUGIN_EXT );
221       std::string real_name = name;
222       if( prefix != "" )
223         real_name.replace( real_name.find( prefix ), prefix.size( ), "" );
224       real_name.replace( real_name.find( ext ), ext.size( ), "" );
225       this->m_LoadedPlugins[ real_folder ].push_back( real_name );
226       this->_LoadClasses( );
227
228     } // fi
229   }
230   catch( ... )
231   {
232     ret = false;
233
234   } // yrt
235   return( ret );
236 }
237
238 // -------------------------------------------------------------------------
239 bool cpPlugins::Interface::Interface::
240 LoadFromFolder( const std::string& folder, bool r )
241 {
242   try
243   {
244     std::list< std::string > f = this->m_Pluma->loadFromFolder( folder, r );
245     if( f.size( ) > 0 )
246     {
247       // Update loaded plugins
248       for( auto i = f.begin( ); i != f.end( ); ++i )
249       {
250         std::string folder, name;
251         Self::_SepFName( *i, folder, name );
252         this->m_LoadedPlugins[ folder ].push_back( name );
253
254       } // rof
255
256       // Load classes
257       this->_LoadClasses( );
258       return( true );
259     }
260     else
261       return( false );
262   }
263   catch( ... )
264   {
265     return( false );
266
267   } // yrt
268 }
269
270 // -------------------------------------------------------------------------
271 bool cpPlugins::Interface::Interface::
272 Unload( const std::string& name )
273 {
274   bool ret = true;
275   try
276   {
277     ret = this->m_Pluma->unload( name );
278     if( ret )
279     {
280       this->m_Providers.clear( );
281       this->m_Classes.clear( );
282
283       // TODO: this->m_LoadedPlugins
284
285       this->_LoadClasses( );
286
287     } // fi
288   }
289   catch( ... )
290   {
291     ret = false;
292
293   } // yrt
294   return( ret );
295 }
296
297 // -------------------------------------------------------------------------
298 void cpPlugins::Interface::Interface::
299 UnloadAll( )
300 {
301   try
302   {
303     this->m_Pluma->unloadAll( );
304   }
305   catch( ... )
306   {
307     // Do nothing
308
309   } // yrt
310   this->m_Providers.clear( );
311   this->m_Classes.clear( );
312   this->m_LoadedPlugins.clear( );
313 }
314
315 // -------------------------------------------------------------------------
316 bool cpPlugins::Interface::Interface::
317 IsLoaded( const std::string& name ) const
318 {
319   return( this->m_Pluma->isLoaded( name ) );
320 }
321
322 // -------------------------------------------------------------------------
323 void cpPlugins::Interface::Interface::
324 _LoadClasses( )
325 {
326   this->m_Providers.clear( );
327   this->m_Classes.clear( );
328   this->m_Pluma->getProviders( this->m_Providers );
329
330   // Get reader provider
331   for( unsigned int i = 0; i < this->m_Providers.size( ); ++i )
332   {
333     ProcessObject::Pointer d = this->m_Providers[ i ]->create( );
334     this->m_Classes[ d->GetClassCategory( ) ][ d->GetClassName( ) ] = i;
335
336   } // rof
337 }
338
339 // -------------------------------------------------------------------------
340 void cpPlugins::Interface::Interface::
341 _SepFName( const std::string& path, std::string& folder, std::string& name )
342 {
343   PathSeparator sep;
344
345   // Get absolute path
346   std::string real_path = cpPlugins_Interface_CanonicalPath( path );
347
348   // Get name
349   name = std::string(
350     std::find_if( real_path.rbegin( ), real_path.rend( ), sep ).base( ),
351     real_path.end( )
352     );
353
354   // Get containing folder
355   folder = real_path;
356   folder.replace( folder.find( name ), name.size( ), "" );
357   if( sep( folder[ folder.size( ) - 1 ] ) )
358     folder = folder.substr( 0, folder.size( ) - 1 );
359
360   // Erase prefix and extension from filename
361   std::string prefix( PLUGIN_PREFIX );
362   std::string ext( PLUGIN_EXT );
363   if( prefix != "" )
364     name.replace( name.find( prefix ), prefix.size( ), "" );
365   name.replace( name.find( ext ), ext.size( ), "" );
366 }
367
368 // eof - $RCSfile$