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 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sfx2.hxx" 30 31 //-------------------------------------------------------------------------------------------------------- 32 #include <com/sun/star/beans/PropertyValue.hpp> 33 34 #ifndef _COM_SUN_STAR_UTL_URL_HPP_ 35 #include <com/sun/star/util/URL.hpp> 36 #endif 37 38 #ifndef _COM_SUN_STAR_UTL_XURLTRANSFORMER_HPP_ 39 #include <com/sun/star/util/XURLTransformer.hpp> 40 #endif 41 #include <tools/urlobj.hxx> 42 #include <tools/diagnose_ex.h> 43 #include <svl/macitem.hxx> 44 #include <sfx2/appuno.hxx> 45 #include <sfx2/objsh.hxx> 46 #include <sfx2/sfxbasemodel.hxx> 47 #include <sfx2/evntconf.hxx> 48 #include <unotools/eventcfg.hxx> 49 50 #include <unotools/securityoptions.hxx> 51 #include <comphelper/processfactory.hxx> 52 #include <comphelper/namedvaluecollection.hxx> 53 #include "eventsupplier.hxx" 54 55 #include <sfx2/app.hxx> 56 #include "sfx2/sfxresid.hxx" 57 58 #include <sfx2/sfxsids.hrc> 59 #include "sfxlocal.hrc" 60 #include <sfx2/docfile.hxx> 61 #include <sfx2/viewfrm.hxx> 62 #include <sfx2/frame.hxx> 63 64 //-------------------------------------------------------------------------------------------------------- 65 66 #define MACRO_PRFIX "macro://" 67 #define MACRO_POSTFIX "()" 68 69 //-------------------------------------------------------------------------------------------------------- 70 71 #define PROPERTYVALUE ::com::sun::star::beans::PropertyValue 72 #define UNO_QUERY ::com::sun::star::uno::UNO_QUERY 73 74 namespace css = ::com::sun::star; 75 using ::com::sun::star::uno::Sequence; 76 using ::com::sun::star::beans::PropertyValue; 77 78 //-------------------------------------------------------------------------------------------------------- 79 // --- XNameReplace --- 80 //-------------------------------------------------------------------------------------------------------- 81 void SAL_CALL SfxEvents_Impl::replaceByName( const OUSTRING & aName, const ANY & rElement ) 82 throw( ILLEGALARGUMENTEXCEPTION, NOSUCHELEMENTEXCEPTION, 83 WRAPPEDTARGETEXCEPTION, RUNTIMEEXCEPTION ) 84 { 85 ::osl::MutexGuard aGuard( maMutex ); 86 87 // find the event in the list and replace the data 88 long nCount = maEventNames.getLength(); 89 for ( long i=0; i<nCount; i++ ) 90 { 91 if ( maEventNames[i] == aName ) 92 { 93 const ::comphelper::NamedValueCollection aEventDescriptor( rElement ); 94 // check for correct type of the element 95 if ( rElement.hasValue() && aEventDescriptor.empty() ) 96 throw ILLEGALARGUMENTEXCEPTION(); 97 98 // create Configuration at first, creation might call this method also and that would overwrite everything 99 // we might have stored before! 100 if ( mpObjShell && !mpObjShell->IsLoading() ) 101 mpObjShell->SetModified( sal_True ); 102 103 ::comphelper::NamedValueCollection aNormalizedDescriptor; 104 NormalizeMacro( aEventDescriptor, aNormalizedDescriptor, mpObjShell ); 105 106 ::rtl::OUString sType; 107 if ( ( aNormalizedDescriptor.size() == 1 ) 108 && ( aNormalizedDescriptor.has( PROP_EVENT_TYPE ) == 0 ) 109 && ( aNormalizedDescriptor.get( PROP_EVENT_TYPE ) >>= sType ) 110 && ( sType.getLength() == 0 ) 111 ) 112 { 113 // An empty event type means no binding. Therefore reset data 114 // to reflect that state. 115 // (that's for compatibility only. Nowadays, the Tools/Customize dialog should 116 // set an empty sequence to indicate the request for resetting the assignment.) 117 OSL_ENSURE( false, "legacy event assignment format detected" ); 118 aNormalizedDescriptor.clear(); 119 } 120 121 if ( !aNormalizedDescriptor.empty() ) 122 { 123 maEventData[i] <<= aNormalizedDescriptor.getPropertyValues(); 124 } 125 else 126 { 127 maEventData[i].clear(); 128 } 129 return; 130 } 131 } 132 133 throw NOSUCHELEMENTEXCEPTION(); 134 } 135 136 //-------------------------------------------------------------------------------------------------------- 137 // --- XNameAccess --- 138 //-------------------------------------------------------------------------------------------------------- 139 ANY SAL_CALL SfxEvents_Impl::getByName( const OUSTRING& aName ) 140 throw( NOSUCHELEMENTEXCEPTION, WRAPPEDTARGETEXCEPTION, 141 RUNTIMEEXCEPTION ) 142 { 143 ::osl::MutexGuard aGuard( maMutex ); 144 145 // find the event in the list and return the data 146 147 long nCount = maEventNames.getLength(); 148 149 for ( long i=0; i<nCount; i++ ) 150 { 151 if ( maEventNames[i] == aName ) 152 return maEventData[i]; 153 } 154 155 throw NOSUCHELEMENTEXCEPTION(); 156 } 157 158 //-------------------------------------------------------------------------------------------------------- 159 SEQUENCE< OUSTRING > SAL_CALL SfxEvents_Impl::getElementNames() throw ( RUNTIMEEXCEPTION ) 160 { 161 return maEventNames; 162 } 163 164 //-------------------------------------------------------------------------------------------------------- 165 sal_Bool SAL_CALL SfxEvents_Impl::hasByName( const OUSTRING& aName ) throw ( RUNTIMEEXCEPTION ) 166 { 167 ::osl::MutexGuard aGuard( maMutex ); 168 169 // find the event in the list and return the data 170 171 long nCount = maEventNames.getLength(); 172 173 for ( long i=0; i<nCount; i++ ) 174 { 175 if ( maEventNames[i] == aName ) 176 return sal_True; 177 } 178 179 return sal_False; 180 } 181 182 //-------------------------------------------------------------------------------------------------------- 183 // --- XElementAccess ( parent of XNameAccess ) --- 184 //-------------------------------------------------------------------------------------------------------- 185 UNOTYPE SAL_CALL SfxEvents_Impl::getElementType() throw ( RUNTIMEEXCEPTION ) 186 { 187 UNOTYPE aElementType = ::getCppuType( (const SEQUENCE < PROPERTYVALUE > *)0 ); 188 return aElementType; 189 } 190 191 //-------------------------------------------------------------------------------------------------------- 192 sal_Bool SAL_CALL SfxEvents_Impl::hasElements() throw ( RUNTIMEEXCEPTION ) 193 { 194 ::osl::MutexGuard aGuard( maMutex ); 195 196 if ( maEventNames.getLength() ) 197 return sal_True; 198 else 199 return sal_False; 200 } 201 202 static void Execute( ANY& aEventData, const css::document::DocumentEvent& aTrigger, SfxObjectShell* pDoc ) 203 { 204 SEQUENCE < PROPERTYVALUE > aProperties; 205 if ( aEventData >>= aProperties ) 206 { 207 OUSTRING aPrefix = OUSTRING( RTL_CONSTASCII_USTRINGPARAM( MACRO_PRFIX ) ); 208 OUSTRING aType; 209 OUSTRING aScript; 210 OUSTRING aLibrary; 211 OUSTRING aMacroName; 212 213 sal_Int32 nCount = aProperties.getLength(); 214 215 if ( !nCount ) 216 return; 217 218 sal_Int32 nIndex = 0; 219 while ( nIndex < nCount ) 220 { 221 if ( aProperties[ nIndex ].Name.compareToAscii( PROP_EVENT_TYPE ) == 0 ) 222 aProperties[ nIndex ].Value >>= aType; 223 else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_SCRIPT ) == 0 ) 224 aProperties[ nIndex ].Value >>= aScript; 225 else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_LIBRARY ) == 0 ) 226 aProperties[ nIndex ].Value >>= aLibrary; 227 else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_MACRO_NAME ) == 0 ) 228 aProperties[ nIndex ].Value >>= aMacroName; 229 else { 230 DBG_ERROR("Unknown property value!"); 231 } 232 nIndex += 1; 233 } 234 235 if ( aType.compareToAscii( STAR_BASIC ) == 0 && aScript.getLength() ) 236 { 237 com::sun::star::uno::Any aAny; 238 SfxMacroLoader::loadMacro( aScript, aAny, pDoc ); 239 } 240 else if ( aType.compareToAscii( "Service" ) == 0 || 241 aType.compareToAscii( "Script" ) == 0 ) 242 { 243 if ( aScript.getLength() ) 244 { 245 SfxViewFrame* pView = pDoc ? 246 SfxViewFrame::GetFirst( pDoc ) : 247 SfxViewFrame::Current(); 248 249 ::com::sun::star::uno::Reference 250 < ::com::sun::star::util::XURLTransformer > xTrans( 251 ::comphelper::getProcessServiceFactory()->createInstance( 252 rtl::OUString::createFromAscii( 253 "com.sun.star.util.URLTransformer" ) ), 254 UNO_QUERY ); 255 256 ::com::sun::star::util::URL aURL; 257 aURL.Complete = aScript; 258 xTrans->parseStrict( aURL ); 259 260 ::com::sun::star::uno::Reference 261 < ::com::sun::star::frame::XDispatchProvider > xProv; 262 263 if ( pView != NULL ) 264 { 265 xProv = ::com::sun::star::uno::Reference 266 < ::com::sun::star::frame::XDispatchProvider > ( 267 pView->GetFrame().GetFrameInterface(), UNO_QUERY ); 268 } 269 else 270 { 271 xProv = ::com::sun::star::uno::Reference 272 < ::com::sun::star::frame::XDispatchProvider > ( 273 ::comphelper::getProcessServiceFactory()->createInstance( 274 rtl::OUString::createFromAscii( 275 "com.sun.star.frame.Desktop" ) ), 276 UNO_QUERY ); 277 } 278 279 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatch > xDisp; 280 if ( xProv.is() ) 281 xDisp = xProv->queryDispatch( aURL, ::rtl::OUString(), 0 ); 282 283 if ( xDisp.is() ) 284 { 285 //::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue > aArgs(1); 286 //aArgs[0].Name = rtl::OUString::createFromAscii("Referer"); 287 //aArs[0].Value <<= ::rtl::OUString( pDoc->GetMedium()->GetName() ); 288 //xDisp->dispatch( aURL, aArgs ); 289 290 css::beans::PropertyValue aEventParam; 291 aEventParam.Value <<= aTrigger; 292 css::uno::Sequence< css::beans::PropertyValue > aDispatchArgs( &aEventParam, 1 ); 293 xDisp->dispatch( aURL, aDispatchArgs ); 294 } 295 } 296 } 297 else if ( aType.getLength() == 0 ) 298 { 299 // Empty type means no active binding for the event. Just ignore do nothing. 300 } 301 else 302 { 303 DBG_ERRORFILE( "notifyEvent(): Unsupported event type" ); 304 } 305 } 306 } 307 308 //-------------------------------------------------------------------------------------------------------- 309 // --- ::document::XEventListener --- 310 //-------------------------------------------------------------------------------------------------------- 311 void SAL_CALL SfxEvents_Impl::notifyEvent( const DOCEVENTOBJECT& aEvent ) throw( RUNTIMEEXCEPTION ) 312 { 313 ::osl::ClearableMutexGuard aGuard( maMutex ); 314 315 // get the event name, find the coresponding data, execute the data 316 317 OUSTRING aName = aEvent.EventName; 318 long nCount = maEventNames.getLength(); 319 long nIndex = 0; 320 sal_Bool bFound = sal_False; 321 322 while ( !bFound && ( nIndex < nCount ) ) 323 { 324 if ( maEventNames[nIndex] == aName ) 325 bFound = sal_True; 326 else 327 nIndex += 1; 328 } 329 330 if ( !bFound ) 331 return; 332 333 ANY aEventData = maEventData[ nIndex ]; 334 aGuard.clear(); 335 Execute( aEventData, css::document::DocumentEvent(aEvent.Source, aEvent.EventName, NULL, css::uno::Any()), mpObjShell ); 336 } 337 338 //-------------------------------------------------------------------------------------------------------- 339 // --- ::lang::XEventListener --- 340 //-------------------------------------------------------------------------------------------------------- 341 void SAL_CALL SfxEvents_Impl::disposing( const EVENTOBJECT& /*Source*/ ) throw( RUNTIMEEXCEPTION ) 342 { 343 ::osl::MutexGuard aGuard( maMutex ); 344 345 if ( mxBroadcaster.is() ) 346 { 347 mxBroadcaster->removeEventListener( this ); 348 mxBroadcaster = NULL; 349 } 350 } 351 352 //-------------------------------------------------------------------------------------------------------- 353 // 354 //-------------------------------------------------------------------------------------------------------- 355 SfxEvents_Impl::SfxEvents_Impl( SfxObjectShell* pShell, 356 REFERENCE< XEVENTBROADCASTER > xBroadcaster ) 357 { 358 // get the list of supported events and store it 359 if ( pShell ) 360 maEventNames = pShell->GetEventNames(); 361 else 362 maEventNames = GlobalEventConfig().getElementNames(); 363 364 maEventData = SEQUENCE < ANY > ( maEventNames.getLength() ); 365 366 mpObjShell = pShell; 367 mxBroadcaster = xBroadcaster; 368 369 if ( mxBroadcaster.is() ) 370 mxBroadcaster->addEventListener( this ); 371 } 372 373 //-------------------------------------------------------------------------------------------------------- 374 SfxEvents_Impl::~SfxEvents_Impl() 375 { 376 } 377 378 //-------------------------------------------------------------------------------------------------------- 379 SvxMacro* SfxEvents_Impl::ConvertToMacro( const ANY& rElement, SfxObjectShell* pObjShell, sal_Bool bNormalizeMacro ) 380 { 381 SvxMacro* pMacro = NULL; 382 SEQUENCE < PROPERTYVALUE > aProperties; 383 ANY aAny; 384 if ( bNormalizeMacro ) 385 NormalizeMacro( rElement, aAny, pObjShell ); 386 else 387 aAny = rElement; 388 389 if ( aAny >>= aProperties ) 390 { 391 OUSTRING aType; 392 OUSTRING aScriptURL; 393 OUSTRING aLibrary; 394 OUSTRING aMacroName; 395 396 long nCount = aProperties.getLength(); 397 long nIndex = 0; 398 399 if ( !nCount ) 400 return pMacro; 401 402 while ( nIndex < nCount ) 403 { 404 if ( aProperties[ nIndex ].Name.compareToAscii( PROP_EVENT_TYPE ) == 0 ) 405 aProperties[ nIndex ].Value >>= aType; 406 else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_SCRIPT ) == 0 ) 407 aProperties[ nIndex ].Value >>= aScriptURL; 408 else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_LIBRARY ) == 0 ) 409 aProperties[ nIndex ].Value >>= aLibrary; 410 else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_MACRO_NAME ) == 0 ) 411 aProperties[ nIndex ].Value >>= aMacroName; 412 else { 413 DBG_ERROR("Unknown propery value!"); 414 } 415 nIndex += 1; 416 } 417 418 // Get the type 419 ScriptType eType( STARBASIC ); 420 if ( aType.compareToAscii( STAR_BASIC ) == COMPARE_EQUAL ) 421 eType = STARBASIC; 422 else if ( aType.compareToAscii( "Script" ) == COMPARE_EQUAL && aScriptURL.getLength() ) 423 eType = EXTENDED_STYPE; 424 else if ( aType.compareToAscii( SVX_MACRO_LANGUAGE_JAVASCRIPT ) == COMPARE_EQUAL ) 425 eType = JAVASCRIPT; 426 else { 427 DBG_ERRORFILE( "ConvertToMacro: Unknown macro type" ); 428 } 429 430 if ( aMacroName.getLength() ) 431 { 432 if ( aLibrary.compareToAscii("application") == 0 ) 433 aLibrary = SFX_APP()->GetName(); 434 else 435 aLibrary = ::rtl::OUString(); 436 pMacro = new SvxMacro( aMacroName, aLibrary, eType ); 437 } 438 else if ( eType == EXTENDED_STYPE ) 439 pMacro = new SvxMacro( aScriptURL, aType ); 440 } 441 442 return pMacro; 443 } 444 445 void SfxEvents_Impl::NormalizeMacro( const ANY& rEvent, ANY& rRet, SfxObjectShell* pDoc ) 446 { 447 const ::comphelper::NamedValueCollection aEventDescriptor( rEvent ); 448 ::comphelper::NamedValueCollection aEventDescriptorOut; 449 450 NormalizeMacro( aEventDescriptor, aEventDescriptorOut, pDoc ); 451 452 rRet <<= aEventDescriptorOut.getPropertyValues(); 453 } 454 455 void SfxEvents_Impl::NormalizeMacro( const ::comphelper::NamedValueCollection& i_eventDescriptor, 456 ::comphelper::NamedValueCollection& o_normalizedDescriptor, SfxObjectShell* i_document ) 457 { 458 SfxObjectShell* pDoc = i_document; 459 if ( !pDoc ) 460 pDoc = SfxObjectShell::Current(); 461 462 ::rtl::OUString aType = i_eventDescriptor.getOrDefault( PROP_EVENT_TYPE, ::rtl::OUString() ); 463 ::rtl::OUString aScript = i_eventDescriptor.getOrDefault( PROP_SCRIPT, ::rtl::OUString() ); 464 ::rtl::OUString aLibrary = i_eventDescriptor.getOrDefault( PROP_LIBRARY, ::rtl::OUString() ); 465 ::rtl::OUString aMacroName = i_eventDescriptor.getOrDefault( PROP_MACRO_NAME, ::rtl::OUString() ); 466 467 if ( aType.getLength() ) 468 o_normalizedDescriptor.put( PROP_EVENT_TYPE, aType ); 469 if ( aScript.getLength() ) 470 o_normalizedDescriptor.put( PROP_SCRIPT, aScript ); 471 472 if ( aType.compareToAscii( STAR_BASIC ) == 0 ) 473 { 474 if ( aScript.getLength() ) 475 { 476 if ( !aMacroName.getLength() || !aLibrary.getLength() ) 477 { 478 sal_Int32 nHashPos = aScript.indexOf( '/', 8 ); 479 sal_Int32 nArgsPos = aScript.indexOf( '(' ); 480 if ( ( nHashPos != STRING_NOTFOUND ) && ( nHashPos < nArgsPos ) ) 481 { 482 OUSTRING aBasMgrName( INetURLObject::decode( aScript.copy( 8, nHashPos-8 ), INET_HEX_ESCAPE, INetURLObject::DECODE_WITH_CHARSET ) ); 483 if ( aBasMgrName.compareToAscii(".") == 0 ) 484 aLibrary = pDoc->GetTitle(); 485 /* 486 else if ( aBasMgrName.getLength() ) 487 aLibrary = aBasMgrName; 488 */ 489 else 490 aLibrary = SFX_APP()->GetName(); 491 492 // Get the macro name 493 aMacroName = aScript.copy( nHashPos+1, nArgsPos - nHashPos - 1 ); 494 } 495 else 496 { 497 DBG_ERRORFILE( "ConvertToMacro: Unknown macro url format" ); 498 } 499 } 500 } 501 else if ( aMacroName.getLength() ) 502 { 503 aScript = OUSTRING( RTL_CONSTASCII_USTRINGPARAM( MACRO_PRFIX ) ); 504 if ( aLibrary.compareTo( SFX_APP()->GetName() ) != 0 && aLibrary.compareToAscii("StarDesktop") != 0 && aLibrary.compareToAscii("application") != 0 ) 505 aScript += String('.'); 506 507 aScript += String('/'); 508 aScript += aMacroName; 509 aScript += OUSTRING( RTL_CONSTASCII_USTRINGPARAM( MACRO_POSTFIX ) ); 510 } 511 else 512 // wrong properties 513 return; 514 515 if ( aLibrary.compareToAscii("document") != 0 ) 516 { 517 if ( !aLibrary.getLength() || (pDoc && ( String(aLibrary) == pDoc->GetTitle( SFX_TITLE_APINAME ) || String(aLibrary) == pDoc->GetTitle() )) ) 518 aLibrary = String::CreateFromAscii("document"); 519 else 520 aLibrary = String::CreateFromAscii("application"); 521 } 522 523 o_normalizedDescriptor.put( PROP_SCRIPT, aScript ); 524 o_normalizedDescriptor.put( PROP_LIBRARY, aLibrary ); 525 o_normalizedDescriptor.put( PROP_MACRO_NAME, aMacroName ); 526 } 527 } 528 529 ModelCollectionEnumeration::ModelCollectionEnumeration(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) 530 : ModelCollectionMutexBase( ) 531 , m_xSMGR (xSMGR ) 532 , m_pEnumerationIt (m_lModels.begin()) 533 { 534 } 535 536 ModelCollectionEnumeration::~ModelCollectionEnumeration() 537 { 538 } 539 540 void ModelCollectionEnumeration::setModelList(const TModelList& rList) 541 { 542 // SAFE -> 543 ::osl::ResettableMutexGuard aLock(m_aLock); 544 m_lModels = rList; 545 m_pEnumerationIt = m_lModels.begin(); 546 aLock.clear(); 547 // <- SAFE 548 } 549 550 sal_Bool SAL_CALL ModelCollectionEnumeration::hasMoreElements() 551 throw(css::uno::RuntimeException) 552 { 553 // SAFE -> 554 ::osl::ResettableMutexGuard aLock(m_aLock); 555 return (m_pEnumerationIt != m_lModels.end()); 556 // <- SAFE 557 } 558 559 css::uno::Any SAL_CALL ModelCollectionEnumeration::nextElement() 560 throw(css::container::NoSuchElementException, 561 css::lang::WrappedTargetException , 562 css::uno::RuntimeException ) 563 { 564 // SAFE -> 565 ::osl::ResettableMutexGuard aLock(m_aLock); 566 if (m_pEnumerationIt == m_lModels.end()) 567 throw css::container::NoSuchElementException( 568 ::rtl::OUString::createFromAscii("End of model enumeration reached."), 569 static_cast< css::container::XEnumeration* >(this)); 570 css::uno::Reference< css::frame::XModel > xModel(*m_pEnumerationIt, UNO_QUERY); 571 ++m_pEnumerationIt; 572 aLock.clear(); 573 // <- SAFE 574 575 return css::uno::makeAny(xModel); 576 } 577 578 SFX_IMPL_XSERVICEINFO( SfxGlobalEvents_Impl, "com.sun.star.frame.GlobalEventBroadcaster", "com.sun.star.comp.sfx2.GlobalEventBroadcaster" ) 579 SFX_IMPL_ONEINSTANCEFACTORY( SfxGlobalEvents_Impl ); 580 581 //----------------------------------------------------------------------------- 582 SfxGlobalEvents_Impl::SfxGlobalEvents_Impl( const com::sun::star::uno::Reference < ::com::sun::star::lang::XMultiServiceFactory >& xSMGR) 583 : ModelCollectionMutexBase( ) 584 , m_xSMGR (xSMGR ) 585 , m_aLegacyListeners (m_aLock) 586 , m_aDocumentListeners (m_aLock) 587 , pImp (0 ) 588 { 589 m_refCount++; 590 SFX_APP(); 591 pImp = new GlobalEventConfig(); 592 m_xEvents = pImp; 593 m_xJobExecutorListener = css::uno::Reference< css::document::XEventListener >( 594 xSMGR->createInstance(::rtl::OUString::createFromAscii("com.sun.star.task.JobExecutor")), 595 UNO_QUERY); 596 m_refCount--; 597 } 598 599 //----------------------------------------------------------------------------- 600 SfxGlobalEvents_Impl::~SfxGlobalEvents_Impl() 601 { 602 } 603 604 //----------------------------------------------------------------------------- 605 css::uno::Reference< css::container::XNameReplace > SAL_CALL SfxGlobalEvents_Impl::getEvents() 606 throw(css::uno::RuntimeException) 607 { 608 // SAFE -> 609 ::osl::ResettableMutexGuard aLock(m_aLock); 610 return m_xEvents; 611 // <- SAFE 612 } 613 614 //----------------------------------------------------------------------------- 615 void SAL_CALL SfxGlobalEvents_Impl::addEventListener(const css::uno::Reference< css::document::XEventListener >& xListener) 616 throw(css::uno::RuntimeException) 617 { 618 // container is threadsafe 619 m_aLegacyListeners.addInterface(xListener); 620 } 621 622 //----------------------------------------------------------------------------- 623 void SAL_CALL SfxGlobalEvents_Impl::removeEventListener(const css::uno::Reference< css::document::XEventListener >& xListener) 624 throw(css::uno::RuntimeException) 625 { 626 // container is threadsafe 627 m_aLegacyListeners.removeInterface(xListener); 628 } 629 630 //----------------------------------------------------------------------------- 631 void SAL_CALL SfxGlobalEvents_Impl::addDocumentEventListener( const css::uno::Reference< css::document::XDocumentEventListener >& _Listener ) 632 throw(css::uno::RuntimeException) 633 { 634 m_aDocumentListeners.addInterface( _Listener ); 635 } 636 637 //----------------------------------------------------------------------------- 638 void SAL_CALL SfxGlobalEvents_Impl::removeDocumentEventListener( const css::uno::Reference< css::document::XDocumentEventListener >& _Listener ) 639 throw(css::uno::RuntimeException) 640 { 641 m_aDocumentListeners.removeInterface( _Listener ); 642 } 643 644 //----------------------------------------------------------------------------- 645 void SAL_CALL SfxGlobalEvents_Impl::notifyDocumentEvent( const ::rtl::OUString& /*_EventName*/, 646 const css::uno::Reference< css::frame::XController2 >& /*_ViewController*/, const css::uno::Any& /*_Supplement*/ ) 647 throw (css::lang::IllegalArgumentException, css::lang::NoSupportException, css::uno::RuntimeException) 648 { 649 // we're a multiplexer only, no chance to generate artifical events here 650 throw css::lang::NoSupportException(::rtl::OUString(), *this); 651 } 652 653 //----------------------------------------------------------------------------- 654 void SAL_CALL SfxGlobalEvents_Impl::notifyEvent(const css::document::EventObject& aEvent) 655 throw(css::uno::RuntimeException) 656 { 657 css::document::DocumentEvent aDocEvent(aEvent.Source, aEvent.EventName, NULL, css::uno::Any()); 658 implts_notifyJobExecution(aEvent); 659 implts_checkAndExecuteEventBindings(aDocEvent); 660 implts_notifyListener(aDocEvent); 661 } 662 663 //----------------------------------------------------------------------------- 664 void SAL_CALL SfxGlobalEvents_Impl::documentEventOccured( const ::css::document::DocumentEvent& _Event ) 665 throw (::css::uno::RuntimeException) 666 { 667 implts_notifyJobExecution(css::document::EventObject(_Event.Source, _Event.EventName)); 668 implts_checkAndExecuteEventBindings(_Event); 669 implts_notifyListener(_Event); 670 } 671 672 //----------------------------------------------------------------------------- 673 void SAL_CALL SfxGlobalEvents_Impl::disposing(const css::lang::EventObject& aEvent) 674 throw(css::uno::RuntimeException) 675 { 676 css::uno::Reference< css::frame::XModel > xDoc(aEvent.Source, UNO_QUERY); 677 678 // SAFE -> 679 ::osl::ResettableMutexGuard aLock(m_aLock); 680 TModelList::iterator pIt = impl_searchDoc(xDoc); 681 if (pIt != m_lModels.end()) 682 m_lModels.erase(pIt); 683 aLock.clear(); 684 // <- SAFE 685 } 686 687 //----------------------------------------------------------------------------- 688 sal_Bool SAL_CALL SfxGlobalEvents_Impl::has(const css::uno::Any& aElement) 689 throw (css::uno::RuntimeException) 690 { 691 css::uno::Reference< css::frame::XModel > xDoc; 692 aElement >>= xDoc; 693 694 sal_Bool bHas = sal_False; 695 696 // SAFE -> 697 ::osl::ResettableMutexGuard aLock(m_aLock); 698 TModelList::iterator pIt = impl_searchDoc(xDoc); 699 if (pIt != m_lModels.end()) 700 bHas = sal_True; 701 aLock.clear(); 702 // <- SAFE 703 704 return bHas; 705 } 706 707 //----------------------------------------------------------------------------- 708 void SAL_CALL SfxGlobalEvents_Impl::insert( const css::uno::Any& aElement ) 709 throw (css::lang::IllegalArgumentException , 710 css::container::ElementExistException, 711 css::uno::RuntimeException ) 712 { 713 css::uno::Reference< css::frame::XModel > xDoc; 714 aElement >>= xDoc; 715 if (!xDoc.is()) 716 throw css::lang::IllegalArgumentException( 717 ::rtl::OUString::createFromAscii("Cant locate at least the model parameter."), 718 static_cast< css::container::XSet* >(this), 719 0); 720 721 // SAFE -> 722 ::osl::ResettableMutexGuard aLock(m_aLock); 723 TModelList::iterator pIt = impl_searchDoc(xDoc); 724 if (pIt != m_lModels.end()) 725 throw css::container::ElementExistException( 726 ::rtl::OUString(), 727 static_cast< css::container::XSet* >(this)); 728 m_lModels.push_back(xDoc); 729 aLock.clear(); 730 // <- SAFE 731 732 css::uno::Reference< css::document::XDocumentEventBroadcaster > xDocBroadcaster(xDoc, UNO_QUERY ); 733 if (xDocBroadcaster.is()) 734 xDocBroadcaster->addDocumentEventListener(this); 735 else 736 { 737 // try the "legacy version" of XDocumentEventBroadcaster, which is XEventBroadcaster 738 css::uno::Reference< css::document::XEventBroadcaster > xBroadcaster(xDoc, UNO_QUERY); 739 if (xBroadcaster.is()) 740 xBroadcaster->addEventListener(static_cast< css::document::XEventListener* >(this)); 741 } 742 } 743 744 //----------------------------------------------------------------------------- 745 void SAL_CALL SfxGlobalEvents_Impl::remove( const css::uno::Any& aElement ) 746 throw (css::lang::IllegalArgumentException , 747 css::container::NoSuchElementException, 748 css::uno::RuntimeException ) 749 { 750 css::uno::Reference< css::frame::XModel > xDoc; 751 aElement >>= xDoc; 752 if (!xDoc.is()) 753 throw css::lang::IllegalArgumentException( 754 ::rtl::OUString::createFromAscii("Cant locate at least the model parameter."), 755 static_cast< css::container::XSet* >(this), 756 0); 757 758 // SAFE -> 759 ::osl::ResettableMutexGuard aLock(m_aLock); 760 TModelList::iterator pIt = impl_searchDoc(xDoc); 761 if (pIt == m_lModels.end()) 762 throw css::container::NoSuchElementException( 763 ::rtl::OUString(), 764 static_cast< css::container::XSet* >(this)); 765 m_lModels.erase(pIt); 766 aLock.clear(); 767 // <- SAFE 768 769 css::uno::Reference< css::document::XDocumentEventBroadcaster > xDocBroadcaster(xDoc, UNO_QUERY ); 770 if (xDocBroadcaster.is()) 771 xDocBroadcaster->removeDocumentEventListener(this); 772 else 773 { 774 // try the "legacy version" of XDocumentEventBroadcaster, which is XEventBroadcaster 775 css::uno::Reference< css::document::XEventBroadcaster > xBroadcaster(xDoc, UNO_QUERY); 776 if (xBroadcaster.is()) 777 xBroadcaster->removeEventListener(static_cast< css::document::XEventListener* >(this)); 778 } 779 } 780 781 //----------------------------------------------------------------------------- 782 css::uno::Reference< css::container::XEnumeration > SAL_CALL SfxGlobalEvents_Impl::createEnumeration() 783 throw (css::uno::RuntimeException) 784 { 785 // SAFE -> 786 ::osl::ResettableMutexGuard aLock(m_aLock); 787 ModelCollectionEnumeration* pEnum = new ModelCollectionEnumeration(m_xSMGR); 788 pEnum->setModelList(m_lModels); 789 css::uno::Reference< css::container::XEnumeration > xEnum( 790 static_cast< css::container::XEnumeration* >(pEnum), 791 UNO_QUERY); 792 aLock.clear(); 793 // <- SAFE 794 795 return xEnum; 796 } 797 798 //----------------------------------------------------------------------------- 799 css::uno::Type SAL_CALL SfxGlobalEvents_Impl::getElementType() 800 throw (css::uno::RuntimeException) 801 { 802 return ::getCppuType(static_cast< css::uno::Reference< css::frame::XModel >* >(NULL)); 803 } 804 805 //----------------------------------------------------------------------------- 806 sal_Bool SAL_CALL SfxGlobalEvents_Impl::hasElements() 807 throw (css::uno::RuntimeException) 808 { 809 // SAFE -> 810 ::osl::ResettableMutexGuard aLock(m_aLock); 811 return (m_lModels.size()>0); 812 // <- SAFE 813 } 814 815 //----------------------------------------------------------------------------- 816 void SfxGlobalEvents_Impl::implts_notifyJobExecution(const css::document::EventObject& aEvent) 817 { 818 try 819 { 820 // SAFE -> 821 ::osl::ResettableMutexGuard aLock(m_aLock); 822 css::uno::Reference< css::document::XEventListener > xJobExecutor(m_xJobExecutorListener); 823 aLock.clear(); 824 // <- SAFE 825 if (xJobExecutor.is()) 826 xJobExecutor->notifyEvent(aEvent); 827 } 828 catch(const css::uno::RuntimeException& exRun) 829 { throw exRun; } 830 catch(const css::uno::Exception&) 831 {} 832 } 833 834 //----------------------------------------------------------------------------- 835 void SfxGlobalEvents_Impl::implts_checkAndExecuteEventBindings(const css::document::DocumentEvent& aEvent) 836 { 837 try 838 { 839 // SAFE -> 840 ::osl::ResettableMutexGuard aLock(m_aLock); 841 css::uno::Reference< css::container::XNameReplace > xEvents = m_xEvents; 842 aLock.clear(); 843 // <- SAFE 844 845 css::uno::Any aAny; 846 if ( xEvents.is() && xEvents->hasByName( aEvent.EventName ) ) 847 aAny = xEvents->getByName(aEvent.EventName); 848 Execute(aAny, aEvent, 0); 849 } 850 catch ( css::uno::RuntimeException const & ) 851 { 852 throw; 853 } 854 catch ( css::uno::Exception const & ) 855 { 856 DBG_UNHANDLED_EXCEPTION(); 857 } 858 } 859 860 //----------------------------------------------------------------------------- 861 void SfxGlobalEvents_Impl::implts_notifyListener(const css::document::DocumentEvent& aEvent) 862 { 863 // containers are threadsafe 864 css::document::EventObject aLegacyEvent(aEvent.Source, aEvent.EventName); 865 m_aLegacyListeners.notifyEach( &css::document::XEventListener::notifyEvent, aLegacyEvent ); 866 867 m_aDocumentListeners.notifyEach( &css::document::XDocumentEventListener::documentEventOccured, aEvent ); 868 } 869 870 //----------------------------------------------------------------------------- 871 // not threadsafe ... must be locked from outside! 872 TModelList::iterator SfxGlobalEvents_Impl::impl_searchDoc(const css::uno::Reference< css::frame::XModel >& xModel) 873 { 874 if (!xModel.is()) 875 return m_lModels.end(); 876 877 TModelList::iterator pIt; 878 for ( pIt = m_lModels.begin(); 879 pIt != m_lModels.end() ; 880 ++pIt ) 881 { 882 css::uno::Reference< css::frame::XModel > xContainerDoc(*pIt, UNO_QUERY); 883 if (xContainerDoc == xModel) 884 break; 885 } 886 887 return pIt; 888 } 889 890