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