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