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

Generated on Sun Apr 27 11:46:48 2008 for libs11n-1.2.6 by  doxygen 1.5.3