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