1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski 
24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove
25*b1cdbd2cSJim Jagielski #include "precompiled_cppuhelper.hxx"
26*b1cdbd2cSJim Jagielski #include <rtl/string.hxx>
27*b1cdbd2cSJim Jagielski #include <osl/diagnose.h>
28*b1cdbd2cSJim Jagielski #include <cppuhelper/component.hxx>
29*b1cdbd2cSJim Jagielski #include <cppuhelper/queryinterface.hxx>
30*b1cdbd2cSJim Jagielski #include <cppuhelper/typeprovider.hxx>
31*b1cdbd2cSJim Jagielski #include "com/sun/star/uno/RuntimeException.hpp"
32*b1cdbd2cSJim Jagielski 
33*b1cdbd2cSJim Jagielski using namespace osl;
34*b1cdbd2cSJim Jagielski using namespace rtl;
35*b1cdbd2cSJim Jagielski using namespace com::sun::star;
36*b1cdbd2cSJim Jagielski using namespace com::sun::star::uno;
37*b1cdbd2cSJim Jagielski using namespace com::sun::star::lang;
38*b1cdbd2cSJim Jagielski 
39*b1cdbd2cSJim Jagielski namespace cppu
40*b1cdbd2cSJim Jagielski {
41*b1cdbd2cSJim Jagielski 
42*b1cdbd2cSJim Jagielski //	----------------------------------------------------
43*b1cdbd2cSJim Jagielski //	class OComponentHelper
44*b1cdbd2cSJim Jagielski //	----------------------------------------------------
45*b1cdbd2cSJim Jagielski 
OComponentHelper(Mutex & rMutex)46*b1cdbd2cSJim Jagielski OComponentHelper::OComponentHelper( Mutex & rMutex ) SAL_THROW( () )
47*b1cdbd2cSJim Jagielski 	: rBHelper( rMutex )
48*b1cdbd2cSJim Jagielski {
49*b1cdbd2cSJim Jagielski }
~OComponentHelper()50*b1cdbd2cSJim Jagielski OComponentHelper::~OComponentHelper() SAL_THROW( (RuntimeException) )
51*b1cdbd2cSJim Jagielski {
52*b1cdbd2cSJim Jagielski }
53*b1cdbd2cSJim Jagielski 
queryInterface(Type const & rType)54*b1cdbd2cSJim Jagielski Any OComponentHelper::queryInterface( Type const & rType ) throw (RuntimeException)
55*b1cdbd2cSJim Jagielski {
56*b1cdbd2cSJim Jagielski     return OWeakAggObject::queryInterface( rType );
57*b1cdbd2cSJim Jagielski }
queryAggregation(Type const & rType)58*b1cdbd2cSJim Jagielski Any OComponentHelper::queryAggregation( Type const & rType ) throw (RuntimeException)
59*b1cdbd2cSJim Jagielski {
60*b1cdbd2cSJim Jagielski     if (rType == ::getCppuType( (Reference< lang::XComponent > const *)0 ))
61*b1cdbd2cSJim Jagielski     {
62*b1cdbd2cSJim Jagielski         void * p = static_cast< lang::XComponent * >( this );
63*b1cdbd2cSJim Jagielski         return Any( &p, rType );
64*b1cdbd2cSJim Jagielski     }
65*b1cdbd2cSJim Jagielski     else if (rType == ::getCppuType( (Reference< lang::XTypeProvider > const *)0 ))
66*b1cdbd2cSJim Jagielski     {
67*b1cdbd2cSJim Jagielski         void * p = static_cast< lang::XTypeProvider * >( this );
68*b1cdbd2cSJim Jagielski         return Any( &p, rType );
69*b1cdbd2cSJim Jagielski     }
70*b1cdbd2cSJim Jagielski     return OWeakAggObject::queryAggregation( rType );
71*b1cdbd2cSJim Jagielski }
acquire()72*b1cdbd2cSJim Jagielski void OComponentHelper::acquire() throw ()
73*b1cdbd2cSJim Jagielski {
74*b1cdbd2cSJim Jagielski 	OWeakAggObject::acquire();
75*b1cdbd2cSJim Jagielski }
76*b1cdbd2cSJim Jagielski 
release()77*b1cdbd2cSJim Jagielski void OComponentHelper::release() throw()
78*b1cdbd2cSJim Jagielski {
79*b1cdbd2cSJim Jagielski 	Reference<XInterface > x( xDelegator );
80*b1cdbd2cSJim Jagielski 	if (! x.is())
81*b1cdbd2cSJim Jagielski 	{
82*b1cdbd2cSJim Jagielski 		if (osl_decrementInterlockedCount( &m_refCount ) == 0)
83*b1cdbd2cSJim Jagielski 		{
84*b1cdbd2cSJim Jagielski 			if (! rBHelper.bDisposed)
85*b1cdbd2cSJim Jagielski 			{
86*b1cdbd2cSJim Jagielski                 // *before* again incrementing our ref count, ensure that our weak connection point
87*b1cdbd2cSJim Jagielski                 // will not create references to us anymore (via XAdapter::queryAdapted)
88*b1cdbd2cSJim Jagielski                 disposeWeakConnectionPoint();
89*b1cdbd2cSJim Jagielski 
90*b1cdbd2cSJim Jagielski 				Reference<XInterface > xHoldAlive( *this );
91*b1cdbd2cSJim Jagielski 				// First dispose
92*b1cdbd2cSJim Jagielski 				try
93*b1cdbd2cSJim Jagielski 				{
94*b1cdbd2cSJim Jagielski 					dispose();
95*b1cdbd2cSJim Jagielski 				}
96*b1cdbd2cSJim Jagielski 				catch (::com::sun::star::uno::RuntimeException & exc)
97*b1cdbd2cSJim Jagielski 				{
98*b1cdbd2cSJim Jagielski 					// release should not throw exceptions
99*b1cdbd2cSJim Jagielski #if OSL_DEBUG_LEVEL > 0
100*b1cdbd2cSJim Jagielski                     OString msg( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) );
101*b1cdbd2cSJim Jagielski                     OSL_ENSURE( 0, msg.getStr() );
102*b1cdbd2cSJim Jagielski #else
103*b1cdbd2cSJim Jagielski                     (void) exc; // avoid warning about unused variable
104*b1cdbd2cSJim Jagielski #endif
105*b1cdbd2cSJim Jagielski 				}
106*b1cdbd2cSJim Jagielski 
107*b1cdbd2cSJim Jagielski 				// only the alive ref holds the object
108*b1cdbd2cSJim Jagielski 				OSL_ASSERT( m_refCount == 1 );
109*b1cdbd2cSJim Jagielski 				// destroy the object if xHoldAlive decrement the refcount to 0
110*b1cdbd2cSJim Jagielski 				return;
111*b1cdbd2cSJim Jagielski 			}
112*b1cdbd2cSJim Jagielski 		}
113*b1cdbd2cSJim Jagielski 		// restore the reference count
114*b1cdbd2cSJim Jagielski 		osl_incrementInterlockedCount( &m_refCount );
115*b1cdbd2cSJim Jagielski 	}
116*b1cdbd2cSJim Jagielski 	OWeakAggObject::release();
117*b1cdbd2cSJim Jagielski }
118*b1cdbd2cSJim Jagielski 
getTypes()119*b1cdbd2cSJim Jagielski Sequence< Type > OComponentHelper::getTypes() throw (RuntimeException)
120*b1cdbd2cSJim Jagielski {
121*b1cdbd2cSJim Jagielski 	static OTypeCollection * s_pTypes = 0;
122*b1cdbd2cSJim Jagielski 	if (! s_pTypes)
123*b1cdbd2cSJim Jagielski 	{
124*b1cdbd2cSJim Jagielski 		MutexGuard aGuard( Mutex::getGlobalMutex() );
125*b1cdbd2cSJim Jagielski 		if (! s_pTypes)
126*b1cdbd2cSJim Jagielski 		{
127*b1cdbd2cSJim Jagielski 			static OTypeCollection s_aTypes(
128*b1cdbd2cSJim Jagielski 				::getCppuType( (const Reference< lang::XComponent > *)0 ),
129*b1cdbd2cSJim Jagielski 				::getCppuType( (const Reference< lang::XTypeProvider > *)0 ),
130*b1cdbd2cSJim Jagielski 				::getCppuType( (const Reference< XAggregation > *)0 ),
131*b1cdbd2cSJim Jagielski 				::getCppuType( (const Reference< XWeak > *)0 ) );
132*b1cdbd2cSJim Jagielski 			s_pTypes = &s_aTypes;
133*b1cdbd2cSJim Jagielski 		}
134*b1cdbd2cSJim Jagielski 	}
135*b1cdbd2cSJim Jagielski 	return s_pTypes->getTypes();
136*b1cdbd2cSJim Jagielski }
137*b1cdbd2cSJim Jagielski 
138*b1cdbd2cSJim Jagielski // XComponent
disposing()139*b1cdbd2cSJim Jagielski void OComponentHelper::disposing()
140*b1cdbd2cSJim Jagielski {
141*b1cdbd2cSJim Jagielski }
142*b1cdbd2cSJim Jagielski 
143*b1cdbd2cSJim Jagielski // XComponent
dispose()144*b1cdbd2cSJim Jagielski void OComponentHelper::dispose()
145*b1cdbd2cSJim Jagielski 	throw(::com::sun::star::uno::RuntimeException)
146*b1cdbd2cSJim Jagielski {
147*b1cdbd2cSJim Jagielski 	// An frequently programming error is to release the last
148*b1cdbd2cSJim Jagielski 	// reference to this object in the disposing message.
149*b1cdbd2cSJim Jagielski 	// Make it rubust, hold a self Reference.
150*b1cdbd2cSJim Jagielski 	Reference<XComponent > xSelf( this );
151*b1cdbd2cSJim Jagielski 
152*b1cdbd2cSJim Jagielski 	// Guard dispose against multible threading
153*b1cdbd2cSJim Jagielski 	// Remark: It is an error to call dispose more than once
154*b1cdbd2cSJim Jagielski 	sal_Bool bDoDispose = sal_False;
155*b1cdbd2cSJim Jagielski 	{
156*b1cdbd2cSJim Jagielski 	MutexGuard aGuard( rBHelper.rMutex );
157*b1cdbd2cSJim Jagielski 	if( !rBHelper.bDisposed && !rBHelper.bInDispose )
158*b1cdbd2cSJim Jagielski 	{
159*b1cdbd2cSJim Jagielski 		// only one call go into this section
160*b1cdbd2cSJim Jagielski 		rBHelper.bInDispose = sal_True;
161*b1cdbd2cSJim Jagielski 		bDoDispose = sal_True;
162*b1cdbd2cSJim Jagielski 	}
163*b1cdbd2cSJim Jagielski 	}
164*b1cdbd2cSJim Jagielski 
165*b1cdbd2cSJim Jagielski 	// Do not hold the mutex because we are broadcasting
166*b1cdbd2cSJim Jagielski 	if( bDoDispose )
167*b1cdbd2cSJim Jagielski 	{
168*b1cdbd2cSJim Jagielski 		// Create an event with this as sender
169*b1cdbd2cSJim Jagielski 		try
170*b1cdbd2cSJim Jagielski 		{
171*b1cdbd2cSJim Jagielski             try
172*b1cdbd2cSJim Jagielski             {
173*b1cdbd2cSJim Jagielski                 Reference<XInterface > xSource(
174*b1cdbd2cSJim Jagielski                     Reference<XInterface >::query( (XComponent *)this ) );
175*b1cdbd2cSJim Jagielski                 EventObject aEvt;
176*b1cdbd2cSJim Jagielski                 aEvt.Source = xSource;
177*b1cdbd2cSJim Jagielski                 // inform all listeners to release this object
178*b1cdbd2cSJim Jagielski                 // The listener container are automaticly cleared
179*b1cdbd2cSJim Jagielski                 rBHelper.aLC.disposeAndClear( aEvt );
180*b1cdbd2cSJim Jagielski                 // notify subclasses to do their dispose
181*b1cdbd2cSJim Jagielski                 disposing();
182*b1cdbd2cSJim Jagielski             }
183*b1cdbd2cSJim Jagielski             catch (...)
184*b1cdbd2cSJim Jagielski             {
185*b1cdbd2cSJim Jagielski                 MutexGuard aGuard( rBHelper.rMutex );
186*b1cdbd2cSJim Jagielski                 // bDispose and bInDisposing must be set in this order:
187*b1cdbd2cSJim Jagielski                 rBHelper.bDisposed = sal_True;
188*b1cdbd2cSJim Jagielski                 rBHelper.bInDispose = sal_False;
189*b1cdbd2cSJim Jagielski                 throw;
190*b1cdbd2cSJim Jagielski             }
191*b1cdbd2cSJim Jagielski             MutexGuard aGuard( rBHelper.rMutex );
192*b1cdbd2cSJim Jagielski             // bDispose and bInDisposing must be set in this order:
193*b1cdbd2cSJim Jagielski             rBHelper.bDisposed = sal_True;
194*b1cdbd2cSJim Jagielski             rBHelper.bInDispose = sal_False;
195*b1cdbd2cSJim Jagielski 		}
196*b1cdbd2cSJim Jagielski 		catch (RuntimeException &)
197*b1cdbd2cSJim Jagielski 		{
198*b1cdbd2cSJim Jagielski 			throw;
199*b1cdbd2cSJim Jagielski 		}
200*b1cdbd2cSJim Jagielski 		catch (Exception & exc)
201*b1cdbd2cSJim Jagielski 		{
202*b1cdbd2cSJim Jagielski             throw RuntimeException(
203*b1cdbd2cSJim Jagielski                 OUString( RTL_CONSTASCII_USTRINGPARAM(
204*b1cdbd2cSJim Jagielski                               "unexpected UNO exception caught: ") ) +
205*b1cdbd2cSJim Jagielski                 exc.Message, Reference< XInterface >() );
206*b1cdbd2cSJim Jagielski 		}
207*b1cdbd2cSJim Jagielski 	}
208*b1cdbd2cSJim Jagielski 	else
209*b1cdbd2cSJim Jagielski 	{
210*b1cdbd2cSJim Jagielski 		// in a multithreaded environment, it can't be avoided,
211*b1cdbd2cSJim Jagielski 		// that dispose is called twice.
212*b1cdbd2cSJim Jagielski 		// However this condition is traced, because it MAY indicate an error.
213*b1cdbd2cSJim Jagielski 		OSL_TRACE( "OComponentHelper::dispose() - dispose called twice" );
214*b1cdbd2cSJim Jagielski 	}
215*b1cdbd2cSJim Jagielski }
216*b1cdbd2cSJim Jagielski 
217*b1cdbd2cSJim Jagielski // XComponent
addEventListener(const Reference<XEventListener> & rxListener)218*b1cdbd2cSJim Jagielski void OComponentHelper::addEventListener(
219*b1cdbd2cSJim Jagielski 	const Reference<XEventListener > & rxListener )
220*b1cdbd2cSJim Jagielski 	throw(::com::sun::star::uno::RuntimeException)
221*b1cdbd2cSJim Jagielski {
222*b1cdbd2cSJim Jagielski 	ClearableMutexGuard aGuard( rBHelper.rMutex );
223*b1cdbd2cSJim Jagielski 	if (rBHelper.bDisposed || rBHelper.bInDispose)
224*b1cdbd2cSJim Jagielski 	{
225*b1cdbd2cSJim Jagielski         aGuard.clear();
226*b1cdbd2cSJim Jagielski         Reference< XInterface > x( (XComponent *)this, UNO_QUERY );
227*b1cdbd2cSJim Jagielski 		rxListener->disposing( EventObject( x ) );
228*b1cdbd2cSJim Jagielski 	}
229*b1cdbd2cSJim Jagielski 	else
230*b1cdbd2cSJim Jagielski 	{
231*b1cdbd2cSJim Jagielski 		rBHelper.addListener( ::getCppuType( &rxListener ) , rxListener );
232*b1cdbd2cSJim Jagielski 	}
233*b1cdbd2cSJim Jagielski }
234*b1cdbd2cSJim Jagielski 
235*b1cdbd2cSJim Jagielski // XComponent
removeEventListener(const Reference<XEventListener> & rxListener)236*b1cdbd2cSJim Jagielski void OComponentHelper::removeEventListener(
237*b1cdbd2cSJim Jagielski 	const Reference<XEventListener > & rxListener )
238*b1cdbd2cSJim Jagielski 	throw(::com::sun::star::uno::RuntimeException)
239*b1cdbd2cSJim Jagielski {
240*b1cdbd2cSJim Jagielski 	rBHelper.removeListener( ::getCppuType( &rxListener ) , rxListener );
241*b1cdbd2cSJim Jagielski }
242*b1cdbd2cSJim Jagielski 
243*b1cdbd2cSJim Jagielski }
244*b1cdbd2cSJim Jagielski 
245