xref: /AOO41X/main/embedserv/source/embed/intercept.cxx (revision f78e906fe6611930dd4144841172bc2d210ddf78)
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