Orfeo Toolbox  4.0
itkObjectFactoryBase.cxx
Go to the documentation of this file.
1 /*=========================================================================
2  *
3  * Copyright Insight Software Consortium
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *=========================================================================*/
18 /*=========================================================================
19  *
20  * Portions of this file are subject to the VTK Toolkit Version 3 copyright.
21  *
22  * Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
23  *
24  * For complete copyright, license and disclaimer of warranty information
25  * please refer to the NOTICE file at the top of the ITK source tree.
26  *
27  *=========================================================================*/
28 
29 #include "itkDynamicLoader.h"
30 #include "itkDirectory.h"
31 #include "itkVersion.h"
32 #include <string.h>
33 #include <algorithm>
34 
35 
36 namespace itk
37 {
38 
51 typedef std::list< ObjectFactoryBase * > FactoryListType;
52 namespace ObjectFactoryBasePrivate
53 {
57 }
58 
59 namespace
60 {
61 class CleanUpObjectFactory
62 {
63 public:
64 
65  ~CleanUpObjectFactory()
66  {
68 
70  {
71  for ( std::list< ObjectFactoryBase * >::iterator i =
74  {
75  (*i)->UnRegister();
76  }
78  }
79  }
80 };
81 //NOTE: KWStyle insists on m_ for m_CleanUpObjectFactoryGlobal
82 static CleanUpObjectFactory m_CleanUpObjectFactoryGlobal;
83 }
84 
93 typedef std::multimap< std::string, ObjectFactoryBase::OverrideInformation >
95 
100 {
101 public:
102 };
103 
110 
111 void
113 {
115 }
116 
117 void
119 {
121 }
122 
123 void
125 {
127 }
128 
129 bool
131 {
133 }
134 
135 
142 ::CreateInstance(const char *itkclassname)
143 {
145 
146  for ( FactoryListType::iterator
149  {
150  LightObject::Pointer newobject = ( *i )->CreateObject(itkclassname);
151  if ( newobject )
152  {
153  newobject->Register();
154  return newobject;
155  }
156  }
157  return 0;
158 }
159 
160 std::list< LightObject::Pointer >
162 ::CreateAllInstance(const char *itkclassname)
163 {
164 
166 
167  std::list< LightObject::Pointer > created;
168  for ( FactoryListType::iterator
171  {
172  std::list< LightObject::Pointer > moreObjects = ( *i )->CreateAllObject(itkclassname);
173  created.splice(created.end(), moreObjects);
174  }
175  return created;
176 }
177 
181 void
184 {
185  static_cast<void>(m_CleanUpObjectFactoryGlobal);
190  {
192  }
193 
195  {
197  }
198 }
199 
203 void
206 {
209  {
214  }
215 }
216 
221 void
224 {
225  // Guaranee that no internal factories have already been registered.
226  itkAssertOrThrowMacro( ObjectFactoryBasePrivate::m_RegisteredFactories->empty(),
227  "Factories unexpectedlly already registered!" );
228 
229  // Register all factories registered by the
230  // "RegisterFactoryInternal" method
231  for ( std::list< ObjectFactoryBase * >::iterator i =
234  {
236  }
237 }
238 
242 void
245 {
249 #ifdef _WIN32
250  char PathSeparator = ';';
251 #else
252  char PathSeparator = ':';
253 #endif
254 
255  std::string LoadPath;
256  if ( getenv("ITK_AUTOLOAD_PATH") )
257  {
258  LoadPath = getenv("ITK_AUTOLOAD_PATH");
259  }
260  else
261  {
262  return;
263  }
264  if ( LoadPath.size() == 0 )
265  {
266  return;
267  }
268  std::string::size_type EndSeparatorPosition = 0;
269  std::string::size_type StartSeparatorPosition = 0;
270 
271  while ( StartSeparatorPosition != std::string::npos )
272  {
273  StartSeparatorPosition = EndSeparatorPosition;
274 
278  EndSeparatorPosition = LoadPath.find(PathSeparator,
279  StartSeparatorPosition);
280  if ( EndSeparatorPosition == std::string::npos )
281  {
282  EndSeparatorPosition = LoadPath.size() + 1; // Add 1 to simulate
283  // having a separator
284  }
285  std::string CurrentPath =
286  LoadPath.substr(StartSeparatorPosition,
287  EndSeparatorPosition - StartSeparatorPosition);
288 
289  ObjectFactoryBase::LoadLibrariesInPath( CurrentPath.c_str() );
290 
294  if ( EndSeparatorPosition > LoadPath.size() )
295  {
296  StartSeparatorPosition = std::string::npos;
297  }
298  else
299  {
300  EndSeparatorPosition++; // Skip the separator
301  }
302  }
303 }
304 
309 static std::string
310 CreateFullPath(const char *path, const char *file)
311 {
312  std::string ret;
313 
314 #ifdef _WIN32
315  const char sep = '\\';
316 #else
317  const char sep = '/';
318 #endif
319 
322  ret = path;
323  if ( !ret.empty() && ret[ret.size() - 1] != sep )
324  {
325  ret += sep;
326  }
327  ret += file;
328  return ret;
329 }
330 
335 typedef ObjectFactoryBase * ( *ITK_LOAD_FUNCTION )();
336 
343 inline bool
344 NameIsSharedLibrary(const char *name)
345 {
346  std::string extension = itksys::DynamicLoader::LibExtension();
347 
348  std::string sname = name;
349  if ( sname.rfind(extension) == sname.size() - extension.size() )
350  {
351  return true;
352  }
353 #ifdef __APPLE__
354  // Need to also check libraries with a .dylib extension.
355  extension = ".dylib";
356 #endif
357  const size_t extensionpos = sname.rfind(extension);
358  if ( ( extensionpos != std::string::npos )
359  && ( extensionpos == ( sname.size() - extension.size() ) )
360  )
361  {
362  return true;
363  }
364  return false;
365 }
366 
370 void
372 ::LoadLibrariesInPath(const char *path)
373 {
375 
376  if ( !dir->Load(path) )
377  {
378  return;
379  }
380 
384  for ( unsigned int i = 0; i < dir->GetNumberOfFiles(); i++ )
385  {
386  const char *file = dir->GetFile(i);
391  if ( NameIsSharedLibrary(file) )
392  {
393  std::string fullpath = CreateFullPath(path, file);
394  LibHandle lib = DynamicLoader::OpenLibrary( fullpath.c_str() );
395  if ( lib )
396  {
400  ITK_LOAD_FUNCTION loadfunction =
406  if ( loadfunction )
407  {
408  ObjectFactoryBase *newfactory = ( *loadfunction )( );
409 
413  newfactory->m_LibraryHandle = (void *)lib;
414  newfactory->m_LibraryPath = fullpath;
415  newfactory->m_LibraryDate = 0; // unused for now...
416  if (!ObjectFactoryBase::RegisterFactory(newfactory))
417  {
419  }
420  }
421  else
422  {
423  // In the past, some platforms crashed on the call
424  // DynamicLoader::CloseLibrary(lib) if the lib has symbols
425  // that the current executable is using.
427  }
428  }
429  }
430  }
431 }
432 
436 void
439 {
442 }
443 
448 {
449  m_LibraryHandle = 0;
450  m_LibraryDate = 0;
452 }
453 
459 {
460  m_OverrideMap->erase( m_OverrideMap->begin(), m_OverrideMap->end() );
461  delete m_OverrideMap;
462 }
463 
469 void
472 {
473  if ( factory->m_LibraryHandle != NULL )
474  {
475  itkGenericExceptionMacro( "A dynamic factory tried to be loaded internally!" );
476  }
477 
478  // Do not call general ::Initialize() method as that may envoke additional
479  // libraries to be loaded and this method is called during static
480  // initialization.
482 
484  factory->Register();
485 
486  // if the internal factories have already been register add this one too
488  {
490  }
491 }
492 
496 bool
499 {
500  if ( factory->m_LibraryHandle == 0 )
501  {
502  const char nonDynamicName[] = "Non-Dynamicaly loaded factory";
503  factory->m_LibraryPath = nonDynamicName;
504  }
505  else
506  {
507  // Factories must only be loaded once
508  for ( std::list< ObjectFactoryBase * >::iterator i =
511  {
512  if ((*i)->m_LibraryPath == factory->m_LibraryPath)
513  {
514  itkGenericOutputMacro(<< factory->m_LibraryPath << " is already loaded");
515  return false;
516  }
517  }
518  }
519  if ( strcmp( factory->GetITKSourceVersion(),
521  {
523  {
524  itkGenericExceptionMacro(<< "Incompatible factory version load attempt:"
525  << "\nRunning itk version :\n" << Version::GetITKSourceVersion()
526  << "\nAttempted loading factory version:\n" << factory->GetITKSourceVersion()
527  << "\nAttempted factory:\n" << factory->m_LibraryPath << "\n");
528  }
529  else
530  {
531  itkGenericOutputMacro(<< "Possible incompatible factory load:"
532  << "\nRunning itk version :\n" << Version::GetITKSourceVersion()
533  << "\nLoaded factory version:\n" << factory->GetITKSourceVersion()
534  << "\nLoading factory:\n" << factory->m_LibraryPath << "\n");
535  }
536  }
538 
539  //
540  // Register the factory in the internal list at the requested location.
541  //
542  switch( where )
543  {
544  case INSERT_AT_BACK:
545  {
546  if( position )
547  {
548  itkGenericExceptionMacro(<< "position argument must not be used with INSERT_AT_BACK option");
549  }
551  break;
552  }
553  case INSERT_AT_FRONT:
554  {
555  if( position )
556  {
557  itkGenericExceptionMacro(<< "position argument must not be used with INSERT_AT_FRONT option");
558  }
560  break;
561  }
562  case INSERT_AT_POSITION:
563  {
564  const size_t numberOfFactories = ObjectFactoryBasePrivate::m_RegisteredFactories->size();
565  if( position < numberOfFactories )
566  {
567  typedef FactoryListType::iterator FactoryIterator;
568  FactoryIterator fitr = ObjectFactoryBasePrivate::m_RegisteredFactories->begin();
569 
570  while( position-- )
571  {
572  ++fitr;
573  }
574 
576  break;
577  }
578  else
579  {
580  itkGenericExceptionMacro("Position" << position << " is outside range. \
581  Only " << numberOfFactories << " factories are registered");
582  }
583  }
584  }
585  factory->Register();
586  return true;
587 }
588 
592 void
594 ::PrintSelf(std::ostream & os, Indent indent) const
595 {
596  Superclass::PrintSelf(os, indent);
597 
598  os << indent << "Factory DLL path: " << m_LibraryPath.c_str() << "\n";
599  os << indent << "Factory description: " << this->GetDescription() << std::endl;
600 
601  int num = static_cast< int >( m_OverrideMap->size() );
602  os << indent << "Factory overides " << num << " classes:" << std::endl;
603 
604  indent = indent.GetNextIndent();
605  for ( OverRideMap::iterator i = m_OverrideMap->begin();
606  i != m_OverrideMap->end(); ++i )
607  {
608  os << indent << "Class : " << ( *i ).first.c_str() << "\n";
609  os << indent << "Overriden with: " << ( *i ).second.m_OverrideWithName.c_str()
610  << std::endl;
611  os << indent << "Enable flag: " << ( *i ).second.m_EnabledFlag
612  << std::endl;
613  os << indent << "Create object: " << ( *i ).second.m_CreateObject
614  << std::endl;
615  os << std::endl;
616  }
617 }
618 
622 void
625 {
626  // if factory is not internal then delete
627  if ( std::find( ObjectFactoryBasePrivate::m_InternalFactories->begin(),
629  factory )
631  {
632  factory->UnRegister();
633  }
634 }
635 
639 void
642 {
644  {
645  for ( std::list< ObjectFactoryBase * >::iterator i =
648  {
649  if ( factory == *i )
650  {
651  DeleteNonInternalFactory(factory);
653  return;
654  }
655  }
656  }
657 }
658 
662 void
665 {
667  {
668  // Collect up all the library handles so they can be closed
669  // AFTER the factory has been deleted.
670  std::list< void * > libs;
671  for ( std::list< ObjectFactoryBase * >::iterator i =
674  {
675  libs.push_back( static_cast< void * >( ( *i )->m_LibraryHandle ) );
676  }
677  // Unregister each factory
678  for ( std::list< ObjectFactoryBase * >::iterator f =
681  {
682  DeleteNonInternalFactory(*f);
683  }
684  // And delete the library handles all at once
685  for ( std::list< void * >::iterator lib = libs.begin();
686  lib != libs.end();
687  ++lib )
688  {
689  if ( ( *lib ) )
690  {
691  DynamicLoader::CloseLibrary( static_cast< LibHandle >( *lib ) );
692  }
693  }
697  }
698 }
699 
703 void
705 ::RegisterOverride(const char *classOverride,
706  const char *subclass,
707  const char *description,
708  bool enableFlag,
710  createFunction)
711 {
713 
714  info.m_Description = description;
715  info.m_OverrideWithName = subclass;
716  info.m_EnabledFlag = enableFlag;
717  info.m_CreateObject = createFunction;
718 
719  m_OverrideMap->insert( OverRideMap::value_type(classOverride, info) );
720 }
721 
724 ::CreateObject(const char *itkclassname)
725 {
726  OverRideMap::iterator start = m_OverrideMap->lower_bound(itkclassname);
727  OverRideMap::iterator end = m_OverrideMap->upper_bound(itkclassname);
728 
729  for ( OverRideMap::iterator i = start; i != end; ++i )
730  {
731  if ( i != m_OverrideMap->end() && ( *i ).second.m_EnabledFlag )
732  {
733  return ( *i ).second.m_CreateObject->CreateObject();
734  }
735  }
736  return 0;
737 }
738 
739 std::list< LightObject::Pointer >
741 ::CreateAllObject(const char *itkclassname)
742 {
743  OverRideMap::iterator start = m_OverrideMap->lower_bound(itkclassname);
744  OverRideMap::iterator end = m_OverrideMap->upper_bound(itkclassname);
745 
746  std::list< LightObject::Pointer > created;
747 
748  for ( OverRideMap::iterator i = start; i != end; ++i )
749  {
750  if ( i != m_OverrideMap->end() && ( *i ).second.m_EnabledFlag )
751  {
752  created.push_back( ( *i ).second.m_CreateObject->CreateObject() );
753  }
754  }
755  return created;
756 }
757 
761 void
763 ::SetEnableFlag(bool flag,
764  const char *className,
765  const char *subclassName)
766 {
767  OverRideMap::iterator start = m_OverrideMap->lower_bound(className);
768  OverRideMap::iterator end = m_OverrideMap->upper_bound(className);
769 
770  for ( OverRideMap::iterator i = start; i != end; ++i )
771  {
772  if ( ( *i ).second.m_OverrideWithName == subclassName )
773  {
774  ( *i ).second.m_EnabledFlag = flag;
775  }
776  }
777 }
778 
782 bool
784 ::GetEnableFlag(const char *className, const char *subclassName)
785 {
786  OverRideMap::iterator start = m_OverrideMap->lower_bound(className);
787  OverRideMap::iterator end = m_OverrideMap->upper_bound(className);
788 
789  for ( OverRideMap::iterator i = start; i != end; ++i )
790  {
791  if ( ( *i ).second.m_OverrideWithName == subclassName )
792  {
793  return ( *i ).second.m_EnabledFlag;
794  }
795  }
796  return 0;
797 }
798 
802 void
804 ::Disable(const char *className)
805 {
806  OverRideMap::iterator start = m_OverrideMap->lower_bound(className);
807  OverRideMap::iterator end = m_OverrideMap->upper_bound(className);
808 
809  for ( OverRideMap::iterator i = start; i != end; ++i )
810  {
811  ( *i ).second.m_EnabledFlag = 0;
812  }
813 }
814 
818 std::list< ObjectFactoryBase * >
821 {
822 
824 
826 }
827 
831 std::list< std::string >
834 {
835  std::list< std::string > ret;
836  for ( OverRideMap::iterator i = m_OverrideMap->begin();
837  i != m_OverrideMap->end(); ++i )
838  {
839  ret.push_back( ( *i ).first );
840  }
841  return ret;
842 }
843 
847 std::list< std::string >
850 {
851  std::list< std::string > ret;
852  for ( OverRideMap::iterator i = m_OverrideMap->begin();
853  i != m_OverrideMap->end(); ++i )
854  {
855  ret.push_back( ( *i ).second.m_OverrideWithName );
856  }
857  return ret;
858 }
859 
863 std::list< std::string >
866 {
867  std::list< std::string > ret;
868  for ( OverRideMap::iterator i = m_OverrideMap->begin();
869  i != m_OverrideMap->end(); ++i )
870  {
871  ret.push_back( ( *i ).second.m_Description );
872  }
873  return ret;
874 }
875 
879 std::list< bool >
882 {
883  std::list< bool > ret;
884  for ( OverRideMap::iterator i = m_OverrideMap->begin();
885  i != m_OverrideMap->end(); ++i )
886  {
887  ret.push_back( ( *i ).second.m_EnabledFlag );
888  }
889  return ret;
890 }
891 
894 const char *
897 {
898  return m_LibraryPath.c_str();
899 }
900 } // end namespace itk

Generated at Sat Mar 8 2014 15:19:02 for Orfeo Toolbox with doxygen 1.8.3.1