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