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