1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
{
39 typedef ::boost::function3
<
40 css::uno::Reference
<css::uno::XInterface
> /* return */,
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
51 class MyClass : public cppu::WeakImplHelper2<XInterface1, XInterface2> {
53 MyClass( uno::Reference<uno::XComponentContext> const& xContext )
57 namespace sdecl = comphelper::service_decl;
58 sdecl::ServiceDecl const myDecl(
59 sdecl::class_<MyClass>(),
60 "my.unique.implementation.name",
61 "MyServiceSpec1;MyServiceSpec2" );
64 If the service demands initialization by arguments, the implementation
65 class has to define a constructor taking both arguments and component
69 class MyClass : public cppu::WeakImplHelper2<XInterface1, XInterface2> {
71 MyClass( uno::Sequence<uno::Any> const& args,
72 uno::Reference<uno:XComponentContext> const& xContext )
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" );
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
88 uno::Reference<uno::XInterface> somePostProcCode( MyClass * p );
90 namespace sdecl = comphelper::service_decl;
91 sdecl::ServiceDecl const myDecl(
92 sdecl::class_<MyClass, ... >(&somePostProcCode),
93 "my.unique.implementation.name",
94 "MyServiceSpec1;MyServiceSpec2" );
97 In the latter case, somePostProcCode gets the yet unacquired "raw" pointer.
99 class COMPHELPER_DLLPUBLIC ServiceDecl
: private ::boost::noncopyable
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
),
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;
133 friend class Factory
;
135 detail::CreateFuncF
const m_createFunc
;
136 char const* const m_pImplName
;
137 char const* const m_pServiceNames
;
141 /** To specify whether the implementation class expects arguments
142 (uno::Sequence<uno::Any>).
144 template <bool> struct with_args
;
148 template <typename ImplT
>
151 private ::boost::noncopyable
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
) {}
162 ServiceDecl
const& rServiceDecl
,
163 css::uno::Reference
<css::uno::XComponentContext
> const& xContext
)
164 : BaseT(xContext
), m_rServiceDecl(rServiceDecl
) {}
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();
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
;
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
) {}
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
;
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
>
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_) \
341 pRet = BOOST_PP_CAT(s, n_).getFactory(pImplName);
343 /** The following preprocessor repetitions generate functions like
346 inline void * component_getFactoryHelper(
347 sal_Char const* pImplName,
348 ServiceDecl const& s0, ServiceDecl const& s1, ... );
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) ) \
362 BOOST_PP_REPEAT(n_, COMPHELPER_SERVICEDECL_getFactory, ~) \
366 #ifndef COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS
367 #define COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS 8
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:
389 // must reside outside _any_ namespace
390 COMPHELPER_SERVICEDECL_EXPORTS3(yourServiceDecl1,
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:
400 // must reside outside _any_ namespace
401 COMPHELPER_SERVICEDECL_make_exports((yourServiceDecl1)(yourServiceDecl2)...(yourServiceDeclN));
404 Note the missing colons between the bracketed arguments.
406 #define COMPHELPER_SERVICEDECL_make_exports(compName, varargs_ ) \
409 SAL_DLLPUBLIC_EXPORT void* SAL_CALL compName##_component_getFactory( sal_Char const* pImplName, \
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: */