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