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 
24 #ifndef UNOTOOLS_INC_SHAREDUNOCOMPONENT_HXX
25 #define UNOTOOLS_INC_SHAREDUNOCOMPONENT_HXX
26 
27 #include "unotoolsdllapi.h"
28 
29 #include <boost/shared_ptr.hpp>
30 #include <com/sun/star/uno/Reference.hxx>
31 #include <rtl/ref.hxx>
32 
33 namespace com { namespace sun { namespace star {
34     namespace lang {
35         class XComponent;
36     }
37 } } }
38 //............................................................................
39 namespace utl
40 {
41 //............................................................................
42 
43     //========================================================================
44     //= DisposableComponent
45     //========================================================================
46     /** is a class which controls lifetime of an UNO component via ->XComponent::dispose
47 
48         You'll usually never use this class directly, but only as parameter for a
49         ->SharedUNOComponent class.
50     */
51     class UNOTOOLS_DLLPUBLIC DisposableComponent
52     {
53         ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >
54             m_xComponent;
55 
56     public:
57         /** constructs a ->DisposableComponent instance
58 
59         @param _rxComponent
60             the component whose life time should be controlled by the instance. Must not be <NULL/>.
61         */
62         DisposableComponent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxComponent );
63 
64         /** disposes the component represented by the instance
65 
66             The component is queried for ->XComponent(which <em>must</em> be supported),
67             and ->XComponent::dispose is invoked. A failure of this invocation (e.g. a thrown
68             exception) is silenced in release builds, and reported in debug builds.
69         */
70         ~DisposableComponent();
71 
72     private:
73         DisposableComponent();                                          // never implemented
74         DisposableComponent( const DisposableComponent& );              // never implemented
75         DisposableComponent& operator=( const DisposableComponent& );   // never implemented
76     };
77 
78     //========================================================================
79     //= CloseableComponent
80     //========================================================================
81     class CloseableComponentImpl;
82     /** is a class which controls lifetime of an UNO component via ->XCloseable::close
83 
84         You'll usually never use this class directly, but only as parameter for a
85         ->SharedUNOComponent class.
86     */
87     class UNOTOOLS_DLLPUBLIC CloseableComponent
88     {
89     private:
90         /** Our IMPL class.
91         */
92         ::rtl::Reference< CloseableComponentImpl >  m_pImpl;
93 
94     public:
95         /** constructs a ->CloseableComponent instance
96 
97         @param _rxComponent
98             the component whose life time should be controlled by the instance. Must not be <NULL/>.
99         */
100         CloseableComponent( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxComponent );
101 
102         /** destroys resources associated with this instance, and disposes the component
103 
104             The component is queried for ->XCloseable (which <em>must</em> be supported),
105             and ->XCloseable::close is invoked, with delivering the ownership.
106             If the invocation fails with a ->CloseVetoException, this is ignored, since in
107             this case the vetoing instance took the ownership.
108 
109             Any other failure will be reported in a debug version via assertion mechanisms,
110             and silenced in release builds.
111         */
112         ~CloseableComponent();
113 
114     private:
115         CloseableComponent();                                           // never implemented
116         CloseableComponent( const CloseableComponent& );                // never implemented
117         CloseableComponent& operator=( const CloseableComponent& );     // never implemented
118     };
119 
120     //========================================================================
121     //= SharedUNOComponent
122     //========================================================================
123     /** is a helper class for sharing ownership of a UNO component
124 
125         If you need to share an UNO component, which normally needs a dedicated owner,
126         and is lifetime controlled by an explicit disposal action (not necessarily ->XComponent::dispose,
127         but <em>any</em> explicit method call, after which the object is considered
128         to be disposed), between different classes, ->SharedUNOComponent is what you need.
129 
130         Instead of passing around a <code>Reference&lt; XFoo &gt;</code>, and bothering
131         with ownership and disposal, you just use a <code>SharedUNOComponent&lt; XFoo &gt;</code>.
132         This instance can be passed around, including copying, and in nearly all respects behaves
133         like the original <code>Reference&lt; XFoo &gt;</code>. However, when the last
134         ->SharedUNOComponent referencing a certain <code>Reference&lt; XFoo &gt;</code> dies, it
135         will automatically get rid of the object held by this reference.
136 
137     @param INTERFACE
138         the UNO interface type as which the component should be held
139 
140     @param COMPONENT_HOLDER
141         a class which can be used to represent and dispose a UNO component.
142         The class must support (maybe explicit only) construction from a
143         <code>Reference&lt; INTERFACE &gt;</code>, and destruction. Upon destruction,
144         the class must dispose (by any suitable means) the component instance it was
145         constructed with.
146     */
147     template < class INTERFACE, class COMPONENT = DisposableComponent >
148     class SharedUNOComponent
149     {
150     private:
151         typedef COMPONENT                           Component;
152         typedef ::boost::shared_ptr< Component >    ComponentPointer;
153 
154     private:
155         ComponentPointer                                m_pComponent;
156         ::com::sun::star::uno::Reference< INTERFACE >   m_xTypedComponent;
157 
158     public:
159         enum AssignmentMode
160         {
161             TakeOwnership,
162             NoTakeOwnership
163         };
164 
165     public:
SharedUNOComponent()166         inline  SharedUNOComponent()
167         {
168         }
169 
SharedUNOComponent(const::com::sun::star::uno::Reference<INTERFACE> & _rxComponent,AssignmentMode eMode=TakeOwnership)170         explicit inline  SharedUNOComponent( const ::com::sun::star::uno::Reference< INTERFACE >& _rxComponent, AssignmentMode eMode = TakeOwnership )
171         {
172             reset( _rxComponent, eMode );
173         }
174 
175 #ifndef EXCEPTIONS_OFF
SharedUNOComponent(const::com::sun::star::uno::XInterface * _pInterface,::com::sun::star::uno::UnoReference_QueryThrow _queryThrow)176         inline SharedUNOComponent( const ::com::sun::star::uno::XInterface* _pInterface, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow )
177         {
178             set( _pInterface, _queryThrow );
179         }
180 
SharedUNOComponent(const::com::sun::star::uno::BaseReference & _rRef,::com::sun::star::uno::UnoReference_QueryThrow _queryThrow)181         inline SharedUNOComponent( const ::com::sun::star::uno::BaseReference & _rRef, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow )
182         {
183             set( _rRef, _queryThrow );
184         }
185 
SharedUNOComponent(const::com::sun::star::uno::Any & _rAny,::com::sun::star::uno::UnoReference_QueryThrow _queryThrow)186         inline SharedUNOComponent( const ::com::sun::star::uno::Any& _rAny, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow )
187         {
188             set( _rAny, _queryThrow );
189         }
190 
SharedUNOComponent(const SharedUNOComponent & _rxComponent,::com::sun::star::uno::UnoReference_SetThrow _setThrow)191         inline  SharedUNOComponent( const SharedUNOComponent& _rxComponent, ::com::sun::star::uno::UnoReference_SetThrow _setThrow )
192         {
193             set( _rxComponent, _setThrow );
194         }
195 #endif
196 
197 //        SharedUNOComponent& operator=( const ::com::sun::star::uno::Reference< INTERFACE >& _rxComponent );
198         // this operator is not implemented by intention. There is no canonic ownership after this operatoer
199         // would have been applied: Should the SharedUNOComponent have the ownership of the component,
200         // or shouldn't it? Hard to guess, and probably wrong in 50 percent of all cases, anyway. So,
201         // instead of tempting clients of this class to use such a dangerous operator, we do
202         // not offer it at all. If you need to assign a Reference< INTERFACE > to your SharedUNOComponent,
203         // use the ->reset method.
204 
205         /** assigns a new component, and releases the old one
206         */
207         void reset( const ::com::sun::star::uno::Reference< INTERFACE >& _rxComponent, AssignmentMode _eMode = TakeOwnership );
208 
209         inline bool set( ::com::sun::star::uno::XInterface* _pInterface, ::com::sun::star::uno::UnoReference_Query _query );
210         inline bool set( const ::com::sun::star::uno::BaseReference& _rRef, ::com::sun::star::uno::UnoReference_Query _query );
211         inline bool set( const ::com::sun::star::uno::Any& _rAny, ::com::sun::star::uno::UnoReference_Query _query );
212 
213 #ifndef EXCEPTIONS_OFF
214         inline void set( const ::com::sun::star::uno::XInterface* _pInterface, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow );
215         inline void set( const ::com::sun::star::uno::BaseReference & _rRef, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow );
216         inline void set( const ::com::sun::star::uno::Any& _rAny, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow );
217 
218         inline void set( const INTERFACE* _pInterface, ::com::sun::star::uno::UnoReference_SetThrow _setThrow );
219         inline void set( const ::com::sun::star::uno::Reference< INTERFACE >& _rRef, ::com::sun::star::uno::UnoReference_SetThrow _setThrow );
220         inline void set( const SharedUNOComponent& _rComp, ::com::sun::star::uno::UnoReference_SetThrow _setThrow );
221 #endif
222 
223 	    INTERFACE* SAL_CALL operator->() const;
224 
225         inline operator const ::com::sun::star::uno::Reference< INTERFACE >&() const
226         {
227             return m_xTypedComponent;
228         }
229 
getTyped() const230         inline const ::com::sun::star::uno::Reference< INTERFACE >& getTyped() const
231         {
232             return m_xTypedComponent;
233         }
234 
is() const235         inline bool is() const
236         {
237             return m_xTypedComponent.is();
238         }
239 
clear()240         inline void clear()
241         {
242             m_pComponent.reset();
243             m_xTypedComponent.clear();
244         }
245     };
246 
247     //-------------------------------------------------------------------------
248     template < class INTERFACE, class COMPONENT >
operator ->() const249     INTERFACE* SAL_CALL SharedUNOComponent< INTERFACE, COMPONENT >::operator->() const
250     {
251         return m_xTypedComponent.operator->();
252     }
253 
254     //-------------------------------------------------------------------------
255     // assignments
256     template < class INTERFACE, class COMPONENT >
reset(const::com::sun::star::uno::Reference<INTERFACE> & _rxComponent,AssignmentMode _eMode)257     void SharedUNOComponent< INTERFACE, COMPONENT >::reset( const ::com::sun::star::uno::Reference< INTERFACE >& _rxComponent, AssignmentMode _eMode )
258     {
259         m_pComponent.reset( _eMode == TakeOwnership ? new COMPONENT( _rxComponent ) : NULL );
260         m_xTypedComponent = _rxComponent;
261     }
262 
263     //-------------------------------------------------------------------------
264     // comparison operators
265     template < class INTERFACE, class COMPONENT >
operator ==(const::com::sun::star::uno::Reference<INTERFACE> & _rLHS,const SharedUNOComponent<INTERFACE,COMPONENT> & _rRHS)266     bool operator==( const ::com::sun::star::uno::Reference< INTERFACE >& _rLHS, const SharedUNOComponent< INTERFACE, COMPONENT >& _rRHS )
267     {
268         return _rLHS == _rRHS.getTyped();
269     }
270 
271     template < class INTERFACE, class COMPONENT >
operator ==(const SharedUNOComponent<INTERFACE,COMPONENT> & _rLHS,const::com::sun::star::uno::Reference<INTERFACE> & _rRHS)272     bool operator==( const SharedUNOComponent< INTERFACE, COMPONENT >& _rLHS, const ::com::sun::star::uno::Reference< INTERFACE >& _rRHS )
273     {
274         return _rLHS.getTyped() == _rRHS;
275     }
276 
277     //-------------------------------------------------------------------------
278     // conversion to Any
279     template < class INTERFACE, class COMPONENT >
operator <<=(::com::sun::star::uno::Any & rAny,const SharedUNOComponent<INTERFACE,COMPONENT> & value)280     inline void SAL_CALL operator <<= ( ::com::sun::star::uno::Any & rAny, const SharedUNOComponent< INTERFACE, COMPONENT >& value ) SAL_THROW( () )
281     {
282         rAny <<= value.getTyped();
283     }
284 
285     //-------------------------------------------------------------------------
286     template < class INTERFACE, class COMPONENT >
makeAny(const SharedUNOComponent<INTERFACE,COMPONENT> & value)287     inline ::com::sun::star::uno::Any SAL_CALL makeAny( const SharedUNOComponent< INTERFACE, COMPONENT >& value ) SAL_THROW( () )
288     {
289         return makeAny( value.getTyped() );
290     }
291 
292 #ifndef EXCEPTIONS_OFF
293     //-------------------------------------------------------------------------
294     template < class INTERFACE, class COMPONENT >
set(const::com::sun::star::uno::XInterface * _pInterface,::com::sun::star::uno::UnoReference_QueryThrow _queryThrow)295     void SharedUNOComponent< INTERFACE, COMPONENT >::set( const ::com::sun::star::uno::XInterface* _pInterface, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow )
296     {
297         reset( ::com::sun::star::uno::Reference< INTERFACE >( _pInterface, _queryThrow ), TakeOwnership );
298     }
299 
300     //-------------------------------------------------------------------------
301     template < class INTERFACE, class COMPONENT >
set(const::com::sun::star::uno::BaseReference & _rRef,::com::sun::star::uno::UnoReference_QueryThrow _queryThrow)302     void SharedUNOComponent< INTERFACE, COMPONENT >::set( const ::com::sun::star::uno::BaseReference & _rRef, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow )
303     {
304         reset( ::com::sun::star::uno::Reference< INTERFACE >( _rRef, _queryThrow ), TakeOwnership );
305     }
306 
307     //-------------------------------------------------------------------------
308     template < class INTERFACE, class COMPONENT >
set(const::com::sun::star::uno::Any & _rAny,::com::sun::star::uno::UnoReference_QueryThrow _queryThrow)309     void SharedUNOComponent< INTERFACE, COMPONENT >::set( const ::com::sun::star::uno::Any& _rAny, ::com::sun::star::uno::UnoReference_QueryThrow _queryThrow )
310     {
311         reset( ::com::sun::star::uno::Reference< INTERFACE >( _rAny, _queryThrow ), TakeOwnership );
312     }
313 
314     //-------------------------------------------------------------------------
315     template < class INTERFACE, class COMPONENT >
set(const INTERFACE * _pInterface,::com::sun::star::uno::UnoReference_SetThrow _setThrow)316     void SharedUNOComponent< INTERFACE, COMPONENT >::set( const INTERFACE* _pInterface, ::com::sun::star::uno::UnoReference_SetThrow _setThrow )
317     {
318         reset( ::com::sun::star::uno::Reference< INTERFACE >( _pInterface, _setThrow ), TakeOwnership );
319     }
320 
321     //-------------------------------------------------------------------------
322     template < class INTERFACE, class COMPONENT >
set(const::com::sun::star::uno::Reference<INTERFACE> & _rRef,::com::sun::star::uno::UnoReference_SetThrow _setThrow)323     void SharedUNOComponent< INTERFACE, COMPONENT >::set( const ::com::sun::star::uno::Reference< INTERFACE >& _rRef, ::com::sun::star::uno::UnoReference_SetThrow _setThrow )
324     {
325         reset( ::com::sun::star::uno::Reference< INTERFACE >( _rRef, _setThrow ), TakeOwnership );
326     }
327 
328     //-------------------------------------------------------------------------
329     template < class INTERFACE, class COMPONENT >
set(const SharedUNOComponent & _rComp,::com::sun::star::uno::UnoReference_SetThrow _setThrow)330     void SharedUNOComponent< INTERFACE, COMPONENT >::set( const SharedUNOComponent& _rComp, ::com::sun::star::uno::UnoReference_SetThrow _setThrow )
331     {
332         *this = _rComp;
333         // provoke an exception in case the component is NULL
334         m_xTypedComponent.set( m_xTypedComponent, _setThrow );
335     }
336 #endif
337 
338     //-------------------------------------------------------------------------
339     template < class INTERFACE, class COMPONENT >
set(::com::sun::star::uno::XInterface * _pInterface,::com::sun::star::uno::UnoReference_Query _query)340     bool SharedUNOComponent< INTERFACE, COMPONENT >::set( ::com::sun::star::uno::XInterface* _pInterface, ::com::sun::star::uno::UnoReference_Query _query )
341     {
342         reset( ::com::sun::star::uno::Reference< INTERFACE >( _pInterface, _query ) );
343         return is();
344     }
345 
346     //-------------------------------------------------------------------------
347     template < class INTERFACE, class COMPONENT >
set(const::com::sun::star::uno::BaseReference & _rRef,::com::sun::star::uno::UnoReference_Query _query)348     bool SharedUNOComponent< INTERFACE, COMPONENT >::set( const ::com::sun::star::uno::BaseReference& _rRef, ::com::sun::star::uno::UnoReference_Query _query )
349     {
350         reset( ::com::sun::star::uno::Reference< INTERFACE >( _rRef, _query ) );
351         return is();
352     }
353 
354     //-------------------------------------------------------------------------
355     template < class INTERFACE, class COMPONENT >
set(const::com::sun::star::uno::Any & _rAny,::com::sun::star::uno::UnoReference_Query _query)356     bool SharedUNOComponent< INTERFACE, COMPONENT >::set( const ::com::sun::star::uno::Any& _rAny, ::com::sun::star::uno::UnoReference_Query _query )
357     {
358         reset( ::com::sun::star::uno::Reference< INTERFACE >( _rAny, _query ) );
359         return is();
360     }
361 
362 //............................................................................
363 }   // namespace utl
364 //............................................................................
365 
366 #endif // UNOTOOLS_INC_SHAREDUNOCOMPONENT_HXX
367