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