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