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