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 { 44 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 { 55 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: 68 StatusChangeListenerContainer( ::osl::Mutex& aMutex ) 69 : cppu::OMultiTypeInterfaceContainerHelperVar< 70 rtl::OUString,hashOUString,equalOUString>(aMutex) 71 { 72 } 73 }; 74 75 76 void SAL_CALL 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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