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