xref: /trunk/main/connectivity/source/commontools/conncleanup.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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