]> Creatis software - cpPlugins.git/blob - lib/cpPlugins/Interface/Loader.cxx
yet another refactoring
[cpPlugins.git] / lib / cpPlugins / Interface / Loader.cxx
1 #include <cpPlugins/Interface/Loader.h>
2 #include <cpPlugins/OS/FileSystem.h>
3 #include <cpPlugins/OS/DLLManager.h>
4 #include <cpPlugins/OS/String.h>
5 #include <set>
6
7 // -------------------------------------------------------------------------
8 // Static attributes initialization
9 // -------------------------------------------------------------------------
10
11 cpPlugins::Interface::Loader::TLibraries
12 cpPlugins::Interface::Loader::m_Libraries;
13
14 cpPlugins::Interface::Loader::TFiltersToLibrariesReferences
15 cpPlugins::Interface::Loader::m_References;
16
17 // -------------------------------------------------------------------------
18 cpPlugins::Interface::Loader::
19 Loader( )
20 {
21 }
22
23 // -------------------------------------------------------------------------
24 cpPlugins::Interface::Loader::
25 ~Loader( )
26 {
27 }
28
29 // -------------------------------------------------------------------------
30 void cpPlugins::Interface::Loader::
31 Register( const std::string& filename )
32 {
33   // Canonicalize path
34   std::string path = cpPlugins::OS::FileSystem::CanonicalPath( filename );
35   if( path == "" )
36   {
37     throw std::runtime_error( "Unknown library file \"" + filename + "\"." );
38     return;
39
40   } // fi
41
42   // Ignore if the library is already loaded
43   if( Self::m_Libraries.find( path ) != Self::m_Libraries.end( ) )
44     return;
45
46   // Try to open library
47   void* hnd = NULL;
48   try
49   {
50     hnd = cpPlugins::OS::DLLManager::Open( path );
51   }
52   catch( std::exception& err )
53   {
54     throw std::runtime_error( err.what( ) );
55
56   } // yrt
57   if( hnd == NULL )
58     throw std::runtime_error( "Unknown file type for \"" + filename + "\"." );
59
60   // Get interfacing functions
61   TContentsFunc contents_func = NULL;
62   try
63   {
64     contents_func = reinterpret_cast< TContentsFunc >(
65       cpPlugins::OS::DLLManager::Sym( hnd, "cpPlugins_Contents" )
66       );
67   }
68   catch( std::exception& err )
69   {
70     cpPlugins::OS::DLLManager::Close( hnd );
71     throw std::runtime_error( "Library \"" + filename + "\" is not recognized as a cpPlugins library (i.e. \"cpPlugins_Contents\" function not found)." );
72
73   } // yrt
74
75   TCreatorFunc creator_func = NULL;
76   try
77   {
78     creator_func = reinterpret_cast< TCreatorFunc >(
79       cpPlugins::OS::DLLManager::Sym( hnd, "cpPlugins_Creator" )
80       );
81   }
82   catch( std::exception& err )
83   {
84     cpPlugins::OS::DLLManager::Close( hnd );
85     throw std::runtime_error( "Library \"" + filename + "\" is not recognized as a cpPlugins library (i.e. \"cpPlugins_Creator\" function not found)." );
86
87   } // yrt
88
89   // Keep track of handlers
90   Self::m_Libraries[ path ] = THandlers( hnd, contents_func, creator_func );
91
92   // Get library contents
93   std::vector< std::string > contents;
94   contents_func( &contents );
95
96   // Register contents
97   for( auto c : contents )
98   {
99     std::vector< std::string > t = cpPlugins::OS::String::Tokenize( c, "@" );
100     if( t.size( ) == 2 )
101       Self::m_References[ t[ 1 ] ][ t[ 0 ] ] = path;
102
103   } // rof
104 }
105
106 // -------------------------------------------------------------------------
107 void cpPlugins::Interface::Loader::
108 RegisterFromDirectory( const std::string& dirname )
109 {
110   std::string patt = "*";
111   patt += cpPlugins_LIB_EXT;
112   std::set< std::string > files =
113     cpPlugins::OS::FileSystem::LoadDirContents(
114       dirname, false, patt
115       );
116   for( auto f : files )
117   {
118     try
119     {
120       Register( f );
121     }
122     catch( ... )
123     {
124       // Do nothing
125
126     } // yrt
127
128   } // rof
129 }
130
131 // -------------------------------------------------------------------------
132 void cpPlugins::Interface::Loader::
133 GuessEnvironment( const std::string& dirname )
134 {
135   std::stringstream fname;
136   fname << dirname << cpPlugins_PATH_SEPARATOR << cpPlugins_PATHS;
137   std::string buffer;
138   if( cpPlugins::OS::FileSystem::Read( buffer, fname.str( ) ) )
139   {
140     std::istringstream input( buffer );
141     for( std::string line; std::getline( input, line ); )
142       Self::RegisterFromDirectory( line );
143   }
144   else
145     Self::RegisterFromDirectory( dirname );
146 }
147
148 // -------------------------------------------------------------------------
149 void cpPlugins::Interface::Loader::
150 SaveEnvironment( const std::string& dirname )
151 {
152   std::set< std::string > locations;
153   for( auto lIt : Self::m_Libraries )
154     locations.insert(
155       cpPlugins::OS::FileSystem::SplitPath( lIt.first ).first
156       );
157   std::stringstream buffer;
158   for( auto loc : locations )
159     buffer << loc << std::endl;
160   std::stringstream fname;
161   fname << dirname << cpPlugins_PATH_SEPARATOR << cpPlugins_PATHS;
162   cpPlugins::OS::FileSystem::Write( buffer.str( ), fname.str( ) );
163 }
164
165 // -------------------------------------------------------------------------
166 void cpPlugins::Interface::Loader::
167 UnRegister( const std::string& filename )
168 {
169   // Canonicalize path
170   std::string path = cpPlugins::OS::FileSystem::CanonicalPath( filename );
171   if( path == "" )
172     return;
173
174   auto lIt = Self::m_Libraries.find( path );
175   if( lIt != Self::m_Libraries.end( ) )
176   {
177     // Unload handlers
178     cpPlugins::OS::DLLManager::Close( std::get< 0 >( lIt->second ) );
179     Self::m_Libraries.erase( lIt );
180
181     // Erase references
182     auto cIt = Self::m_References.begin( );
183     while( cIt != Self::m_References.end( ) )
184     {
185       auto fIt = cIt->second.begin( );
186       while( fIt != cIt->second.end( ) )
187       {
188         if( fIt->second == path )
189         {
190           cIt->second.erase( fIt );
191           fIt = cIt->second.begin( );
192         }
193         else
194           ++fIt;
195
196       } // elihw
197       if( cIt->second.size( ) == 0 )
198       {
199         Self::m_References.erase( cIt );
200         cIt = Self::m_References.begin( );
201       }
202       else
203         ++cIt;
204
205     } // elihw
206
207   } // fi
208 }
209
210 // -------------------------------------------------------------------------
211 void cpPlugins::Interface::Loader::
212 UnRegisterAll( )
213 {
214   for( auto lIt : Self::m_Libraries )
215     cpPlugins::OS::DLLManager::Close( std::get< 0 >( lIt.second ) );
216   Self::m_Libraries.clear( );
217   Self::m_References.clear( );
218 }
219
220 // -------------------------------------------------------------------------
221 std::map< std::string, std::set< std::string > >
222 cpPlugins::Interface::Loader::
223 GetFilters( ) const
224 {
225   std::map< std::string, std::set< std::string > > filters;
226   for( auto ref : Self::m_References )
227     for( auto fil : ref.second )
228       filters[ ref.first ].insert( fil.first );
229   return( filters );
230 }
231
232 // -------------------------------------------------------------------------
233 cpPlugins::Pipeline::ProcessObject::Pointer cpPlugins::Interface::Loader::
234 CreateFilter(
235   const std::string& category, const std::string& filter,
236   const std::string& name
237   )
238 {
239   cpPlugins::Pipeline::ProcessObject::Pointer ptr = NULL;
240   auto cIt = Self::m_References.find( category );
241   if( cIt != Self::m_References.end( ) )
242   {
243     auto fIt = cIt->second.find( filter );
244     if( fIt != cIt->second.end( ) )
245     {
246       auto lIt = Self::m_Libraries.find( fIt->second );
247       if( lIt != Self::m_Libraries.end( ) )
248       {
249         auto creator_func = std::get< 2 >( lIt->second );
250         if( creator_func != NULL )
251         {
252           itk::LightObject::Pointer l_ptr;
253           creator_func( l_ptr, category, filter );
254           ptr =
255             dynamic_cast< cpPlugins::Pipeline::ProcessObject* >(
256               l_ptr.GetPointer( )
257               );
258
259         } // fi
260
261       } // fi
262
263     } // fi
264
265   } // fi
266
267   if( ptr.IsNotNull( ) )
268   {
269     if( name == "" )
270       ptr->SetName( filter + "@" + category );
271     else
272       ptr->SetName( name );
273
274   } // fi
275   return( ptr );
276 }
277
278 // eof - $RCSfile$