]> 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       {
167         po = provider->create( );
168         po->SetName( name );
169
170       } // fi
171       catIt = this->m_Classes.end( );
172     }
173     else
174       catIt++;
175
176   } // elihw
177
178   return( po );
179 }
180
181 // -------------------------------------------------------------------------
182 bool cpPlugins::Interface::Interface::
183 Load( const std::string& path )
184 {
185   bool ret = true;
186   try
187   {
188     ret = this->m_Pluma->load( path );
189     if( ret )
190     {
191       std::string folder, name;
192       Self::_SepFName( path, folder, name );
193       this->m_LoadedPlugins[ folder ].push_back( name );
194       this->_LoadClasses( );
195
196     } // fi
197   }
198   catch( ... )
199   {
200     ret = false;
201
202   } // yrt
203   return( ret );
204 }
205
206 // -------------------------------------------------------------------------
207 bool cpPlugins::Interface::Interface::
208 Load( const std::string& folder, const std::string& name )
209 {
210   std::string real_folder = folder;
211   PathSeparator sep;
212   if( sep( folder[ folder.size( ) - 1 ] ) )
213     real_folder = folder.substr( 0, folder.size( ) - 1 );
214   real_folder = cpPlugins_Interface_CanonicalPath( real_folder );
215
216   bool ret = true;
217   try
218   {
219     ret = this->m_Pluma->load( real_folder, name );
220     if( ret )
221     {
222       // Update loaded plugins
223       std::string prefix( PLUGIN_PREFIX );
224       std::string ext( PLUGIN_EXT );
225       std::string real_name = name;
226       if( prefix != "" )
227         real_name.replace( real_name.find( prefix ), prefix.size( ), "" );
228       real_name.replace( real_name.find( ext ), ext.size( ), "" );
229       this->m_LoadedPlugins[ real_folder ].push_back( real_name );
230       this->_LoadClasses( );
231
232     } // fi
233   }
234   catch( ... )
235   {
236     ret = false;
237
238   } // yrt
239   return( ret );
240 }
241
242 // -------------------------------------------------------------------------
243 bool cpPlugins::Interface::Interface::
244 LoadFromFolder( const std::string& folder, bool r )
245 {
246   try
247   {
248     std::list< std::string > f = this->m_Pluma->loadFromFolder( folder, r );
249     if( f.size( ) > 0 )
250     {
251       // Update loaded plugins
252       for( auto i = f.begin( ); i != f.end( ); ++i )
253       {
254         std::string folder, name;
255         Self::_SepFName( *i, folder, name );
256         this->m_LoadedPlugins[ folder ].push_back( name );
257
258       } // rof
259
260       // Load classes
261       this->_LoadClasses( );
262       return( true );
263     }
264     else
265       return( false );
266   }
267   catch( ... )
268   {
269     return( false );
270
271   } // yrt
272 }
273
274 // -------------------------------------------------------------------------
275 bool cpPlugins::Interface::Interface::
276 Unload( const std::string& name )
277 {
278   bool ret = true;
279   try
280   {
281     ret = this->m_Pluma->unload( name );
282     if( ret )
283     {
284       this->m_Providers.clear( );
285       this->m_Classes.clear( );
286
287       // TODO: this->m_LoadedPlugins
288
289       this->_LoadClasses( );
290
291     } // fi
292   }
293   catch( ... )
294   {
295     ret = false;
296
297   } // yrt
298   return( ret );
299 }
300
301 // -------------------------------------------------------------------------
302 void cpPlugins::Interface::Interface::
303 UnloadAll( )
304 {
305   try
306   {
307     this->m_Pluma->unloadAll( );
308   }
309   catch( ... )
310   {
311     // Do nothing
312
313   } // yrt
314   this->m_Providers.clear( );
315   this->m_Classes.clear( );
316   this->m_LoadedPlugins.clear( );
317 }
318
319 // -------------------------------------------------------------------------
320 bool cpPlugins::Interface::Interface::
321 IsLoaded( const std::string& name ) const
322 {
323   return( this->m_Pluma->isLoaded( name ) );
324 }
325
326 // -------------------------------------------------------------------------
327 void cpPlugins::Interface::Interface::
328 _LoadClasses( )
329 {
330   this->m_Providers.clear( );
331   this->m_Classes.clear( );
332   this->m_Pluma->getProviders( this->m_Providers );
333
334   // Get reader provider
335   for( unsigned int i = 0; i < this->m_Providers.size( ); ++i )
336   {
337     ProcessObject::Pointer d = this->m_Providers[ i ]->create( );
338     this->m_Classes[ d->GetClassCategory( ) ][ d->GetClassName( ) ] = i;
339
340   } // rof
341 }
342
343 // -------------------------------------------------------------------------
344 void cpPlugins::Interface::Interface::
345 _SepFName( const std::string& path, std::string& folder, std::string& name )
346 {
347   PathSeparator sep;
348
349   // Get absolute path
350   std::string real_path = cpPlugins_Interface_CanonicalPath( path );
351
352   // Get name
353   name = std::string(
354     std::find_if( real_path.rbegin( ), real_path.rend( ), sep ).base( ),
355     real_path.end( )
356     );
357
358   // Get containing folder
359   folder = real_path;
360   folder.replace( folder.find( name ), name.size( ), "" );
361   if( sep( folder[ folder.size( ) - 1 ] ) )
362     folder = folder.substr( 0, folder.size( ) - 1 );
363
364   // Erase prefix and extension from filename
365   std::string prefix( PLUGIN_PREFIX );
366   std::string ext( PLUGIN_EXT );
367   if( prefix != "" )
368     name.replace( name.find( prefix ), prefix.size( ), "" );
369   name.replace( name.find( ext ), ext.size( ), "" );
370 }
371
372 // eof - $RCSfile$