xref: /trunk/main/cppuhelper/source/component.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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