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