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