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