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