| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_cppuhelper.hxx" |
| #include <cppuhelper/implbase.hxx> |
| #include <cppuhelper/compbase.hxx> |
| #include <osl/diagnose.h> |
| #include <rtl/uuid.h> |
| |
| #include <com/sun/star/lang/XComponent.hpp> |
| #include "com/sun/star/uno/RuntimeException.hpp" |
| |
| using namespace ::osl; |
| using namespace ::rtl; |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::uno; |
| |
| namespace cppu |
| { |
| //================================================================================================== |
| Mutex & SAL_CALL getImplHelperInitMutex(void) SAL_THROW( () ) |
| { |
| static Mutex * s_pMutex = 0; |
| if (! s_pMutex) |
| { |
| MutexGuard aGuard( Mutex::getGlobalMutex() ); |
| if (! s_pMutex) |
| { |
| static Mutex s_aMutex; |
| s_pMutex = & s_aMutex; |
| } |
| } |
| return * s_pMutex; |
| } |
| |
| // ClassDataBase |
| //__________________________________________________________________________________________________ |
| ClassDataBase::ClassDataBase() SAL_THROW( () ) |
| : bOffsetsInit( sal_False ) |
| , nType2Offset( 0 ) |
| , nClassCode( 0 ) |
| , pTypes( 0 ) |
| , pId( 0 ) |
| { |
| } |
| //__________________________________________________________________________________________________ |
| ClassDataBase::ClassDataBase( sal_Int32 nClassCode_ ) SAL_THROW( () ) |
| : bOffsetsInit( sal_False ) |
| , nType2Offset( 0 ) |
| , nClassCode( nClassCode_ ) |
| , pTypes( 0 ) |
| , pId( 0 ) |
| { |
| } |
| //__________________________________________________________________________________________________ |
| ClassDataBase::~ClassDataBase() SAL_THROW( () ) |
| { |
| delete pTypes; |
| delete pId; |
| |
| for ( sal_Int32 nPos = nType2Offset; nPos--; ) |
| { |
| typelib_typedescription_release( |
| (typelib_TypeDescription *)((ClassData *)this)->arType2Offset[nPos].pTD ); |
| } |
| } |
| |
| // ClassData |
| //__________________________________________________________________________________________________ |
| void ClassData::writeTypeOffset( const Type & rType, sal_Int32 nOffset ) SAL_THROW( () ) |
| { |
| arType2Offset[nType2Offset].nOffset = nOffset; |
| |
| arType2Offset[nType2Offset].pTD = 0; |
| typelib_typedescriptionreference_getDescription( |
| (typelib_TypeDescription **)&arType2Offset[nType2Offset].pTD, rType.getTypeLibType() ); |
| |
| if (arType2Offset[nType2Offset].pTD) |
| ++nType2Offset; |
| #if OSL_DEBUG_LEVEL > 1 |
| else |
| { |
| OString msg( "### cannot get type description for " ); |
| msg += OUStringToOString( rType.getTypeName(), RTL_TEXTENCODING_ASCII_US ); |
| OSL_ENSURE( sal_False, msg.getStr() ); |
| } |
| #endif |
| } |
| //__________________________________________________________________________________________________ |
| void ClassData::initTypeProvider() SAL_THROW( () ) |
| { |
| ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); |
| if (! pTypes) |
| { |
| // create id |
| pId = new Sequence< sal_Int8 >( 16 ); |
| rtl_createUuid( (sal_uInt8 *)pId->getArray(), 0, sal_True ); |
| |
| // collect types |
| Sequence< Type > * types = new Sequence< Type >( |
| nType2Offset + 1 + (nClassCode == 4 ? 2 : nClassCode) ); |
| Type * pTypeAr = types->getArray(); |
| |
| // given types |
| sal_Int32 nPos = nType2Offset; |
| while (nPos--) |
| pTypeAr[nPos] = ((typelib_TypeDescription *)arType2Offset[nPos].pTD)->pWeakRef; |
| |
| // XTypeProvider |
| pTypeAr[nType2Offset] = ::getCppuType( (const Reference< lang::XTypeProvider > *)0 ); |
| |
| // class code extra types: [[XComponent,] XWeak[, XAggregation]] |
| switch (nClassCode) |
| { |
| case 4: |
| pTypeAr[nType2Offset +2] = ::getCppuType( (const Reference< lang::XComponent > *)0 ); |
| pTypeAr[nType2Offset +1] = ::getCppuType( (const Reference< XWeak > *)0 ); |
| break; |
| case 3: |
| pTypeAr[nType2Offset +3] = ::getCppuType( (const Reference< lang::XComponent > *)0 ); |
| case 2: |
| pTypeAr[nType2Offset +2] = ::getCppuType( (const Reference< XAggregation > *)0 ); |
| case 1: |
| pTypeAr[nType2Offset +1] = ::getCppuType( (const Reference< XWeak > *)0 ); |
| } |
| |
| pTypes = types; |
| } |
| } |
| //__________________________________________________________________________________________________ |
| Sequence< Type > ClassData::getTypes() SAL_THROW( () ) |
| { |
| if (! pTypes) |
| initTypeProvider(); |
| return *pTypes; |
| } |
| //__________________________________________________________________________________________________ |
| Sequence< sal_Int8 > ClassData::getImplementationId() SAL_THROW( () ) |
| { |
| if (! pTypes) |
| initTypeProvider(); |
| return *pId; |
| } |
| |
| //-------------------------------------------------------------------------------------------------- |
| static inline sal_Bool td_equals( |
| typelib_TypeDescription * pTD, typelib_TypeDescriptionReference * pType ) |
| SAL_THROW( () ) |
| { |
| return (pTD->pWeakRef == pType || |
| (pTD->pTypeName->length == pType->pTypeName->length && |
| rtl_ustr_compare( pTD->pTypeName->buffer, pType->pTypeName->buffer ) == 0)); |
| } |
| //__________________________________________________________________________________________________ |
| Any ClassData::query( const Type & rType, lang::XTypeProvider * pBase ) SAL_THROW( () ) |
| { |
| if (rType == ::getCppuType( (const Reference< XInterface > *)0 )) |
| return Any( &pBase, ::getCppuType( (const Reference< XInterface > *)0 ) ); |
| for ( sal_Int32 nPos = 0; nPos < nType2Offset; ++nPos ) |
| { |
| const Type_Offset & rTO = arType2Offset[nPos]; |
| typelib_InterfaceTypeDescription * pTD = rTO.pTD; |
| while (pTD) |
| { |
| if (td_equals( (typelib_TypeDescription *)pTD, |
| *(typelib_TypeDescriptionReference **)&rType )) |
| { |
| void * pInterface = (char *)pBase + rTO.nOffset; |
| return Any( &pInterface, (typelib_TypeDescription *)pTD ); |
| } |
| pTD = pTD->pBaseTypeDescription; |
| } |
| } |
| if (rType == ::getCppuType( (const Reference< lang::XTypeProvider > *)0 )) |
| return Any( &pBase, ::getCppuType( (const Reference< lang::XTypeProvider > *)0 ) ); |
| |
| return Any(); |
| } |
| |
| //################################################################################################## |
| //################################################################################################## |
| //################################################################################################## |
| |
| // WeakComponentImplHelperBase |
| //__________________________________________________________________________________________________ |
| WeakComponentImplHelperBase::WeakComponentImplHelperBase( Mutex & rMutex ) |
| SAL_THROW( () ) |
| : rBHelper( rMutex ) |
| { |
| } |
| //__________________________________________________________________________________________________ |
| WeakComponentImplHelperBase::~WeakComponentImplHelperBase() |
| SAL_THROW( () ) |
| { |
| } |
| //__________________________________________________________________________________________________ |
| void WeakComponentImplHelperBase::disposing() |
| { |
| } |
| //__________________________________________________________________________________________________ |
| Any WeakComponentImplHelperBase::queryInterface( Type const & rType ) |
| throw (RuntimeException) |
| { |
| if (rType == ::getCppuType( (Reference< lang::XComponent > const *)0 )) |
| { |
| void * p = static_cast< lang::XComponent * >( this ); |
| return Any( &p, rType ); |
| } |
| return OWeakObject::queryInterface( rType ); |
| } |
| //__________________________________________________________________________________________________ |
| void WeakComponentImplHelperBase::acquire() |
| throw () |
| { |
| OWeakObject::acquire(); |
| } |
| //__________________________________________________________________________________________________ |
| void WeakComponentImplHelperBase::release() |
| throw () |
| { |
| if (osl_decrementInterlockedCount( &m_refCount ) == 0) { |
| // ensure no other references are created, via the weak connection point, from now on |
| disposeWeakConnectionPoint(); |
| // restore reference count: |
| osl_incrementInterlockedCount( &m_refCount ); |
| if (! rBHelper.bDisposed) { |
| try { |
| dispose(); |
| } |
| catch (RuntimeException const& exc) { // don't break throw () |
| OSL_ENSURE( |
| false, OUStringToOString( |
| exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); |
| static_cast<void>(exc); |
| } |
| OSL_ASSERT( rBHelper.bDisposed ); |
| } |
| OWeakObject::release(); |
| } |
| } |
| //__________________________________________________________________________________________________ |
| void WeakComponentImplHelperBase::dispose() |
| throw (RuntimeException) |
| { |
| ClearableMutexGuard aGuard( rBHelper.rMutex ); |
| if (!rBHelper.bDisposed && !rBHelper.bInDispose) |
| { |
| rBHelper.bInDispose = sal_True; |
| aGuard.clear(); |
| try |
| { |
| // side effect: keeping a reference to this |
| lang::EventObject aEvt( static_cast< OWeakObject * >( this ) ); |
| try |
| { |
| rBHelper.aLC.disposeAndClear( aEvt ); |
| disposing(); |
| } |
| catch (...) |
| { |
| MutexGuard aGuard2( rBHelper.rMutex ); |
| // bDisposed and bInDispose must be set in this order: |
| rBHelper.bDisposed = sal_True; |
| rBHelper.bInDispose = sal_False; |
| throw; |
| } |
| MutexGuard aGuard2( rBHelper.rMutex ); |
| // bDisposed and bInDispose must be set in this order: |
| rBHelper.bDisposed = sal_True; |
| rBHelper.bInDispose = sal_False; |
| } |
| catch (RuntimeException &) |
| { |
| throw; |
| } |
| catch (Exception & exc) |
| { |
| throw RuntimeException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( |
| "unexpected UNO exception caught: ") ) + |
| exc.Message, Reference< XInterface >() ); |
| } |
| } |
| } |
| //__________________________________________________________________________________________________ |
| void WeakComponentImplHelperBase::addEventListener( |
| Reference< lang::XEventListener > const & xListener ) |
| throw (RuntimeException) |
| { |
| ClearableMutexGuard aGuard( rBHelper.rMutex ); |
| if (rBHelper.bDisposed || rBHelper.bInDispose) |
| { |
| aGuard.clear(); |
| lang::EventObject aEvt( static_cast< OWeakObject * >( this ) ); |
| xListener->disposing( aEvt ); |
| } |
| else |
| { |
| rBHelper.addListener( ::getCppuType( &xListener ), xListener ); |
| } |
| } |
| //__________________________________________________________________________________________________ |
| void WeakComponentImplHelperBase::removeEventListener( |
| Reference< lang::XEventListener > const & xListener ) |
| throw (RuntimeException) |
| { |
| rBHelper.removeListener( ::getCppuType( &xListener ), xListener ); |
| } |
| |
| // WeakAggComponentImplHelperBase |
| //__________________________________________________________________________________________________ |
| WeakAggComponentImplHelperBase::WeakAggComponentImplHelperBase( Mutex & rMutex ) |
| SAL_THROW( () ) |
| : rBHelper( rMutex ) |
| { |
| } |
| //__________________________________________________________________________________________________ |
| WeakAggComponentImplHelperBase::~WeakAggComponentImplHelperBase() |
| SAL_THROW( () ) |
| { |
| } |
| //__________________________________________________________________________________________________ |
| void WeakAggComponentImplHelperBase::disposing() |
| { |
| } |
| //__________________________________________________________________________________________________ |
| Any WeakAggComponentImplHelperBase::queryInterface( Type const & rType ) |
| throw (RuntimeException) |
| { |
| return OWeakAggObject::queryInterface( rType ); |
| } |
| //__________________________________________________________________________________________________ |
| Any WeakAggComponentImplHelperBase::queryAggregation( Type const & rType ) |
| throw (RuntimeException) |
| { |
| if (rType == ::getCppuType( (Reference< lang::XComponent > const *)0 )) |
| { |
| void * p = static_cast< lang::XComponent * >( this ); |
| return Any( &p, rType ); |
| } |
| return OWeakAggObject::queryAggregation( rType ); |
| } |
| //__________________________________________________________________________________________________ |
| void WeakAggComponentImplHelperBase::acquire() |
| throw () |
| { |
| OWeakAggObject::acquire(); |
| } |
| //__________________________________________________________________________________________________ |
| void WeakAggComponentImplHelperBase::release() |
| throw () |
| { |
| Reference<XInterface> const xDelegator_(xDelegator); |
| if (xDelegator_.is()) { |
| OWeakAggObject::release(); |
| } |
| else if (osl_decrementInterlockedCount( &m_refCount ) == 0) { |
| // ensure no other references are created, via the weak connection point, from now on |
| disposeWeakConnectionPoint(); |
| // restore reference count: |
| osl_incrementInterlockedCount( &m_refCount ); |
| if (! rBHelper.bDisposed) { |
| try { |
| dispose(); |
| } |
| catch (RuntimeException const& exc) { // don't break throw () |
| OSL_ENSURE( |
| false, OUStringToOString( |
| exc.Message, RTL_TEXTENCODING_ASCII_US ).getStr() ); |
| static_cast<void>(exc); |
| } |
| OSL_ASSERT( rBHelper.bDisposed ); |
| } |
| OWeakAggObject::release(); |
| } |
| } |
| //__________________________________________________________________________________________________ |
| void WeakAggComponentImplHelperBase::dispose() |
| throw (RuntimeException) |
| { |
| ClearableMutexGuard aGuard( rBHelper.rMutex ); |
| if (!rBHelper.bDisposed && !rBHelper.bInDispose) |
| { |
| rBHelper.bInDispose = sal_True; |
| aGuard.clear(); |
| try |
| { |
| // side effect: keeping a reference to this |
| lang::EventObject aEvt( static_cast< OWeakObject * >( this ) ); |
| try |
| { |
| rBHelper.aLC.disposeAndClear( aEvt ); |
| disposing(); |
| } |
| catch (...) |
| { |
| MutexGuard aGuard2( rBHelper.rMutex ); |
| // bDisposed and bInDispose must be set in this order: |
| rBHelper.bDisposed = sal_True; |
| rBHelper.bInDispose = sal_False; |
| throw; |
| } |
| MutexGuard aGuard2( rBHelper.rMutex ); |
| // bDisposed and bInDispose must be set in this order: |
| rBHelper.bDisposed = sal_True; |
| rBHelper.bInDispose = sal_False; |
| } |
| catch (RuntimeException &) |
| { |
| throw; |
| } |
| catch (Exception & exc) |
| { |
| throw RuntimeException( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( |
| "unexpected UNO exception caught: ") ) + |
| exc.Message, Reference< XInterface >() ); |
| } |
| } |
| } |
| //__________________________________________________________________________________________________ |
| void WeakAggComponentImplHelperBase::addEventListener( |
| Reference< lang::XEventListener > const & xListener ) |
| throw (RuntimeException) |
| { |
| ClearableMutexGuard aGuard( rBHelper.rMutex ); |
| if (rBHelper.bDisposed || rBHelper.bInDispose) |
| { |
| aGuard.clear(); |
| lang::EventObject aEvt( static_cast< OWeakObject * >( this ) ); |
| xListener->disposing( aEvt ); |
| } |
| else |
| { |
| rBHelper.addListener( ::getCppuType( &xListener ), xListener ); |
| } |
| } |
| //__________________________________________________________________________________________________ |
| void WeakAggComponentImplHelperBase::removeEventListener( |
| Reference< lang::XEventListener > const & xListener ) |
| throw (RuntimeException) |
| { |
| rBHelper.removeListener( ::getCppuType( &xListener ), xListener ); |
| } |
| |
| } |