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 return m_rServiceDecl.getImplementationName(); 175 } supportsService(::rtl::OUString const & name)176 virtual sal_Bool SAL_CALL supportsService( ::rtl::OUString const& name ) { 177 return m_rServiceDecl.supportsService(name); 178 } 179 virtual css::uno::Sequence< ::rtl::OUString> getSupportedServiceNames()180 SAL_CALL getSupportedServiceNames() { 181 return m_rServiceDecl.getSupportedServiceNames(); 182 } 183 184 private: 185 ServiceDecl const& m_rServiceDecl; 186 }; 187 188 template <typename ImplT> 189 class ServiceImpl : public OwnServiceImpl< ::cppu::ImplInheritanceHelper1<ImplT,css::lang::XServiceInfo> > 190 { 191 typedef OwnServiceImpl< ::cppu::ImplInheritanceHelper1<ImplT,css::lang::XServiceInfo> > ServiceImpl_BASE; 192 public: ServiceImpl(ServiceDecl const & rServiceDecl,css::uno::Sequence<css::uno::Any> const & args,css::uno::Reference<css::uno::XComponentContext> const & xContext)193 ServiceImpl( 194 ServiceDecl const& rServiceDecl, 195 css::uno::Sequence<css::uno::Any> const& args, 196 css::uno::Reference<css::uno::XComponentContext> const& xContext ) 197 : ServiceImpl_BASE(rServiceDecl, args, xContext) {} ServiceImpl(ServiceDecl const & rServiceDecl,css::uno::Reference<css::uno::XComponentContext> const & xContext)198 ServiceImpl( 199 ServiceDecl const& rServiceDecl, 200 css::uno::Reference<css::uno::XComponentContext> const& xContext ) 201 : ServiceImpl_BASE(rServiceDecl, xContext) {} 202 }; 203 204 template <typename ServiceImplT> 205 struct PostProcessDefault { 206 css::uno::Reference<css::uno::XInterface> operator ()comphelper::service_decl::detail::PostProcessDefault207 operator()( ServiceImplT * p ) const { 208 return static_cast<css::lang::XServiceInfo *>(p); 209 } 210 }; 211 212 template <typename ImplT, typename PostProcessFuncT, typename WithArgsT> 213 struct CreateFunc; 214 215 template <typename ImplT, typename PostProcessFuncT> 216 struct CreateFunc<ImplT, PostProcessFuncT, with_args<false> > { 217 PostProcessFuncT const m_postProcessFunc; CreateFunccomphelper::service_decl::detail::CreateFunc218 explicit CreateFunc( PostProcessFuncT const& postProcessFunc ) 219 : m_postProcessFunc(postProcessFunc) {} 220 221 css::uno::Reference<css::uno::XInterface> operator ()comphelper::service_decl::detail::CreateFunc222 operator()( ServiceDecl const& rServiceDecl, 223 css::uno::Sequence<css::uno::Any> const&, 224 css::uno::Reference<css::uno::XComponentContext> 225 const& xContext ) const 226 { 227 return m_postProcessFunc( 228 new ImplT( rServiceDecl, xContext ) ); 229 } 230 }; 231 232 template <typename ImplT, typename PostProcessFuncT> 233 struct CreateFunc<ImplT, PostProcessFuncT, with_args<true> > { 234 PostProcessFuncT const m_postProcessFunc; CreateFunccomphelper::service_decl::detail::CreateFunc235 explicit CreateFunc( PostProcessFuncT const& postProcessFunc ) 236 : m_postProcessFunc(postProcessFunc) {} 237 238 css::uno::Reference<css::uno::XInterface> operator ()comphelper::service_decl::detail::CreateFunc239 operator()( ServiceDecl const& rServiceDecl, 240 css::uno::Sequence<css::uno::Any> const& args, 241 css::uno::Reference<css::uno::XComponentContext> 242 const& xContext ) const 243 { 244 return m_postProcessFunc( 245 new ImplT( rServiceDecl, args, xContext ) ); 246 } 247 }; 248 249 } // namespace detail 250 251 /** Defines a service implementation class. 252 253 @tpl ImplT_ service implementation class 254 @WithArgsT whether the implementation class ctor expects arguments 255 (uno::Sequence<uno::Any>, uno::Reference<uno::XComponentContext>) 256 or just (uno::Reference<uno::XComponentContext>) 257 */ 258 template <typename ImplT_, typename WithArgsT = with_args<false> > 259 struct serviceimpl_base { 260 typedef ImplT_ ImplT; 261 262 detail::CreateFuncF const m_createFunc; 263 264 typedef detail::PostProcessDefault<ImplT> PostProcessDefaultT; 265 266 /** Default ctor. Implementation class without args, expecting 267 component context as single argument. 268 */ serviceimpl_basecomphelper::service_decl::serviceimpl_base269 serviceimpl_base() : m_createFunc( 270 detail::CreateFunc<ImplT, PostProcessDefaultT, WithArgsT>( 271 PostProcessDefaultT() ) ) {} 272 273 /** Ctor to pass a post processing function/functor. 274 275 @tpl PostProcessDefaultT let your compiler deduce this 276 @param postProcessFunc function/functor that gets the yet unacquired 277 ImplT_ pointer returning a 278 uno::Reference<uno::XInterface> 279 */ 280 template <typename PostProcessFuncT> serviceimpl_basecomphelper::service_decl::serviceimpl_base281 explicit serviceimpl_base( PostProcessFuncT const& postProcessFunc ) 282 : m_createFunc( detail::CreateFunc<ImplT, PostProcessFuncT, WithArgsT>( 283 postProcessFunc ) ) {} 284 }; 285 286 template <typename ImplT_, typename WithArgsT = with_args<false> > 287 struct class_ : public serviceimpl_base< detail::ServiceImpl<ImplT_>, WithArgsT > 288 { 289 typedef serviceimpl_base< detail::ServiceImpl<ImplT_>, WithArgsT > baseT; 290 /** Default ctor. Implementation class without args, expecting 291 component context as single argument. 292 */ class_comphelper::service_decl::class_293 class_() : baseT() {} 294 template <typename PostProcessFuncT> 295 /** Ctor to pass a post processing function/functor. 296 297 @tpl PostProcessDefaultT let your compiler deduce this 298 @param postProcessFunc function/functor that gets the yet unacquired 299 ImplT_ pointer returning a 300 uno::Reference<uno::XInterface> 301 */ class_comphelper::service_decl::class_302 explicit class_( PostProcessFuncT const& postProcessFunc ) : baseT( postProcessFunc ) {} 303 }; 304 305 // 306 // component_... helpers with arbitrary service declarations: 307 // 308 309 #define COMPHELPER_SERVICEDECL_getFactory(z_, n_, unused_) \ 310 if (pRet == 0) \ 311 pRet = BOOST_PP_CAT(s, n_).getFactory(pImplName); 312 313 /** The following preprocessor repetitions generate functions like 314 315 <pre> 316 inline void * component_getFactoryHelper( 317 sal_Char const* pImplName, 318 ::com::sun::star::lang::XMultiServiceFactory *, 319 ::com::sun::star::registry::XRegistryKey * xRegistryKey, 320 ServiceDecl const& s0, ServiceDecl const& s1, ... ); 321 </pre> 322 323 which call on the passed service declarations. 324 325 The maximum number of service declarations can be set by defining 326 COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS; its default is 8. 327 */ 328 #define COMPHELPER_SERVICEDECL_make(z_, n_, unused_) \ 329 inline void * component_getFactoryHelper( \ 330 sal_Char const* pImplName, \ 331 ::com::sun::star::lang::XMultiServiceFactory *, \ 332 ::com::sun::star::registry::XRegistryKey *, \ 333 BOOST_PP_ENUM_PARAMS(n_, ServiceDecl const& s) ) \ 334 { \ 335 void * pRet = 0; \ 336 BOOST_PP_REPEAT(n_, COMPHELPER_SERVICEDECL_getFactory, ~) \ 337 return pRet; \ 338 } 339 340 #if ! defined(COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS) 341 #define COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS 8 342 #endif 343 344 BOOST_PP_REPEAT_FROM_TO(1, COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS, 345 COMPHELPER_SERVICEDECL_make, ~) 346 347 #undef COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS 348 #undef COMPHELPER_SERVICEDECL_make 349 #undef COMPHELPER_SERVICEDECL_getFactory 350 351 } // namespace service_decl 352 } // namespace comphelper 353 354 /** The following preprocessor macro generates the C access functions, 355 that are used to initialize and register the components of a 356 shared library object. 357 358 If you have, say, written a lib that contains three distinct 359 components, each with its own ServiceDecl object, you might want 360 to employ the following code: 361 362 <pre> 363 // must reside outside _any_ namespace 364 COMPHELPER_SERVICEDECL_EXPORTS3(yourServiceDecl1, 365 yourServiceDecl2, 366 yourServiceDecl3); 367 </pre> 368 369 For your convenience, the COMPHELPER_SERVICEDECL_EXPORTS<N> macro 370 comes pre-defined up to N=8, if you should need more arguments, 371 call COMPHELPER_SERVICEDECL_make_exports directly, like this: 372 373 <pre> 374 // must reside outside _any_ namespace 375 COMPHELPER_SERVICEDECL_make_exports((yourServiceDecl1)(yourServiceDecl2)...(yourServiceDeclN)); 376 </pre> 377 378 Note the missing colons between the bracketed arguments. 379 */ 380 #define COMPHELPER_SERVICEDECL_make_exports(varargs_ ) \ 381 extern "C" \ 382 { \ 383 SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( const sal_Char** ppEnvTypeName, \ 384 uno_Environment** /*ppEnv*/ ) \ 385 { \ 386 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; \ 387 } \ 388 \ 389 SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory( sal_Char const* pImplName, \ 390 ::com::sun::star::lang::XMultiServiceFactory* pServiceManager, \ 391 ::com::sun::star::registry::XRegistryKey* pRegistryKey ) \ 392 { \ 393 return component_getFactoryHelper( pImplName, pServiceManager, \ 394 pRegistryKey, \ 395 BOOST_PP_SEQ_ENUM(varargs_) ); \ 396 } \ 397 } 398 399 #define COMPHELPER_SERVICEDECL_EXPORTS1(comp0_) \ 400 COMPHELPER_SERVICEDECL_make_exports((comp0_)) 401 #define COMPHELPER_SERVICEDECL_EXPORTS2(comp0_,comp1_) \ 402 COMPHELPER_SERVICEDECL_make_exports((comp0_)(comp1_)) 403 #define COMPHELPER_SERVICEDECL_EXPORTS3(comp0_,comp1_,comp2_) \ 404 COMPHELPER_SERVICEDECL_make_exports((comp0_)(comp1_)(comp2_)) 405 #define COMPHELPER_SERVICEDECL_EXPORTS4(comp0_,comp1_,comp2_,comp3_) \ 406 COMPHELPER_SERVICEDECL_make_exports((comp0_)(comp1_)(comp2_)(comp3_)) 407 #define COMPHELPER_SERVICEDECL_EXPORTS5(comp0_,comp1_,comp2_,comp3_,comp4_) \ 408 COMPHELPER_SERVICEDECL_make_exports((comp0_)(comp1_)(comp2_)(comp3_)(comp4_)) 409 #define COMPHELPER_SERVICEDECL_EXPORTS6(comp0_,comp1_,comp2_,comp3_,comp4_,comp5_) \ 410 COMPHELPER_SERVICEDECL_make_exports((comp0_)(comp1_)(comp2_)(comp3_)(comp4_)(comp5_)) 411 #define COMPHELPER_SERVICEDECL_EXPORTS7(comp0_,comp1_,comp2_,comp3_,comp4_,comp5_,comp6_) \ 412 COMPHELPER_SERVICEDECL_make_exports((comp0_)(comp1_)(comp2_)(comp3_)(comp4_)(comp5_)(comp6_)) 413 #define COMPHELPER_SERVICEDECL_EXPORTS8(comp0_,comp1_,comp2_,comp3_,comp4_,comp5_,comp6_,comp7_) \ 414 COMPHELPER_SERVICEDECL_make_exports((comp0_)(comp1_)(comp2_)(comp3_)(comp4_)(comp5_)(comp6_)(comp7_)) 415 416 #endif // ! defined(COMPHELPER_SERVICEDECL_HXX_INCLUDED) 417