xref: /trunk/main/comphelper/source/misc/proxyaggregation.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3) !
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 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_comphelper.hxx"
30 #include <comphelper/proxyaggregation.hxx>
31 #include <com/sun/star/reflection/XProxyFactory.hpp>
32 
33 //.............................................................................
34 namespace comphelper
35 {
36 //.............................................................................
37 
38     using namespace ::com::sun::star::uno;
39     using namespace ::com::sun::star::lang;
40     using namespace ::com::sun::star::reflection;
41 
42     //=========================================================================
43     //= OProxyAggregation
44     //=========================================================================
45     //-------------------------------------------------------------------------
46     OProxyAggregation::OProxyAggregation( const Reference< XMultiServiceFactory >& _rxORB )
47         :m_xORB( _rxORB )
48     {
49     }
50 
51     //-------------------------------------------------------------------------
52     void OProxyAggregation::baseAggregateProxyFor( const Reference< XInterface >& _rxComponent, oslInterlockedCount& _rRefCount,
53             ::cppu::OWeakObject& _rDelegator )
54     {
55         // first a factory for the proxy
56         Reference< XProxyFactory > xFactory(
57             m_xORB->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.reflection.ProxyFactory" ) ) ),
58             UNO_QUERY
59         );
60         OSL_ENSURE( xFactory.is(), "OProxyAggregation::baseAggregateProxyFor: could not create a proxy factory!" );
61 
62         // then the proxy itself
63         if ( xFactory.is() )
64         {
65             { // i36686 OJ: achieve the desctruction of the tempoary -> otherwise it leads to _rRefCount -= 2
66                 m_xProxyAggregate = xFactory->createProxy( _rxComponent );
67             }
68             if ( m_xProxyAggregate.is() )
69                 m_xProxyAggregate->queryAggregation( ::getCppuType( &m_xProxyTypeAccess ) ) >>= m_xProxyTypeAccess;
70 
71             // aggregate the proxy
72             osl_incrementInterlockedCount( &_rRefCount );
73             if ( m_xProxyAggregate.is() )
74             {
75                 // At this point in time, the proxy has a ref count of exactly two - in m_xControlContextProxy,
76                 // and in m_xProxyTypeAccess.
77                 // Remember to _not_ reset these members unless the delegator of the proxy has been reset, too!
78                 m_xProxyAggregate->setDelegator( _rDelegator );
79             }
80             osl_decrementInterlockedCount( &_rRefCount );
81         }
82     }
83 
84     //-------------------------------------------------------------------------
85     Any SAL_CALL OProxyAggregation::queryAggregation( const Type& _rType ) throw (RuntimeException)
86     {
87         return m_xProxyAggregate.is() ? m_xProxyAggregate->queryAggregation( _rType ) : Any();
88     }
89 
90     //-------------------------------------------------------------------------
91     Sequence< Type > SAL_CALL OProxyAggregation::getTypes(  ) throw (RuntimeException)
92     {
93         Sequence< Type > aTypes;
94         if ( m_xProxyAggregate.is() )
95         {
96             if ( m_xProxyTypeAccess.is() )
97                 aTypes = m_xProxyTypeAccess->getTypes();
98         }
99         return aTypes;
100     }
101 
102     //-------------------------------------------------------------------------
103     OProxyAggregation::~OProxyAggregation()
104     {
105         if ( m_xProxyAggregate.is() )
106             m_xProxyAggregate->setDelegator( NULL );
107         m_xProxyAggregate.clear();
108         m_xProxyTypeAccess.clear();
109             // this should remove the _two_only_ "real" references (means not delegated to
110             // ourself) to this proxy, and thus delete it
111     }
112 
113     //=========================================================================
114     //= OComponentProxyAggregationHelper
115     //=========================================================================
116     //-------------------------------------------------------------------------
117     OComponentProxyAggregationHelper::OComponentProxyAggregationHelper( const Reference< XMultiServiceFactory >& _rxORB,
118         ::cppu::OBroadcastHelper& _rBHelper )
119         :OProxyAggregation( _rxORB )
120         ,m_rBHelper( _rBHelper )
121     {
122         OSL_ENSURE( _rxORB.is(), "OComponentProxyAggregationHelper::OComponentProxyAggregationHelper: invalid arguments!" );
123     }
124 
125     //-------------------------------------------------------------------------
126     void OComponentProxyAggregationHelper::componentAggregateProxyFor(
127         const Reference< XComponent >& _rxComponent, oslInterlockedCount& _rRefCount,
128         ::cppu::OWeakObject& _rDelegator )
129     {
130         OSL_ENSURE( _rxComponent.is(), "OComponentProxyAggregationHelper::componentAggregateProxyFor: invalid inner component!" );
131         m_xInner = _rxComponent;
132 
133         // aggregate a proxy for the object
134         baseAggregateProxyFor( m_xInner.get(), _rRefCount, _rDelegator );
135 
136         // add as event listener to the inner context, because we want to be notified of disposals
137         osl_incrementInterlockedCount( &_rRefCount );
138         {
139             if ( m_xInner.is() )
140                 m_xInner->addEventListener( this );
141         }
142         osl_decrementInterlockedCount( &_rRefCount );
143     }
144 
145     //-------------------------------------------------------------------------
146     Any SAL_CALL OComponentProxyAggregationHelper::queryInterface( const Type& _rType ) throw (RuntimeException)
147     {
148         Any aReturn( BASE::queryInterface( _rType ) );
149         if ( !aReturn.hasValue() )
150             aReturn = OProxyAggregation::queryAggregation( _rType );
151         return aReturn;
152     }
153 
154     //-------------------------------------------------------------------------
155     IMPLEMENT_FORWARD_XTYPEPROVIDER2( OComponentProxyAggregationHelper, BASE, OProxyAggregation )
156 
157     //-------------------------------------------------------------------------
158     OComponentProxyAggregationHelper::~OComponentProxyAggregationHelper( )
159     {
160         OSL_ENSURE( m_rBHelper.bDisposed, "OComponentProxyAggregationHelper::~OComponentProxyAggregationHelper: you should dispose your derived class in the dtor, if necessary!" );
161             // if this asserts, add the following to your derived class dtor:
162             //
163             // if ( !m_rBHelper.bDisposed )
164             // {
165             //   acquire(); // to prevent duplicate dtor calls
166             //   dispose();
167             // }
168 
169         m_xInner.clear();
170     }
171 
172     //-------------------------------------------------------------------------
173     void SAL_CALL OComponentProxyAggregationHelper::disposing( const EventObject& _rSource ) throw (RuntimeException)
174     {
175         if ( _rSource.Source == m_xInner )
176         {   // it's our inner context which is dying -> dispose ourself
177             if ( !m_rBHelper.bDisposed && !m_rBHelper.bInDispose )
178             {   // (if necessary only, of course)
179                 dispose();
180             }
181         }
182     }
183 
184     //-------------------------------------------------------------------------
185     void SAL_CALL OComponentProxyAggregationHelper::dispose() throw( RuntimeException )
186     {
187         ::osl::MutexGuard aGuard( m_rBHelper.rMutex );
188 
189         // dispose our inner context
190         // before we do this, remove ourself as listener - else in disposing( EventObject ), we
191         // would dispose ourself a second time
192         Reference< XComponent > xComp( m_xInner, UNO_QUERY );
193         if ( xComp.is() )
194         {
195             xComp->removeEventListener( this );
196             xComp->dispose();
197             xComp.clear();
198         }
199     }
200 
201     //=========================================================================
202     //= OComponentProxyAggregation
203     //=========================================================================
204     //-------------------------------------------------------------------------
205     OComponentProxyAggregation::OComponentProxyAggregation( const Reference< XMultiServiceFactory >& _rxORB,
206             const Reference< XComponent >& _rxComponent )
207         :OComponentProxyAggregation_CBase( m_aMutex )
208         ,OComponentProxyAggregationHelper( _rxORB, rBHelper )
209     {
210         OSL_ENSURE( _rxComponent.is(), "OComponentProxyAggregation::OComponentProxyAggregation: accessible is no XComponent!" );
211         if ( _rxComponent.is() )
212             componentAggregateProxyFor( _rxComponent, m_refCount, *this );
213     }
214 
215     //-------------------------------------------------------------------------
216     OComponentProxyAggregation::~OComponentProxyAggregation()
217     {
218         implEnsureDisposeInDtor( );
219     }
220 
221     //-------------------------------------------------------------------------
222     IMPLEMENT_FORWARD_XINTERFACE2( OComponentProxyAggregation, OComponentProxyAggregation_CBase, OComponentProxyAggregationHelper )
223 
224     //-------------------------------------------------------------------------
225     IMPLEMENT_GET_IMPLEMENTATION_ID( OComponentProxyAggregation )
226 
227     //-------------------------------------------------------------------------
228     Sequence< Type > SAL_CALL OComponentProxyAggregation::getTypes(  ) throw (RuntimeException)
229     {
230         Sequence< Type > aTypes( OComponentProxyAggregationHelper::getTypes() );
231 
232         // append XComponent, coming from OComponentProxyAggregation_CBase
233         sal_Int32 nLen = aTypes.getLength();
234         aTypes.realloc( nLen + 1 );
235         aTypes[ nLen ] = ::getCppuType( static_cast< Reference< XComponent >* >( NULL ) );
236 
237         return aTypes;
238     }
239 
240     //-------------------------------------------------------------------------
241     void OComponentProxyAggregation::implEnsureDisposeInDtor( )
242     {
243         if ( !rBHelper.bDisposed )
244         {
245             acquire();  // to prevent duplicate dtor calls
246             dispose();
247         }
248     }
249 
250     //--------------------------------------------------------------------
251     void SAL_CALL OComponentProxyAggregation::disposing( const EventObject& _rSource ) throw (RuntimeException)
252     {
253         // simly disambiguate - this is necessary for MSVC to distinguish
254         // "disposing( EventObject )" from "disposing()"
255         OComponentProxyAggregationHelper::disposing( _rSource );
256     }
257 
258     //--------------------------------------------------------------------
259     void SAL_CALL OComponentProxyAggregation::disposing()  throw (RuntimeException)
260     {
261         // call the dispose-functionality of the base, which will dispose our aggregated component
262         OComponentProxyAggregationHelper::dispose();
263     }
264 
265     //--------------------------------------------------------------------
266     void SAL_CALL OComponentProxyAggregation::dispose() throw( RuntimeException )
267     {
268         // simply disambiguate
269         OComponentProxyAggregation_CBase::dispose();
270     }
271 
272 
273 //.............................................................................
274 }   // namespace comphelper
275 //.............................................................................
276 
277