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