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