LCOV - code coverage report
Current view: top level - include/comphelper - servicedecl.hxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 40 43 93.0 %
Date: 2015-06-13 12:38:46 Functions: 391 649 60.2 %
Legend: Lines: hit not hit

          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: */

Generated by: LCOV version 1.11