1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <connectivity/conncleanup.hxx>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/lang/XComponent.hpp>
32 #include <osl/diagnose.h>
34 //.........................................................................
37 //.........................................................................
39 using namespace ::com::sun::star::uno
;
40 using namespace ::com::sun::star::beans
;
41 using namespace ::com::sun::star::sdbc
;
42 using namespace ::com::sun::star::lang
;
44 //=====================================================================
45 static const ::rtl::OUString
& getActiveConnectionPropertyName()
47 static const ::rtl::OUString
s_sActiveConnectionPropertyName( RTL_CONSTASCII_USTRINGPARAM( "ActiveConnection" ));
48 return s_sActiveConnectionPropertyName
;
51 //=====================================================================
52 //= OAutoConnectionDisposer
53 //=====================================================================
54 //---------------------------------------------------------------------
55 OAutoConnectionDisposer::OAutoConnectionDisposer(const Reference
< XRowSet
>& _rxRowSet
, const Reference
< XConnection
>& _rxConnection
)
56 :m_xRowSet( _rxRowSet
)
57 ,m_bRSListening( sal_False
)
58 ,m_bPropertyListening( sal_False
)
60 Reference
< XPropertySet
> xProps(_rxRowSet
, UNO_QUERY
);
61 OSL_ENSURE(xProps
.is(), "OAutoConnectionDisposer::OAutoConnectionDisposer: invalid rowset (no XPropertySet)!");
68 xProps
->setPropertyValue( getActiveConnectionPropertyName(), makeAny( _rxConnection
) );
69 m_xOriginalConnection
= _rxConnection
;
70 startPropertyListening( xProps
);
72 catch( const Exception
& )
74 OSL_FAIL( "OAutoConnectionDisposer::OAutoConnectionDisposer: caught an exception!" );
78 //---------------------------------------------------------------------
79 void OAutoConnectionDisposer::startPropertyListening( const Reference
< XPropertySet
>& _rxRowSet
)
83 _rxRowSet
->addPropertyChangeListener( getActiveConnectionPropertyName(), this );
84 m_bPropertyListening
= sal_True
;
86 catch( const Exception
& )
88 OSL_FAIL( "OAutoConnectionDisposer::startPropertyListening: caught an exception!" );
92 //---------------------------------------------------------------------
93 void OAutoConnectionDisposer::stopPropertyListening( const Reference
< XPropertySet
>& _rxEventSource
)
95 // prevent deletion of ourself while we're herein
96 Reference
< XInterface
> xKeepAlive(static_cast< XWeak
* >(this));
99 { // remove ourself as property change listener
100 OSL_ENSURE( _rxEventSource
.is(), "OAutoConnectionDisposer::stopPropertyListening: invalid event source (no XPropertySet)!" );
101 if ( _rxEventSource
.is() )
103 _rxEventSource
->removePropertyChangeListener( getActiveConnectionPropertyName(), this );
104 m_bPropertyListening
= sal_False
;
107 catch( const Exception
& )
109 OSL_FAIL( "OAutoConnectionDisposer::stopPropertyListening: caught an exception!" );
113 //---------------------------------------------------------------------
114 void OAutoConnectionDisposer::startRowSetListening()
116 OSL_ENSURE( !m_bRSListening
, "OAutoConnectionDisposer::startRowSetListening: already listening!" );
119 if ( !m_bRSListening
)
120 m_xRowSet
->addRowSetListener( this );
122 catch( const Exception
& )
124 OSL_FAIL( "OAutoConnectionDisposer::startRowSetListening: caught an exception!" );
126 m_bRSListening
= sal_True
;
129 //---------------------------------------------------------------------
130 void OAutoConnectionDisposer::stopRowSetListening()
132 OSL_ENSURE( m_bRSListening
, "OAutoConnectionDisposer::stopRowSetListening: not listening!" );
135 m_xRowSet
->removeRowSetListener( this );
137 catch( const Exception
& )
139 OSL_FAIL( "OAutoConnectionDisposer::stopRowSetListening: caught an exception!" );
141 m_bRSListening
= sal_False
;
144 //---------------------------------------------------------------------
145 void SAL_CALL
OAutoConnectionDisposer::propertyChange( const PropertyChangeEvent
& _rEvent
) throw (RuntimeException
)
147 if ( _rEvent
.PropertyName
.equals( getActiveConnectionPropertyName() ) )
148 { // somebody set a new ActiveConnection
150 Reference
< XConnection
> xNewConnection
;
151 _rEvent
.NewValue
>>= xNewConnection
;
153 if ( isRowSetListening() )
155 // we're listening at the row set, this means that the row set does not have our
156 // m_xOriginalConnection as active connection anymore
157 // So there are two possibilities
158 // a. somebody sets a new connection which is not our original one
159 // b. somebody sets a new connection, which is exactly the original one
160 // a. we're not interested in a, but in b: In this case, we simply need to move to the state
161 // we had originally: listen for property changes, do not listen for row set changes, and
162 // do not dispose the connection until the row set does not need it anymore
163 if ( xNewConnection
.get() == m_xOriginalConnection
.get() )
165 stopRowSetListening();
170 // start listening at the row set. We're allowed to dispose the old connection as soon
171 // as the RowSet changed
173 // Unfortunately, the our database form implementations sometimes fire the change of their
174 // ActiveConnection twice. This is a error in forms/source/component/DatabaseForm.cxx, but
175 // changing this would require incompatible changes we can't do for a while.
176 // So for the moment, we have to live with it here.
178 // The only scenario where this doubled notification causes problems is when the connection
179 // of the form is reset to the one we're responsible for (m_xOriginalConnection), so we
182 // Yes, this is a HACK :(
183 if ( xNewConnection
.get() != m_xOriginalConnection
.get() )
185 #if OSL_DEBUG_LEVEL > 0
186 Reference
< XConnection
> xOldConnection
;
187 _rEvent
.OldValue
>>= xOldConnection
;
188 OSL_ENSURE( xOldConnection
.get() == m_xOriginalConnection
.get(), "OAutoConnectionDisposer::propertyChange: unexpected (original) property value!" );
190 startRowSetListening();
196 //---------------------------------------------------------------------
197 void SAL_CALL
OAutoConnectionDisposer::disposing( const EventObject
& _rSource
) throw (RuntimeException
)
199 // the rowset is beeing disposed, and nobody has set a new ActiveConnection in the meantime
200 if ( isRowSetListening() )
201 stopRowSetListening();
205 if ( isPropertyListening() )
206 stopPropertyListening( Reference
< XPropertySet
>( _rSource
.Source
, UNO_QUERY
) );
208 //---------------------------------------------------------------------
209 void OAutoConnectionDisposer::clearConnection()
213 // dispose the old connection
214 Reference
< XComponent
> xComp(m_xOriginalConnection
, UNO_QUERY
);
217 m_xOriginalConnection
.clear();
221 OSL_FAIL("OAutoConnectionDisposer::clearConnection: caught an exception!");
224 //---------------------------------------------------------------------
225 void SAL_CALL
OAutoConnectionDisposer::cursorMoved( const ::com::sun::star::lang::EventObject
& /*event*/ ) throw (::com::sun::star::uno::RuntimeException
)
228 //---------------------------------------------------------------------
229 void SAL_CALL
OAutoConnectionDisposer::rowChanged( const ::com::sun::star::lang::EventObject
& /*event*/ ) throw (::com::sun::star::uno::RuntimeException
)
232 //---------------------------------------------------------------------
233 void SAL_CALL
OAutoConnectionDisposer::rowSetChanged( const ::com::sun::star::lang::EventObject
& /*event*/ ) throw (::com::sun::star::uno::RuntimeException
)
235 stopRowSetListening();
239 //---------------------------------------------------------------------
241 //.........................................................................
242 } // namespace dbtools
243 //.........................................................................
245 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */