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