1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <sal/config.h> 21 22 #include <cassert> 23 24 #include <comphelper/proxyaggregation.hxx> 25 #include <com/sun/star/reflection/ProxyFactory.hpp> 26 27 28 namespace comphelper 29 { 30 31 32 using namespace ::com::sun::star::uno; 33 using namespace ::com::sun::star::lang; 34 using namespace ::com::sun::star::reflection; 35 OProxyAggregation(const Reference<XComponentContext> & _rxContext)36 OProxyAggregation::OProxyAggregation( const Reference< XComponentContext >& _rxContext ) 37 :m_xContext( _rxContext ) 38 { 39 } 40 41 baseAggregateProxyFor(const Reference<XInterface> & _rxComponent,oslInterlockedCount & _rRefCount,::cppu::OWeakObject & _rDelegator)42 void OProxyAggregation::baseAggregateProxyFor( const Reference< XInterface >& _rxComponent, oslInterlockedCount& _rRefCount, 43 ::cppu::OWeakObject& _rDelegator ) 44 { 45 // first a factory for the proxy 46 Reference< XProxyFactory > xFactory = ProxyFactory::create( m_xContext ); 47 48 // then the proxy itself 49 { // i36686 OJ: achieve the destruction of the temporary -> otherwise it leads to _rRefCount -= 2 50 m_xProxyAggregate = xFactory->createProxy( _rxComponent ); 51 } 52 if ( m_xProxyAggregate.is() ) 53 m_xProxyAggregate->queryAggregation( cppu::UnoType<decltype(m_xProxyTypeAccess)>::get() ) >>= m_xProxyTypeAccess; 54 55 // aggregate the proxy 56 osl_atomic_increment( &_rRefCount ); 57 if ( m_xProxyAggregate.is() ) 58 { 59 // At this point in time, the proxy has a ref count of exactly two - in m_xControlContextProxy, 60 // and in m_xProxyTypeAccess. 61 // Remember to _not_ reset these members unless the delegator of the proxy has been reset, too! 62 m_xProxyAggregate->setDelegator( _rDelegator ); 63 } 64 osl_atomic_decrement( &_rRefCount ); 65 } 66 67 queryAggregation(const Type & _rType)68 Any SAL_CALL OProxyAggregation::queryAggregation( const Type& _rType ) 69 { 70 return m_xProxyAggregate.is() ? m_xProxyAggregate->queryAggregation( _rType ) : Any(); 71 } 72 73 getTypes()74 Sequence< Type > SAL_CALL OProxyAggregation::getTypes( ) 75 { 76 Sequence< Type > aTypes; 77 if ( m_xProxyAggregate.is() ) 78 { 79 if ( m_xProxyTypeAccess.is() ) 80 aTypes = m_xProxyTypeAccess->getTypes(); 81 } 82 return aTypes; 83 } 84 85 ~OProxyAggregation()86 OProxyAggregation::~OProxyAggregation() 87 { 88 if ( m_xProxyAggregate.is() ) 89 m_xProxyAggregate->setDelegator( nullptr ); 90 m_xProxyAggregate.clear(); 91 m_xProxyTypeAccess.clear(); 92 // this should remove the _two_only_ "real" references (means not delegated to 93 // ourself) to this proxy, and thus delete it 94 } 95 OComponentProxyAggregationHelper(const Reference<XComponentContext> & _rxContext,::cppu::OBroadcastHelper & _rBHelper)96 OComponentProxyAggregationHelper::OComponentProxyAggregationHelper( const Reference< XComponentContext >& _rxContext, 97 ::cppu::OBroadcastHelper& _rBHelper ) 98 :OProxyAggregation( _rxContext ) 99 ,m_rBHelper( _rBHelper ) 100 { 101 OSL_ENSURE( _rxContext.is(), "OComponentProxyAggregationHelper::OComponentProxyAggregationHelper: invalid arguments!" ); 102 } 103 104 componentAggregateProxyFor(const Reference<XComponent> & _rxComponent,oslInterlockedCount & _rRefCount,::cppu::OWeakObject & _rDelegator)105 void OComponentProxyAggregationHelper::componentAggregateProxyFor( 106 const Reference< XComponent >& _rxComponent, oslInterlockedCount& _rRefCount, 107 ::cppu::OWeakObject& _rDelegator ) 108 { 109 OSL_ENSURE( _rxComponent.is(), "OComponentProxyAggregationHelper::componentAggregateProxyFor: invalid inner component!" ); 110 m_xInner = _rxComponent; 111 112 // aggregate a proxy for the object 113 baseAggregateProxyFor( m_xInner, _rRefCount, _rDelegator ); 114 115 // add as event listener to the inner context, because we want to be notified of disposals 116 osl_atomic_increment( &_rRefCount ); 117 { 118 if ( m_xInner.is() ) 119 m_xInner->addEventListener( this ); 120 } 121 osl_atomic_decrement( &_rRefCount ); 122 } 123 124 queryInterface(const Type & _rType)125 Any SAL_CALL OComponentProxyAggregationHelper::queryInterface( const Type& _rType ) 126 { 127 Any aReturn( BASE::queryInterface( _rType ) ); 128 if ( !aReturn.hasValue() ) 129 aReturn = OProxyAggregation::queryAggregation( _rType ); 130 return aReturn; 131 } 132 133 IMPLEMENT_FORWARD_XTYPEPROVIDER2(OComponentProxyAggregationHelper,BASE,OProxyAggregation)134 IMPLEMENT_FORWARD_XTYPEPROVIDER2( OComponentProxyAggregationHelper, BASE, OProxyAggregation ) 135 136 137 OComponentProxyAggregationHelper::~OComponentProxyAggregationHelper( ) 138 { 139 OSL_ENSURE( m_rBHelper.bDisposed, "OComponentProxyAggregationHelper::~OComponentProxyAggregationHelper: you should dispose your derived class in the dtor, if necessary!" ); 140 // if this asserts, add the following to your derived class dtor: 141 142 // if ( !m_rBHelper.bDisposed ) 143 // { 144 // acquire(); // to prevent duplicate dtor calls 145 // dispose(); 146 // } 147 148 m_xInner.clear(); 149 } 150 151 disposing(const EventObject & _rSource)152 void SAL_CALL OComponentProxyAggregationHelper::disposing( const EventObject& _rSource ) 153 { 154 if ( _rSource.Source == m_xInner ) 155 { // it's our inner context which is dying -> dispose ourself 156 if ( !m_rBHelper.bDisposed && !m_rBHelper.bInDispose ) 157 { // (if necessary only, of course) 158 dispose(); 159 } 160 } 161 } 162 163 dispose()164 void SAL_CALL OComponentProxyAggregationHelper::dispose() 165 { 166 ::osl::MutexGuard aGuard( m_rBHelper.rMutex ); 167 168 // dispose our inner context 169 // before we do this, remove ourself as listener - else in disposing( EventObject ), we 170 // would dispose ourself a second time 171 if ( m_xInner.is() ) 172 { 173 m_xInner->removeEventListener( this ); 174 m_xInner->dispose(); 175 m_xInner.clear(); 176 } 177 } 178 OComponentProxyAggregation(const Reference<XComponentContext> & _rxContext,const Reference<XComponent> & _rxComponent)179 OComponentProxyAggregation::OComponentProxyAggregation( const Reference< XComponentContext >& _rxContext, 180 const Reference< XComponent >& _rxComponent ) 181 :WeakComponentImplHelperBase( m_aMutex ) 182 ,OComponentProxyAggregationHelper( _rxContext, rBHelper ) 183 { 184 OSL_ENSURE( _rxComponent.is(), "OComponentProxyAggregation::OComponentProxyAggregation: accessible is no XComponent!" ); 185 if ( _rxComponent.is() ) 186 componentAggregateProxyFor( _rxComponent, m_refCount, *this ); 187 } 188 189 ~OComponentProxyAggregation()190 OComponentProxyAggregation::~OComponentProxyAggregation() 191 { 192 if ( !rBHelper.bDisposed ) 193 { 194 acquire(); // to prevent duplicate dtor calls 195 dispose(); 196 } 197 } 198 199 IMPLEMENT_FORWARD_XINTERFACE2(OComponentProxyAggregation,WeakComponentImplHelperBase,OComponentProxyAggregationHelper)200 IMPLEMENT_FORWARD_XINTERFACE2( OComponentProxyAggregation, WeakComponentImplHelperBase, OComponentProxyAggregationHelper ) 201 202 203 IMPLEMENT_GET_IMPLEMENTATION_ID( OComponentProxyAggregation ) 204 205 206 Sequence< Type > SAL_CALL OComponentProxyAggregation::getTypes( ) 207 { 208 return comphelper::concatSequences( 209 OComponentProxyAggregationHelper::getTypes(), 210 // append XComponent, coming from WeakComponentImplHelperBase 211 Sequence { cppu::UnoType<XComponent>::get() }); 212 } 213 214 disposing(const EventObject & _rSource)215 void SAL_CALL OComponentProxyAggregation::disposing( const EventObject& _rSource ) 216 { 217 // Simply disambiguate---this is necessary for MSVC to distinguish 218 // "disposing(EventObject)" from "disposing()"; but it is also a good 219 // place to check for recursive calls that would be caused by an object 220 // being registered as an XEventListener at itself (cf. rhbz#928568): 221 assert(_rSource.Source != static_cast< cppu::OWeakObject * >(this)); 222 OComponentProxyAggregationHelper::disposing( _rSource ); 223 } 224 225 disposing()226 void SAL_CALL OComponentProxyAggregation::disposing() 227 { 228 // call the dispose-functionality of the base, which will dispose our aggregated component 229 OComponentProxyAggregationHelper::dispose(); 230 } 231 232 dispose()233 void SAL_CALL OComponentProxyAggregation::dispose() 234 { 235 // simply disambiguate 236 WeakComponentImplHelperBase::dispose(); 237 } 238 239 240 } // namespace comphelper 241 242 243 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 244