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