xref: /trunk/main/dbaccess/source/core/dataaccess/intercept.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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_dbaccess.hxx"
26 
27 #include "intercept.hxx"
28 #include "dbastrings.hrc"
29 
30 #include <com/sun/star/embed/EmbedStates.hpp>
31 #include <com/sun/star/document/XEventBroadcaster.hpp>
32 #include <com/sun/star/util/XModifiable.hpp>
33 #include <cppuhelper/weak.hxx>
34 
35 #include <comphelper/types.hxx>
36 #include <tools/debug.hxx>
37 #include <tools/diagnose_ex.h>
38 
39 
40 namespace dbaccess
41 {
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star::util;
44 using namespace ::com::sun::star::ucb;
45 using namespace ::com::sun::star::beans;
46 using namespace ::com::sun::star::lang;
47 using namespace ::com::sun::star::sdbc;
48 using namespace ::com::sun::star::frame;
49 using namespace ::com::sun::star::io;
50 using namespace ::com::sun::star::embed;
51 using namespace ::com::sun::star::container;
52 using namespace ::comphelper;
53 using namespace ::cppu;
54 
55 #define DISPATCH_SAVEAS     0
56 #define DISPATCH_SAVE       1
57 #define DISPATCH_CLOSEDOC   2
58 #define DISPATCH_CLOSEWIN   3
59 #define DISPATCH_CLOSEFRAME 4
60 #define DISPATCH_RELOAD     5
61 // the OSL_ENSURE in CTOR has to be changed too, when adding new defines
62 
dispose()63 void SAL_CALL OInterceptor::dispose()
64 {
65     EventObject aEvt( *this );
66 
67     osl::MutexGuard aGuard(m_aMutex);
68 
69     if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
70         m_pDisposeEventListeners->disposeAndClear( aEvt );
71 
72     if ( m_pStatCL )
73         m_pStatCL->disposeAndClear( aEvt );
74 
75     m_xSlaveDispatchProvider.clear();
76     m_xMasterDispatchProvider.clear();
77 
78     m_pContentHolder = NULL;
79 }
80 
81 
DBG_NAME(OInterceptor)82 DBG_NAME(OInterceptor)
83 
84 OInterceptor::OInterceptor( ODocumentDefinition* _pContentHolder,sal_Bool _bAllowEditDoc )
85     :m_pContentHolder( _pContentHolder )
86     ,m_aInterceptedURL(7)
87     ,m_pDisposeEventListeners(0)
88     ,m_pStatCL(0)
89     ,m_bAllowEditDoc(_bAllowEditDoc)
90 {
91     DBG_CTOR(OInterceptor,NULL);
92 
93     OSL_ENSURE(DISPATCH_RELOAD < m_aInterceptedURL.getLength(),"Illegal size.");
94 
95     m_aInterceptedURL[DISPATCH_SAVEAS]      = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:SaveAs"));
96     m_aInterceptedURL[DISPATCH_SAVE]        = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:Save"));
97     m_aInterceptedURL[DISPATCH_CLOSEDOC]    = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:CloseDoc"));
98     m_aInterceptedURL[DISPATCH_CLOSEWIN]    = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:CloseWin"));
99     m_aInterceptedURL[DISPATCH_CLOSEFRAME]  = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:CloseFrame"));
100     m_aInterceptedURL[DISPATCH_RELOAD]      = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:Reload"));
101 }
102 
103 
~OInterceptor()104 OInterceptor::~OInterceptor()
105 {
106     if( m_pDisposeEventListeners )
107         delete m_pDisposeEventListeners;
108 
109     if(m_pStatCL)
110         delete m_pStatCL;
111 
112     DBG_DTOR(OInterceptor,NULL);
113 }
114 
115 struct DispatchHelper
116 {
117     URL aURL;
118     Sequence<PropertyValue > aArguments;
119 };
120 
121 //XDispatch
dispatch(const URL & _URL,const Sequence<PropertyValue> & Arguments)122 void SAL_CALL OInterceptor::dispatch( const URL& _URL,const Sequence<PropertyValue >& Arguments )
123 {
124     ::osl::MutexGuard aGuard( m_aMutex );
125     if ( !m_pContentHolder )
126         return;
127 
128     if ( _URL.Complete == m_aInterceptedURL[ DISPATCH_SAVE ] )
129     {
130         m_pContentHolder->save( sal_False );
131         return;
132     }
133 
134     if ( _URL.Complete == m_aInterceptedURL[ DISPATCH_RELOAD ] )
135     {
136         ODocumentDefinition::fillReportData(
137             m_pContentHolder->getContext(),
138             m_pContentHolder->getComponent(),
139             m_pContentHolder->getConnection()
140         );
141         return;
142     }
143 
144     if( _URL.Complete == m_aInterceptedURL[ DISPATCH_SAVEAS ] )
145     {
146         if ( m_pContentHolder->isNewReport() )
147         {
148             m_pContentHolder->saveAs();
149         }
150         else if ( m_xSlaveDispatchProvider.is() )
151         {
152             Sequence< PropertyValue > aNewArgs = Arguments;
153             sal_Int32 nInd = 0;
154 
155             while( nInd < aNewArgs.getLength() )
156             {
157                 if ( aNewArgs[nInd].Name.equalsAscii( "SaveTo" ) )
158                 {
159                     aNewArgs[nInd].Value <<= sal_True;
160                     break;
161                 }
162                 nInd++;
163             }
164 
165             if ( nInd == aNewArgs.getLength() )
166             {
167                 aNewArgs.realloc( nInd + 1 );
168                 aNewArgs[nInd].Name = ::rtl::OUString::createFromAscii( "SaveTo" );
169                 aNewArgs[nInd].Value <<= sal_True;
170             }
171 
172             Reference< XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch(
173                 _URL, ::rtl::OUString::createFromAscii( "_self" ), 0 );
174             if ( xDispatch.is() )
175                 xDispatch->dispatch( _URL, aNewArgs );
176         }
177         return;
178     }
179 
180     if  (   _URL.Complete == m_aInterceptedURL[ DISPATCH_CLOSEDOC ]
181         ||  _URL.Complete == m_aInterceptedURL[ DISPATCH_CLOSEWIN ]
182         ||  _URL.Complete == m_aInterceptedURL[ DISPATCH_CLOSEFRAME ]
183         )
184     {
185         DispatchHelper* pHelper = new DispatchHelper;
186         pHelper->aArguments = Arguments;
187         pHelper->aURL = _URL;
188         Application::PostUserEvent( LINK( this, OInterceptor, OnDispatch ), reinterpret_cast< void* >( pHelper ) );
189         return;
190     }
191 }
192 
IMPL_LINK(OInterceptor,OnDispatch,void *,_pDispatcher)193 IMPL_LINK( OInterceptor, OnDispatch, void*, _pDispatcher )
194 {
195     ::std::auto_ptr<DispatchHelper> pHelper( reinterpret_cast< DispatchHelper* >( _pDispatcher ) );
196     try
197     {
198         if ( m_pContentHolder && m_pContentHolder->prepareClose() && m_xSlaveDispatchProvider.is() )
199         {
200             Reference< XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch(
201                 pHelper->aURL, ::rtl::OUString::createFromAscii( "_self" ), 0 );
202             if ( xDispatch.is() )
203             {
204                 Reference< ::com::sun::star::document::XEventBroadcaster> xEvtB(m_pContentHolder->getComponent(),UNO_QUERY);
205                 if ( xEvtB.is() )
206                     xEvtB->removeEventListener(this);
207 
208                 Reference< XInterface > xKeepContentHolderAlive( *m_pContentHolder );
209                 xDispatch->dispatch( pHelper->aURL,pHelper->aArguments);
210             }
211         }
212     }
213     catch ( const Exception& )
214     {
215         DBG_UNHANDLED_EXCEPTION();
216     }
217 
218     return 0L;
219 }
220 
addStatusListener(const Reference<XStatusListener> & Control,const URL & _URL)221 void SAL_CALL OInterceptor::addStatusListener(
222     const Reference<
223     XStatusListener >& Control,
224     const URL& _URL )
225 {
226     if(!Control.is())
227         return;
228 
229     if ( m_pContentHolder && _URL.Complete == m_aInterceptedURL[DISPATCH_SAVEAS] )
230     {   // SaveAs
231 
232         if ( !m_pContentHolder->isNewReport() )
233         {
234             FeatureStateEvent aStateEvent;
235             aStateEvent.FeatureURL.Complete = m_aInterceptedURL[DISPATCH_SAVEAS];
236             aStateEvent.FeatureDescriptor = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SaveCopyTo"));
237             aStateEvent.IsEnabled = sal_True;
238             aStateEvent.Requery = sal_False;
239             aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($3)")));
240             Control->statusChanged(aStateEvent);
241         }
242 
243         {
244             osl::MutexGuard aGuard(m_aMutex);
245             if(!m_pStatCL)
246                 m_pStatCL = new PropertyChangeListenerContainer(m_aMutex);
247         }
248 
249         m_pStatCL->addInterface(_URL.Complete,Control);
250     }
251     else if ( m_pContentHolder && _URL.Complete == m_aInterceptedURL[DISPATCH_SAVE] )
252     {   // Save
253         FeatureStateEvent aStateEvent;
254         aStateEvent.FeatureURL.Complete = m_aInterceptedURL[DISPATCH_SAVE];
255         aStateEvent.FeatureDescriptor = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Update"));
256         aStateEvent.IsEnabled = m_pContentHolder != NULL && m_pContentHolder->isModified();
257         aStateEvent.Requery = sal_False;
258 
259         Control->statusChanged(aStateEvent);
260         {
261             osl::MutexGuard aGuard(m_aMutex);
262             if(!m_pStatCL)
263                 m_pStatCL = new PropertyChangeListenerContainer(m_aMutex);
264         }
265 
266         m_pStatCL->addInterface(_URL.Complete,Control);
267         Reference< ::com::sun::star::document::XEventBroadcaster> xEvtB(m_pContentHolder->getComponent(),UNO_QUERY);
268         if ( xEvtB.is() )
269             xEvtB->addEventListener(this);
270     }
271     else
272     {
273         sal_Int32 i = 2;
274         if(_URL.Complete == m_aInterceptedURL[i] ||
275             _URL.Complete == m_aInterceptedURL[++i] ||
276             _URL.Complete == m_aInterceptedURL[++i] ||
277             _URL.Complete == m_aInterceptedURL[i = DISPATCH_RELOAD] )
278         {   // Close and return
279             FeatureStateEvent aStateEvent;
280             aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i];
281             aStateEvent.FeatureDescriptor = rtl::OUString(
282                 RTL_CONSTASCII_USTRINGPARAM("Close and Return"));
283             aStateEvent.IsEnabled = sal_True;
284             aStateEvent.Requery = sal_False;
285             Control->statusChanged(aStateEvent);
286 
287 
288             {
289                 osl::MutexGuard aGuard(m_aMutex);
290                 if(!m_pStatCL)
291                     m_pStatCL = new PropertyChangeListenerContainer(m_aMutex);
292             }
293 
294             m_pStatCL->addInterface(_URL.Complete,Control);
295             return;
296         }
297     }
298 }
299 
300 
removeStatusListener(const Reference<XStatusListener> & Control,const URL & _URL)301 void SAL_CALL OInterceptor::removeStatusListener(
302     const Reference<
303     XStatusListener >& Control,
304     const URL& _URL )
305 {
306     if(!(Control.is() && m_pStatCL))
307         return;
308     else
309     {
310         m_pStatCL->removeInterface(_URL.Complete,Control);
311         return;
312     }
313 }
314 
315 
316 //XInterceptorInfo
getInterceptedURLs()317 Sequence< ::rtl::OUString > SAL_CALL OInterceptor::getInterceptedURLs(  )
318 {
319     // now implemented as update
320     return m_aInterceptedURL;
321 }
322 
323 
324 // XDispatchProvider
325 
queryDispatch(const URL & _URL,const::rtl::OUString & TargetFrameName,sal_Int32 SearchFlags)326 Reference< XDispatch > SAL_CALL OInterceptor::queryDispatch( const URL& _URL,const ::rtl::OUString& TargetFrameName,sal_Int32 SearchFlags )
327 {
328     osl::MutexGuard aGuard(m_aMutex);
329     const ::rtl::OUString* pIter = m_aInterceptedURL.getConstArray();
330     const ::rtl::OUString* pEnd   = pIter + m_aInterceptedURL.getLength();
331     for(;pIter != pEnd;++pIter)
332     {
333         if ( _URL.Complete == *pIter )
334             return (XDispatch*)this;
335     }
336 
337     if(m_xSlaveDispatchProvider.is())
338         return m_xSlaveDispatchProvider->queryDispatch(_URL,TargetFrameName,SearchFlags);
339     else
340         return Reference<XDispatch>();
341 }
342 
queryDispatches(const Sequence<DispatchDescriptor> & Requests)343 Sequence< Reference< XDispatch > > SAL_CALL OInterceptor::queryDispatches(  const Sequence<DispatchDescriptor >& Requests )
344 {
345     Sequence< Reference< XDispatch > > aRet;
346     osl::MutexGuard aGuard(m_aMutex);
347     if(m_xSlaveDispatchProvider.is())
348         aRet = m_xSlaveDispatchProvider->queryDispatches(Requests);
349     else
350         aRet.realloc(Requests.getLength());
351 
352     for(sal_Int32 i = 0; i < Requests.getLength(); ++i)
353     {
354         const ::rtl::OUString* pIter = m_aInterceptedURL.getConstArray();
355         const ::rtl::OUString* pEnd   = pIter + m_aInterceptedURL.getLength();
356         for(;pIter != pEnd;++pIter)
357         {
358             if ( Requests[i].FeatureURL.Complete == *pIter )
359             {
360                 aRet[i] = (XDispatch*) this;
361                 break;
362             }
363         }
364     }
365 
366     return aRet;
367 }
368 
369 
370 
371 //XDispatchProviderInterceptor
372 
getSlaveDispatchProvider()373 Reference< XDispatchProvider > SAL_CALL OInterceptor::getSlaveDispatchProvider(  )
374 {
375     osl::MutexGuard aGuard(m_aMutex);
376     return m_xSlaveDispatchProvider;
377 }
378 
379 void SAL_CALL
setSlaveDispatchProvider(const Reference<XDispatchProvider> & NewDispatchProvider)380 OInterceptor::setSlaveDispatchProvider( const Reference< XDispatchProvider >& NewDispatchProvider )
381 {
382     osl::MutexGuard aGuard(m_aMutex);
383     m_xSlaveDispatchProvider = NewDispatchProvider;
384 }
385 
386 
getMasterDispatchProvider()387 Reference< XDispatchProvider > SAL_CALL OInterceptor::getMasterDispatchProvider(  )
388 {
389     osl::MutexGuard aGuard(m_aMutex);
390     return m_xMasterDispatchProvider;
391 }
392 
393 
setMasterDispatchProvider(const Reference<XDispatchProvider> & NewSupplier)394 void SAL_CALL OInterceptor::setMasterDispatchProvider(
395     const Reference< XDispatchProvider >& NewSupplier )
396 {
397     osl::MutexGuard aGuard(m_aMutex);
398     m_xMasterDispatchProvider = NewSupplier;
399 }
400 // -----------------------------------------------------------------------------
notifyEvent(const::com::sun::star::document::EventObject & Event)401 void SAL_CALL OInterceptor::notifyEvent( const ::com::sun::star::document::EventObject& Event )
402 {
403     osl::ResettableMutexGuard _rGuard(m_aMutex);
404     if ( m_pStatCL &&   Event.EventName == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OnModifyChanged")) )
405     {
406         OInterfaceContainerHelper* pListener = m_pStatCL->getContainer(m_aInterceptedURL[DISPATCH_SAVE]);
407         if ( pListener )
408         {
409             FeatureStateEvent aEvt;
410             aEvt.FeatureURL.Complete = m_aInterceptedURL[DISPATCH_SAVE];
411             aEvt.FeatureDescriptor = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Update"));
412             Reference<XModifiable> xModel(Event.Source,UNO_QUERY);
413             aEvt.IsEnabled = xModel.is() && xModel->isModified();
414             aEvt.Requery = sal_False;
415 
416             NOTIFY_LISTERNERS((*pListener),XStatusListener,statusChanged)
417         }
418     }
419 }
420 // -----------------------------------------------------------------------------
disposing(const::com::sun::star::lang::EventObject &)421 void SAL_CALL OInterceptor::disposing( const ::com::sun::star::lang::EventObject& /*Source*/ )
422 {
423 }
424 
425 //........................................................................
426 }   // namespace dbaccess
427 //........................................................................
428