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 if ( aURL.Protocol.equals( ::rtl::OUString::createFromAscii( "vnd.sun.star.script:" ) ) ) 257 { 258 ::com::sun::star::uno::Reference 259 < ::com::sun::star::frame::XDispatchProvider > xProv; 260 261 if ( pView != NULL ) 262 { 263 xProv = ::com::sun::star::uno::Reference 264 < ::com::sun::star::frame::XDispatchProvider > ( 265 pView->GetFrame().GetFrameInterface(), UNO_QUERY ); 266 } 267 else 268 { 269 xProv = ::com::sun::star::uno::Reference 270 < ::com::sun::star::frame::XDispatchProvider > ( 271 ::comphelper::getProcessServiceFactory()->createInstance( 272 rtl::OUString::createFromAscii( 273 "com.sun.star.frame.Desktop" ) ), 274 UNO_QUERY ); 275 } 276 277 ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatch > xDisp; 278 if ( xProv.is() ) 279 xDisp = xProv->queryDispatch( aURL, ::rtl::OUString(), 0 ); 280 281 if ( xDisp.is() ) 282 { 283 //::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue > aArgs(1); 284 //aArgs[0].Name = rtl::OUString::createFromAscii("Referer"); 285 //aArs[0].Value <<= ::rtl::OUString( pDoc->GetMedium()->GetName() ); 286 //xDisp->dispatch( aURL, aArgs ); 287 288 css::beans::PropertyValue aEventParam; 289 aEventParam.Value <<= aTrigger; 290 css::uno::Sequence< css::beans::PropertyValue > aDispatchArgs( &aEventParam, 1 ); 291 xDisp->dispatch( aURL, aDispatchArgs ); 292 } 293 } 294 } 295 } 296 else if ( aType.getLength() == 0 ) 297 { 298 // Empty type means no active binding for the event. Just ignore do nothing. 299 } 300 else 301 { 302 DBG_ERRORFILE( "notifyEvent(): Unsupported event type" ); 303 } 304 } 305 } 306 307 //-------------------------------------------------------------------------------------------------------- 308 // --- ::document::XEventListener --- 309 //-------------------------------------------------------------------------------------------------------- 310 void SAL_CALL SfxEvents_Impl::notifyEvent( const DOCEVENTOBJECT& aEvent ) throw( RUNTIMEEXCEPTION ) 311 { 312 ::osl::ClearableMutexGuard aGuard( maMutex ); 313 314 // get the event name, find the coresponding data, execute the data 315 316 OUSTRING aName = aEvent.EventName; 317 long nCount = maEventNames.getLength(); 318 long nIndex = 0; 319 sal_Bool bFound = sal_False; 320 321 while ( !bFound && ( nIndex < nCount ) ) 322 { 323 if ( maEventNames[nIndex] == aName ) 324 bFound = sal_True; 325 else 326 nIndex += 1; 327 } 328 329 if ( !bFound ) 330 return; 331 332 ANY aEventData = maEventData[ nIndex ]; 333 aGuard.clear(); 334 Execute( aEventData, css::document::DocumentEvent(aEvent.Source, aEvent.EventName, NULL, css::uno::Any()), mpObjShell ); 335 } 336 337 //-------------------------------------------------------------------------------------------------------- 338 // --- ::lang::XEventListener --- 339 //-------------------------------------------------------------------------------------------------------- 340 void SAL_CALL SfxEvents_Impl::disposing( const EVENTOBJECT& /*Source*/ ) throw( RUNTIMEEXCEPTION ) 341 { 342 ::osl::MutexGuard aGuard( maMutex ); 343 344 if ( mxBroadcaster.is() ) 345 { 346 mxBroadcaster->removeEventListener( this ); 347 mxBroadcaster = NULL; 348 } 349 } 350 351 //-------------------------------------------------------------------------------------------------------- 352 // 353 //-------------------------------------------------------------------------------------------------------- 354 SfxEvents_Impl::SfxEvents_Impl( SfxObjectShell* pShell, 355 REFERENCE< XEVENTBROADCASTER > xBroadcaster ) 356 { 357 // get the list of supported events and store it 358 if ( pShell ) 359 maEventNames = pShell->GetEventNames(); 360 else 361 maEventNames = GlobalEventConfig().getElementNames(); 362 363 maEventData = SEQUENCE < ANY > ( maEventNames.getLength() ); 364 365 mpObjShell = pShell; 366 mxBroadcaster = xBroadcaster; 367 368 if ( mxBroadcaster.is() ) 369 mxBroadcaster->addEventListener( this ); 370 } 371 372 //-------------------------------------------------------------------------------------------------------- 373 SfxEvents_Impl::~SfxEvents_Impl() 374 { 375 } 376 377 //-------------------------------------------------------------------------------------------------------- 378 SvxMacro* SfxEvents_Impl::ConvertToMacro( const ANY& rElement, SfxObjectShell* pObjShell, sal_Bool bNormalizeMacro ) 379 { 380 SvxMacro* pMacro = NULL; 381 SEQUENCE < PROPERTYVALUE > aProperties; 382 ANY aAny; 383 if ( bNormalizeMacro ) 384 NormalizeMacro( rElement, aAny, pObjShell ); 385 else 386 aAny = rElement; 387 388 if ( aAny >>= aProperties ) 389 { 390 OUSTRING aType; 391 OUSTRING aScriptURL; 392 OUSTRING aLibrary; 393 OUSTRING aMacroName; 394 395 long nCount = aProperties.getLength(); 396 long nIndex = 0; 397 398 if ( !nCount ) 399 return pMacro; 400 401 while ( nIndex < nCount ) 402 { 403 if ( aProperties[ nIndex ].Name.compareToAscii( PROP_EVENT_TYPE ) == 0 ) 404 aProperties[ nIndex ].Value >>= aType; 405 else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_SCRIPT ) == 0 ) 406 aProperties[ nIndex ].Value >>= aScriptURL; 407 else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_LIBRARY ) == 0 ) 408 aProperties[ nIndex ].Value >>= aLibrary; 409 else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_MACRO_NAME ) == 0 ) 410 aProperties[ nIndex ].Value >>= aMacroName; 411 else { 412 DBG_ERROR("Unknown propery value!"); 413 } 414 nIndex += 1; 415 } 416 417 // Get the type 418 ScriptType eType( STARBASIC ); 419 if ( aType.compareToAscii( STAR_BASIC ) == COMPARE_EQUAL ) 420 eType = STARBASIC; 421 else if ( aType.compareToAscii( "Script" ) == COMPARE_EQUAL && aScriptURL.getLength() ) 422 eType = EXTENDED_STYPE; 423 else if ( aType.compareToAscii( SVX_MACRO_LANGUAGE_JAVASCRIPT ) == COMPARE_EQUAL ) 424 eType = JAVASCRIPT; 425 else { 426 DBG_ERRORFILE( "ConvertToMacro: Unknown macro type" ); 427 } 428 429 if ( aMacroName.getLength() ) 430 { 431 if ( aLibrary.compareToAscii("application") == 0 ) 432 aLibrary = SFX_APP()->GetName(); 433 else 434 aLibrary = ::rtl::OUString(); 435 pMacro = new SvxMacro( aMacroName, aLibrary, eType ); 436 } 437 else if ( eType == EXTENDED_STYPE ) 438 pMacro = new SvxMacro( aScriptURL, aType ); 439 } 440 441 return pMacro; 442 } 443 444 void SfxEvents_Impl::NormalizeMacro( const ANY& rEvent, ANY& rRet, SfxObjectShell* pDoc ) 445 { 446 const ::comphelper::NamedValueCollection aEventDescriptor( rEvent ); 447 ::comphelper::NamedValueCollection aEventDescriptorOut; 448 449 NormalizeMacro( aEventDescriptor, aEventDescriptorOut, pDoc ); 450 451 rRet <<= aEventDescriptorOut.getPropertyValues(); 452 } 453 454 void SfxEvents_Impl::NormalizeMacro( const ::comphelper::NamedValueCollection& i_eventDescriptor, 455 ::comphelper::NamedValueCollection& o_normalizedDescriptor, SfxObjectShell* i_document ) 456 { 457 SfxObjectShell* pDoc = i_document; 458 if ( !pDoc ) 459 pDoc = SfxObjectShell::Current(); 460 461 ::rtl::OUString aType = i_eventDescriptor.getOrDefault( PROP_EVENT_TYPE, ::rtl::OUString() ); 462 ::rtl::OUString aScript = i_eventDescriptor.getOrDefault( PROP_SCRIPT, ::rtl::OUString() ); 463 ::rtl::OUString aLibrary = i_eventDescriptor.getOrDefault( PROP_LIBRARY, ::rtl::OUString() ); 464 ::rtl::OUString aMacroName = i_eventDescriptor.getOrDefault( PROP_MACRO_NAME, ::rtl::OUString() ); 465 466 if ( aType.getLength() ) 467 o_normalizedDescriptor.put( PROP_EVENT_TYPE, aType ); 468 if ( aScript.getLength() ) 469 o_normalizedDescriptor.put( PROP_SCRIPT, aScript ); 470 471 if ( aType.compareToAscii( STAR_BASIC ) == 0 ) 472 { 473 if ( aScript.getLength() ) 474 { 475 if ( !aMacroName.getLength() || !aLibrary.getLength() ) 476 { 477 sal_Int32 nHashPos = aScript.indexOf( '/', 8 ); 478 sal_Int32 nArgsPos = aScript.indexOf( '(' ); 479 if ( ( nHashPos != STRING_NOTFOUND ) && ( nHashPos < nArgsPos ) ) 480 { 481 OUSTRING aBasMgrName( INetURLObject::decode( aScript.copy( 8, nHashPos-8 ), INET_HEX_ESCAPE, INetURLObject::DECODE_WITH_CHARSET ) ); 482 if ( aBasMgrName.compareToAscii(".") == 0 ) 483 aLibrary = pDoc->GetTitle(); 484 /* 485 else if ( aBasMgrName.getLength() ) 486 aLibrary = aBasMgrName; 487 */ 488 else 489 aLibrary = SFX_APP()->GetName(); 490 491 // Get the macro name 492 aMacroName = aScript.copy( nHashPos+1, nArgsPos - nHashPos - 1 ); 493 } 494 else 495 { 496 DBG_ERRORFILE( "ConvertToMacro: Unknown macro url format" ); 497 } 498 } 499 } 500 else if ( aMacroName.getLength() ) 501 { 502 aScript = OUSTRING( RTL_CONSTASCII_USTRINGPARAM( MACRO_PRFIX ) ); 503 if ( aLibrary.compareTo( SFX_APP()->GetName() ) != 0 && aLibrary.compareToAscii("StarDesktop") != 0 && aLibrary.compareToAscii("application") != 0 ) 504 aScript += String('.'); 505 506 aScript += String('/'); 507 aScript += aMacroName; 508 aScript += OUSTRING( RTL_CONSTASCII_USTRINGPARAM( MACRO_POSTFIX ) ); 509 } 510 else 511 // wrong properties 512 return; 513 514 if ( aLibrary.compareToAscii("document") != 0 ) 515 { 516 if ( !aLibrary.getLength() || (pDoc && ( String(aLibrary) == pDoc->GetTitle( SFX_TITLE_APINAME ) || String(aLibrary) == pDoc->GetTitle() )) ) 517 aLibrary = String::CreateFromAscii("document"); 518 else 519 aLibrary = String::CreateFromAscii("application"); 520 } 521 522 o_normalizedDescriptor.put( PROP_SCRIPT, aScript ); 523 o_normalizedDescriptor.put( PROP_LIBRARY, aLibrary ); 524 o_normalizedDescriptor.put( PROP_MACRO_NAME, aMacroName ); 525 } 526 } 527 528 ModelCollectionEnumeration::ModelCollectionEnumeration(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) 529 : ModelCollectionMutexBase( ) 530 , m_xSMGR (xSMGR ) 531 , m_pEnumerationIt (m_lModels.begin()) 532 { 533 } 534 535 ModelCollectionEnumeration::~ModelCollectionEnumeration() 536 { 537 } 538 539 void ModelCollectionEnumeration::setModelList(const TModelList& rList) 540 { 541 // SAFE -> 542 ::osl::ResettableMutexGuard aLock(m_aLock); 543 m_lModels = rList; 544 m_pEnumerationIt = m_lModels.begin(); 545 aLock.clear(); 546 // <- SAFE 547 } 548 549 sal_Bool SAL_CALL ModelCollectionEnumeration::hasMoreElements() 550 throw(css::uno::RuntimeException) 551 { 552 // SAFE -> 553 ::osl::ResettableMutexGuard aLock(m_aLock); 554 return (m_pEnumerationIt != m_lModels.end()); 555 // <- SAFE 556 } 557 558 css::uno::Any SAL_CALL ModelCollectionEnumeration::nextElement() 559 throw(css::container::NoSuchElementException, 560 css::lang::WrappedTargetException , 561 css::uno::RuntimeException ) 562 { 563 // SAFE -> 564 ::osl::ResettableMutexGuard aLock(m_aLock); 565 if (m_pEnumerationIt == m_lModels.end()) 566 throw css::container::NoSuchElementException( 567 ::rtl::OUString::createFromAscii("End of model enumeration reached."), 568 static_cast< css::container::XEnumeration* >(this)); 569 css::uno::Reference< css::frame::XModel > xModel(*m_pEnumerationIt, UNO_QUERY); 570 ++m_pEnumerationIt; 571 aLock.clear(); 572 // <- SAFE 573 574 return css::uno::makeAny(xModel); 575 } 576 577 SFX_IMPL_XSERVICEINFO( SfxGlobalEvents_Impl, "com.sun.star.frame.GlobalEventBroadcaster", "com.sun.star.comp.sfx2.GlobalEventBroadcaster" ) 578 SFX_IMPL_ONEINSTANCEFACTORY( SfxGlobalEvents_Impl ); 579 580 //----------------------------------------------------------------------------- 581 SfxGlobalEvents_Impl::SfxGlobalEvents_Impl( const com::sun::star::uno::Reference < ::com::sun::star::lang::XMultiServiceFactory >& xSMGR) 582 : ModelCollectionMutexBase( ) 583 , m_xSMGR (xSMGR ) 584 , m_aLegacyListeners (m_aLock) 585 , m_aDocumentListeners (m_aLock) 586 , pImp (0 ) 587 { 588 m_refCount++; 589 SFX_APP(); 590 pImp = new GlobalEventConfig(); 591 m_xEvents = pImp; 592 m_xJobExecutorListener = css::uno::Reference< css::document::XEventListener >( 593 xSMGR->createInstance(::rtl::OUString::createFromAscii("com.sun.star.task.JobExecutor")), 594 UNO_QUERY); 595 m_refCount--; 596 } 597 598 //----------------------------------------------------------------------------- 599 SfxGlobalEvents_Impl::~SfxGlobalEvents_Impl() 600 { 601 } 602 603 //----------------------------------------------------------------------------- 604 css::uno::Reference< css::container::XNameReplace > SAL_CALL SfxGlobalEvents_Impl::getEvents() 605 throw(css::uno::RuntimeException) 606 { 607 // SAFE -> 608 ::osl::ResettableMutexGuard aLock(m_aLock); 609 return m_xEvents; 610 // <- SAFE 611 } 612 613 //----------------------------------------------------------------------------- 614 void SAL_CALL SfxGlobalEvents_Impl::addEventListener(const css::uno::Reference< css::document::XEventListener >& xListener) 615 throw(css::uno::RuntimeException) 616 { 617 // container is threadsafe 618 m_aLegacyListeners.addInterface(xListener); 619 } 620 621 //----------------------------------------------------------------------------- 622 void SAL_CALL SfxGlobalEvents_Impl::removeEventListener(const css::uno::Reference< css::document::XEventListener >& xListener) 623 throw(css::uno::RuntimeException) 624 { 625 // container is threadsafe 626 m_aLegacyListeners.removeInterface(xListener); 627 } 628 629 //----------------------------------------------------------------------------- 630 void SAL_CALL SfxGlobalEvents_Impl::addDocumentEventListener( const css::uno::Reference< css::document::XDocumentEventListener >& _Listener ) 631 throw(css::uno::RuntimeException) 632 { 633 m_aDocumentListeners.addInterface( _Listener ); 634 } 635 636 //----------------------------------------------------------------------------- 637 void SAL_CALL SfxGlobalEvents_Impl::removeDocumentEventListener( const css::uno::Reference< css::document::XDocumentEventListener >& _Listener ) 638 throw(css::uno::RuntimeException) 639 { 640 m_aDocumentListeners.removeInterface( _Listener ); 641 } 642 643 //----------------------------------------------------------------------------- 644 void SAL_CALL SfxGlobalEvents_Impl::notifyDocumentEvent( const ::rtl::OUString& /*_EventName*/, 645 const css::uno::Reference< css::frame::XController2 >& /*_ViewController*/, const css::uno::Any& /*_Supplement*/ ) 646 throw (css::lang::IllegalArgumentException, css::lang::NoSupportException, css::uno::RuntimeException) 647 { 648 // we're a multiplexer only, no chance to generate artificial events here 649 throw css::lang::NoSupportException(::rtl::OUString(), *this); 650 } 651 652 //----------------------------------------------------------------------------- 653 void SAL_CALL SfxGlobalEvents_Impl::notifyEvent(const css::document::EventObject& aEvent) 654 throw(css::uno::RuntimeException) 655 { 656 css::document::DocumentEvent aDocEvent(aEvent.Source, aEvent.EventName, NULL, css::uno::Any()); 657 implts_notifyJobExecution(aEvent); 658 implts_checkAndExecuteEventBindings(aDocEvent); 659 implts_notifyListener(aDocEvent); 660 } 661 662 //----------------------------------------------------------------------------- 663 void SAL_CALL SfxGlobalEvents_Impl::documentEventOccured( const ::css::document::DocumentEvent& _Event ) 664 throw (::css::uno::RuntimeException) 665 { 666 implts_notifyJobExecution(css::document::EventObject(_Event.Source, _Event.EventName)); 667 implts_checkAndExecuteEventBindings(_Event); 668 implts_notifyListener(_Event); 669 } 670 671 //----------------------------------------------------------------------------- 672 void SAL_CALL SfxGlobalEvents_Impl::disposing(const css::lang::EventObject& aEvent) 673 throw(css::uno::RuntimeException) 674 { 675 css::uno::Reference< css::frame::XModel > xDoc(aEvent.Source, UNO_QUERY); 676 677 // SAFE -> 678 ::osl::ResettableMutexGuard aLock(m_aLock); 679 TModelList::iterator pIt = impl_searchDoc(xDoc); 680 if (pIt != m_lModels.end()) 681 m_lModels.erase(pIt); 682 aLock.clear(); 683 // <- SAFE 684 } 685 686 //----------------------------------------------------------------------------- 687 sal_Bool SAL_CALL SfxGlobalEvents_Impl::has(const css::uno::Any& aElement) 688 throw (css::uno::RuntimeException) 689 { 690 css::uno::Reference< css::frame::XModel > xDoc; 691 aElement >>= xDoc; 692 693 sal_Bool bHas = sal_False; 694 695 // SAFE -> 696 ::osl::ResettableMutexGuard aLock(m_aLock); 697 TModelList::iterator pIt = impl_searchDoc(xDoc); 698 if (pIt != m_lModels.end()) 699 bHas = sal_True; 700 aLock.clear(); 701 // <- SAFE 702 703 return bHas; 704 } 705 706 //----------------------------------------------------------------------------- 707 void SAL_CALL SfxGlobalEvents_Impl::insert( const css::uno::Any& aElement ) 708 throw (css::lang::IllegalArgumentException , 709 css::container::ElementExistException, 710 css::uno::RuntimeException ) 711 { 712 css::uno::Reference< css::frame::XModel > xDoc; 713 aElement >>= xDoc; 714 if (!xDoc.is()) 715 throw css::lang::IllegalArgumentException( 716 ::rtl::OUString::createFromAscii("Can't locate at least the model parameter."), 717 static_cast< css::container::XSet* >(this), 718 0); 719 720 // SAFE -> 721 ::osl::ResettableMutexGuard aLock(m_aLock); 722 TModelList::iterator pIt = impl_searchDoc(xDoc); 723 if (pIt != m_lModels.end()) 724 throw css::container::ElementExistException( 725 ::rtl::OUString(), 726 static_cast< css::container::XSet* >(this)); 727 m_lModels.push_back(xDoc); 728 aLock.clear(); 729 // <- SAFE 730 731 css::uno::Reference< css::document::XDocumentEventBroadcaster > xDocBroadcaster(xDoc, UNO_QUERY ); 732 if (xDocBroadcaster.is()) 733 xDocBroadcaster->addDocumentEventListener(this); 734 else 735 { 736 // try the "legacy version" of XDocumentEventBroadcaster, which is XEventBroadcaster 737 css::uno::Reference< css::document::XEventBroadcaster > xBroadcaster(xDoc, UNO_QUERY); 738 if (xBroadcaster.is()) 739 xBroadcaster->addEventListener(static_cast< css::document::XEventListener* >(this)); 740 } 741 } 742 743 //----------------------------------------------------------------------------- 744 void SAL_CALL SfxGlobalEvents_Impl::remove( const css::uno::Any& aElement ) 745 throw (css::lang::IllegalArgumentException , 746 css::container::NoSuchElementException, 747 css::uno::RuntimeException ) 748 { 749 css::uno::Reference< css::frame::XModel > xDoc; 750 aElement >>= xDoc; 751 if (!xDoc.is()) 752 throw css::lang::IllegalArgumentException( 753 ::rtl::OUString::createFromAscii("Can't locate at least the model parameter."), 754 static_cast< css::container::XSet* >(this), 755 0); 756 757 // SAFE -> 758 ::osl::ResettableMutexGuard aLock(m_aLock); 759 TModelList::iterator pIt = impl_searchDoc(xDoc); 760 if (pIt == m_lModels.end()) 761 throw css::container::NoSuchElementException( 762 ::rtl::OUString(), 763 static_cast< css::container::XSet* >(this)); 764 m_lModels.erase(pIt); 765 aLock.clear(); 766 // <- SAFE 767 768 css::uno::Reference< css::document::XDocumentEventBroadcaster > xDocBroadcaster(xDoc, UNO_QUERY ); 769 if (xDocBroadcaster.is()) 770 xDocBroadcaster->removeDocumentEventListener(this); 771 else 772 { 773 // try the "legacy version" of XDocumentEventBroadcaster, which is XEventBroadcaster 774 css::uno::Reference< css::document::XEventBroadcaster > xBroadcaster(xDoc, UNO_QUERY); 775 if (xBroadcaster.is()) 776 xBroadcaster->removeEventListener(static_cast< css::document::XEventListener* >(this)); 777 } 778 } 779 780 //----------------------------------------------------------------------------- 781 css::uno::Reference< css::container::XEnumeration > SAL_CALL SfxGlobalEvents_Impl::createEnumeration() 782 throw (css::uno::RuntimeException) 783 { 784 // SAFE -> 785 ::osl::ResettableMutexGuard aLock(m_aLock); 786 ModelCollectionEnumeration* pEnum = new ModelCollectionEnumeration(m_xSMGR); 787 pEnum->setModelList(m_lModels); 788 css::uno::Reference< css::container::XEnumeration > xEnum( 789 static_cast< css::container::XEnumeration* >(pEnum), 790 UNO_QUERY); 791 aLock.clear(); 792 // <- SAFE 793 794 return xEnum; 795 } 796 797 //----------------------------------------------------------------------------- 798 css::uno::Type SAL_CALL SfxGlobalEvents_Impl::getElementType() 799 throw (css::uno::RuntimeException) 800 { 801 return ::getCppuType(static_cast< css::uno::Reference< css::frame::XModel >* >(NULL)); 802 } 803 804 //----------------------------------------------------------------------------- 805 sal_Bool SAL_CALL SfxGlobalEvents_Impl::hasElements() 806 throw (css::uno::RuntimeException) 807 { 808 // SAFE -> 809 ::osl::ResettableMutexGuard aLock(m_aLock); 810 return (m_lModels.size()>0); 811 // <- SAFE 812 } 813 814 //----------------------------------------------------------------------------- 815 void SfxGlobalEvents_Impl::implts_notifyJobExecution(const css::document::EventObject& aEvent) 816 { 817 try 818 { 819 // SAFE -> 820 ::osl::ResettableMutexGuard aLock(m_aLock); 821 css::uno::Reference< css::document::XEventListener > xJobExecutor(m_xJobExecutorListener); 822 aLock.clear(); 823 // <- SAFE 824 if (xJobExecutor.is()) 825 xJobExecutor->notifyEvent(aEvent); 826 } 827 catch(const css::uno::RuntimeException& exRun) 828 { throw exRun; } 829 catch(const css::uno::Exception&) 830 {} 831 } 832 833 //----------------------------------------------------------------------------- 834 void SfxGlobalEvents_Impl::implts_checkAndExecuteEventBindings(const css::document::DocumentEvent& aEvent) 835 { 836 try 837 { 838 // SAFE -> 839 ::osl::ResettableMutexGuard aLock(m_aLock); 840 css::uno::Reference< css::container::XNameReplace > xEvents = m_xEvents; 841 aLock.clear(); 842 // <- SAFE 843 844 css::uno::Any aAny; 845 if ( xEvents.is() && xEvents->hasByName( aEvent.EventName ) ) 846 aAny = xEvents->getByName(aEvent.EventName); 847 Execute(aAny, aEvent, 0); 848 } 849 catch ( css::uno::RuntimeException const & ) 850 { 851 throw; 852 } 853 catch ( css::uno::Exception const & ) 854 { 855 DBG_UNHANDLED_EXCEPTION(); 856 } 857 } 858 859 //----------------------------------------------------------------------------- 860 void SfxGlobalEvents_Impl::implts_notifyListener(const css::document::DocumentEvent& aEvent) 861 { 862 // containers are threadsafe 863 css::document::EventObject aLegacyEvent(aEvent.Source, aEvent.EventName); 864 m_aLegacyListeners.notifyEach( &css::document::XEventListener::notifyEvent, aLegacyEvent ); 865 866 m_aDocumentListeners.notifyEach( &css::document::XDocumentEventListener::documentEventOccured, aEvent ); 867 } 868 869 //----------------------------------------------------------------------------- 870 // not threadsafe ... must be locked from outside! 871 TModelList::iterator SfxGlobalEvents_Impl::impl_searchDoc(const css::uno::Reference< css::frame::XModel >& xModel) 872 { 873 if (!xModel.is()) 874 return m_lModels.end(); 875 876 TModelList::iterator pIt; 877 for ( pIt = m_lModels.begin(); 878 pIt != m_lModels.end() ; 879 ++pIt ) 880 { 881 css::uno::Reference< css::frame::XModel > xContainerDoc(*pIt, UNO_QUERY); 882 if (xContainerDoc == xModel) 883 break; 884 } 885 886 return pIt; 887 } 888 889