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 #include <cppuhelper/weak.hxx>
24
25 #include <embeddoc.hxx>
26 #include <docholder.hxx>
27 #include <intercept.hxx>
28
29 using namespace ::com::sun::star;
30
31
32
33 #define IUL 6
34
35
36
37 uno::Sequence< ::rtl::OUString > Interceptor::m_aInterceptedURL(IUL);
38
39
40
41
42 struct equalOUString
43 {
operator ()equalOUString44 bool operator()(
45 const rtl::OUString& rKey1,
46 const rtl::OUString& rKey2 ) const
47 {
48 return !!( rKey1 == rKey2 );
49 }
50 };
51
52
53 struct hashOUString
54 {
operator ()hashOUString55 size_t operator()( const rtl::OUString& rName ) const
56 {
57 return rName.hashCode();
58 }
59 };
60
61
62
63 class StatusChangeListenerContainer
64 : public ::cppu::OMultiTypeInterfaceContainerHelperVar<
65 rtl::OUString,hashOUString,equalOUString>
66 {
67 public:
StatusChangeListenerContainer(::osl::Mutex & aMutex)68 StatusChangeListenerContainer( ::osl::Mutex& aMutex )
69 : cppu::OMultiTypeInterfaceContainerHelperVar<
70 rtl::OUString,hashOUString,equalOUString>(aMutex)
71 {
72 }
73 };
74
75
76 void SAL_CALL
addEventListener(const uno::Reference<lang::XEventListener> & Listener)77 Interceptor::addEventListener(
78 const uno::Reference<lang::XEventListener >& Listener )
79 {
80 osl::MutexGuard aGuard( m_aMutex );
81
82 if ( ! m_pDisposeEventListeners )
83 m_pDisposeEventListeners =
84 new cppu::OInterfaceContainerHelper( m_aMutex );
85
86 m_pDisposeEventListeners->addInterface( Listener );
87 }
88
89
90 void SAL_CALL
removeEventListener(const uno::Reference<lang::XEventListener> & Listener)91 Interceptor::removeEventListener(
92 const uno::Reference< lang::XEventListener >& Listener )
93 {
94 osl::MutexGuard aGuard( m_aMutex );
95
96 if ( m_pDisposeEventListeners )
97 m_pDisposeEventListeners->removeInterface( Listener );
98 }
99
100
dispose()101 void SAL_CALL Interceptor::dispose()
102 {
103 lang::EventObject aEvt;
104 aEvt.Source = static_cast< frame::XDispatch* >( this );
105
106 osl::MutexGuard aGuard(m_aMutex);
107
108 if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() )
109 m_pDisposeEventListeners->disposeAndClear( aEvt );
110
111 if(m_pStatCL)
112 m_pStatCL->disposeAndClear( aEvt );
113
114 m_xSlaveDispatchProvider = 0;
115 m_xMasterDispatchProvider = 0;
116 }
117
118
119
Interceptor(const::rtl::Reference<EmbeddedDocumentInstanceAccess_Impl> & xOleAccess,DocumentHolder * pDocH,sal_Bool bLink)120 Interceptor::Interceptor(
121 const ::rtl::Reference< EmbeddedDocumentInstanceAccess_Impl >& xOleAccess,
122 DocumentHolder* pDocH,
123 sal_Bool bLink )
124 : m_xOleAccess( xOleAccess ),
125 m_xDocHLocker( static_cast< ::cppu::OWeakObject* >( pDocH ) ),
126 m_pDocH(pDocH),
127 m_pStatCL(0),
128 m_pDisposeEventListeners(0),
129 m_bLink( bLink )
130 {
131 m_aInterceptedURL[0] = rtl::OUString(
132 RTL_CONSTASCII_USTRINGPARAM(".uno:Save"));
133 m_aInterceptedURL[1] = rtl::OUString(
134 RTL_CONSTASCII_USTRINGPARAM(".uno:SaveAll"));
135 m_aInterceptedURL[2] = rtl::OUString(
136 RTL_CONSTASCII_USTRINGPARAM(".uno:CloseDoc"));
137 m_aInterceptedURL[3] = rtl::OUString(
138 RTL_CONSTASCII_USTRINGPARAM(".uno:CloseWin"));
139 m_aInterceptedURL[4] = rtl::OUString(
140 RTL_CONSTASCII_USTRINGPARAM(".uno:CloseFrame"));
141 m_aInterceptedURL[5] = rtl::OUString(
142 RTL_CONSTASCII_USTRINGPARAM(".uno:SaveAs"));
143 }
144
145
~Interceptor()146 Interceptor::~Interceptor()
147 {
148 if( m_pDisposeEventListeners )
149 delete m_pDisposeEventListeners;
150
151 if(m_pStatCL)
152 delete m_pStatCL;
153
154 DocumentHolder* pTmpDocH = NULL;
155 uno::Reference< uno::XInterface > xLock;
156 {
157 osl::MutexGuard aGuard(m_aMutex);
158 xLock = m_xDocHLocker.get();
159 if ( xLock.is() )
160 pTmpDocH = m_pDocH;
161 }
162
163 if ( pTmpDocH )
164 pTmpDocH->ClearInterceptor();
165 }
166
DisconnectDocHolder()167 void Interceptor::DisconnectDocHolder()
168 {
169 osl::MutexGuard aGuard(m_aMutex);
170 m_xDocHLocker.clear();
171 m_pDocH = NULL;
172 m_xOleAccess = NULL;
173 }
174
175 //XDispatch
176 void SAL_CALL
dispatch(const util::URL & URL,const uno::Sequence<beans::PropertyValue> & Arguments)177 Interceptor::dispatch(
178 const util::URL& URL,
179 const uno::Sequence<
180 beans::PropertyValue >& Arguments )
181 {
182 ::rtl::Reference< EmbeddedDocumentInstanceAccess_Impl > xOleAccess;
183 {
184 osl::MutexGuard aGuard(m_aMutex);
185 xOleAccess = m_xOleAccess;
186 }
187
188 if ( xOleAccess.is() )
189 {
190 LockedEmbedDocument_Impl aDocLock = xOleAccess->GetEmbedDocument();
191 if ( aDocLock.GetEmbedDocument() )
192 {
193 if( !m_bLink && URL.Complete == m_aInterceptedURL[0])
194 aDocLock.GetEmbedDocument()->SaveObject();
195 else if(!m_bLink
196 && ( URL.Complete == m_aInterceptedURL[2] ||
197 URL.Complete == m_aInterceptedURL[3] ||
198 URL.Complete == m_aInterceptedURL[4] ) )
199 aDocLock.GetEmbedDocument()->Close( 0 );
200 else if ( URL.Complete == m_aInterceptedURL[5] )
201 {
202 uno::Sequence< beans::PropertyValue > aNewArgs = Arguments;
203 sal_Int32 nInd = 0;
204
205 while( nInd < aNewArgs.getLength() )
206 {
207 if ( aNewArgs[nInd].Name.equalsAscii( "SaveTo" ) )
208 {
209 aNewArgs[nInd].Value <<= sal_True;
210 break;
211 }
212 nInd++;
213 }
214
215 if ( nInd == aNewArgs.getLength() )
216 {
217 aNewArgs.realloc( nInd + 1 );
218 aNewArgs[nInd].Name = ::rtl::OUString::createFromAscii( "SaveTo" );
219 aNewArgs[nInd].Value <<= sal_True;
220 }
221
222 uno::Reference< frame::XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch(
223 URL, ::rtl::OUString::createFromAscii( "_self" ), 0 );
224 if ( xDispatch.is() )
225 xDispatch->dispatch( URL, aNewArgs );
226 }
227 }
228 }
229 }
230
231
generateFeatureStateEvent()232 void Interceptor::generateFeatureStateEvent()
233 {
234 if( m_pStatCL )
235 {
236 DocumentHolder* pTmpDocH = NULL;
237 uno::Reference< uno::XInterface > xLock;
238 {
239 osl::MutexGuard aGuard(m_aMutex);
240 xLock = m_xDocHLocker.get();
241 if ( xLock.is() )
242 pTmpDocH = m_pDocH;
243 }
244
245 ::rtl::OUString aTitle;
246 if ( pTmpDocH )
247 aTitle = pTmpDocH->getTitle();
248
249 for(int i = 0; i < IUL; ++i)
250 {
251 if( i == 1 || m_bLink && i != 5 )
252 continue;
253
254 cppu::OInterfaceContainerHelper* pICH =
255 m_pStatCL->getContainer(m_aInterceptedURL[i]);
256 uno::Sequence<uno::Reference<uno::XInterface> > aSeq;
257 if(pICH)
258 aSeq = pICH->getElements();
259 if(!aSeq.getLength())
260 continue;
261
262 frame::FeatureStateEvent aStateEvent;
263 aStateEvent.IsEnabled = sal_True;
264 aStateEvent.Requery = sal_False;
265 if(i == 0)
266 {
267
268 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[0];
269 aStateEvent.FeatureDescriptor = rtl::OUString(
270 RTL_CONSTASCII_USTRINGPARAM("Update"));
271 aStateEvent.State <<= (rtl::OUString(
272 RTL_CONSTASCII_USTRINGPARAM("($1) ")) +
273 aTitle);
274
275 }
276 else if ( i == 5 )
277 {
278 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[5];
279 aStateEvent.FeatureDescriptor = rtl::OUString(
280 RTL_CONSTASCII_USTRINGPARAM("SaveCopyTo"));
281 aStateEvent.State <<= (rtl::OUString(
282 RTL_CONSTASCII_USTRINGPARAM("($3)")));
283 }
284 else
285 {
286 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i];
287 aStateEvent.FeatureDescriptor = rtl::OUString(
288 RTL_CONSTASCII_USTRINGPARAM("Close and Return"));
289 aStateEvent.State <<= (rtl::OUString(
290 RTL_CONSTASCII_USTRINGPARAM("($2) ")) +
291 aTitle);
292
293 }
294
295 for(sal_Int32 k = 0; k < aSeq.getLength(); ++k)
296 {
297 uno::Reference<frame::XStatusListener>
298 Control(aSeq[k],uno::UNO_QUERY);
299 if(Control.is())
300 Control->statusChanged(aStateEvent);
301
302 }
303 }
304 }
305 }
306
307
308 void SAL_CALL
addStatusListener(const uno::Reference<frame::XStatusListener> & Control,const util::URL & URL)309 Interceptor::addStatusListener(
310 const uno::Reference<
311 frame::XStatusListener >& Control,
312 const util::URL& URL )
313 {
314 if(!Control.is())
315 return;
316
317 if( !m_bLink && URL.Complete == m_aInterceptedURL[0] )
318 { // Save
319 DocumentHolder* pTmpDocH = NULL;
320 uno::Reference< uno::XInterface > xLock;
321 {
322 osl::MutexGuard aGuard(m_aMutex);
323 xLock = m_xDocHLocker.get();
324 if ( xLock.is() )
325 pTmpDocH = m_pDocH;
326 }
327
328 ::rtl::OUString aTitle;
329 if ( pTmpDocH )
330 aTitle = pTmpDocH->getTitle();
331
332 frame::FeatureStateEvent aStateEvent;
333 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[0];
334 aStateEvent.FeatureDescriptor = rtl::OUString(
335 RTL_CONSTASCII_USTRINGPARAM("Update"));
336 aStateEvent.IsEnabled = sal_True;
337 aStateEvent.Requery = sal_False;
338 aStateEvent.State <<= (rtl::OUString(
339 RTL_CONSTASCII_USTRINGPARAM("($1) ")) +
340 aTitle );
341 Control->statusChanged(aStateEvent);
342
343 {
344 osl::MutexGuard aGuard(m_aMutex);
345 if(!m_pStatCL)
346 m_pStatCL =
347 new StatusChangeListenerContainer(m_aMutex);
348 }
349
350 m_pStatCL->addInterface(URL.Complete,Control);
351 return;
352 }
353
354 sal_Int32 i = 2;
355 if ( !m_bLink
356 && ( URL.Complete == m_aInterceptedURL[i] ||
357 URL.Complete == m_aInterceptedURL[++i] ||
358 URL.Complete == m_aInterceptedURL[++i] ) )
359 { // Close and return
360 DocumentHolder* pTmpDocH = NULL;
361 uno::Reference< uno::XInterface > xLock;
362 {
363 osl::MutexGuard aGuard(m_aMutex);
364 xLock = m_xDocHLocker.get();
365 if ( xLock.is() )
366 pTmpDocH = m_pDocH;
367 }
368
369 ::rtl::OUString aTitle;
370 if ( pTmpDocH )
371 aTitle = pTmpDocH->getTitle();
372
373 frame::FeatureStateEvent aStateEvent;
374 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i];
375 aStateEvent.FeatureDescriptor = rtl::OUString(
376 RTL_CONSTASCII_USTRINGPARAM("Close and Return"));
377 aStateEvent.IsEnabled = sal_True;
378 aStateEvent.Requery = sal_False;
379 aStateEvent.State <<= (rtl::OUString(
380 RTL_CONSTASCII_USTRINGPARAM("($2) ")) +
381 aTitle );
382 Control->statusChanged(aStateEvent);
383
384
385 {
386 osl::MutexGuard aGuard(m_aMutex);
387 if(!m_pStatCL)
388 m_pStatCL =
389 new StatusChangeListenerContainer(m_aMutex);
390 }
391
392 m_pStatCL->addInterface(URL.Complete,Control);
393 return;
394 }
395
396 if(URL.Complete == m_aInterceptedURL[5])
397 { // SaveAs
398 frame::FeatureStateEvent aStateEvent;
399 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[5];
400 aStateEvent.FeatureDescriptor = rtl::OUString(
401 RTL_CONSTASCII_USTRINGPARAM("SaveCopyTo"));
402 aStateEvent.IsEnabled = sal_True;
403 aStateEvent.Requery = sal_False;
404 aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($3)")));
405 Control->statusChanged(aStateEvent);
406
407 {
408 osl::MutexGuard aGuard(m_aMutex);
409 if(!m_pStatCL)
410 m_pStatCL =
411 new StatusChangeListenerContainer(m_aMutex);
412 }
413
414 m_pStatCL->addInterface(URL.Complete,Control);
415 return;
416 }
417
418 }
419
420
421 void SAL_CALL
removeStatusListener(const uno::Reference<frame::XStatusListener> & Control,const util::URL & URL)422 Interceptor::removeStatusListener(
423 const uno::Reference<
424 frame::XStatusListener >& Control,
425 const util::URL& URL )
426 {
427 if(!(Control.is() && m_pStatCL))
428 return;
429 else {
430 m_pStatCL->removeInterface(URL.Complete,Control);
431 return;
432 }
433 }
434
435
436 //XInterceptorInfo
437 uno::Sequence< ::rtl::OUString >
438 SAL_CALL
getInterceptedURLs()439 Interceptor::getInterceptedURLs( )
440 {
441 // now implemented as update
442 if ( m_bLink )
443 {
444 uno::Sequence< ::rtl::OUString > aResult( 2 );
445 aResult[0] = m_aInterceptedURL[1];
446 aResult[1] = m_aInterceptedURL[5];
447
448 return aResult;
449 }
450
451 return m_aInterceptedURL;
452 }
453
454
455 // XDispatchProvider
456
457 uno::Reference< frame::XDispatch > SAL_CALL
queryDispatch(const util::URL & URL,const::rtl::OUString & TargetFrameName,sal_Int32 SearchFlags)458 Interceptor::queryDispatch(
459 const util::URL& URL,
460 const ::rtl::OUString& TargetFrameName,
461 sal_Int32 SearchFlags )
462 {
463 osl::MutexGuard aGuard(m_aMutex);
464 if( !m_bLink && URL.Complete == m_aInterceptedURL[0] )
465 return (frame::XDispatch*)this;
466 else if(URL.Complete == m_aInterceptedURL[1])
467 return (frame::XDispatch*)0 ;
468 else if( !m_bLink && URL.Complete == m_aInterceptedURL[2] )
469 return (frame::XDispatch*)this;
470 else if( !m_bLink && URL.Complete == m_aInterceptedURL[3] )
471 return (frame::XDispatch*)this;
472 else if( !m_bLink && URL.Complete == m_aInterceptedURL[4] )
473 return (frame::XDispatch*)this;
474 else if(URL.Complete == m_aInterceptedURL[5])
475 return (frame::XDispatch*)this;
476 else {
477 if(m_xSlaveDispatchProvider.is())
478 return m_xSlaveDispatchProvider->queryDispatch(
479 URL,TargetFrameName,SearchFlags);
480 else
481 return uno::Reference<frame::XDispatch>(0);
482 }
483 }
484
485 uno::Sequence< uno::Reference< frame::XDispatch > > SAL_CALL
queryDispatches(const uno::Sequence<frame::DispatchDescriptor> & Requests)486 Interceptor::queryDispatches(
487 const uno::Sequence<frame::DispatchDescriptor >& Requests )
488 {
489 uno::Sequence< uno::Reference< frame::XDispatch > > aRet;
490 osl::MutexGuard aGuard(m_aMutex);
491 if(m_xSlaveDispatchProvider.is())
492 aRet = m_xSlaveDispatchProvider->queryDispatches(Requests);
493 else
494 aRet.realloc(Requests.getLength());
495
496 for(sal_Int32 i = 0; i < Requests.getLength(); ++i)
497 if ( !m_bLink && m_aInterceptedURL[0] == Requests[i].FeatureURL.Complete )
498 aRet[i] = (frame::XDispatch*) this;
499 else if(m_aInterceptedURL[1] == Requests[i].FeatureURL.Complete)
500 aRet[i] = (frame::XDispatch*) 0;
501 else if( !m_bLink && m_aInterceptedURL[2] == Requests[i].FeatureURL.Complete )
502 aRet[i] = (frame::XDispatch*) this;
503 else if( !m_bLink && m_aInterceptedURL[3] == Requests[i].FeatureURL.Complete )
504 aRet[i] = (frame::XDispatch*) this;
505 else if( !m_bLink && m_aInterceptedURL[4] == Requests[i].FeatureURL.Complete )
506 aRet[i] = (frame::XDispatch*) this;
507 else if(m_aInterceptedURL[5] == Requests[i].FeatureURL.Complete)
508 aRet[i] = (frame::XDispatch*) this;
509
510 return aRet;
511 }
512
513
514
515 //XDispatchProviderInterceptor
516
517 uno::Reference< frame::XDispatchProvider > SAL_CALL
getSlaveDispatchProvider()518 Interceptor::getSlaveDispatchProvider( )
519 {
520 osl::MutexGuard aGuard(m_aMutex);
521 return m_xSlaveDispatchProvider;
522 }
523
524 void SAL_CALL
setSlaveDispatchProvider(const uno::Reference<frame::XDispatchProvider> & NewDispatchProvider)525 Interceptor::setSlaveDispatchProvider(
526 const uno::Reference< frame::XDispatchProvider >& NewDispatchProvider )
527 {
528 osl::MutexGuard aGuard(m_aMutex);
529 m_xSlaveDispatchProvider = NewDispatchProvider;
530 }
531
532
533 uno::Reference< frame::XDispatchProvider > SAL_CALL
getMasterDispatchProvider()534 Interceptor::getMasterDispatchProvider( )
535 {
536 osl::MutexGuard aGuard(m_aMutex);
537 return m_xMasterDispatchProvider;
538 }
539
540
541 void SAL_CALL
setMasterDispatchProvider(const uno::Reference<frame::XDispatchProvider> & NewSupplier)542 Interceptor::setMasterDispatchProvider(
543 const uno::Reference< frame::XDispatchProvider >& NewSupplier )
544 {
545 osl::MutexGuard aGuard(m_aMutex);
546 m_xMasterDispatchProvider = NewSupplier;
547 }
548
549 // Fix strange warnings about some
550 // ATL::CAxHostWindow::QueryInterface|AddRef|Releae functions.
551 // warning C4505: 'xxx' : unreferenced local function has been removed
552 #if defined(_MSC_VER)
553 #pragma warning(disable: 4505)
554 #endif
555