1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_unotools.hxx" 26 #include <unotools/sharedunocomponent.hxx> 27 #include <com/sun/star/lang/XComponent.hpp> 28 #include <com/sun/star/util/XCloseable.hpp> 29 #include <cppuhelper/implbase1.hxx> 30 #include <tools/debug.hxx> 31 32 //............................................................................ 33 namespace utl 34 { 35 //............................................................................ 36 37 using ::com::sun::star::uno::XInterface; 38 using ::com::sun::star::uno::Reference; 39 using ::com::sun::star::uno::Exception; 40 using ::com::sun::star::uno::UNO_QUERY; 41 using ::com::sun::star::uno::RuntimeException; 42 using ::com::sun::star::lang::XComponent; 43 using ::com::sun::star::lang::EventObject; 44 using ::com::sun::star::util::XCloseable; 45 using ::com::sun::star::util::XCloseListener; 46 using ::com::sun::star::util::CloseVetoException; 47 48 //======================================================================== 49 //= DisposableComponent 50 //======================================================================== 51 //------------------------------------------------------------------------ DisposableComponent(const Reference<XInterface> & _rxComponent)52 DisposableComponent::DisposableComponent( const Reference< XInterface >& _rxComponent ) 53 :m_xComponent( _rxComponent, UNO_QUERY ) 54 { 55 DBG_ASSERT( m_xComponent.is() || !_rxComponent.is(), "DisposableComponent::DisposableComponent: should be an XComponent!" ); 56 } 57 58 //------------------------------------------------------------------------ ~DisposableComponent()59 DisposableComponent::~DisposableComponent() 60 { 61 if ( m_xComponent.is() ) 62 { 63 try 64 { 65 m_xComponent->dispose(); 66 } 67 catch( const Exception& ) 68 { 69 OSL_ENSURE( sal_False, "DisposableComponent::~DisposableComponent: caught an exception!" ); 70 } 71 m_xComponent.clear(); 72 } 73 } 74 75 //======================================================================== 76 //= CloseableComponentImpl 77 //======================================================================== 78 DBG_NAME( CloseableComponentImpl ) 79 typedef ::cppu::WeakImplHelper1 < XCloseListener 80 > CloseableComponentImpl_Base; 81 class CloseableComponentImpl : public CloseableComponentImpl_Base 82 { 83 private: 84 Reference< XCloseable > m_xCloseable; 85 86 public: 87 CloseableComponentImpl( const Reference< XInterface >& _rxComponent ); 88 89 /** closes the component 90 91 @nofail 92 */ 93 void nf_closeComponent(); 94 95 protected: 96 virtual ~CloseableComponentImpl(); 97 98 // XCloseListener overridables 99 virtual void SAL_CALL queryClosing( const EventObject& Source, ::sal_Bool GetsOwnership ) throw (CloseVetoException, RuntimeException); 100 virtual void SAL_CALL notifyClosing( const EventObject& Source ) throw (RuntimeException); 101 102 // XEventListener overridables 103 virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); 104 105 private: 106 /** starts or stops being a CloseListener at the component 107 108 Only to be called upon construction of the instance, or when the component 109 is to be closed. 110 111 @nofail 112 */ 113 void impl_nf_switchListening( bool _bListen ); 114 115 116 private: 117 CloseableComponentImpl(); // never implemented 118 CloseableComponentImpl( const CloseableComponentImpl& ); // never implemented 119 CloseableComponentImpl& operator=( const CloseableComponentImpl& ); // never implemented 120 }; 121 122 //------------------------------------------------------------------------ CloseableComponentImpl(const Reference<XInterface> & _rxComponent)123 CloseableComponentImpl::CloseableComponentImpl( const Reference< XInterface >& _rxComponent ) 124 :m_xCloseable( _rxComponent, UNO_QUERY ) 125 { 126 DBG_CTOR( CloseableComponentImpl, NULL ); 127 DBG_ASSERT( m_xCloseable.is() || !_rxComponent.is(), "CloseableComponentImpl::CloseableComponentImpl: component is not an XCloseable!" ); 128 impl_nf_switchListening( true ); 129 } 130 //------------------------------------------------------------------------ ~CloseableComponentImpl()131 CloseableComponentImpl::~CloseableComponentImpl() 132 { 133 nf_closeComponent(); 134 DBG_DTOR( CloseableComponentImpl, NULL ); 135 } 136 137 //------------------------------------------------------------------------ nf_closeComponent()138 void CloseableComponentImpl::nf_closeComponent() 139 { 140 if ( !m_xCloseable.is() ) 141 // nothing to do 142 return; 143 144 // stop listening 145 impl_nf_switchListening( false ); 146 147 // close 148 try 149 { 150 m_xCloseable->close( sal_True ); 151 } 152 catch( const CloseVetoException& ) { /* fine */ } 153 catch( const Exception& ) 154 { 155 OSL_ENSURE( sal_False, "CloseableComponentImpl::nf_closeComponent: caught an unexpected exception!" ); 156 } 157 158 // reset 159 m_xCloseable.clear(); 160 } 161 162 //------------------------------------------------------------------------ impl_nf_switchListening(bool _bListen)163 void CloseableComponentImpl::impl_nf_switchListening( bool _bListen ) 164 { 165 if ( !m_xCloseable.is() ) 166 return; 167 168 try 169 { 170 if ( _bListen ) 171 m_xCloseable->addCloseListener( this ); 172 else 173 m_xCloseable->removeCloseListener( this ); 174 } 175 catch( const Exception& ) 176 { 177 OSL_ENSURE( sal_False, "CloseableComponentImpl::impl_nf_switchListening: caught an exception!" ); 178 } 179 } 180 181 //-------------------------------------------------------------------- queryClosing(const EventObject & Source,::sal_Bool)182 void SAL_CALL CloseableComponentImpl::queryClosing( const EventObject& 183 #ifdef DBG_UTIL 184 Source 185 #endif 186 , ::sal_Bool /*GetsOwnership*/ ) throw (CloseVetoException, RuntimeException) 187 { 188 // as long as we live, somebody wants to keep the object alive. So, veto the 189 // closing 190 DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::queryClosing: where did this come from?" ); 191 throw CloseVetoException(); 192 } 193 194 //-------------------------------------------------------------------- notifyClosing(const EventObject & Source)195 void SAL_CALL CloseableComponentImpl::notifyClosing( const EventObject& 196 #ifdef DBG_UTIL 197 Source 198 #endif 199 ) throw (RuntimeException) 200 { 201 DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::notifyClosing: where did this come from?" ); 202 203 // this should be unreachable: As long as we're a CloseListener, we veto the closing. If we're going 204 // to close the component ourself, then we revoke ourself as listener *before* the close call. So, 205 // if this here fires, something went definitely wrong. 206 DBG_ERROR( "CloseableComponentImpl::notifyClosing: unreachable!" ); 207 } 208 209 //-------------------------------------------------------------------- disposing(const EventObject & Source)210 void SAL_CALL CloseableComponentImpl::disposing( const EventObject& 211 #ifdef DBG_UTIL 212 Source 213 #endif 214 ) throw (RuntimeException) 215 { 216 DBG_ASSERT( Source.Source == m_xCloseable, "CloseableComponentImpl::disposing: where did this come from?" ); 217 DBG_ERROR( "CloseableComponentImpl::disposing: unreachable!" ); 218 // same reasoning for this assertion as in ->notifyClosing 219 } 220 221 //======================================================================== 222 //= CloseableComponentImpl 223 //======================================================================== DBG_NAME(CloseableComponent)224 DBG_NAME( CloseableComponent ) 225 //------------------------------------------------------------------------ 226 CloseableComponent::CloseableComponent( const Reference< XInterface >& _rxComponent ) 227 :m_pImpl( new CloseableComponentImpl( _rxComponent ) ) 228 { 229 DBG_CTOR( CloseableComponent, NULL ); 230 } 231 232 //------------------------------------------------------------------------ ~CloseableComponent()233 CloseableComponent::~CloseableComponent() 234 { 235 // close the component, deliver ownership to anybody who wants to veto the close 236 m_pImpl->nf_closeComponent(); 237 DBG_DTOR( CloseableComponent, NULL ); 238 } 239 240 //............................................................................ 241 } // namespace utl 242 //............................................................................ 243