Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

classload.hpp

Go to the documentation of this file.
00001 #ifndef s11n_cl_S11N_CLASSLOAD_HPP_INCLUDED
00002 #define s11n_cl_S11N_CLASSLOAD_HPP_INCLUDED 1
00003 
00004 #include <s11n.net/s11n/s11n_debuggering_macros.hpp> // S11N_TRACE()
00005 #include <s11n.net/s11n/factory.hpp>
00006 #include <s11n.net/s11n/exception.hpp>
00007 #include <s11n.net/s11n/type_traits.hpp> 
00008 
00009 #include <s11n.net/s11n/s11n_config.hpp>
00010 #if s11n_CONFIG_ENABLE_PLUGINS
00011 #    include <s11n.net/s11n/plugin/plugin.hpp>
00012 #endif
00013 
00014 namespace s11n {
00015         /**
00016            The s11n::cl namespace encapsulates the public
00017            classloader-related API for libs11n.
00018 
00019            Note that the registration functions in this namespace
00020            register with the s11n::fac family of classes. Clients wishing to use
00021            their own factories should:
00022 
00023            - register with their appropriate classloader.
00024 
00025            - specialize the object_factory class template
00026            so that it forwards calls to their classloader.
00027 
00028            This layer is used for classloading anything which s11n
00029            needs to dynamically load, including:
00030 
00031            - Serializables
00032 
00033            - Serializers
00034 
00035            - FlexLexers
00036 
00037            It supports loading types via DLLs if the optional s11n::plugin
00038        layer is enabled.
00039 
00040        Changes from 1.0.x to 1.1.x:
00041 
00042        - Now internally uses s11n::factory_mgr and s11n::plugin
00043        instead of the cllite API.
00044 
00045         */
00046         namespace cl {
00047 
00048                 /**
00049                    A default object factory functor for use
00050                    with the s11n::s11n_traits type.
00051 
00052                    Clients may specialize this to return objects from
00053                    their own factories. By default it uses s11n::fac's
00054            mini-framework, and thus can load any type registered with
00055                    that API.
00056                 */
00057                 template <typename InterfaceBase>
00058                 struct S11N_EXPORT_API object_factory
00059                 {
00060                         /** Same as InterfaceBase. */
00061                         typedef InterfaceBase base_type;
00062 
00063                         /**
00064                The default implementation returns
00065                ::s11n::fac::factory<InterfaceBase>().create(key). The
00066                caller owns the returned pointer, which may
00067                be 0.
00068 
00069                If the underlying factory does not have the
00070                requested class and s11n is built with the
00071                s11n::plugin layer, then
00072                s11n::plugin::open(classname) is used to
00073                search for a DLL. Under the s11n classloader
00074                model, opening a plugin will register classes
00075                defined in the plugin back with the factory.
00076 
00077                This function propagates exceptions if the
00078                underlying factory's create() feature throws.
00079 
00080                a) s11n_exceptions are passed on as-is.
00081 
00082                b) std::exceptions are translated to
00083                s11n::factory_exceptions, keeping the
00084                what() text.
00085 
00086                c) Unknown exceptions (...) are translated
00087                to s11n::factory_exceptions with an
00088                unspecified non-empty what() text.
00089 
00090                         */
00091                         base_type * operator()( const std::string & key ) const
00092                         {
00093                 try
00094                 {
00095                     typedef ::s11n::fac::factory_mgr<base_type> FacMgr;
00096                     FacMgr & fm = FacMgr::instance();
00097 #if s11n_CONFIG_ENABLE_PLUGINS
00098                     // Attempt a DLL lookup if the class isn't already registered.
00099                     if( ! fm.provides( key ) )
00100                     {
00101                         using namespace ::s11n::debug;
00102                         S11N_TRACE(TRACE_FACTORY_PLUGINS) << "Trying to find plugin for " << key << "...\n";
00103                         std::string where = ::s11n::plugin::open( key );
00104                         if( where.empty()  )
00105                         {
00106                             S11N_TRACE(TRACE_FACTORY_PLUGINS) << "Plugin load failed for '"<<key<<"': " << ::s11n::plugin::dll_error() << "\n";
00107                             return 0;
00108                         }
00109                     }
00110 #endif // s11n_CONFIG_ENABLE_PLUGINS
00111                     return fm.create( key );
00112                 }
00113                 catch( const ::s11n::s11n_exception & )
00114                 {
00115                     throw;
00116                 }
00117                 catch( const std::exception & ex )
00118                 {
00119                     throw ::s11n::factory_exception( ex.what() );
00120                 }
00121                 catch(...)
00122                 {
00123                     throw ::s11n::factory_exception( "Unknown exception: Factory load failed for class '"+key+"'.", __FILE__, __LINE__ );
00124                 }
00125                 return 0;
00126                         }
00127                 };
00128 
00129 
00130                 /**
00131            Returns object_factory<InterfaceBase>()(key).
00132                 */
00133                 template <typename InterfaceBase>
00134                 InterfaceBase * classload( const std::string key );
00135 
00136                 /**
00137                    Registers a factory with InterfaceBase's
00138                    classloader.
00139 
00140            Trivia: 'register' is a reserved word in C++,
00141            inherited from C, so this function has an unduly
00142            long name. register() was the first choice.
00143                 */
00144                 template <typename InterfaceBase>
00145                 void classloader_register( const std::string & classname, InterfaceBase * (*factory_func)() );
00146 
00147         /**
00148            Registers a default factory which returns a SubType
00149            object. SubType must be a public subtype of
00150            InterfaceBase, or must be InterfaceBase, and must
00151            not be abstract.
00152         */
00153                 template <typename InterfaceBase, typename SubType>
00154                 inline void classloader_register_subtype( const std::string & classname )
00155         {
00156             classloader_register<InterfaceBase>( classname, 
00157                                  ::s11n::fac::create_hook<InterfaceBase,SubType>::create
00158                                  );
00159         }
00160 
00161                 /**
00162                    Registers InterfaceBase with its own classloader
00163                    using a default factory. InterfaceBase must be creatable
00164            with 'new', or the default factory implementation must
00165            be specialized to accomodate the abstract class.
00166                 */
00167                 template <typename InterfaceBase>
00168                 inline void classloader_register_base( const std::string & classname )
00169                 {
00170                         classloader_register_subtype<InterfaceBase,InterfaceBase>( classname );
00171                 }
00172 
00173 
00174         namespace Detail
00175         {
00176             /** Internal no-op factory. Always returns 0. */
00177             template <typename T>
00178             inline T * noop_factory() { return 0; }
00179         }
00180 
00181                 /**
00182                    Registers InterfaceBase as an abstract type. That is, it
00183                    assigns it a factory which always returns 0.
00184 
00185                    If types you register with classloader_register()
00186                    (and friends) have an abstract InterfaceBase then that
00187                    InterfaceBase should be registered via this function (or
00188                    equivalent).
00189 
00190            Note that this is also suitable for registering abstract subtypes
00191            of an abstract type, but InterfaceBase MUST be the type passed
00192            here, or the registrations will go to the subtype's classloader,
00193            which isn't what you want to do.
00194                 */
00195                 template <typename InterfaceBase>
00196                 inline void classloader_register_abstract( const std::string & classname )
00197                 {
00198             classloader_register<InterfaceBase>( classname, Detail::noop_factory<InterfaceBase> );
00199                 }
00200 
00201 
00202         /**
00203            Aliases the given classname with the underlying
00204            factory layer, such that classload<InterfaceBase>(_alias)
00205            will return the same as classload<InterfaceBase>(classname).
00206 
00207            Added in 1.1.0.
00208 
00209            Maintenance reminder: this function relies directly on
00210            the s11n::fac API, which isn't "really" public. That functionality
00211            is commonly useful which hand-registering types, thus we
00212            have a public-API wrapper around this fac-layer-specific
00213            feature.
00214         */
00215                 template <typename InterfaceBase>
00216                 inline void classloader_alias( const std::string & _alias,
00217                            const std::string & classname)
00218                 {
00219             ::s11n::fac::factory<InterfaceBase>().aliases().alias( _alias, classname );
00220                 }
00221 
00222 
00223         } // namespace cl
00224 } // namespace s11n
00225 
00226 #include <s11n.net/s11n/classload.tpp> // implementations
00227 #endif // s11n_cl_S11N_CLASSLOAD_HPP_INCLUDED

Generated on Thu Sep 29 20:01:14 2005 for libs11n-1.1.3-dev by  doxygen 1.4.1