xref: /trunk/main/cppuhelper/source/component.cxx (revision cdf0e10c)
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_cppuhelper.hxx"
30 #include <rtl/string.hxx>
31 #include <osl/diagnose.h>
32 #include <cppuhelper/component.hxx>
33 #include <cppuhelper/queryinterface.hxx>
34 #include <cppuhelper/typeprovider.hxx>
35 #include "com/sun/star/uno/RuntimeException.hpp"
36 
37 using namespace osl;
38 using namespace rtl;
39 using namespace com::sun::star;
40 using namespace com::sun::star::uno;
41 using namespace com::sun::star::lang;
42 
43 namespace cppu
44 {
45 
46 //	----------------------------------------------------
47 //	class OComponentHelper
48 //	----------------------------------------------------
49 
50 OComponentHelper::OComponentHelper( Mutex & rMutex ) SAL_THROW( () )
51 	: rBHelper( rMutex )
52 {
53 }
54 OComponentHelper::~OComponentHelper() SAL_THROW( (RuntimeException) )
55 {
56 }
57 
58 Any OComponentHelper::queryInterface( Type const & rType ) throw (RuntimeException)
59 {
60     return OWeakAggObject::queryInterface( rType );
61 }
62 Any OComponentHelper::queryAggregation( Type const & rType ) throw (RuntimeException)
63 {
64     if (rType == ::getCppuType( (Reference< lang::XComponent > const *)0 ))
65     {
66         void * p = static_cast< lang::XComponent * >( this );
67         return Any( &p, rType );
68     }
69     else if (rType == ::getCppuType( (Reference< lang::XTypeProvider > const *)0 ))
70     {
71         void * p = static_cast< lang::XTypeProvider * >( this );
72         return Any( &p, rType );
73     }
74     return OWeakAggObject::queryAggregation( rType );
75 }
76 void OComponentHelper::acquire() throw ()
77 {
78 	OWeakAggObject::acquire();
79 }
80 
81 void OComponentHelper::release() throw()
82 {
83 	Reference<XInterface > x( xDelegator );
84 	if (! x.is())
85 	{
86 		if (osl_decrementInterlockedCount( &m_refCount ) == 0)
87 		{
88 			if (! rBHelper.bDisposed)
89 			{
90                 // *before* again incrementing our ref count, ensure that our weak connection point
91                 // will not create references to us anymore (via XAdapter::queryAdapted)
92                 disposeWeakConnectionPoint();
93 
94 				Reference<XInterface > xHoldAlive( *this );
95 				// First dispose
96 				try
97 				{
98 					dispose();
99 				}
100 				catch (::com::sun::star::uno::RuntimeException & exc)
101 				{
102 					// release should not throw exceptions
103 #if OSL_DEBUG_LEVEL > 0
104                     OString msg( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) );
105                     OSL_ENSURE( 0, msg.getStr() );
106 #else
107                     (void) exc; // avoid warning about unused variable
108 #endif
109 				}
110 
111 				// only the alive ref holds the object
112 				OSL_ASSERT( m_refCount == 1 );
113 				// destroy the object if xHoldAlive decrement the refcount to 0
114 				return;
115 			}
116 		}
117 		// restore the reference count
118 		osl_incrementInterlockedCount( &m_refCount );
119 	}
120 	OWeakAggObject::release();
121 }
122 
123 Sequence< Type > OComponentHelper::getTypes() throw (RuntimeException)
124 {
125 	static OTypeCollection * s_pTypes = 0;
126 	if (! s_pTypes)
127 	{
128 		MutexGuard aGuard( Mutex::getGlobalMutex() );
129 		if (! s_pTypes)
130 		{
131 			static OTypeCollection s_aTypes(
132 				::getCppuType( (const Reference< lang::XComponent > *)0 ),
133 				::getCppuType( (const Reference< lang::XTypeProvider > *)0 ),
134 				::getCppuType( (const Reference< XAggregation > *)0 ),
135 				::getCppuType( (const Reference< XWeak > *)0 ) );
136 			s_pTypes = &s_aTypes;
137 		}
138 	}
139 	return s_pTypes->getTypes();
140 }
141 
142 // XComponent
143 void OComponentHelper::disposing()
144 {
145 }
146 
147 // XComponent
148 void OComponentHelper::dispose()
149 	throw(::com::sun::star::uno::RuntimeException)
150 {
151 	// An frequently programming error is to release the last
152 	// reference to this object in the disposing message.
153 	// Make it rubust, hold a self Reference.
154 	Reference<XComponent > xSelf( this );
155 
156 	// Guard dispose against multible threading
157 	// Remark: It is an error to call dispose more than once
158 	sal_Bool bDoDispose = sal_False;
159 	{
160 	MutexGuard aGuard( rBHelper.rMutex );
161 	if( !rBHelper.bDisposed && !rBHelper.bInDispose )
162 	{
163 		// only one call go into this section
164 		rBHelper.bInDispose = sal_True;
165 		bDoDispose = sal_True;
166 	}
167 	}
168 
169 	// Do not hold the mutex because we are broadcasting
170 	if( bDoDispose )
171 	{
172 		// Create an event with this as sender
173 		try
174 		{
175             try
176             {
177                 Reference<XInterface > xSource(
178                     Reference<XInterface >::query( (XComponent *)this ) );
179                 EventObject aEvt;
180                 aEvt.Source = xSource;
181                 // inform all listeners to release this object
182                 // The listener container are automaticly cleared
183                 rBHelper.aLC.disposeAndClear( aEvt );
184                 // notify subclasses to do their dispose
185                 disposing();
186             }
187             catch (...)
188             {
189                 MutexGuard aGuard( rBHelper.rMutex );
190                 // bDispose and bInDisposing must be set in this order:
191                 rBHelper.bDisposed = sal_True;
192                 rBHelper.bInDispose = sal_False;
193                 throw;
194             }
195             MutexGuard aGuard( rBHelper.rMutex );
196             // bDispose and bInDisposing must be set in this order:
197             rBHelper.bDisposed = sal_True;
198             rBHelper.bInDispose = sal_False;
199 		}
200 		catch (RuntimeException &)
201 		{
202 			throw;
203 		}
204 		catch (Exception & exc)
205 		{
206             throw RuntimeException(
207                 OUString( RTL_CONSTASCII_USTRINGPARAM(
208                               "unexpected UNO exception caught: ") ) +
209                 exc.Message, Reference< XInterface >() );
210 		}
211 	}
212 	else
213 	{
214 		// in a multithreaded environment, it can't be avoided,
215 		// that dispose is called twice.
216 		// However this condition is traced, because it MAY indicate an error.
217 		OSL_TRACE( "OComponentHelper::dispose() - dispose called twice" );
218 	}
219 }
220 
221 // XComponent
222 void OComponentHelper::addEventListener(
223 	const Reference<XEventListener > & rxListener )
224 	throw(::com::sun::star::uno::RuntimeException)
225 {
226 	ClearableMutexGuard aGuard( rBHelper.rMutex );
227 	if (rBHelper.bDisposed || rBHelper.bInDispose)
228 	{
229         aGuard.clear();
230         Reference< XInterface > x( (XComponent *)this, UNO_QUERY );
231 		rxListener->disposing( EventObject( x ) );
232 	}
233 	else
234 	{
235 		rBHelper.addListener( ::getCppuType( &rxListener ) , rxListener );
236 	}
237 }
238 
239 // XComponent
240 void OComponentHelper::removeEventListener(
241 	const Reference<XEventListener > & rxListener )
242 	throw(::com::sun::star::uno::RuntimeException)
243 {
244 	rBHelper.removeListener( ::getCppuType( &rxListener ) , rxListener );
245 }
246 
247 }
248 
249