plugin_manager.hpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:28k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: plugin_manager.hpp,v $
  4.  * PRODUCTION Revision 1000.7  2004/06/01 19:08:16  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.22
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. #ifndef CORELIB___PLUGIN_MANAGER__HPP
  10. #define CORELIB___PLUGIN_MANAGER__HPP
  11. /* $Id: plugin_manager.hpp,v 1000.7 2004/06/01 19:08:16 gouriano Exp $
  12.  * ===========================================================================
  13.  *
  14.  *                            PUBLIC DOMAIN NOTICE
  15.  *               National Center for Biotechnology Information
  16.  *
  17.  *  This software/database is a "United States Government Work" under the
  18.  *  terms of the United States Copyright Act.  It was written as part of
  19.  *  the author's official duties as a United States Government employee and
  20.  *  thus cannot be copyrighted.  This software/database is freely available
  21.  *  to the public for use. The National Library of Medicine and the U.S.
  22.  *  Government have not placed any restriction on its use or reproduction.
  23.  *
  24.  *  Although all reasonable efforts have been taken to ensure the accuracy
  25.  *  and reliability of the software and data, the NLM and the U.S.
  26.  *  Government do not and cannot warrant the performance or results that
  27.  *  may be obtained by using this software or data. The NLM and the U.S.
  28.  *  Government disclaim all warranties, express or implied, including
  29.  *  warranties of performance, merchantability or fitness for any particular
  30.  *  purpose.
  31.  *
  32.  *  Please cite the author in any work or product based on this material.
  33.  *
  34.  * ===========================================================================
  35.  *
  36.  * Author:  Denis Vakatov, Anatoliy Kuznetsov
  37.  *
  38.  * File Description:  Plugin manager (using class factory paradigm)
  39.  *
  40.  */
  41. /// @file plugin_manager.hpp
  42. /// Plugin manager (using class factory paradigm).
  43. ///
  44. /// Describe generic interface and provide basic functionality to advertise
  45. /// and export a class factory. 
  46. /// The class and class factory implementation code can be linked to
  47. /// either statically (then, the class factory will need to be registered
  48. /// explicitly by the user code) or dynamically (then, the DLL will be
  49. /// searched for using plugin name, and the well-known DLL entry point
  50. /// will be used to register the class factory, automagically).
  51. /// 
  52. /// - "class factory" -- An entity used to generate objects of the given class.
  53. ///                      One class factory can generate more than one version
  54. ///                      of the class.
  55. /// 
  56. /// - "interface"  -- Defines the implementation-independent API and expected
  57. ///                   behaviour of a class.
  58. ///                   Interface's name is provided by its class's factory,
  59. ///                   see IClassFactory::GetInterfaceName().
  60. ///                   Interfaces are versioned to track the compatibility.
  61. /// 
  62. /// - "driver"  -- A concrete implementation of the interface and its factory.
  63. ///                Each driver has its own name (do not confuse it with the
  64. ///                interface name!) and version.
  65. /// 
  66. /// - "host"    -- An entity (DLL or the EXEcutable itself) that contains
  67. ///                one or more drivers (or versions of the same driver),
  68. ///                which can implement one or more interfaces.
  69. /// 
  70. /// - "version" -- MAJOR (backward- and forward-incompatible changes in the
  71. ///                       interface and/or its expected behaviour);
  72. ///                MINOR (backward compatible changes in the driver code);
  73. ///                PATCH_LEVEL (100% compatible plugin or driver code changes).
  74. /// 
  75. #include <corelib/ncbimtx.hpp>
  76. #include <corelib/version.hpp>
  77. #include <corelib/ncbidll.hpp>
  78. #include <corelib/ncbi_tree.hpp>
  79. #include <set>
  80. #include <string>
  81. BEGIN_NCBI_SCOPE
  82. /** @addtogroup PluginMgr
  83.  *
  84.  * @{
  85.  */
  86. /////////////////////////////////////////////////////////////////////////////
  87. ///
  88. /// CPluginManagerException --
  89. ///
  90. /// Exception generated by CPluginManager.
  91. class NCBI_XNCBI_EXPORT CPluginManagerException : public CCoreException
  92. {
  93. public:
  94.     /// Error types that CTime can generate.
  95.     enum EErrCode {
  96.         eResolveFailure       ///< Cannot resolve interface driver
  97.     };
  98.     /// Translate from the error code value to its string representation.
  99.     virtual const char* GetErrCodeString(void) const
  100.     {
  101.         switch (GetErrCode()) {
  102.         case eResolveFailure:   return "eResolveFailure";
  103.         default:    return CException::GetErrCodeString();
  104.         }
  105.     }
  106.     // Standard exception boilerplate code.
  107.     NCBI_EXCEPTION_DEFAULT(CPluginManagerException, CCoreException);
  108. };
  109. /// CInterfaceVersion<> --
  110. ///
  111. /// Current interface version.
  112. ///
  113. /// It is just a boilerplate, to be hard-coded in the concrete interface header
  114. /// @sa NCBI_PLUGIN_VERSION, CVersionInfo
  115. template <class TClass>
  116. class CInterfaceVersion
  117. {
  118. };
  119. /// Macro to auto-setup the current interface name and version.
  120. ///
  121. /// This macro must be "called" once per interface, usually in the
  122. /// very header that describes that interface.
  123. ///
  124. /// Example:
  125. ///    NCBI_INTERFACE_VERSION(IFooBar, "IFooBar", 1, 3, 8);
  126. /// @sa CInterfaceVersion
  127. #define NCBI_DECLARE_INTERFACE_VERSION(iface, iface_name, major, minor, patch_level) 
  128. template<> 
  129. class CInterfaceVersion<iface> 
  130. public: 
  131.     enum { 
  132.         eMajor      = major, 
  133.         eMinor      = minor, 
  134.         ePatchLevel = patch_level 
  135.     }; 
  136.     static const char* GetName() { return iface_name; } 
  137. }
  138. /// Macro to contruct CVersionInfo class using interface name
  139. /// (relies on CInterfaceVersion class)
  140. /// @sa CVersionInfo
  141. #define NCBI_INTERFACE_VERSION(iface) 
  142. CVersionInfo(ncbi::CInterfaceVersion<iface>::eMajor, 
  143.              ncbi::CInterfaceVersion<iface>::eMinor, 
  144.              ncbi::CInterfaceVersion<iface>::ePatchLevel)
  145. /// Instantiation parameters tree.
  146. typedef CTreePairNode<string, string>  TPluginManagerParamTree;
  147. /// IClassFactory<> --
  148. ///
  149. /// Class factory for the given interface.
  150. ///
  151. /// IClassFactory should be implemented for collection of drivers
  152. /// and exported by hosts
  153. template <class TClass, class TIfVer = CInterfaceVersion<TClass> >
  154. class IClassFactory
  155. {
  156. public:
  157.     typedef TClass TInterface;
  158.     struct SDriverInfo
  159.     {
  160.         string         name;        ///< Driver name
  161.         CVersionInfo   version;     ///< Driver version
  162.         SDriverInfo(const string&       driver_name,
  163.                     const CVersionInfo& driver_version)
  164.             : name(driver_name),
  165.               version(driver_version)
  166.         {}
  167.     };
  168.     typedef list<SDriverInfo>  TDriverList;
  169.     /// Create driver's instance
  170.     ///
  171.     /// Function creates driver by its name and version.
  172.     /// The requirements is the drivers version should match the interface
  173.     /// up to the patch level.
  174.     ///
  175.     /// @param driver
  176.     ///  Requested driver's name (not the name of the supported interface)
  177.     /// @param version
  178.     ///  Requested interface version (as understood by the caller).
  179.     ///  By default it will be passed the version which is current from
  180.     ///  the calling code's point of view.
  181.     /// @param 
  182.     /// @return
  183.     ///  NULL on any error (not found entry point, version mismatch, etc.)
  184.     virtual TClass* CreateInstance
  185.       (const string&  driver  = kEmptyStr,
  186.        CVersionInfo   version = CVersionInfo(TIfVer::eMajor, TIfVer::eMinor,
  187.                                              TIfVer::ePatchLevel),
  188.        const TPluginManagerParamTree* params = 0) const = 0;
  189.     /// Versions of the interface exported by the factory
  190.     virtual void GetDriverVersions(TDriverList& driver_list) const = 0;
  191.     virtual ~IClassFactory(void) {}
  192. };
  193. class CPluginManager_DllResolver;
  194. /// CPluginManager<> --
  195. ///
  196. /// To register (either directly, or via an "entry point") class factories
  197. /// for the given interface.
  198. ///
  199. /// Then, to facilitate the process of instantiating the class given
  200. /// the registered pool of drivers, and also taking into accont the driver name
  201. /// and/or version as requested by the calling code.
  202. ///
  203. /// Template class is protected by mutex and safe for use from diffrent threads
  204. template <class TClass, class TIfVer = CInterfaceVersion<TClass> >
  205. class CPluginManager
  206. {
  207. public:
  208.     typedef IClassFactory<TClass, TIfVer> TClassFactory;
  209.     /// Create class instance
  210.     /// @return
  211.     ///  Never returns NULL -- always throw exception on error.
  212.     /// @sa GetFactory()
  213.     TClass* CreateInstance
  214.     (const string&       driver  = kEmptyStr,
  215.      const CVersionInfo& version = CVersionInfo(TIfVer::eMajor, TIfVer::eMinor,
  216.                                                 TIfVer::ePatchLevel),
  217.      const TPluginManagerParamTree* params = 0)
  218.     {
  219.         TClassFactory* factory = GetFactory(driver, version);
  220.         return factory->CreateInstance(driver, version, params);
  221.     }
  222.     /// Get class factory
  223.     ///
  224.     /// If more than one (of registered) class factory contain eligible
  225.     /// driver candidates, then pick the class factory containing driver of
  226.     /// the latest version.
  227.     /// @param driver
  228.     ///  Name of the driver. If passed empty, then -- any.
  229.     /// @param version
  230.     ///  Requested version. The returned driver can have a different (newer)
  231.     ///  version (provided that the new implementation is backward-compatible
  232.     ///  with the requested version.
  233.     /// @return
  234.     ///  Never return NULL -- always throw exception on error.
  235.     TClassFactory* GetFactory
  236.     (const string&       driver  = kEmptyStr,
  237.      const CVersionInfo& version = CVersionInfo(TIfVer::eMajor, TIfVer::eMinor,
  238.                                                 TIfVer::ePatchLevel));
  239.     /// Information about a driver, with maybe a pointer to an instantiated
  240.     /// class factory that contains the driver.
  241.     /// @sa FNCBI_EntryPoint
  242.     struct SDriverInfo {
  243.         string         name;        ///< Driver name
  244.         CVersionInfo   version;     ///< Driver version
  245.         // It's the plugin manager's (and not SDriverInfo) responsibility to
  246.         // keep and then destroy class factories.
  247.         TClassFactory* factory;     ///< Class factory (can be NULL)
  248.         SDriverInfo(const string&       driver_name,
  249.                     const CVersionInfo& driver_version)
  250.             : name(driver_name),
  251.               version(driver_version),
  252.               factory(0)
  253.         {}
  254.     };
  255.     /// List of driver information.
  256.     ///
  257.     /// It is used to communicate using the entry points mechanism.
  258.     /// @sa FNCBI_EntryPoint
  259.     typedef list<SDriverInfo> TDriverInfoList;
  260.     /// Register factory in the manager.
  261.     ///  
  262.     /// The registered factory will be owned by the manager.
  263.     /// @sa UnregisterFactory()
  264.     void RegisterFactory(TClassFactory& factory);
  265.     /// Unregister and release (un-own)
  266.     /// @sa RegisterFactory()
  267.     bool UnregisterFactory(TClassFactory& factory);
  268.     /// Actions performed by the entry point
  269.     /// @sa FNCBI_EntryPoint
  270.     enum EEntryPointRequest {
  271.         /// Add info about all drivers exported through the entry point
  272.         /// to the end of list.
  273.         ///
  274.         /// "SFactoryInfo::factory" in the added info should be assigned NULL.
  275.         eGetFactoryInfo,
  276.         /// Scan the driver info list passed to the entry point for the
  277.         /// [name,version] pairs exported by the given entry point.
  278.         ///
  279.         /// For each pair found, if its "SDriverInfo::factory" is NULL,
  280.         /// instantiate its class factory and assign it to the
  281.         /// "SDriverInfo::factory".
  282.         eInstantiateFactory
  283.     };
  284.     /// Entry point to get drivers' info, and (if requested) their class
  285.     /// factori(es).
  286.     ///
  287.     /// This function is usually (but not necessarily) called by
  288.     /// RegisterWithEntryPoint().
  289.     ///
  290.     /// Usually, it's called twice -- the first time to get the info
  291.     /// about the drivers exported by the entry point, and then
  292.     /// to instantiate selected factories.
  293.     ///
  294.     /// Caller is responsible for the proper destruction (deallocation)
  295.     /// of the instantiated factories.
  296.     typedef void (*FNCBI_EntryPoint)(TDriverInfoList&   info_list,
  297.                                      EEntryPointRequest method);
  298.     /// Register all factories exported by the plugin entry point.
  299.     /// @sa RegisterFactory()
  300.     void RegisterWithEntryPoint(FNCBI_EntryPoint plugin_entry_point);
  301.     /// Attach DLL resolver to plugin manager 
  302.     /// 
  303.     /// Plugin mananger uses all attached resolvers to search for DLLs
  304.     /// exporting drivers of this interface. 
  305.     ///
  306.     /// @param resolver
  307.     ///   DLL resolver. Plugin manager takes ownership of the resolver.
  308.     ///
  309.     /// @sa DetachResolver
  310.     void AddResolver(CPluginManager_DllResolver* resolver);
  311.     /// Remove resolver from the list of active resolvers.
  312.     ///
  313.     /// Method is used when we need to freeze some of the resolution variants
  314.     /// Resolver is not deleted, and can be reattached again by AddResolver
  315.     ///
  316.     /// @param resolver
  317.     ///   DLL resolver. Ownership is returned to the caller and resolver
  318.     ///   should be deleted by the caller
  319.     ///
  320.     /// @return Pointer on the detached resolver (same as resolver parameter)
  321.     /// or NULL if resolver not found
  322.     CPluginManager_DllResolver* 
  323.     DetachResolver(CPluginManager_DllResolver* resolver);
  324.     /// Add path for the DLL lookup (for all resolvers)
  325.     void AddDllSearchPath(const string& path);
  326.     /// Scan DLLs for specified driver using attached resolvers
  327.     void Resolve(const string&       driver  = kEmptyStr,
  328.                  const CVersionInfo& version = CVersionInfo
  329.                  (TIfVer::eMajor, TIfVer::eMinor, TIfVer::ePatchLevel));
  330.     /// Disable/enable DLL resolution (search for class factories in DLLs)
  331.     void FreezeResolution(bool value = true) { m_BlockResolution = value; }
  332.     
  333.     /// Disable/enable DLL resolution (search for class factories in DLLs)
  334.     /// for the specified driver
  335.     void FreezeResolution(const string& driver, bool value = true);
  336.     // ctors
  337.     CPluginManager(void) : m_BlockResolution(false) {}
  338.     virtual ~CPluginManager();
  339. protected:
  340.     TClassFactory* FindClassFactory(const string&  driver,
  341.                                     const CVersionInfo& version);
  342.     /// Protective mutex to syncronize the access to the plugin manager
  343.     /// from different threads
  344.     CFastMutex m_Mutex;
  345.     typedef vector<CDllResolver::SResolvedEntry> TResolvedEntries;
  346.     typedef vector<CPluginManager_DllResolver*>  TDllResolvers;
  347.     typedef set<string>                          TStringSet;
  348. private:
  349.     /// List of factories presently registered with (and owned by)
  350.     /// the plugin manager.
  351.     set<TClassFactory*>                  m_Factories;
  352.     /// DLL resolvers
  353.     TDllResolvers                        m_Resolvers;
  354.     /// Paths used for DLL search
  355.     vector<string>                       m_DllSearchPaths;
  356.     /// DLL entries resolved and registered with dll resolver(s)
  357.     TResolvedEntries                     m_RegisteredEntries;
  358.     /// Flag, prohibits DLL resolution
  359.     bool                                 m_BlockResolution;
  360.     /// Set of drivers prohibited from DLL resolution
  361.     TStringSet                           m_FreezeResolutionDrivers;
  362. };
  363. /// Service class for DLLs resolution.
  364. /// 
  365. /// Class is used by CPluginManager to scan directories for DLLs, 
  366. /// load and resolve entry points.
  367. ///
  368. class NCBI_XNCBI_EXPORT CPluginManager_DllResolver
  369. {
  370. public:
  371.     //
  372.     CPluginManager_DllResolver(void);
  373.     /// Construction
  374.     ///
  375.     /// @param interface_name
  376.     ///   Target interface name
  377.     /// @param plugin_name
  378.     ///   Plugin family name (dbapi, xloader, etc)
  379.     /// @param driver_name
  380.     ///   Name of the driver (dblib, id1, etc)
  381.     /// @param version
  382.     ///   Interface version
  383.     CPluginManager_DllResolver
  384.     (const string&       interface_name,
  385.      const string&       driver_name = kEmptyStr,
  386.      const CVersionInfo& version     = CVersionInfo::kAny);
  387.     //
  388.     virtual ~CPluginManager_DllResolver(void);
  389.     /// Search for plugin DLLs, resolve entry points.
  390.     ///
  391.     /// @param paths
  392.     ///   List of directories to scan for DLLs
  393.     /// @return
  394.     ///   Reference on DLL resolver holding all entry points
  395.     CDllResolver& Resolve(const vector<string>& paths);
  396.     /// Search for plugin DLLs, resolve entry points.
  397.     ///
  398.     /// @param paths
  399.     ///   Path to scan for DLLs
  400.     /// @return
  401.     ///   Reference on DLL resolver holding all entry points
  402.     CDllResolver& Resolve(const string& path);
  403.     /// Return dll file name. Name does not include path.
  404.     ///
  405.     /// Example:
  406.     ///    "ncbi_plugin_dbapi_ftds_3_1_7".
  407.     ///    "ncbi_pulgin_dbapi_ftds.so.3.1.7"
  408.     /// In this case, the DLL will be searched for in the standard
  409.     /// DLL search paths, with automatic addition of any platform-specific
  410.     /// prefixes and suffixes.
  411.     ///
  412.     /// @param driver_name
  413.     ///    Driver name ("id1", "lds", etc)
  414.     /// @param version
  415.     ///    Requested version of the driver
  416.     virtual
  417.     string GetDllName(const string&       interface_name,
  418.                       const string&       driver_name  = kEmptyStr,
  419.                       const CVersionInfo& version      = CVersionInfo::kAny)
  420.         const;
  421.     /// Return DLL name mask 
  422.     ///
  423.     /// DLL name mask is used for DLL file search.
  424.     ///
  425.     /// Example:
  426.     ///    "ncbi_plugin_objmgr_*.dll"
  427.     ///    "ncbi_plugin_dbapi_ftds.so.*"
  428.     virtual
  429.     string GetDllNameMask(const string&       interface_name,
  430.                           const string&       driver_name = kEmptyStr,
  431.                           const CVersionInfo& version     = CVersionInfo::kAny)
  432.         const;
  433.     /// Return DLL entry point name:
  434.     ///
  435.     /// Default name pattern is:
  436.     ///  - "NCBI_EntryPoint_interface_driver"
  437.     /// Alternative variants:
  438.     ///  - "NCBI_EntryPoint"
  439.     ///  - "NCBI_EntryPoint_interface"
  440.     ///  - "NCBI_EntryPoint_driver"
  441.     ///
  442.     /// @sa GetEntryPointPrefix
  443.     virtual
  444.     string GetEntryPointName(const string& interface_name = kEmptyStr,
  445.                              const string& driver_name    = kEmptyStr) const;
  446.     /// Return DLL entry point prefix ("NCBI_EntryPoint")
  447.     virtual string GetEntryPointPrefix() const;
  448.     /// Return DLL file name prefix ("ncbi_plugin")
  449.     virtual string GetDllNamePrefix() const;
  450.     /// Set DLL file name prefix
  451.     virtual void SetDllNamePrefix(const string& prefix);
  452.     /// Return name of the driver
  453.     const string& GetDriverName() const { return m_DriverName; }
  454. protected:
  455.     CDllResolver* GetCreateDllResolver();
  456.     CDllResolver* CreateDllResolver() const;
  457. protected:
  458.     string          m_DllNamePrefix;
  459.     string          m_EntryPointPrefix;
  460.     string          m_InterfaceName;
  461.     string          m_DriverName;
  462.     CVersionInfo    m_Version;
  463.     CDllResolver*   m_DllResolver;
  464. };
  465. /* @} */
  466. /////////////////////////////////////////////////////////////////////////////
  467. //  IMPLEMENTATION of INLINE functions
  468. /////////////////////////////////////////////////////////////////////////////
  469. template <class TClass, class TIfVer>
  470. typename CPluginManager<TClass, TIfVer>::TClassFactory* 
  471. CPluginManager<TClass, TIfVer>::GetFactory(const string&       driver,
  472.                                            const CVersionInfo& version)
  473. {
  474.     CFastMutexGuard guard(m_Mutex);
  475.     TClassFactory* cf = 0;
  476.     // Search among already registered factories
  477.     cf = FindClassFactory(driver, version);
  478.     if (cf) {
  479.         return cf;
  480.     }
  481.     if (!m_BlockResolution) {
  482.         typename TStringSet::const_iterator it = 
  483.                  m_FreezeResolutionDrivers.find(driver);
  484.         if (it == m_FreezeResolutionDrivers.end()) {
  485.             // Trying to resolve the driver's factory
  486.             Resolve(driver, version);
  487.             // Re-scanning factories...
  488.             cf = FindClassFactory(driver, version);
  489.             if (cf) {
  490.                 return cf;
  491.             }
  492.         }
  493.     }
  494.     NCBI_THROW(CPluginManagerException, eResolveFailure, 
  495.                "Cannot resolve class factory");
  496. }
  497. template <class TClass, class TIfVer>
  498. typename CPluginManager<TClass, TIfVer>::TClassFactory* 
  499. CPluginManager<TClass, TIfVer>::FindClassFactory(const string&  driver,
  500.                                                  const CVersionInfo& version)
  501. {
  502.     TClassFactory* best_factory = 0;
  503.     int best_major = -1;
  504.     int best_minor = -1;
  505.     int best_patch_level = -1;
  506.     NON_CONST_ITERATE(typename set<TClassFactory*>, it, m_Factories) {
  507.         TClassFactory* cf = *it;
  508.         typename TClassFactory::TDriverList drv_list;
  509.         if (!cf)
  510.             continue;
  511.         cf->GetDriverVersions(drv_list);
  512.         NON_CONST_ITERATE(typename TClassFactory::TDriverList, it2, drv_list) {
  513.              typename TClassFactory::SDriverInfo& drv_info = *it2;
  514.              if (!driver.empty()) {
  515.                 if (driver != drv_info.name) {
  516.                     continue;
  517.                 }
  518.              }
  519.              const CVersionInfo& vinfo = drv_info.version;
  520.              if (IsBetterVersion(version, vinfo, 
  521.                                  best_major, best_minor, best_patch_level))
  522.              {
  523.                 best_factory = cf;
  524.              }
  525.         }
  526.     }
  527.     
  528.     return best_factory;
  529. }
  530. template <class TClass, class TIfVer>
  531. void CPluginManager<TClass, TIfVer>::RegisterFactory(TClassFactory& factory)
  532. {
  533.     CFastMutexGuard guard(m_Mutex);
  534.     m_Factories.insert(&factory);
  535. }
  536. template <class TClass, class TIfVer>
  537. bool CPluginManager<TClass, TIfVer>::UnregisterFactory(TClassFactory& factory)
  538. {
  539.     CFastMutexGuard guard(m_Mutex);
  540.     typename set<TClassFactory*>::iterator it = m_Factories.find(&factory);
  541.     if (it != m_Factories.end()) {
  542.         delete *it;
  543.         m_Factories.erase(it);
  544.     }
  545.     return true; //?
  546. }
  547. template <class TClass, class TIfVer>
  548. void CPluginManager<TClass, TIfVer>::RegisterWithEntryPoint
  549. (FNCBI_EntryPoint plugin_entry_point)
  550. {
  551.     TDriverInfoList drv_list;
  552.     plugin_entry_point(drv_list, eGetFactoryInfo);
  553.     if ( !drv_list.empty() ) {
  554.         plugin_entry_point(drv_list, eInstantiateFactory);
  555.         NON_CONST_ITERATE(typename TDriverInfoList, it, drv_list) {
  556.             if (it->factory) {
  557.                 RegisterFactory(*(it->factory));
  558.             }
  559.         }
  560.     }
  561. }
  562. template <class TClass, class TIfVer>
  563. void CPluginManager<TClass, TIfVer>::AddResolver
  564. (CPluginManager_DllResolver* resolver)
  565. {
  566.     _ASSERT(resolver);
  567.     m_Resolvers.push_back(resolver);
  568. }
  569. template <class TClass, class TIfVer>
  570. CPluginManager_DllResolver* 
  571. CPluginManager<TClass, TIfVer>::DetachResolver(CPluginManager_DllResolver* 
  572.                                                                     resolver)
  573. {
  574.     NON_CONST_ITERATE(TDllResolvers, it, m_Resolvers) {
  575.         if (resolver == *it) {
  576.             m_Resolvers.erase(it);
  577.             return resolver;
  578.         }
  579.     }
  580.     return 0;
  581. }
  582. template <class TClass, class TIfVer>
  583. void CPluginManager<TClass, TIfVer>::AddDllSearchPath(const string& path)
  584. {
  585.     m_DllSearchPaths.push_back(path);
  586. }
  587. template <class TClass, class TIfVer>
  588. void CPluginManager<TClass, TIfVer>::FreezeResolution(const string& driver, 
  589.                                                       bool          value)
  590. {
  591.     if (value) {
  592.         m_FreezeResolutionDrivers.insert(driver);
  593.     } else {
  594.         m_FreezeResolutionDrivers.erase(driver);
  595.     }
  596. }
  597. template <class TClass, class TIfVer>
  598. void CPluginManager<TClass, TIfVer>::Resolve(const string&       /*driver*/,
  599.                                              const CVersionInfo& /*version*/)
  600. {
  601.     vector<CDllResolver*> resolvers;
  602.     // Run all resolvers to search for driver
  603.     ITERATE(vector<CPluginManager_DllResolver*>, it, m_Resolvers) {
  604.         CDllResolver& dll_resolver = (*it)->Resolve(m_DllSearchPaths);
  605.         resolvers.push_back(&dll_resolver);
  606.     }
  607.     // Now choose the DLL entry point to register the class factory
  608.     NON_CONST_ITERATE(vector<CDllResolver*>, it, resolvers) {
  609.         CDllResolver::TEntries& entry_points = (*it)->GetResolvedEntries();
  610.         NON_CONST_ITERATE(CDllResolver::TEntries, ite, entry_points) {
  611.             CDllResolver::SResolvedEntry& entry = *ite;
  612.             if (entry.entry_points.empty()) {
  613.                 continue;
  614.             }
  615.             CDllResolver::SNamedEntryPoint& epoint = entry.entry_points[0];
  616.             // TODO:
  617.             // check if entry point provides the required interface-driver-version
  618.             // and do not register otherwise...
  619.             if (epoint.entry_point.func) {
  620.                 FNCBI_EntryPoint ep = 
  621.                    (FNCBI_EntryPoint)epoint.entry_point.func;
  622.                 RegisterWithEntryPoint(ep);
  623.                 m_RegisteredEntries.push_back(entry);
  624.             }
  625.         }
  626.         entry_points.resize(0);
  627.     }
  628. }
  629. template <class TClass, class TIfVer>
  630. CPluginManager<TClass, TIfVer>::~CPluginManager()
  631. {
  632.     {{
  633.         typename set<TClassFactory*>::iterator it = m_Factories.begin();
  634.         typename set<TClassFactory*>::iterator it_end = m_Factories.end();
  635.         for (; it != it_end; ++it) {
  636.             TClassFactory* f = *it;
  637.             delete f;
  638.         }
  639.     }}
  640.     {{
  641.         typename vector<CPluginManager_DllResolver*>::iterator it =
  642.             m_Resolvers.begin();
  643.         typename vector<CPluginManager_DllResolver*>::iterator it_end = 
  644.             m_Resolvers.end();
  645.         for (; it != it_end; ++it) {
  646.             CPluginManager_DllResolver* r = *it;
  647.             delete r;
  648.         }
  649.     }}
  650.     NON_CONST_ITERATE(TResolvedEntries, it, m_RegisteredEntries) {
  651.         delete it->dll;
  652.     }
  653. }
  654. END_NCBI_SCOPE
  655. /*
  656.  * ===========================================================================
  657.  * $Log: plugin_manager.hpp,v $
  658.  * Revision 1000.7  2004/06/01 19:08:16  gouriano
  659.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.22
  660.  *
  661.  * Revision 1.22  2004/04/26 14:46:36  ucko
  662.  * Fix a typo in FreezeResolution, and make sure to give
  663.  * UnregisterFactory a return value per its prototype.
  664.  *
  665.  * Revision 1.21  2004/03/19 19:16:20  kuznets
  666.  * Added group of functions to better control DLL resolution (FreezeResolution)
  667.  *
  668.  * Revision 1.20  2004/02/10 20:21:13  ucko
  669.  * Make the interface version class a template parameter with the
  670.  * appropriate default value to work around limitations in IBM's
  671.  * VisualAge compiler.  (It otherwise effectively ignores specializations
  672.  * of CInterfaceVersion that follow the templates that use them.)
  673.  *
  674.  * Revision 1.19  2004/01/13 17:21:23  kuznets
  675.  * Class factory CreateInstance method received an additional parameter
  676.  * TPluginManagerParamTree (to specify initialization parameters or prefrences)
  677.  *
  678.  * Revision 1.18  2003/12/02 12:44:39  kuznets
  679.  * Fixed minor compilation issue.
  680.  *
  681.  * Revision 1.17  2003/12/01 19:53:06  kuznets
  682.  * Reflecting changes in CDllResolver
  683.  *
  684.  * Revision 1.16  2003/11/19 15:46:04  kuznets
  685.  * Removed clumsy function pointer conversion from plugin manager.
  686.  * (it is now covered by CDll)
  687.  *
  688.  * Revision 1.15  2003/11/19 13:48:20  kuznets
  689.  * Helper classes migrated into a plugin_manager_impl.hpp
  690.  *
  691.  * Revision 1.14  2003/11/18 17:09:25  kuznets
  692.  * Fixing compilation warnings
  693.  *
  694.  * Revision 1.13  2003/11/18 15:26:29  kuznets
  695.  * Numerous fixes here and there as a result of testing and debugging.
  696.  *
  697.  * Revision 1.12  2003/11/17 17:04:11  kuznets
  698.  * Cosmetic fixes
  699.  *
  700.  * Revision 1.11  2003/11/12 18:56:53  kuznets
  701.  * Implemented dll resolution.
  702.  *
  703.  * Revision 1.10  2003/11/07 17:02:48  kuznets
  704.  * Drafted CPluginManager_DllResolver.
  705.  *
  706.  * Revision 1.9  2003/11/03 20:08:01  kuznets
  707.  * Fixing various compiler warnings
  708.  *
  709.  * Revision 1.8  2003/11/03 17:52:00  kuznets
  710.  * Added CSimpleClassFactoryImpl template.
  711.  * Helps quickly implement basic PM compatible class factory.
  712.  *
  713.  * Revision 1.7  2003/11/03 16:32:58  kuznets
  714.  * Cleaning the code to be compatible with GCC, WorkShop 53 and MSVC at the
  715.  * same time...
  716.  *
  717.  * Revision 1.6  2003/10/31 19:53:52  kuznets
  718.  * +CHostEntryPointImpl
  719.  *
  720.  * Revision 1.5  2003/10/30 20:03:49  kuznets
  721.  * Work in progress. Added implementations of CPluginManager<> methods.
  722.  *
  723.  * Revision 1.4  2003/10/29 23:35:46  vakatov
  724.  * Just starting with CDllResolver...
  725.  *
  726.  * Revision 1.3  2003/10/29 19:34:43  vakatov
  727.  * Comment out unfinished defined APIs (using "#if 0")
  728.  *
  729.  * Revision 1.2  2003/10/28 22:29:04  vakatov
  730.  * Draft-done with:
  731.  *   general terminology
  732.  *   CInterfaceVersion<>
  733.  *   NCBI_PLUGIN_VERSION()
  734.  *   IClassFactory<>
  735.  *   CPluginManager<>
  736.  * TODO:
  737.  *   Host-related API
  738.  *   DLL resolution
  739.  *
  740.  * Revision 1.1  2003/10/28 00:12:23  vakatov
  741.  * Initial revision
  742.  *
  743.  * Work-in-progress, totally unfinished.
  744.  * Note: DLL resolution shall be split and partially moved to the NCBIDLL.
  745.  *
  746.  * ===========================================================================
  747.  */
  748. #endif  /* CORELIB___PLUGIN_MANAGER__HPP */