bump product version to 4.2.0.1
[LibreOffice.git] / include / comphelper / servicedecl.hxx
blobf210fcd4fdfadfaba2f80daea7858480896626b9
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 <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 {
37 class ServiceDecl;
39 namespace detail {
40 typedef ::boost::function3<
41 css::uno::Reference<css::uno::XInterface> /* return */,
42 ServiceDecl const&,
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
51 <pre>
52 class MyClass : public cppu::WeakImplHelper2<XInterface1, XInterface2> {
53 public:
54 MyClass( uno::Reference<uno::XComponentContext> const& xContext )
55 [...]
57 [...]
58 namespace sdecl = comphelper::service_decl;
59 sdecl::ServiceDecl const myDecl(
60 sdecl::class_<MyClass>(),
61 "my.unique.implementation.name",
62 "MyServiceSpec1;MyServiceSpec2" );
63 </pre>
65 If the service demands initialization by arguments, the implementation
66 class has to define a constructor taking both arguments and component
67 context:
69 <pre>
70 class MyClass : public cppu::WeakImplHelper2<XInterface1, XInterface2> {
71 public:
72 MyClass( uno::Sequence<uno::Any> const& args,
73 uno::Reference<uno:XComponentContext> const& xContext )
74 [...]
76 [...]
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" );
82 </pre>
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
86 (C++-UNO only):
88 <pre>
89 uno::Reference<uno::XInterface> somePostProcCode( MyClass * p );
90 [...]
91 namespace sdecl = comphelper::service_decl;
92 sdecl::ServiceDecl const myDecl(
93 sdecl::class_<MyClass, ... >(&somePostProcCode),
94 "my.unique.implementation.name",
95 "MyServiceSpec1;MyServiceSpec2" );
96 </pre>
98 In the latter case, somePostProcCode gets the yet unacquired "raw" pointer.
100 class COMPHELPER_DLLPUBLIC ServiceDecl : private ::boost::noncopyable
102 public:
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),
117 m_cDelim(cDelim) {}
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;
132 private:
133 class Factory;
134 friend class Factory;
136 detail::CreateFuncF const m_createFunc;
137 char const* const m_pImplName;
138 char const* const m_pServiceNames;
139 char const m_cDelim;
142 /** To specify whether the implementation class expects arguments
143 (uno::Sequence<uno::Any>).
145 template <bool> struct with_args;
147 /// @internal
148 namespace detail {
149 template <typename ImplT>
150 class OwnServiceImpl
151 : public ImplT,
152 private ::boost::noncopyable
154 typedef ImplT BaseT;
156 public:
157 OwnServiceImpl(
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) {}
162 OwnServiceImpl(
163 ServiceDecl const& rServiceDecl,
164 css::uno::Reference<css::uno::XComponentContext> const& xContext )
165 : BaseT(xContext), m_rServiceDecl(rServiceDecl) {}
167 // XServiceInfo
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();
181 private:
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;
189 public:
190 ServiceImpl(
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) {}
195 ServiceImpl(
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>
210 struct CreateFunc;
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_) \
307 if (pRet == 0) \
308 pRet = BOOST_PP_CAT(s, n_).getFactory(pImplName);
310 /** The following preprocessor repetitions generate functions like
312 <pre>
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, ... );
318 </pre>
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) ) \
332 void * pRet = 0; \
333 BOOST_PP_REPEAT(n_, COMPHELPER_SERVICEDECL_getFactory, ~) \
334 return pRet; \
337 #ifndef COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS
338 #define COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS 8
339 #endif
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:
359 <pre>
360 // must reside outside _any_ namespace
361 COMPHELPER_SERVICEDECL_EXPORTS3(yourServiceDecl1,
362 yourServiceDecl2,
363 yourServiceDecl3);
364 </pre>
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:
370 <pre>
371 // must reside outside _any_ namespace
372 COMPHELPER_SERVICEDECL_make_exports((yourServiceDecl1)(yourServiceDecl2)...(yourServiceDeclN));
373 </pre>
375 Note the missing colons between the bracketed arguments.
377 #define COMPHELPER_SERVICEDECL_make_exports(compName, varargs_ ) \
378 extern "C" \
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, \
385 pRegistryKey, \
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: */