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 <com/sun/star/registry/XRegistryKey.hpp>
27 #include <uno/environment.h>
28 #include <boost/utility.hpp>
29 #include <boost/function.hpp>
30 #include <boost/preprocessor/cat.hpp>
31 #include <boost/preprocessor/repetition.hpp>
32 #include <boost/preprocessor/seq/enum.hpp>
34 namespace comphelper
{
35 namespace service_decl
{
40 typedef ::boost::function3
<
41 css::uno::Reference
<css::uno::XInterface
> /* return */,
43 css::uno::Sequence
<css::uno::Any
> const&,
44 css::uno::Reference
<css::uno::XComponentContext
> const&> CreateFuncF
;
47 /** Class to declare a service implementation. There is no need to implement
48 lang::XServiceInfo nor lang::XInitialization anymore.
49 The declaration can be done in various ways, the (simplest) form is
52 class MyClass : public cppu::WeakImplHelper2<XInterface1, XInterface2> {
54 MyClass( uno::Reference<uno::XComponentContext> const& xContext )
58 namespace sdecl = comphelper::service_decl;
59 sdecl::ServiceDecl const myDecl(
60 sdecl::class_<MyClass>(),
61 "my.unique.implementation.name",
62 "MyServiceSpec1;MyServiceSpec2" );
65 If the service demands initialization by arguments, the implementation
66 class has to define a constructor taking both arguments and component
70 class MyClass : public cppu::WeakImplHelper2<XInterface1, XInterface2> {
72 MyClass( uno::Sequence<uno::Any> const& args,
73 uno::Reference<uno:XComponentContext> const& xContext )
77 namespace sdecl = comphelper::service_decl;
78 sdecl::ServiceDecl const myDecl(
79 sdecl::class_<MyClass, sdecl::with_args<true> >(),
80 "my.unique.implementation.name",
81 "MyServiceSpec1;MyServiceSpec2" );
84 Additionally, there is the possibility to process some code after creation,
85 e.g. to add the newly created object as a listener or perform aggregation
89 uno::Reference<uno::XInterface> somePostProcCode( MyClass * p );
91 namespace sdecl = comphelper::service_decl;
92 sdecl::ServiceDecl const myDecl(
93 sdecl::class_<MyClass, ... >(&somePostProcCode),
94 "my.unique.implementation.name",
95 "MyServiceSpec1;MyServiceSpec2" );
98 In the latter case, somePostProcCode gets the yet unacquired "raw" pointer.
100 class COMPHELPER_DLLPUBLIC ServiceDecl
: private ::boost::noncopyable
103 /** Ctor for multiple supported service names.
105 @param implClass implementation class description
106 @param pImplName implementation name
107 @param pSupportedServiceNames supported service names
108 @param cDelim delimiter for supported service names
110 template <typename ImplClassT
>
111 ServiceDecl( ImplClassT
const& implClass
,
112 char const* pImplName
,
113 char const* pSupportedServiceNames
, char cDelim
= ';' )
114 : m_createFunc(implClass
.m_createFunc
),
115 m_pImplName(pImplName
),
116 m_pServiceNames(pSupportedServiceNames
),
119 /// @internal gets called by component_getFactoryHelper()
120 void * getFactory( sal_Char
const* pImplName
) const;
122 /// @return supported service names
123 ::com::sun::star::uno::Sequence
< OUString
>
124 getSupportedServiceNames() const;
126 /// @return whether name is in set of supported service names
127 bool supportsService( OUString
const& name
) const;
129 /// @return implementation name
130 OUString
getImplementationName() const;
134 friend class Factory
;
136 detail::CreateFuncF
const m_createFunc
;
137 char const* const m_pImplName
;
138 char const* const m_pServiceNames
;
142 /** To specify whether the implementation class expects arguments
143 (uno::Sequence<uno::Any>).
145 template <bool> struct with_args
;
149 template <typename ImplT
>
152 private ::boost::noncopyable
158 ServiceDecl
const& rServiceDecl
,
159 css::uno::Sequence
<css::uno::Any
> const& args
,
160 css::uno::Reference
<css::uno::XComponentContext
> const& xContext
)
161 :BaseT(args
, xContext
), m_rServiceDecl(rServiceDecl
) {}
163 ServiceDecl
const& rServiceDecl
,
164 css::uno::Reference
<css::uno::XComponentContext
> const& xContext
)
165 : BaseT(xContext
), m_rServiceDecl(rServiceDecl
) {}
168 virtual OUString SAL_CALL
getImplementationName()
169 throw (css::uno::RuntimeException
) {
170 return m_rServiceDecl
.getImplementationName();
172 virtual sal_Bool SAL_CALL
supportsService( OUString
const& name
)
173 throw (css::uno::RuntimeException
) {
174 return m_rServiceDecl
.supportsService(name
);
176 virtual css::uno::Sequence
< OUString
>
177 SAL_CALL
getSupportedServiceNames() throw (css::uno::RuntimeException
) {
178 return m_rServiceDecl
.getSupportedServiceNames();
182 ServiceDecl
const& m_rServiceDecl
;
185 template <typename ImplT
>
186 class ServiceImpl
: public OwnServiceImpl
< ::cppu::ImplInheritanceHelper1
<ImplT
,css::lang::XServiceInfo
> >
188 typedef OwnServiceImpl
< ::cppu::ImplInheritanceHelper1
<ImplT
,css::lang::XServiceInfo
> > ServiceImpl_BASE
;
191 ServiceDecl
const& rServiceDecl
,
192 css::uno::Sequence
<css::uno::Any
> const& args
,
193 css::uno::Reference
<css::uno::XComponentContext
> const& xContext
)
194 : ServiceImpl_BASE(rServiceDecl
, args
, xContext
) {}
196 ServiceDecl
const& rServiceDecl
,
197 css::uno::Reference
<css::uno::XComponentContext
> const& xContext
)
198 : ServiceImpl_BASE(rServiceDecl
, xContext
) {}
201 template <typename ServiceImplT
>
202 struct PostProcessDefault
{
203 css::uno::Reference
<css::uno::XInterface
>
204 operator()( ServiceImplT
* p
) const {
205 return static_cast<css::lang::XServiceInfo
*>(p
);
209 template <typename ImplT
, typename PostProcessFuncT
, typename WithArgsT
>
212 template <typename ImplT
, typename PostProcessFuncT
>
213 struct CreateFunc
<ImplT
, PostProcessFuncT
, with_args
<false> > {
214 PostProcessFuncT
const m_postProcessFunc
;
215 explicit CreateFunc( PostProcessFuncT
const& postProcessFunc
)
216 : m_postProcessFunc(postProcessFunc
) {}
218 css::uno::Reference
<css::uno::XInterface
>
219 operator()( ServiceDecl
const& rServiceDecl
,
220 css::uno::Sequence
<css::uno::Any
> const&,
221 css::uno::Reference
<css::uno::XComponentContext
>
222 const& xContext
) const
224 return m_postProcessFunc(
225 new ImplT( rServiceDecl
, xContext
) );
229 template <typename ImplT
, typename PostProcessFuncT
>
230 struct CreateFunc
<ImplT
, PostProcessFuncT
, with_args
<true> > {
231 PostProcessFuncT
const m_postProcessFunc
;
232 explicit CreateFunc( PostProcessFuncT
const& postProcessFunc
)
233 : m_postProcessFunc(postProcessFunc
) {}
235 css::uno::Reference
<css::uno::XInterface
>
236 operator()( ServiceDecl
const& rServiceDecl
,
237 css::uno::Sequence
<css::uno::Any
> const& args
,
238 css::uno::Reference
<css::uno::XComponentContext
>
239 const& xContext
) const
241 return m_postProcessFunc(
242 new ImplT( rServiceDecl
, args
, xContext
) );
246 } // namespace detail
248 /** Defines a service implementation class.
250 @tpl ImplT_ service implementation class
251 @WithArgsT whether the implementation class ctor expects arguments
252 (uno::Sequence<uno::Any>, uno::Reference<uno::XComponentContext>)
253 or just (uno::Reference<uno::XComponentContext>)
255 template <typename ImplT_
, typename WithArgsT
= with_args
<false> >
256 struct serviceimpl_base
{
257 typedef ImplT_ ImplT
;
259 detail::CreateFuncF
const m_createFunc
;
261 typedef detail::PostProcessDefault
<ImplT
> PostProcessDefaultT
;
263 /** Default ctor. Implementation class without args, expecting
264 component context as single argument.
266 serviceimpl_base() : m_createFunc(
267 detail::CreateFunc
<ImplT
, PostProcessDefaultT
, WithArgsT
>(
268 PostProcessDefaultT() ) ) {}
270 /** Ctor to pass a post processing function/functor.
272 @tpl PostProcessDefaultT let your compiler deduce this
273 @param postProcessFunc function/functor that gets the yet unacquired
274 ImplT_ pointer returning a
275 uno::Reference<uno::XInterface>
277 template <typename PostProcessFuncT
>
278 explicit serviceimpl_base( PostProcessFuncT
const& postProcessFunc
)
279 : m_createFunc( detail::CreateFunc
<ImplT
, PostProcessFuncT
, WithArgsT
>(
280 postProcessFunc
) ) {}
283 template <typename ImplT_
, typename WithArgsT
= with_args
<false> >
284 struct class_
: public serviceimpl_base
< detail::ServiceImpl
<ImplT_
>, WithArgsT
>
286 typedef serviceimpl_base
< detail::ServiceImpl
<ImplT_
>, WithArgsT
> baseT
;
287 /** Default ctor. Implementation class without args, expecting
288 component context as single argument.
290 class_() : baseT() {}
291 template <typename PostProcessFuncT
>
292 /** Ctor to pass a post processing function/functor.
294 @tpl PostProcessDefaultT let your compiler deduce this
295 @param postProcessFunc function/functor that gets the yet unacquired
296 ImplT_ pointer returning a
297 uno::Reference<uno::XInterface>
299 explicit class_( PostProcessFuncT
const& postProcessFunc
) : baseT( postProcessFunc
) {}
303 // component_... helpers with arbitrary service declarations:
306 #define COMPHELPER_SERVICEDECL_getFactory(z_, n_, unused_) \
308 pRet = BOOST_PP_CAT(s, n_).getFactory(pImplName);
310 /** The following preprocessor repetitions generate functions like
313 inline void * component_getFactoryHelper(
314 sal_Char const* pImplName,
315 ::com::sun::star::lang::XMultiServiceFactory *,
316 ::com::sun::star::registry::XRegistryKey * xRegistryKey,
317 ServiceDecl const& s0, ServiceDecl const& s1, ... );
320 which call on the passed service declarations.
322 The maximum number of service declarations can be set by defining
323 COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS; its default is 8.
325 #define COMPHELPER_SERVICEDECL_make(z_, n_, unused_) \
326 inline void * component_getFactoryHelper( \
327 sal_Char const* pImplName, \
328 ::com::sun::star::lang::XMultiServiceFactory *, \
329 ::com::sun::star::registry::XRegistryKey *, \
330 BOOST_PP_ENUM_PARAMS(n_, ServiceDecl const& s) ) \
333 BOOST_PP_REPEAT(n_, COMPHELPER_SERVICEDECL_getFactory, ~) \
337 #ifndef COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS
338 #define COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS 8
341 BOOST_PP_REPEAT_FROM_TO(1, COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS
,
342 COMPHELPER_SERVICEDECL_make
, ~)
344 #undef COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS
345 #undef COMPHELPER_SERVICEDECL_make
346 #undef COMPHELPER_SERVICEDECL_getFactory
348 } // namespace service_decl
349 } // namespace comphelper
351 /** The following preprocessor macro generates the C access functions,
352 that are used to initialize and register the components of a
353 shared library object.
355 If you have, say, written a lib that contains three distinct
356 components, each with its own ServiceDecl object, you might want
357 to employ the following code:
360 // must reside outside _any_ namespace
361 COMPHELPER_SERVICEDECL_EXPORTS3(yourServiceDecl1,
366 For your convenience, the COMPHELPER_SERVICEDECL_EXPORTS<N> macro
367 comes pre-defined up to N=8, if you should need more arguments,
368 call COMPHELPER_SERVICEDECL_make_exports directly, like this:
371 // must reside outside _any_ namespace
372 COMPHELPER_SERVICEDECL_make_exports((yourServiceDecl1)(yourServiceDecl2)...(yourServiceDeclN));
375 Note the missing colons between the bracketed arguments.
377 #define COMPHELPER_SERVICEDECL_make_exports(compName, varargs_ ) \
380 SAL_DLLPUBLIC_EXPORT void* SAL_CALL compName##_component_getFactory( sal_Char const* pImplName, \
381 ::com::sun::star::lang::XMultiServiceFactory* pServiceManager, \
382 ::com::sun::star::registry::XRegistryKey* pRegistryKey ) \
384 return component_getFactoryHelper( pImplName, pServiceManager, \
386 BOOST_PP_SEQ_ENUM(varargs_) ); \
390 #define COMPHELPER_SERVICEDECL_EXPORTS1(compName,comp0_) \
391 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_))
392 #define COMPHELPER_SERVICEDECL_EXPORTS2(compName,comp0_,comp1_) \
393 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_)(comp1_))
394 #define COMPHELPER_SERVICEDECL_EXPORTS3(compName,comp0_,comp1_,comp2_) \
395 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_)(comp1_)(comp2_))
396 #define COMPHELPER_SERVICEDECL_EXPORTS4(compName,comp0_,comp1_,comp2_,comp3_) \
397 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_)(comp1_)(comp2_)(comp3_))
398 #define COMPHELPER_SERVICEDECL_EXPORTS5(compName,comp0_,comp1_,comp2_,comp3_,comp4_) \
399 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_)(comp1_)(comp2_)(comp3_)(comp4_))
400 #define COMPHELPER_SERVICEDECL_EXPORTS6(compName,comp0_,comp1_,comp2_,comp3_,comp4_,comp5_) \
401 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_)(comp1_)(comp2_)(comp3_)(comp4_)(comp5_))
402 #define COMPHELPER_SERVICEDECL_EXPORTS7(compName,comp0_,comp1_,comp2_,comp3_,comp4_,comp5_,comp6_) \
403 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_)(comp1_)(comp2_)(comp3_)(comp4_)(comp5_)(comp6_))
404 #define COMPHELPER_SERVICEDECL_EXPORTS8(compName,comp0_,comp1_,comp2_,comp3_,comp4_,comp5_,comp6_,comp7_) \
405 COMPHELPER_SERVICEDECL_make_exports(compName,(comp0_)(comp1_)(comp2_)(comp3_)(comp4_)(comp5_)(comp6_)(comp7_))
407 #endif // ! defined( INCLUDED_COMPHELPER_SERVICEDECL_HXX)
409 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */