1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 #ifndef COMPHELPER_INC_COMPHELPER_COMPONENTMODULE_HXX
28 #define COMPHELPER_INC_COMPHELPER_COMPONENTMODULE_HXX
29 
30 #include <comphelper/comphelperdllapi.h>
31 #include <comphelper/legacysingletonfactory.hxx>
32 
33 /** === begin UNO includes === **/
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
36 #include <com/sun/star/uno/Sequence.hxx>
37 /** === end UNO includes === **/
38 
39 #include <cppuhelper/factory.hxx>
40 
41 #include <osl/mutex.hxx>
42 
43 #include <rtl/string.hxx>
44 #include <rtl/instance.hxx>
45 
46 //........................................................................
47 namespace comphelper
48 {
49 //........................................................................
50 
51     /** factory factory declaration
52     */
53     typedef ::com::sun::star::uno::Reference< ::com::sun::star::lang::XSingleComponentFactory > (SAL_CALL *FactoryInstantiation)
54     (
55         ::cppu::ComponentFactoryFunc _pFactoryFunc,
56         ::rtl::OUString const& _rComponentName,
57         ::com::sun::star::uno::Sequence< ::rtl::OUString > const & _rServiceNames,
58         rtl_ModuleCount* _pModuleCounter
59     ) SAL_THROW(());
60 
61 	//=========================================================================
62 	//= ComponentDescription
63 	//=========================================================================
64     struct COMPHELPER_DLLPUBLIC ComponentDescription
65     {
66         /// the implementation name of the component
67         ::rtl::OUString                                     sImplementationName;
68         /// the services supported by the component implementation
69         ::com::sun::star::uno::Sequence< ::rtl::OUString >  aSupportedServices;
70         /** the name under which the component implementation should be registered as singleton,
71             or empty if the component does not implement a singleton.
72         */
73         ::rtl::OUString                                     sSingletonName;
74         /// the function to create an instance of the component
75         ::cppu::ComponentFactoryFunc                        pComponentCreationFunc;
76         /// the function to create a factory for the component (usually <code>::cppu::createSingleComponentFactory</code>)
77         FactoryInstantiation                                pFactoryCreationFunc;
78 
79         ComponentDescription()
80             :sImplementationName()
81             ,aSupportedServices()
82             ,sSingletonName()
83             ,pComponentCreationFunc( NULL )
84             ,pFactoryCreationFunc( NULL )
85         {
86         }
87 
88         ComponentDescription(
89                 const ::rtl::OUString& _rImplementationName,
90                 const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rSupportedServices,
91                 const ::rtl::OUString& _rSingletonName,
92                 ::cppu::ComponentFactoryFunc _pComponentCreationFunc,
93                 FactoryInstantiation _pFactoryCreationFunc
94             )
95             :sImplementationName( _rImplementationName )
96             ,aSupportedServices( _rSupportedServices )
97             ,sSingletonName( _rSingletonName )
98             ,pComponentCreationFunc( _pComponentCreationFunc )
99             ,pFactoryCreationFunc( _pFactoryCreationFunc )
100         {
101         }
102     };
103 
104     //=========================================================================
105     //= OModule
106     //=========================================================================
107     class OModuleImpl;
108     class COMPHELPER_DLLPUBLIC OModule
109     {
110     private:
111         oslInterlockedCount     m_nClients;     /// number of registered clients
112         OModuleImpl*            m_pImpl;        /// impl class. lives as long as at least one client for the module is registered
113 
114     protected:
115         mutable ::osl::Mutex    m_aMutex;       /// access safety
116 
117     public:
118         OModule();
119 
120         virtual ~OModule();
121 
122         /** register a component implementing a service with the given data.
123             @param _rImplementationName
124                 the implementation name of the component
125             @param _rServiceNames
126                 the services the component supports
127             @param _pCreateFunction
128                 a function for creating an instance of the component
129             @param _pFactoryFunction
130                 a function for creating a factory for that component
131         */
132         void registerImplementation(
133             const ::rtl::OUString& _rImplementationName,
134             const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rServiceNames,
135             ::cppu::ComponentFactoryFunc _pCreateFunction,
136             FactoryInstantiation _pFactoryFunction = ::cppu::createSingleComponentFactory );
137 
138         /** registers a component given by <type>ComponentDescription</type>
139         */
140         void registerImplementation( const ComponentDescription& _rComp );
141 
142         /** creates a Factory for the component with the given implementation name.
143             <p>Usually used from within component_getFactory.<p/>
144             @param _rxServiceManager
145                 a pointer to an XMultiServiceFactory interface as got in component_getFactory
146             @param _pImplementationName
147                 the implementation name of the component
148             @return
149                 the XInterface access to a factory for the component
150         */
151         ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > getComponentFactory(
152             const ::rtl::OUString& _rImplementationName,
153             const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxServiceManager
154         );
155 
156         /** version of getComponentFactory which directly takes the arguments you got in your component_getFactory call
157         */
158         void* getComponentFactory(
159             const sal_Char* _pImplementationName, void* _pServiceManager, void* _pRegistryKey
160         );
161 
162     public:
163         class ClientAccess { friend class OModuleClient; private: ClientAccess() { } };
164         /// register a client for the module
165         void registerClient( ClientAccess );
166         /// revoke a client for the module
167         void revokeClient( ClientAccess );
168 
169     protected:
170         /** called when the first client has been registered
171             @precond
172                 <member>m_aMutex</member> is locked
173         */
174         virtual void onFirstClient();
175 
176         /** called when the last client has been revoked
177             @precond
178                 <member>m_aMutex</member> is locked
179         */
180         virtual void onLastClient();
181 
182     private:
183         OModule( const OModule& );              // never implemented
184         OModule& operator=( const OModule& );   // never implemented
185     };
186 
187     //=========================================================================
188     //= OModuleClient
189     //=========================================================================
190     /** base class for objects which uses any global module-specific ressources
191     */
192     class COMPHELPER_DLLPUBLIC OModuleClient
193     {
194     protected:
195         OModule&    m_rModule;
196 
197     public:
198         OModuleClient( OModule& _rModule ) :m_rModule( _rModule )   { m_rModule.registerClient( OModule::ClientAccess() ); }
199         ~OModuleClient()                                            { m_rModule.revokeClient( OModule::ClientAccess() ); }
200     };
201 
202     //==========================================================================
203     //= OAutoRegistration
204     //==========================================================================
205     template <class TYPE>
206     class OAutoRegistration
207     {
208     public:
209         /** automatically provides all component information to an OModule instance
210             <p>Assumed that the template argument has the three methods
211                 <ul>
212                     <li><code>static ::rtl::OUString getImplementationName_static()</code><li/>
213                     <li><code>static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static()</code><li/>
214                     <li><code>static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >
215                         Create(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&)</code>
216                         </li>
217                 <ul/>
218             the instantiation of this object will automatically register the class via <member>OModule::registerImplementation</member>.
219             <p/>
220             The factory creation function used is <code>::cppu::createSingleComponentFactory</code>.
221         */
222         OAutoRegistration( OModule& _rModule );
223     };
224 
225     template <class TYPE>
226     OAutoRegistration<TYPE>::OAutoRegistration( OModule& _rModule )
227     {
228         _rModule.registerImplementation(
229             TYPE::getImplementationName_static(),
230             TYPE::getSupportedServiceNames_static(),
231             TYPE::Create
232         );
233     }
234 
235     //==========================================================================
236     //= OSingletonRegistration
237     //==========================================================================
238     template <class TYPE>
239     class OSingletonRegistration
240     {
241     public:
242         /** automatically provides all component information to an OModule instance,
243             for a singleton component
244 
245             <p>Assumed that the template argument has the three methods
246                 <ul>
247                     <li><code>static ::rtl::OUString getImplementationName_static()</code><li/>
248                     <li><code>static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_static()</code><li/>
249                     <li><code>static ::rtl::OUString getSingletonName_static()</code></li>
250                     <li><code>static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >
251                         Create(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&)</code>
252                         </li>
253                 <ul/>
254             the instantiation of this object will automatically register the class via <member>OModule::registerImplementation</member>.
255             </p>
256         */
257         OSingletonRegistration( OModule& _rModule );
258     };
259 
260     template <class TYPE>
261     //--------------------------------------------------------------------------
262     OSingletonRegistration<TYPE>::OSingletonRegistration( OModule& _rModule )
263     {
264         _rModule.registerImplementation( ComponentDescription(
265             TYPE::getImplementationName_static(),
266             TYPE::getSupportedServiceNames_static(),
267             TYPE::getSingletonName_static(),
268             &TYPE::Create,
269             &::cppu::createSingleComponentFactory
270         ) );
271     }
272 
273     //==========================================================================
274     //= OLegacySingletonRegistration
275     //==========================================================================
276     template <class TYPE>
277     class OLegacySingletonRegistration
278     {
279     public:
280         OLegacySingletonRegistration( OModule& _rModule );
281     };
282 
283     //--------------------------------------------------------------------------
284     template <class TYPE>
285     OLegacySingletonRegistration<TYPE>::OLegacySingletonRegistration( OModule& _rModule )
286     {
287         _rModule.registerImplementation( ComponentDescription(
288             TYPE::getImplementationName_static(),
289             TYPE::getSupportedServiceNames_static(),
290             ::rtl::OUString(),
291             &TYPE::Create,
292             &::comphelper::createLegacySingletonFactory
293         ) );
294     }
295 
296     //==========================================================================
297     //= helpers
298     //==========================================================================
299 
300     //==========================================================================
301     // declaring a OModule for a component library
302 
303 #define DECLARE_COMPONENT_MODULE( ModuleClass, ClientClass ) \
304     /* -------------------------------------------------------------------- */ \
305     class ModuleClass : public ::comphelper::OModule \
306     { \
307         friend struct CreateModuleClass; \
308         typedef ::comphelper::OModule BaseClass; \
309     \
310     public: \
311         static ModuleClass& getInstance(); \
312     \
313     private: \
314         ModuleClass(); \
315     }; \
316     \
317     /* -------------------------------------------------------------------- */ \
318     class ClientClass : public ::comphelper::OModuleClient \
319     { \
320     private: \
321         typedef ::comphelper::OModuleClient BaseClass; \
322     \
323     public: \
324         ClientClass() : BaseClass( ModuleClass::getInstance() ) \
325         { \
326         } \
327     }; \
328     \
329     /* -------------------------------------------------------------------- */ \
330     template < class TYPE > \
331     class OAutoRegistration : public ::comphelper::OAutoRegistration< TYPE > \
332     { \
333     private: \
334         typedef ::comphelper::OAutoRegistration< TYPE >    BaseClass; \
335     \
336     public: \
337         OAutoRegistration() : BaseClass( ModuleClass::getInstance() ) \
338         { \
339         } \
340     }; \
341     /* -------------------------------------------------------------------- */ \
342     template < class TYPE > \
343     class OSingletonRegistration : public ::comphelper::OSingletonRegistration< TYPE > \
344     { \
345     private: \
346         typedef ::comphelper::OSingletonRegistration< TYPE >    BaseClass; \
347     \
348     public: \
349         OSingletonRegistration() : BaseClass( ModuleClass::getInstance() ) \
350         { \
351         } \
352     }; \
353     /* -------------------------------------------------------------------- */ \
354     template < class TYPE > \
355     class OLegacySingletonRegistration : public ::comphelper::OLegacySingletonRegistration< TYPE > \
356     { \
357     private: \
358         typedef ::comphelper::OLegacySingletonRegistration< TYPE >  BaseClass; \
359     \
360     public: \
361         OLegacySingletonRegistration() : BaseClass( ModuleClass::getInstance() ) \
362         { \
363         } \
364     }; \
365 
366     //==========================================================================
367     //= implementing a OModule for a component library
368 
369 #define IMPLEMENT_COMPONENT_MODULE( ModuleClass ) \
370     struct CreateModuleClass \
371     { \
372         ModuleClass* operator()() \
373         { \
374             static ModuleClass* pModule = new ModuleClass; \
375             return pModule; \
376         } \
377     }; \
378     \
379     ModuleClass::ModuleClass() \
380         :BaseClass() \
381     { \
382     } \
383     \
384     ModuleClass& ModuleClass::getInstance() \
385     { \
386         return *rtl_Instance< ModuleClass, CreateModuleClass, ::osl::MutexGuard, ::osl::GetGlobalMutex >:: \
387             create( CreateModuleClass(), ::osl::GetGlobalMutex() ); \
388     } \
389 
390     //==========================================================================
391     //= implementing the API of a component library (component_*)
392 
393 #define IMPLEMENT_COMPONENT_LIBRARY_API( module_class, initializer_function )   \
394     extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL \
395     component_getImplementationEnvironment(    \
396         const sal_Char **ppEnvTypeName, uno_Environment ** /*ppEnv*/ )  \
397     {   \
398         *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;    \
399     }   \
400     extern "C" SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory( \
401         const sal_Char* pImplementationName, void* pServiceManager, void* pRegistryKey ) \
402     { \
403         initializer_function(); \
404         return module_class::getInstance().getComponentFactory( pImplementationName, pServiceManager, pRegistryKey );   \
405     }
406 
407 //........................................................................
408 } // namespace comphelper
409 //........................................................................
410 
411 #endif // COMPHELPER_INC_COMPHELPER_COMPONENTMODULE_HXX
412 
413