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 Changed in 1.3.0: this now propogates exceptions 00079 as-is, instead of re-wrapping certain exception 00080 types as s11n_exceptions. 00081 */ 00082 base_type * operator()( const std::string & key ) const; 00083 }; 00084 00085 /** 00086 Returns object_factory<InterfaceBase>(key). 00087 */ 00088 template <typename InterfaceBase> 00089 InterfaceBase * classload( const std::string key ); 00090 00091 /** 00092 Registers a factory with InterfaceBase's 00093 classloader. 00094 00095 Trivia: 'register' is a reserved word in C++, 00096 inherited from C, so this function has an unduly 00097 long name. register() was the first choice. 00098 */ 00099 template <typename InterfaceBase> 00100 void classloader_register( const std::string & classname, InterfaceBase * (*factory_func)() ); 00101 00102 /** 00103 Registers a default factory which returns a SubType 00104 object. SubType must be a public subtype of 00105 InterfaceBase, or must be InterfaceBase, and must 00106 not be abstract. 00107 */ 00108 template <typename InterfaceBase, typename SubType> 00109 inline void classloader_register_subtype( const std::string & classname ) 00110 { 00111 classloader_register<InterfaceBase>( classname, 00112 ::s11n::fac::create_hook<InterfaceBase,SubType>::create 00113 ); 00114 } 00115 00116 /** 00117 Registers InterfaceBase with its own classloader 00118 using a default factory. InterfaceBase must be creatable 00119 with 'new', or the default factory implementation must 00120 be specialized to accomodate the abstract class. 00121 */ 00122 template <typename InterfaceBase> 00123 inline void classloader_register_base( const std::string & classname ) 00124 { 00125 classloader_register_subtype<InterfaceBase,InterfaceBase>( classname ); 00126 } 00127 00128 00129 namespace Detail 00130 { 00131 /** Internal no-op factory. Always returns 0. */ 00132 template <typename T> 00133 inline T * noop_factory() { return 0; } 00134 } 00135 00136 /** 00137 Registers InterfaceBase as an abstract type. That is, it 00138 assigns it a factory which always returns 0. 00139 00140 If types you register with classloader_register() 00141 (and friends) have an abstract InterfaceBase then that 00142 InterfaceBase should be registered via this function (or 00143 equivalent). 00144 00145 Note that this is also suitable for registering 00146 abstract subtypes of an abstract type, but 00147 InterfaceBase MUST be the type passed here (not the 00148 subtype's type), or the registrations will go to 00149 the subtype's classloader, which normally isn't 00150 what you want to do. 00151 */ 00152 template <typename InterfaceBase> 00153 inline void classloader_register_abstract( const std::string & classname ) 00154 { 00155 classloader_register<InterfaceBase>( classname, Detail::noop_factory<InterfaceBase> ); 00156 } 00157 00158 00159 /** 00160 Aliases the given classname with the underlying 00161 factory layer, such that classload<InterfaceBase>(_alias) 00162 will return the same as classload<InterfaceBase>(classname). 00163 00164 A tip for remembering the order of the arguments: 00165 it follows the same order as when assigning an alias 00166 via a Unix shell: alias thealias="the original string" 00167 00168 Added in 1.1.0. 00169 00170 Maintenance reminder: this function relies directly 00171 on the s11n::fac API, which isn't "really" 00172 public. This functionality is commonly useful when 00173 hand-registering types, thus we have a public-API 00174 wrapper around this fac-layer-specific feature. 00175 */ 00176 template <typename InterfaceBase> 00177 inline void classloader_alias( const std::string & _alias, 00178 const std::string & classname) 00179 { 00180 ::s11n::fac::factory<InterfaceBase>().alias( _alias, classname ); 00181 } 00182 00183 00184 } // namespace cl 00185 } // namespace s11n 00186 00187 #include <s11n.net/s11n/classload.tpp> // implementations 00188 #endif // s11n_cl_S11N_CLASSLOAD_HPP_INCLUDED