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_connectivity.hxx" 30 #include <connectivity/conncleanup.hxx> 31 #include <com/sun/star/beans/XPropertySet.hpp> 32 #include <com/sun/star/lang/XComponent.hpp> 33 #include <osl/diagnose.h> 34 35 //......................................................................... 36 namespace dbtools 37 { 38 //......................................................................... 39 40 using namespace ::com::sun::star::uno; 41 using namespace ::com::sun::star::beans; 42 using namespace ::com::sun::star::sdbc; 43 using namespace ::com::sun::star::lang; 44 45 //===================================================================== 46 static const ::rtl::OUString& getActiveConnectionPropertyName() 47 { 48 static const ::rtl::OUString s_sActiveConnectionPropertyName = ::rtl::OUString::createFromAscii("ActiveConnection"); 49 return s_sActiveConnectionPropertyName; 50 } 51 52 //===================================================================== 53 //= OAutoConnectionDisposer 54 //===================================================================== 55 //--------------------------------------------------------------------- 56 OAutoConnectionDisposer::OAutoConnectionDisposer(const Reference< XRowSet >& _rxRowSet, const Reference< XConnection >& _rxConnection) 57 :m_xRowSet( _rxRowSet ) 58 ,m_bRSListening( sal_False ) 59 ,m_bPropertyListening( sal_False ) 60 { 61 Reference< XPropertySet > xProps(_rxRowSet, UNO_QUERY); 62 OSL_ENSURE(xProps.is(), "OAutoConnectionDisposer::OAutoConnectionDisposer: invalid rowset (no XPropertySet)!"); 63 64 if (!xProps.is()) 65 return; 66 67 try 68 { 69 xProps->setPropertyValue( getActiveConnectionPropertyName(), makeAny( _rxConnection ) ); 70 m_xOriginalConnection = _rxConnection; 71 startPropertyListening( xProps ); 72 } 73 catch( const Exception& ) 74 { 75 OSL_ENSURE( sal_False, "OAutoConnectionDisposer::OAutoConnectionDisposer: caught an exception!" ); 76 } 77 } 78 79 //--------------------------------------------------------------------- 80 void OAutoConnectionDisposer::startPropertyListening( const Reference< XPropertySet >& _rxRowSet ) 81 { 82 try 83 { 84 _rxRowSet->addPropertyChangeListener( getActiveConnectionPropertyName(), this ); 85 m_bPropertyListening = sal_True; 86 } 87 catch( const Exception& ) 88 { 89 OSL_ENSURE( sal_False, "OAutoConnectionDisposer::startPropertyListening: caught an exception!" ); 90 } 91 } 92 93 //--------------------------------------------------------------------- 94 void OAutoConnectionDisposer::stopPropertyListening( const Reference< XPropertySet >& _rxEventSource ) 95 { 96 // prevent deletion of ourself while we're herein 97 Reference< XInterface > xKeepAlive(static_cast< XWeak* >(this)); 98 99 try 100 { // remove ourself as property change listener 101 OSL_ENSURE( _rxEventSource.is(), "OAutoConnectionDisposer::stopPropertyListening: invalid event source (no XPropertySet)!" ); 102 if ( _rxEventSource.is() ) 103 { 104 _rxEventSource->removePropertyChangeListener( getActiveConnectionPropertyName(), this ); 105 m_bPropertyListening = sal_False; 106 } 107 } 108 catch( const Exception& ) 109 { 110 OSL_ENSURE( sal_False, "OAutoConnectionDisposer::stopPropertyListening: caught an exception!" ); 111 } 112 } 113 114 //--------------------------------------------------------------------- 115 void OAutoConnectionDisposer::startRowSetListening() 116 { 117 OSL_ENSURE( !m_bRSListening, "OAutoConnectionDisposer::startRowSetListening: already listening!" ); 118 try 119 { 120 if ( !m_bRSListening ) 121 m_xRowSet->addRowSetListener( this ); 122 } 123 catch( const Exception& ) 124 { 125 OSL_ENSURE( sal_False, "OAutoConnectionDisposer::startRowSetListening: caught an exception!" ); 126 } 127 m_bRSListening = sal_True; 128 } 129 130 //--------------------------------------------------------------------- 131 void OAutoConnectionDisposer::stopRowSetListening() 132 { 133 OSL_ENSURE( m_bRSListening, "OAutoConnectionDisposer::stopRowSetListening: not listening!" ); 134 try 135 { 136 m_xRowSet->removeRowSetListener( this ); 137 } 138 catch( const Exception& ) 139 { 140 OSL_ENSURE( sal_False, "OAutoConnectionDisposer::stopRowSetListening: caught an exception!" ); 141 } 142 m_bRSListening = sal_False; 143 } 144 145 //--------------------------------------------------------------------- 146 void SAL_CALL OAutoConnectionDisposer::propertyChange( const PropertyChangeEvent& _rEvent ) throw (RuntimeException) 147 { 148 if ( _rEvent.PropertyName.equals( getActiveConnectionPropertyName() ) ) 149 { // somebody set a new ActiveConnection 150 151 Reference< XConnection > xNewConnection; 152 _rEvent.NewValue >>= xNewConnection; 153 154 if ( isRowSetListening() ) 155 { 156 // we're listening at the row set, this means that the row set does not have our 157 // m_xOriginalConnection as active connection anymore 158 // So there are two possibilities 159 // a. somebody sets a new connection which is not our original one 160 // b. somebody sets a new connection, which is exactly the original one 161 // a. we're not interested in a, but in b: In this case, we simply need to move to the state 162 // we had originally: listen for property changes, do not listen for row set changes, and 163 // do not dispose the connection until the row set does not need it anymore 164 if ( xNewConnection.get() == m_xOriginalConnection.get() ) 165 { 166 stopRowSetListening(); 167 } 168 } 169 else 170 { 171 // start listening at the row set. We're allowed to dispose the old connection as soon 172 // as the RowSet changed 173 174 // Unfortunately, the our database form implementations sometimes fire the change of their 175 // ActiveConnection twice. This is a error in forms/source/component/DatabaseForm.cxx, but 176 // changing this would require incompatible changes we can't do for a while. 177 // So for the moment, we have to live with it here. 178 // 179 // The only scenario where this doubled notification causes problems is when the connection 180 // of the form is reset to the one we're responsible for (m_xOriginalConnection), so we 181 // check this here. 182 // 183 // Yes, this is a HACK :( 184 // 185 // 94407 - 08.11.2001 - fs@openoffice.org 186 if ( xNewConnection.get() != m_xOriginalConnection.get() ) 187 { 188 #if OSL_DEBUG_LEVEL > 0 189 Reference< XConnection > xOldConnection; 190 _rEvent.OldValue >>= xOldConnection; 191 OSL_ENSURE( xOldConnection.get() == m_xOriginalConnection.get(), "OAutoConnectionDisposer::propertyChange: unexpected (original) property value!" ); 192 #endif 193 startRowSetListening(); 194 } 195 } 196 } 197 } 198 199 //--------------------------------------------------------------------- 200 void SAL_CALL OAutoConnectionDisposer::disposing( const EventObject& _rSource ) throw (RuntimeException) 201 { 202 // the rowset is beeing disposed, and nobody has set a new ActiveConnection in the meantime 203 if ( isRowSetListening() ) 204 stopRowSetListening(); 205 206 clearConnection(); 207 208 if ( isPropertyListening() ) 209 stopPropertyListening( Reference< XPropertySet >( _rSource.Source, UNO_QUERY ) ); 210 } 211 //--------------------------------------------------------------------- 212 void OAutoConnectionDisposer::clearConnection() 213 { 214 try 215 { 216 // dispose the old connection 217 Reference< XComponent > xComp(m_xOriginalConnection, UNO_QUERY); 218 if (xComp.is()) 219 xComp->dispose(); 220 m_xOriginalConnection.clear(); 221 } 222 catch(Exception&) 223 { 224 OSL_ENSURE(sal_False, "OAutoConnectionDisposer::clearConnection: caught an exception!"); 225 } 226 } 227 //--------------------------------------------------------------------- 228 void SAL_CALL OAutoConnectionDisposer::cursorMoved( const ::com::sun::star::lang::EventObject& /*event*/ ) throw (::com::sun::star::uno::RuntimeException) 229 { 230 } 231 //--------------------------------------------------------------------- 232 void SAL_CALL OAutoConnectionDisposer::rowChanged( const ::com::sun::star::lang::EventObject& /*event*/ ) throw (::com::sun::star::uno::RuntimeException) 233 { 234 } 235 //--------------------------------------------------------------------- 236 void SAL_CALL OAutoConnectionDisposer::rowSetChanged( const ::com::sun::star::lang::EventObject& /*event*/ ) throw (::com::sun::star::uno::RuntimeException) 237 { 238 stopRowSetListening(); 239 clearConnection(); 240 241 } 242 //--------------------------------------------------------------------- 243 244 //......................................................................... 245 } // namespace dbtools 246 //......................................................................... 247 248