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