1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 #if ! defined(COMPHELPER_SERVICEDECL_HXX_INCLUDED) 24 #define COMPHELPER_SERVICEDECL_HXX_INCLUDED 25 26 #include <comphelper/comphelperdllapi.h> 27 #include <cppuhelper/implbase1.hxx> 28 #include <com/sun/star/uno/XComponentContext.hpp> 29 #include <com/sun/star/lang/XServiceInfo.hpp> 30 #include <com/sun/star/registry/XRegistryKey.hpp> 31 #include <uno/environment.h> 32 #include <boost/utility.hpp> 33 #include <boost/function.hpp> 34 #include <boost/preprocessor/cat.hpp> 35 #include <boost/preprocessor/repetition.hpp> 36 #include <boost/preprocessor/seq/enum.hpp> 37 38 namespace comphelper { 39 namespace service_decl { 40 41 class ServiceDecl; 42 43 namespace detail { 44 namespace css = ::com::sun::star; 45 typedef ::boost::function3< 46 css::uno::Reference<css::uno::XInterface> /* return */, 47 ServiceDecl const&, 48 css::uno::Sequence<css::uno::Any> const&, 49 css::uno::Reference<css::uno::XComponentContext> const&> CreateFuncF; 50 } 51 52 /** Class to declare a service implementation. There is no need to implement 53 lang::XServiceInfo nor lang::XInitialization anymore. 54 The declaration can be done in various ways, the (simplest) form is 55 56 <pre> 57 class MyClass : public cppu::WeakImplHelper2<XInterface1, XInterface2> { 58 public: 59 MyClass( uno::Reference<uno::XComponentContext> const& xContext ) 60 [...] 61 }; 62 [...] 63 namespace sdecl = comphelper::service_decl; 64 sdecl::ServiceDecl const myDecl( 65 sdecl::class_<MyClass>(), 66 "my.unique.implementation.name", 67 "MyServiceSpec1;MyServiceSpec2" ); 68 </pre> 69 70 If the service demands initialization by arguments, the implementation 71 class has to define a constructor taking both arguments and component 72 context: 73 74 <pre> 75 class MyClass : public cppu::WeakImplHelper2<XInterface1, XInterface2> { 76 public: 77 MyClass( uno::Sequence<uno::Any> const& args, 78 uno::Reference<uno:XComponentContext> const& xContext ) 79 [...] 80 }; 81 [...] 82 namespace sdecl = comphelper::service_decl; 83 sdecl::ServiceDecl const myDecl( 84 sdecl::class_<MyClass, sdecl::with_args<true> >(), 85 "my.unique.implementation.name", 86 "MyServiceSpec1;MyServiceSpec2" ); 87 </pre> 88 89 Additionally, there is the possibility to process some code after creation, 90 e.g. to add the newly created object as a listener or perform aggregation 91 (C++-UNO only): 92 93 <pre> 94 uno::Reference<uno::XInterface> somePostProcCode( MyClass * p ); 95 [...] 96 namespace sdecl = comphelper::service_decl; 97 sdecl::ServiceDecl const myDecl( 98 sdecl::class_<MyClass, ... >(&somePostProcCode), 99 "my.unique.implementation.name", 100 "MyServiceSpec1;MyServiceSpec2" ); 101 </pre> 102 103 In the latter case, somePostProcCode gets the yet unacquired "raw" pointer. 104 */ 105 class COMPHELPER_DLLPUBLIC ServiceDecl : private ::boost::noncopyable 106 { 107 public: 108 /** Ctor for multiple supported service names. 109 110 @param implClass implementation class description 111 @param pImplName implementation name 112 @param pSupportedServiceNames supported service names 113 @param cDelim delimiter for supported service names 114 */ 115 template <typename ImplClassT> ServiceDecl(ImplClassT const & implClass,char const * pImplName,char const * pSupportedServiceNames,char cDelim=';')116 ServiceDecl( ImplClassT const& implClass, 117 char const* pImplName, 118 char const* pSupportedServiceNames, char cDelim = ';' ) 119 : m_createFunc(implClass.m_createFunc), 120 m_pImplName(pImplName), 121 m_pServiceNames(pSupportedServiceNames), 122 m_cDelim(cDelim) {} 123 124 /// @internal gets called by component_getFactoryHelper() 125 void * getFactory( sal_Char const* pImplName ) const; 126 127 /// @return supported service names 128 ::com::sun::star::uno::Sequence< ::rtl::OUString> 129 getSupportedServiceNames() const; 130 131 /// @return whether name is in set of supported service names 132 bool supportsService( ::rtl::OUString const& name ) const; 133 134 /// @return implementation name 135 ::rtl::OUString getImplementationName() const; 136 137 private: 138 class Factory; 139 friend class Factory; 140 141 detail::CreateFuncF const m_createFunc; 142 char const* const m_pImplName; 143 char const* const m_pServiceNames; 144 char const m_cDelim; 145 }; 146 147 /** To specify whether the implementation class expects arguments 148 (uno::Sequence<uno::Any>). 149 */ 150 template <bool> struct with_args; 151 152 /// @internal 153 namespace detail { 154 template <typename ImplT> 155 class OwnServiceImpl 156 : public ImplT, 157 private ::boost::noncopyable 158 { 159 typedef ImplT BaseT; 160 161 public: OwnServiceImpl(ServiceDecl const & rServiceDecl,css::uno::Sequence<css::uno::Any> const & args,css::uno::Reference<css::uno::XComponentContext> const & xContext)162 OwnServiceImpl( 163 ServiceDecl const& rServiceDecl, 164 css::uno::Sequence<css::uno::Any> const& args, 165 css::uno::Reference<css::uno::XComponentContext> const& xContext ) 166 :BaseT(args, xContext), m_rServiceDecl(rServiceDecl) {} OwnServiceImpl(ServiceDecl const & rServiceDecl,css::uno::Reference<css::uno::XComponentContext> const & xContext)167 OwnServiceImpl( 168 ServiceDecl const& rServiceDecl, 169 css::uno::Reference<css::uno::XComponentContext> const& xContext ) 170 : BaseT(xContext), m_rServiceDecl(rServiceDecl) {} 171 172 // XServiceInfo getImplementationName()173 virtual ::rtl::OUString SAL_CALL getImplementationName() 174 throw (css::uno::RuntimeException) { 175 return m_rServiceDecl.getImplementationName(); 176 } supportsService(::rtl::OUString const & name)177 virtual sal_Bool SAL_CALL supportsService( ::rtl::OUString const& name ) 178 throw (css::uno::RuntimeException) { 179 return m_rServiceDecl.supportsService(name); 180 } 181 virtual css::uno::Sequence< ::rtl::OUString> getSupportedServiceNames()182 SAL_CALL getSupportedServiceNames() throw (css::uno::RuntimeException) { 183 return m_rServiceDecl.getSupportedServiceNames(); 184 } 185 186 private: 187 ServiceDecl const& m_rServiceDecl; 188 }; 189 190 template <typename ImplT> 191 class ServiceImpl : public OwnServiceImpl< ::cppu::ImplInheritanceHelper1<ImplT,css::lang::XServiceInfo> > 192 { 193 typedef OwnServiceImpl< ::cppu::ImplInheritanceHelper1<ImplT,css::lang::XServiceInfo> > ServiceImpl_BASE; 194 public: ServiceImpl(ServiceDecl const & rServiceDecl,css::uno::Sequence<css::uno::Any> const & args,css::uno::Reference<css::uno::XComponentContext> const & xContext)195 ServiceImpl( 196 ServiceDecl const& rServiceDecl, 197 css::uno::Sequence<css::uno::Any> const& args, 198 css::uno::Reference<css::uno::XComponentContext> const& xContext ) 199 : ServiceImpl_BASE(rServiceDecl, args, xContext) {} ServiceImpl(ServiceDecl const & rServiceDecl,css::uno::Reference<css::uno::XComponentContext> const & xContext)200 ServiceImpl( 201 ServiceDecl const& rServiceDecl, 202 css::uno::Reference<css::uno::XComponentContext> const& xContext ) 203 : ServiceImpl_BASE(rServiceDecl, xContext) {} 204 }; 205 206 template <typename ServiceImplT> 207 struct PostProcessDefault { 208 css::uno::Reference<css::uno::XInterface> operator ()comphelper::service_decl::detail::PostProcessDefault209 operator()( ServiceImplT * p ) const { 210 return static_cast<css::lang::XServiceInfo *>(p); 211 } 212 }; 213 214 template <typename ImplT, typename PostProcessFuncT, typename WithArgsT> 215 struct CreateFunc; 216 217 template <typename ImplT, typename PostProcessFuncT> 218 struct CreateFunc<ImplT, PostProcessFuncT, with_args<false> > { 219 PostProcessFuncT const m_postProcessFunc; CreateFunccomphelper::service_decl::detail::CreateFunc220 explicit CreateFunc( PostProcessFuncT const& postProcessFunc ) 221 : m_postProcessFunc(postProcessFunc) {} 222 223 css::uno::Reference<css::uno::XInterface> operator ()comphelper::service_decl::detail::CreateFunc224 operator()( ServiceDecl const& rServiceDecl, 225 css::uno::Sequence<css::uno::Any> const&, 226 css::uno::Reference<css::uno::XComponentContext> 227 const& xContext ) const 228 { 229 return m_postProcessFunc( 230 new ImplT( rServiceDecl, xContext ) ); 231 } 232 }; 233 234 template <typename ImplT, typename PostProcessFuncT> 235 struct CreateFunc<ImplT, PostProcessFuncT, with_args<true> > { 236 PostProcessFuncT const m_postProcessFunc; CreateFunccomphelper::service_decl::detail::CreateFunc237 explicit CreateFunc( PostProcessFuncT const& postProcessFunc ) 238 : m_postProcessFunc(postProcessFunc) {} 239 240 css::uno::Reference<css::uno::XInterface> operator ()comphelper::service_decl::detail::CreateFunc241 operator()( ServiceDecl const& rServiceDecl, 242 css::uno::Sequence<css::uno::Any> const& args, 243 css::uno::Reference<css::uno::XComponentContext> 244 const& xContext ) const 245 { 246 return m_postProcessFunc( 247 new ImplT( rServiceDecl, args, xContext ) ); 248 } 249 }; 250 251 } // namespace detail 252 253 /** Defines a service implementation class. 254 255 @tpl ImplT_ service implementation class 256 @WithArgsT whether the implementation class ctor expects arguments 257 (uno::Sequence<uno::Any>, uno::Reference<uno::XComponentContext>) 258 or just (uno::Reference<uno::XComponentContext>) 259 */ 260 template <typename ImplT_, typename WithArgsT = with_args<false> > 261 struct serviceimpl_base { 262 typedef ImplT_ ImplT; 263 264 detail::CreateFuncF const m_createFunc; 265 266 typedef detail::PostProcessDefault<ImplT> PostProcessDefaultT; 267 268 /** Default ctor. Implementation class without args, expecting 269 component context as single argument. 270 */ serviceimpl_basecomphelper::service_decl::serviceimpl_base271 serviceimpl_base() : m_createFunc( 272 detail::CreateFunc<ImplT, PostProcessDefaultT, WithArgsT>( 273 PostProcessDefaultT() ) ) {} 274 275 /** Ctor to pass a post processing function/functor. 276 277 @tpl PostProcessDefaultT let your compiler deduce this 278 @param postProcessFunc function/functor that gets the yet unacquired 279 ImplT_ pointer returning a 280 uno::Reference<uno::XInterface> 281 */ 282 template <typename PostProcessFuncT> serviceimpl_basecomphelper::service_decl::serviceimpl_base283 explicit serviceimpl_base( PostProcessFuncT const& postProcessFunc ) 284 : m_createFunc( detail::CreateFunc<ImplT, PostProcessFuncT, WithArgsT>( 285 postProcessFunc ) ) {} 286 }; 287 288 template <typename ImplT_, typename WithArgsT = with_args<false> > 289 struct class_ : public serviceimpl_base< detail::ServiceImpl<ImplT_>, WithArgsT > 290 { 291 typedef serviceimpl_base< detail::ServiceImpl<ImplT_>, WithArgsT > baseT; 292 /** Default ctor. Implementation class without args, expecting 293 component context as single argument. 294 */ class_comphelper::service_decl::class_295 class_() : baseT() {} 296 template <typename PostProcessFuncT> 297 /** Ctor to pass a post processing function/functor. 298 299 @tpl PostProcessDefaultT let your compiler deduce this 300 @param postProcessFunc function/functor that gets the yet unacquired 301 ImplT_ pointer returning a 302 uno::Reference<uno::XInterface> 303 */ class_comphelper::service_decl::class_304 explicit class_( PostProcessFuncT const& postProcessFunc ) : baseT( postProcessFunc ) {} 305 }; 306 307 // 308 // component_... helpers with arbitrary service declarations: 309 // 310 311 #define COMPHELPER_SERVICEDECL_getFactory(z_, n_, unused_) \ 312 if (pRet == 0) \ 313 pRet = BOOST_PP_CAT(s, n_).getFactory(pImplName); 314 315 /** The following preprocessor repetitions generate functions like 316 317 <pre> 318 inline void * component_getFactoryHelper( 319 sal_Char const* pImplName, 320 ::com::sun::star::lang::XMultiServiceFactory *, 321 ::com::sun::star::registry::XRegistryKey * xRegistryKey, 322 ServiceDecl const& s0, ServiceDecl const& s1, ... ); 323 </pre> 324 325 which call on the passed service declarations. 326 327 The maximum number of service declarations can be set by defining 328 COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS; its default is 8. 329 */ 330 #define COMPHELPER_SERVICEDECL_make(z_, n_, unused_) \ 331 inline void * component_getFactoryHelper( \ 332 sal_Char const* pImplName, \ 333 ::com::sun::star::lang::XMultiServiceFactory *, \ 334 ::com::sun::star::registry::XRegistryKey *, \ 335 BOOST_PP_ENUM_PARAMS(n_, ServiceDecl const& s) ) \ 336 { \ 337 void * pRet = 0; \ 338 BOOST_PP_REPEAT(n_, COMPHELPER_SERVICEDECL_getFactory, ~) \ 339 return pRet; \ 340 } 341 342 #if ! defined(COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS) 343 #define COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS 8 344 #endif 345 346 BOOST_PP_REPEAT_FROM_TO(1, COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS, 347 COMPHELPER_SERVICEDECL_make, ~) 348 349 #undef COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS 350 #undef COMPHELPER_SERVICEDECL_make 351 #undef COMPHELPER_SERVICEDECL_getFactory 352 353 } // namespace service_decl 354 } // namespace comphelper 355 356 /** The following preprocessor macro generates the C access functions, 357 that are used to initialize and register the components of a 358 shared library object. 359 360 If you have, say, written a lib that contains three distinct 361 components, each with its own ServiceDecl object, you might want 362 to employ the following code: 363 364 <pre> 365 // must reside outside _any_ namespace 366 COMPHELPER_SERVICEDECL_EXPORTS3(yourServiceDecl1, 367 yourServiceDecl2, 368 yourServiceDecl3); 369 </pre> 370 371 For your convenience, the COMPHELPER_SERVICEDECL_EXPORTS<N> macro 372 comes pre-defined up to N=8, if you should need more arguments, 373 call COMPHELPER_SERVICEDECL_make_exports directly, like this: 374 375 <pre> 376 // must reside outside _any_ namespace 377 COMPHELPER_SERVICEDECL_make_exports((yourServiceDecl1)(yourServiceDecl2)...(yourServiceDeclN)); 378 </pre> 379 380 Note the missing colons between the bracketed arguments. 381 */ 382 #define COMPHELPER_SERVICEDECL_make_exports(varargs_ ) \ 383 extern "C" \ 384 { \ 385 SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( const sal_Char** ppEnvTypeName, \ 386 uno_Environment** /*ppEnv*/ ) \ 387 { \ 388 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; \ 389 } \ 390 \ 391 SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory( sal_Char const* pImplName, \ 392 ::com::sun::star::lang::XMultiServiceFactory* pServiceManager, \ 393 ::com::sun::star::registry::XRegistryKey* pRegistryKey ) \ 394 { \ 395 return component_getFactoryHelper( pImplName, pServiceManager, \ 396 pRegistryKey, \ 397 BOOST_PP_SEQ_ENUM(varargs_) ); \ 398 } \ 399 } 400 401 #define COMPHELPER_SERVICEDECL_EXPORTS1(comp0_) \ 402 COMPHELPER_SERVICEDECL_make_exports((comp0_)) 403 #define COMPHELPER_SERVICEDECL_EXPORTS2(comp0_,comp1_) \ 404 COMPHELPER_SERVICEDECL_make_exports((comp0_)(comp1_)) 405 #define COMPHELPER_SERVICEDECL_EXPORTS3(comp0_,comp1_,comp2_) \ 406 COMPHELPER_SERVICEDECL_make_exports((comp0_)(comp1_)(comp2_)) 407 #define COMPHELPER_SERVICEDECL_EXPORTS4(comp0_,comp1_,comp2_,comp3_) \ 408 COMPHELPER_SERVICEDECL_make_exports((comp0_)(comp1_)(comp2_)(comp3_)) 409 #define COMPHELPER_SERVICEDECL_EXPORTS5(comp0_,comp1_,comp2_,comp3_,comp4_) \ 410 COMPHELPER_SERVICEDECL_make_exports((comp0_)(comp1_)(comp2_)(comp3_)(comp4_)) 411 #define COMPHELPER_SERVICEDECL_EXPORTS6(comp0_,comp1_,comp2_,comp3_,comp4_,comp5_) \ 412 COMPHELPER_SERVICEDECL_make_exports((comp0_)(comp1_)(comp2_)(comp3_)(comp4_)(comp5_)) 413 #define COMPHELPER_SERVICEDECL_EXPORTS7(comp0_,comp1_,comp2_,comp3_,comp4_,comp5_,comp6_) \ 414 COMPHELPER_SERVICEDECL_make_exports((comp0_)(comp1_)(comp2_)(comp3_)(comp4_)(comp5_)(comp6_)) 415 #define COMPHELPER_SERVICEDECL_EXPORTS8(comp0_,comp1_,comp2_,comp3_,comp4_,comp5_,comp6_,comp7_) \ 416 COMPHELPER_SERVICEDECL_make_exports((comp0_)(comp1_)(comp2_)(comp3_)(comp4_)(comp5_)(comp6_)(comp7_)) 417 418 #endif // ! defined(COMPHELPER_SERVICEDECL_HXX_INCLUDED) 419 420