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