update credits
[LibreOffice.git] / include / comphelper / servicedecl.hxx
blob0e3fef2e2380d35bccec0f828c0bcca883fade33
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #ifndef INCLUDED_COMPHELPER_SERVICEDECL_HXX
20 #define INCLUDED_COMPHELPER_SERVICEDECL_HXX
22 #include <comphelper/comphelperdllapi.h>
23 #include <cppuhelper/implbase1.hxx>
24 #include <com/sun/star/uno/XComponentContext.hpp>
25 #include <com/sun/star/lang/XServiceInfo.hpp>
26 #include <uno/environment.h>
27 #include <boost/utility.hpp>
28 #include <boost/function.hpp>
29 #include <boost/preprocessor/cat.hpp>
30 #include <boost/preprocessor/repetition.hpp>
31 #include <boost/preprocessor/seq/enum.hpp>
33 namespace comphelper {
34 namespace service_decl {
36 class ServiceDecl;
38 namespace detail {
39 typedef ::boost::function3<
40 css::uno::Reference<css::uno::XInterface> /* return */,
41 ServiceDecl const&,
42 css::uno::Sequence<css::uno::Any> const&,
43 css::uno::Reference<css::uno::XComponentContext> const&> CreateFuncF;
46 /** Class to declare a service implementation. There is no need to implement
47 lang::XServiceInfo nor lang::XInitialization anymore.
48 The declaration can be done in various ways, the (simplest) form is
50 <pre>
51 class MyClass : public cppu::WeakImplHelper2<XInterface1, XInterface2> {
52 public:
53 MyClass( uno::Reference<uno::XComponentContext> const& xContext )
54 [...]
56 [...]
57 namespace sdecl = comphelper::service_decl;
58 sdecl::ServiceDecl const myDecl(
59 sdecl::class_<MyClass>(),
60 "my.unique.implementation.name",
61 "MyServiceSpec1;MyServiceSpec2" );
62 </pre>
64 If the service demands initialization by arguments, the implementation
65 class has to define a constructor taking both arguments and component
66 context:
68 <pre>
69 class MyClass : public cppu::WeakImplHelper2<XInterface1, XInterface2> {
70 public:
71 MyClass( uno::Sequence<uno::Any> const& args,
72 uno::Reference<uno:XComponentContext> const& xContext )
73 [...]
75 [...]
76 namespace sdecl = comphelper::service_decl;
77 sdecl::ServiceDecl const myDecl(
78 sdecl::class_<MyClass, sdecl::with_args<true> >(),
79 "my.unique.implementation.name",
80 "MyServiceSpec1;MyServiceSpec2" );
81 </pre>
83 Additionally, there is the possibility to process some code after creation,
84 e.g. to add the newly created object as a listener or perform aggregation
85 (C++-UNO only):
87 <pre>
88 uno::Reference<uno::XInterface> somePostProcCode( MyClass * p );
89 [...]
90 namespace sdecl = comphelper::service_decl;
91 sdecl::ServiceDecl const myDecl(
92 sdecl::class_<MyClass, ... >(&somePostProcCode),
93 "my.unique.implementation.name",
94 "MyServiceSpec1;MyServiceSpec2" );
95 </pre>
97 In the latter case, somePostProcCode gets the yet unacquired "raw" pointer.
99 class COMPHELPER_DLLPUBLIC ServiceDecl : private ::boost::noncopyable
101 public:
102 /** Ctor for multiple supported service names.
104 @param implClass implementation class description
105 @param pImplName implementation name
106 @param pSupportedServiceNames supported service names
107 @param cDelim delimiter for supported service names
109 template <typename ImplClassT>
110 ServiceDecl( ImplClassT const& implClass,
111 char const* pImplName,
112 char const* pSupportedServiceNames, char cDelim = ';' )
113 : m_createFunc(implClass.m_createFunc),
114 m_pImplName(pImplName),
115 m_pServiceNames(pSupportedServiceNames),
116 m_cDelim(cDelim) {}
118 /// @internal gets called by component_getFactoryHelper()
119 void * getFactory( sal_Char const* pImplName ) const;
121 /// @return supported service names
122 ::com::sun::star::uno::Sequence< OUString>
123 getSupportedServiceNames() const;
125 /// @return whether name is in set of supported service names
126 bool supportsService( OUString const& name ) const;
128 /// @return implementation name
129 OUString getImplementationName() const;
131 private:
132 class Factory;
133 friend class Factory;
135 detail::CreateFuncF const m_createFunc;
136 char const* const m_pImplName;
137 char const* const m_pServiceNames;
138 char const m_cDelim;
141 /** To specify whether the implementation class expects arguments
142 (uno::Sequence<uno::Any>).
144 template <bool> struct with_args;
146 /// @internal
147 namespace detail {
148 template <typename ImplT>
149 class OwnServiceImpl
150 : public ImplT,
151 private ::boost::noncopyable
153 typedef ImplT BaseT;
155 public:
156 OwnServiceImpl(
157 ServiceDecl const& rServiceDecl,
158 css::uno::Sequence<css::uno::Any> const& args,
159 css::uno::Reference<css::uno::XComponentContext> const& xContext )
160 :BaseT(args, xContext), m_rServiceDecl(rServiceDecl) {}
161 OwnServiceImpl(
162 ServiceDecl const& rServiceDecl,
163 css::uno::Reference<css::uno::XComponentContext> const& xContext )
164 : BaseT(xContext), m_rServiceDecl(rServiceDecl) {}
166 // XServiceInfo
167 virtual OUString SAL_CALL getImplementationName()
168 throw (css::uno::RuntimeException) SAL_OVERRIDE {
169 return m_rServiceDecl.getImplementationName();
171 virtual sal_Bool SAL_CALL supportsService( OUString const& name )
172 throw (css::uno::RuntimeException) SAL_OVERRIDE {
173 return m_rServiceDecl.supportsService(name);
175 virtual css::uno::Sequence< OUString>
176 SAL_CALL getSupportedServiceNames() throw (css::uno::RuntimeException) SAL_OVERRIDE {
177 return m_rServiceDecl.getSupportedServiceNames();
180 private:
181 ServiceDecl const& m_rServiceDecl;
184 template <typename ImplT>
185 class ServiceImpl : public OwnServiceImpl< ::cppu::ImplInheritanceHelper1<ImplT,css::lang::XServiceInfo> >
187 typedef OwnServiceImpl< ::cppu::ImplInheritanceHelper1<ImplT,css::lang::XServiceInfo> > ServiceImpl_BASE;
188 public:
189 ServiceImpl(
190 ServiceDecl const& rServiceDecl,
191 css::uno::Sequence<css::uno::Any> const& args,
192 css::uno::Reference<css::uno::XComponentContext> const& xContext )
193 : ServiceImpl_BASE(rServiceDecl, args, xContext) {}
194 ServiceImpl(
195 ServiceDecl const& rServiceDecl,
196 css::uno::Reference<css::uno::XComponentContext> const& xContext )
197 : ServiceImpl_BASE(rServiceDecl, xContext) {}
200 template <typename ImplT>
201 class InheritingServiceImpl : public OwnServiceImpl< ImplT >
203 typedef OwnServiceImpl< ImplT > ServiceImpl_BASE;
204 public:
205 InheritingServiceImpl(
206 ServiceDecl const& rServiceDecl,
207 css::uno::Sequence<css::uno::Any> const& args,
208 css::uno::Reference<css::uno::XComponentContext> const& xContext )
209 : ServiceImpl_BASE(rServiceDecl, args, xContext) {}
210 InheritingServiceImpl(
211 ServiceDecl const& rServiceDecl,
212 css::uno::Reference<css::uno::XComponentContext> const& xContext )
213 : ServiceImpl_BASE(rServiceDecl, xContext) {}
216 template <typename ServiceImplT>
217 struct PostProcessDefault {
218 css::uno::Reference<css::uno::XInterface>
219 operator()( ServiceImplT * p ) const {
220 return static_cast<css::lang::XServiceInfo *>(p);
224 template <typename ImplT, typename PostProcessFuncT, typename WithArgsT>
225 struct CreateFunc;
227 template <typename ImplT, typename PostProcessFuncT>
228 struct CreateFunc<ImplT, PostProcessFuncT, with_args<false> > {
229 PostProcessFuncT const m_postProcessFunc;
230 explicit CreateFunc( PostProcessFuncT const& postProcessFunc )
231 : m_postProcessFunc(postProcessFunc) {}
233 css::uno::Reference<css::uno::XInterface>
234 operator()( ServiceDecl const& rServiceDecl,
235 css::uno::Sequence<css::uno::Any> const&,
236 css::uno::Reference<css::uno::XComponentContext>
237 const& xContext ) const
239 return m_postProcessFunc(
240 new ImplT( rServiceDecl, xContext ) );
244 template <typename ImplT, typename PostProcessFuncT>
245 struct CreateFunc<ImplT, PostProcessFuncT, with_args<true> > {
246 PostProcessFuncT const m_postProcessFunc;
247 explicit CreateFunc( PostProcessFuncT const& postProcessFunc )
248 : m_postProcessFunc(postProcessFunc) {}
250 css::uno::Reference<css::uno::XInterface>
251 operator()( ServiceDecl const& rServiceDecl,
252 css::uno::Sequence<css::uno::Any> const& args,
253 css::uno::Reference<css::uno::XComponentContext>
254 const& xContext ) const
256 return m_postProcessFunc(
257 new ImplT( rServiceDecl, args, xContext ) );
261 } // namespace detail
263 /** Defines a service implementation class.
265 @tpl ImplT_ service implementation class
266 @WithArgsT whether the implementation class ctor expects arguments
267 (uno::Sequence<uno::Any>, uno::Reference<uno::XComponentContext>)
268 or just (uno::Reference<uno::XComponentContext>)
270 template <typename ImplT_, typename WithArgsT = with_args<false> >
271 struct serviceimpl_base {
272 typedef ImplT_ ImplT;
274 detail::CreateFuncF const m_createFunc;
276 typedef detail::PostProcessDefault<ImplT> PostProcessDefaultT;
278 /** Default ctor. Implementation class without args, expecting
279 component context as single argument.
281 serviceimpl_base() : m_createFunc(
282 detail::CreateFunc<ImplT, PostProcessDefaultT, WithArgsT>(
283 PostProcessDefaultT() ) ) {}
285 /** Ctor to pass a post processing function/functor.
287 @tpl PostProcessDefaultT let your compiler deduce this
288 @param postProcessFunc function/functor that gets the yet unacquired
289 ImplT_ pointer returning a
290 uno::Reference<uno::XInterface>
292 template <typename PostProcessFuncT>
293 explicit serviceimpl_base( PostProcessFuncT const& postProcessFunc )
294 : m_createFunc( detail::CreateFunc<ImplT, PostProcessFuncT, WithArgsT>(
295 postProcessFunc ) ) {}
298 template <typename ImplT_, typename WithArgsT = with_args<false> >
299 struct class_ : public serviceimpl_base< detail::ServiceImpl<ImplT_>, WithArgsT >
301 typedef serviceimpl_base< detail::ServiceImpl<ImplT_>, WithArgsT > baseT;
302 /** Default ctor. Implementation class without args, expecting
303 component context as single argument.
305 class_() : baseT() {}
306 template <typename PostProcessFuncT>
307 /** Ctor to pass a post processing function/functor.
309 @tpl PostProcessDefaultT let your compiler deduce this
310 @param postProcessFunc function/functor that gets the yet unacquired
311 ImplT_ pointer returning a
312 uno::Reference<uno::XInterface>
314 explicit class_( PostProcessFuncT const& postProcessFunc ) : baseT( postProcessFunc ) {}
317 template <typename ImplT_, typename WithArgsT = with_args<false> >
318 struct inheritingClass_ : public serviceimpl_base< detail::InheritingServiceImpl<ImplT_>, WithArgsT >
320 typedef serviceimpl_base< detail::InheritingServiceImpl<ImplT_>, WithArgsT > baseT;
321 /** Default ctor. Implementation class without args, expecting
322 component context as single argument.
324 inheritingClass_() : baseT() {}
325 template <typename PostProcessFuncT>
326 /** Ctor to pass a post processing function/functor.
328 @tpl PostProcessDefaultT let your compiler deduce this
329 @param postProcessFunc function/functor that gets the yet unacquired
330 ImplT_ pointer returning a
331 uno::Reference<uno::XInterface>
333 explicit inheritingClass_( PostProcessFuncT const& postProcessFunc ) : baseT( postProcessFunc ) {}
336 // component_... helpers with arbitrary service declarations:
339 #define COMPHELPER_SERVICEDECL_getFactory(z_, n_, unused_) \
340 if (pRet == 0) \
341 pRet = BOOST_PP_CAT(s, n_).getFactory(pImplName);
343 /** The following preprocessor repetitions generate functions like
345 <pre>
346 inline void * component_getFactoryHelper(
347 sal_Char const* pImplName,
348 ServiceDecl const& s0, ServiceDecl const& s1, ... );
349 </pre>
351 which call on the passed service declarations.
353 The maximum number of service declarations can be set by defining
354 COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS; its default is 8.
356 #define COMPHELPER_SERVICEDECL_make(z_, n_, unused_) \
357 inline void * component_getFactoryHelper( \
358 sal_Char const* pImplName, \
359 BOOST_PP_ENUM_PARAMS(n_, ServiceDecl const& s) ) \
361 void * pRet = 0; \
362 BOOST_PP_REPEAT(n_, COMPHELPER_SERVICEDECL_getFactory, ~) \
363 return pRet; \
366 #ifndef COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS
367 #define COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS 8
368 #endif
370 BOOST_PP_REPEAT_FROM_TO(1, COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS,
371 COMPHELPER_SERVICEDECL_make, ~)
373 #undef COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS
374 #undef COMPHELPER_SERVICEDECL_make
375 #undef COMPHELPER_SERVICEDECL_getFactory
377 } // namespace service_decl
378 } // namespace comphelper
380 /** The following preprocessor macro generates the C access functions,
381 that are used to initialize and register the components of a
382 shared library object.
384 If you have, say, written a lib that contains three distinct
385 components, each with its own ServiceDecl object, you might want
386 to employ the following code:
388 <pre>
389 // must reside outside _any_ namespace
390 COMPHELPER_SERVICEDECL_EXPORTS3(yourServiceDecl1,
391 yourServiceDecl2,
392 yourServiceDecl3);
393 </pre>
395 For your convenience, the COMPHELPER_SERVICEDECL_EXPORTS<N> macro
396 comes pre-defined up to N=8, if you should need more arguments,
397 call COMPHELPER_SERVICEDECL_make_exports directly, like this:
399 <pre>
400 // must reside outside _any_ namespace
401 COMPHELPER_SERVICEDECL_make_exports((yourServiceDecl1)(yourServiceDecl2)...(yourServiceDeclN));
402 </pre>
404 Note the missing colons between the bracketed arguments.
406 #define COMPHELPER_SERVICEDECL_make_exports(compName, varargs_ ) \
407 extern "C" \
409 SAL_DLLPUBLIC_EXPORT void* SAL_CALL compName##_component_getFactory( sal_Char const* pImplName, \
410 void*, void* ) \
412 return component_getFactoryHelper( pImplName, \
413 BOOST_PP_SEQ_ENUM(varargs_) ); \
417 #define COMPHELPER_SERVICEDECL_EXPORTS1(compName,comp0_) \
418 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_))
419 #define COMPHELPER_SERVICEDECL_EXPORTS2(compName,comp0_,comp1_) \
420 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_)(comp1_))
421 #define COMPHELPER_SERVICEDECL_EXPORTS3(compName,comp0_,comp1_,comp2_) \
422 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_)(comp1_)(comp2_))
423 #define COMPHELPER_SERVICEDECL_EXPORTS4(compName,comp0_,comp1_,comp2_,comp3_) \
424 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_)(comp1_)(comp2_)(comp3_))
425 #define COMPHELPER_SERVICEDECL_EXPORTS5(compName,comp0_,comp1_,comp2_,comp3_,comp4_) \
426 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_)(comp1_)(comp2_)(comp3_)(comp4_))
427 #define COMPHELPER_SERVICEDECL_EXPORTS6(compName,comp0_,comp1_,comp2_,comp3_,comp4_,comp5_) \
428 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_)(comp1_)(comp2_)(comp3_)(comp4_)(comp5_))
429 #define COMPHELPER_SERVICEDECL_EXPORTS7(compName,comp0_,comp1_,comp2_,comp3_,comp4_,comp5_,comp6_) \
430 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_)(comp1_)(comp2_)(comp3_)(comp4_)(comp5_)(comp6_))
431 #define COMPHELPER_SERVICEDECL_EXPORTS8(compName,comp0_,comp1_,comp2_,comp3_,comp4_,comp5_,comp6_,comp7_) \
432 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_)(comp1_)(comp2_)(comp3_)(comp4_)(comp5_)(comp6_)(comp7_))
434 #endif // ! defined( INCLUDED_COMPHELPER_SERVICEDECL_HXX)
436 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */