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