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