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