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