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