Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 : #ifndef INCLUDED_COMPHELPER_SERVICEDECL_HXX
20 : #define INCLUDED_COMPHELPER_SERVICEDECL_HXX
21 :
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>
32 :
33 : namespace comphelper {
34 : namespace service_decl {
35 :
36 : class ServiceDecl;
37 :
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;
44 : }
45 :
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
49 :
50 : <pre>
51 : class MyClass : public cppu::WeakImplHelper2<XInterface1, XInterface2> {
52 : public:
53 : MyClass( uno::Reference<uno::XComponentContext> const& xContext )
54 : [...]
55 : };
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>
63 :
64 : If the service demands initialization by arguments, the implementation
65 : class has to define a constructor taking both arguments and component
66 : context:
67 :
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 : [...]
74 : };
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>
82 :
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):
86 :
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>
96 :
97 : In the latter case, somePostProcCode gets the yet unacquired "raw" pointer.
98 : */
99 1054 : class COMPHELPER_DLLPUBLIC ServiceDecl : private ::boost::noncopyable
100 : {
101 : public:
102 : /** Ctor for multiple supported service names.
103 :
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
108 : */
109 : template <typename ImplClassT>
110 1167 : 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 1167 : m_cDelim(cDelim) {}
117 :
118 : /// @internal gets called by component_getFactoryHelper()
119 : void * getFactory( sal_Char const* pImplName ) const;
120 :
121 : /// @return supported service names
122 : ::com::sun::star::uno::Sequence< OUString>
123 : getSupportedServiceNames() const;
124 :
125 : /// @return whether name is in set of supported service names
126 : bool supportsService( OUString const& name ) const;
127 :
128 : /// @return implementation name
129 : OUString getImplementationName() const;
130 :
131 : private:
132 : class Factory;
133 : friend class Factory;
134 :
135 : detail::CreateFuncF const m_createFunc;
136 : char const* const m_pImplName;
137 : char const* const m_pServiceNames;
138 : char const m_cDelim;
139 : };
140 :
141 : /** To specify whether the implementation class expects arguments
142 : (uno::Sequence<uno::Any>).
143 : */
144 : template <bool> struct with_args;
145 :
146 : /// @internal
147 : namespace detail {
148 : template <typename ImplT>
149 2917 : class OwnServiceImpl
150 : : public ImplT,
151 : private ::boost::noncopyable
152 : {
153 : typedef ImplT BaseT;
154 :
155 : public:
156 2629 : OwnServiceImpl(
157 : ServiceDecl const& rServiceDecl,
158 : css::uno::Sequence<css::uno::Any> const& args,
159 : css::uno::Reference<css::uno::XComponentContext> const& xContext )
160 2629 : :BaseT(args, xContext), m_rServiceDecl(rServiceDecl) {}
161 380 : OwnServiceImpl(
162 : ServiceDecl const& rServiceDecl,
163 : css::uno::Reference<css::uno::XComponentContext> const& xContext )
164 380 : : BaseT(xContext), m_rServiceDecl(rServiceDecl) {}
165 :
166 : // XServiceInfo
167 8 : virtual OUString SAL_CALL getImplementationName()
168 : throw (css::uno::RuntimeException) SAL_OVERRIDE {
169 8 : return m_rServiceDecl.getImplementationName();
170 : }
171 138 : virtual sal_Bool SAL_CALL supportsService( OUString const& name )
172 : throw (css::uno::RuntimeException) SAL_OVERRIDE {
173 138 : return m_rServiceDecl.supportsService(name);
174 : }
175 : virtual css::uno::Sequence< OUString>
176 8 : SAL_CALL getSupportedServiceNames() throw (css::uno::RuntimeException) SAL_OVERRIDE {
177 8 : return m_rServiceDecl.getSupportedServiceNames();
178 : }
179 :
180 : private:
181 : ServiceDecl const& m_rServiceDecl;
182 : };
183 :
184 : template <typename ImplT>
185 5746 : class ServiceImpl : public OwnServiceImpl< ::cppu::ImplInheritanceHelper1<ImplT,css::lang::XServiceInfo> >
186 : {
187 : typedef OwnServiceImpl< ::cppu::ImplInheritanceHelper1<ImplT,css::lang::XServiceInfo> > ServiceImpl_BASE;
188 : public:
189 2498 : ServiceImpl(
190 : ServiceDecl const& rServiceDecl,
191 : css::uno::Sequence<css::uno::Any> const& args,
192 : css::uno::Reference<css::uno::XComponentContext> const& xContext )
193 2498 : : ServiceImpl_BASE(rServiceDecl, args, xContext) {}
194 380 : ServiceImpl(
195 : ServiceDecl const& rServiceDecl,
196 : css::uno::Reference<css::uno::XComponentContext> const& xContext )
197 380 : : ServiceImpl_BASE(rServiceDecl, xContext) {}
198 : };
199 :
200 : template <typename ImplT>
201 0 : class InheritingServiceImpl : public OwnServiceImpl< ImplT >
202 : {
203 : typedef OwnServiceImpl< ImplT > ServiceImpl_BASE;
204 : public:
205 0 : InheritingServiceImpl(
206 : ServiceDecl const& rServiceDecl,
207 : css::uno::Sequence<css::uno::Any> const& args,
208 : css::uno::Reference<css::uno::XComponentContext> const& xContext )
209 0 : : 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) {}
214 : };
215 :
216 : template <typename ServiceImplT>
217 : struct PostProcessDefault {
218 : css::uno::Reference<css::uno::XInterface>
219 3005 : operator()( ServiceImplT * p ) const {
220 3005 : return static_cast<css::lang::XServiceInfo *>(p);
221 : }
222 : };
223 :
224 : template <typename ImplT, typename PostProcessFuncT, typename WithArgsT>
225 : struct CreateFunc;
226 :
227 : template <typename ImplT, typename PostProcessFuncT>
228 : struct CreateFunc<ImplT, PostProcessFuncT, with_args<false> > {
229 : PostProcessFuncT const m_postProcessFunc;
230 353 : explicit CreateFunc( PostProcessFuncT const& postProcessFunc )
231 353 : : m_postProcessFunc(postProcessFunc) {}
232 :
233 : css::uno::Reference<css::uno::XInterface>
234 380 : operator()( ServiceDecl const& rServiceDecl,
235 : css::uno::Sequence<css::uno::Any> const&,
236 : css::uno::Reference<css::uno::XComponentContext>
237 : const& xContext ) const
238 : {
239 : return m_postProcessFunc(
240 380 : new ImplT( rServiceDecl, xContext ) );
241 : }
242 : };
243 :
244 : template <typename ImplT, typename PostProcessFuncT>
245 : struct CreateFunc<ImplT, PostProcessFuncT, with_args<true> > {
246 : PostProcessFuncT const m_postProcessFunc;
247 814 : explicit CreateFunc( PostProcessFuncT const& postProcessFunc )
248 814 : : m_postProcessFunc(postProcessFunc) {}
249 :
250 : css::uno::Reference<css::uno::XInterface>
251 2629 : operator()( ServiceDecl const& rServiceDecl,
252 : css::uno::Sequence<css::uno::Any> const& args,
253 : css::uno::Reference<css::uno::XComponentContext>
254 : const& xContext ) const
255 : {
256 : return m_postProcessFunc(
257 2629 : new ImplT( rServiceDecl, args, xContext ) );
258 : }
259 : };
260 :
261 : } // namespace detail
262 :
263 : /** Defines a service implementation class.
264 :
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>)
269 : */
270 : template <typename ImplT_, typename WithArgsT = with_args<false> >
271 1056 : struct serviceimpl_base {
272 : typedef ImplT_ ImplT;
273 :
274 : detail::CreateFuncF const m_createFunc;
275 :
276 : typedef detail::PostProcessDefault<ImplT> PostProcessDefaultT;
277 :
278 : /** Default ctor. Implementation class without args, expecting
279 : component context as single argument.
280 : */
281 1163 : serviceimpl_base() : m_createFunc(
282 : detail::CreateFunc<ImplT, PostProcessDefaultT, WithArgsT>(
283 1163 : PostProcessDefaultT() ) ) {}
284 :
285 : /** Ctor to pass a post processing function/functor.
286 :
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>
291 : */
292 : template <typename PostProcessFuncT>
293 4 : explicit serviceimpl_base( PostProcessFuncT const& postProcessFunc )
294 : : m_createFunc( detail::CreateFunc<ImplT, PostProcessFuncT, WithArgsT>(
295 4 : postProcessFunc ) ) {}
296 : };
297 :
298 : template <typename ImplT_, typename WithArgsT = with_args<false> >
299 1032 : struct class_ : public serviceimpl_base< detail::ServiceImpl<ImplT_>, WithArgsT >
300 : {
301 : typedef serviceimpl_base< detail::ServiceImpl<ImplT_>, WithArgsT > baseT;
302 : /** Default ctor. Implementation class without args, expecting
303 : component context as single argument.
304 : */
305 1139 : class_() : baseT() {}
306 : template <typename PostProcessFuncT>
307 : /** Ctor to pass a post processing function/functor.
308 :
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>
313 : */
314 4 : explicit class_( PostProcessFuncT const& postProcessFunc ) : baseT( postProcessFunc ) {}
315 : };
316 :
317 : template <typename ImplT_, typename WithArgsT = with_args<false> >
318 1 : struct inheritingClass_ : public serviceimpl_base< detail::InheritingServiceImpl<ImplT_>, WithArgsT >
319 : {
320 : typedef serviceimpl_base< detail::InheritingServiceImpl<ImplT_>, WithArgsT > baseT;
321 : /** Default ctor. Implementation class without args, expecting
322 : component context as single argument.
323 : */
324 1 : inheritingClass_() : baseT() {}
325 : template <typename PostProcessFuncT>
326 : /** Ctor to pass a post processing function/functor.
327 :
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>
332 : */
333 : explicit inheritingClass_( PostProcessFuncT const& postProcessFunc ) : baseT( postProcessFunc ) {}
334 : };
335 :
336 : // component_... helpers with arbitrary service declarations:
337 :
338 :
339 : #define COMPHELPER_SERVICEDECL_getFactory(z_, n_, unused_) \
340 : if (pRet == 0) \
341 : pRet = BOOST_PP_CAT(s, n_).getFactory(pImplName);
342 :
343 : /** The following preprocessor repetitions generate functions like
344 :
345 : <pre>
346 : inline void * component_getFactoryHelper(
347 : sal_Char const* pImplName,
348 : ServiceDecl const& s0, ServiceDecl const& s1, ... );
349 : </pre>
350 :
351 : which call on the passed service declarations.
352 :
353 : The maximum number of service declarations can be set by defining
354 : COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS; its default is 8.
355 : */
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) ) \
360 : { \
361 : void * pRet = 0; \
362 : BOOST_PP_REPEAT(n_, COMPHELPER_SERVICEDECL_getFactory, ~) \
363 : return pRet; \
364 : }
365 :
366 : #ifndef COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS
367 : #define COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS 8
368 : #endif
369 :
370 914 : BOOST_PP_REPEAT_FROM_TO(1, COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS,
371 : COMPHELPER_SERVICEDECL_make, ~)
372 :
373 : #undef COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS
374 : #undef COMPHELPER_SERVICEDECL_make
375 : #undef COMPHELPER_SERVICEDECL_getFactory
376 :
377 : } // namespace service_decl
378 : } // namespace comphelper
379 :
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.
383 :
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:
387 :
388 : <pre>
389 : // must reside outside _any_ namespace
390 : COMPHELPER_SERVICEDECL_EXPORTS3(yourServiceDecl1,
391 : yourServiceDecl2,
392 : yourServiceDecl3);
393 : </pre>
394 :
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:
398 :
399 : <pre>
400 : // must reside outside _any_ namespace
401 : COMPHELPER_SERVICEDECL_make_exports((yourServiceDecl1)(yourServiceDecl2)...(yourServiceDeclN));
402 : </pre>
403 :
404 : Note the missing colons between the bracketed arguments.
405 : */
406 : #define COMPHELPER_SERVICEDECL_make_exports(compName, varargs_ ) \
407 : extern "C" \
408 : { \
409 : SAL_DLLPUBLIC_EXPORT void* SAL_CALL compName##_component_getFactory( sal_Char const* pImplName, \
410 : void*, void* ) \
411 : { \
412 : return component_getFactoryHelper( pImplName, \
413 : BOOST_PP_SEQ_ENUM(varargs_) ); \
414 : } \
415 : }
416 :
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_))
433 :
434 : #endif // ! defined( INCLUDED_COMPHELPER_SERVICEDECL_HXX)
435 :
436 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|