diff options
Diffstat (limited to 'sfx2/source/notify/eventsupplier.cxx')
-rw-r--r-- | sfx2/source/notify/eventsupplier.cxx | 920 |
1 files changed, 920 insertions, 0 deletions
diff --git a/sfx2/source/notify/eventsupplier.cxx b/sfx2/source/notify/eventsupplier.cxx new file mode 100644 index 000000000000..32e6887f802c --- /dev/null +++ b/sfx2/source/notify/eventsupplier.cxx @@ -0,0 +1,920 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sfx2.hxx" + +//-------------------------------------------------------------------------------------------------------- +#include <com/sun/star/beans/PropertyValue.hpp> + +#ifndef _COM_SUN_STAR_UTL_URL_HPP_ +#include <com/sun/star/util/URL.hpp> +#endif + +#ifndef _COM_SUN_STAR_UTL_XURLTRANSFORMER_HPP_ +#include <com/sun/star/util/XURLTransformer.hpp> +#endif +#include <tools/urlobj.hxx> +#include <svl/macitem.hxx> +#include <sfx2/appuno.hxx> +#include <sfx2/objsh.hxx> +#include <sfx2/sfxbasemodel.hxx> +#include <sfx2/evntconf.hxx> +#include <unotools/eventcfg.hxx> + +#include <unotools/securityoptions.hxx> +#include <comphelper/processfactory.hxx> +#include "eventsupplier.hxx" + +#include <sfx2/app.hxx> +#include "sfxresid.hxx" + +#include <sfx2/sfxsids.hrc> +#include "sfxlocal.hrc" +#include <sfx2/docfile.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/frame.hxx> + +//-------------------------------------------------------------------------------------------------------- + +#define MACRO_PRFIX "macro://" +#define MACRO_POSTFIX "()" + +//-------------------------------------------------------------------------------------------------------- + +#define PROPERTYVALUE ::com::sun::star::beans::PropertyValue +#define UNO_QUERY ::com::sun::star::uno::UNO_QUERY + +namespace css = ::com::sun::star; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::beans::PropertyValue; + +//-------------------------------------------------------------------------------------------------------- + // --- XNameReplace --- +//-------------------------------------------------------------------------------------------------------- +void SAL_CALL SfxEvents_Impl::replaceByName( const OUSTRING & aName, const ANY & rElement ) + throw( ILLEGALARGUMENTEXCEPTION, NOSUCHELEMENTEXCEPTION, + WRAPPEDTARGETEXCEPTION, RUNTIMEEXCEPTION ) +{ + ::osl::MutexGuard aGuard( maMutex ); + + // find the event in the list and replace the data + long nCount = maEventNames.getLength(); + for ( long i=0; i<nCount; i++ ) + { + if ( maEventNames[i] == aName ) + { + Sequence< PropertyValue > aProperties; + // check for correct type of the element + if ( rElement.hasValue() && !( rElement >>= aProperties ) ) + throw ILLEGALARGUMENTEXCEPTION(); + + // create Configuration at first, creation might call this method also and that would overwrite everything + // we might have stored before! + if ( mpObjShell && !mpObjShell->IsLoading() ) + mpObjShell->SetModified( TRUE ); + + if ( aProperties.getLength() ) + { + // "normalize" the macro descriptor + ANY aValue; + BlowUpMacro( rElement, aValue, mpObjShell ); + aValue >>= aProperties; + + ::rtl::OUString sType; + if ( ( aProperties.getLength() == 1 ) + && ( aProperties[0].Name.compareToAscii( PROP_EVENT_TYPE ) == 0 ) + && ( aProperties[0].Value >>= sType ) + && ( sType.getLength() == 0 ) + ) + { + // An empty event type means no binding. Therefore reset data + // to reflect that state. + // (that's for compatibility only. Nowadays, the Tools/Customize dialog should + // set an empty sequence to indicate the request for resetting the assignment.) + aProperties.realloc( 0 ); + } + } + + if ( aProperties.getLength() ) + { + maEventData[i] = makeAny( aProperties ); + } + else + { + maEventData[i].clear(); + } + return; + } + } + + throw NOSUCHELEMENTEXCEPTION(); +} + +//-------------------------------------------------------------------------------------------------------- +// --- XNameAccess --- +//-------------------------------------------------------------------------------------------------------- +ANY SAL_CALL SfxEvents_Impl::getByName( const OUSTRING& aName ) + throw( NOSUCHELEMENTEXCEPTION, WRAPPEDTARGETEXCEPTION, + RUNTIMEEXCEPTION ) +{ + ::osl::MutexGuard aGuard( maMutex ); + + // find the event in the list and return the data + + long nCount = maEventNames.getLength(); + + for ( long i=0; i<nCount; i++ ) + { + if ( maEventNames[i] == aName ) + return maEventData[i]; + } + + throw NOSUCHELEMENTEXCEPTION(); +} + +//-------------------------------------------------------------------------------------------------------- +SEQUENCE< OUSTRING > SAL_CALL SfxEvents_Impl::getElementNames() throw ( RUNTIMEEXCEPTION ) +{ + return maEventNames; +} + +//-------------------------------------------------------------------------------------------------------- +sal_Bool SAL_CALL SfxEvents_Impl::hasByName( const OUSTRING& aName ) throw ( RUNTIMEEXCEPTION ) +{ + ::osl::MutexGuard aGuard( maMutex ); + + // find the event in the list and return the data + + long nCount = maEventNames.getLength(); + + for ( long i=0; i<nCount; i++ ) + { + if ( maEventNames[i] == aName ) + return sal_True; + } + + return sal_False; +} + +//-------------------------------------------------------------------------------------------------------- +// --- XElementAccess ( parent of XNameAccess ) --- +//-------------------------------------------------------------------------------------------------------- +UNOTYPE SAL_CALL SfxEvents_Impl::getElementType() throw ( RUNTIMEEXCEPTION ) +{ + UNOTYPE aElementType = ::getCppuType( (const SEQUENCE < PROPERTYVALUE > *)0 ); + return aElementType; +} + +//-------------------------------------------------------------------------------------------------------- +sal_Bool SAL_CALL SfxEvents_Impl::hasElements() throw ( RUNTIMEEXCEPTION ) +{ + ::osl::MutexGuard aGuard( maMutex ); + + if ( maEventNames.getLength() ) + return sal_True; + else + return sal_False; +} + +static void Execute( ANY& aEventData, const css::document::DocumentEvent& aTrigger, SfxObjectShell* pDoc ) +{ + SEQUENCE < PROPERTYVALUE > aProperties; + if ( aEventData >>= aProperties ) + { + OUSTRING aPrefix = OUSTRING( RTL_CONSTASCII_USTRINGPARAM( MACRO_PRFIX ) ); + OUSTRING aType; + OUSTRING aScript; + OUSTRING aLibrary; + OUSTRING aMacroName; + + sal_Int32 nCount = aProperties.getLength(); + + if ( !nCount ) + return; + + sal_Int32 nIndex = 0; + while ( nIndex < nCount ) + { + if ( aProperties[ nIndex ].Name.compareToAscii( PROP_EVENT_TYPE ) == 0 ) + aProperties[ nIndex ].Value >>= aType; + else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_SCRIPT ) == 0 ) + aProperties[ nIndex ].Value >>= aScript; + else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_LIBRARY ) == 0 ) + aProperties[ nIndex ].Value >>= aLibrary; + else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_MACRO_NAME ) == 0 ) + aProperties[ nIndex ].Value >>= aMacroName; + else { + DBG_ERROR("Unknown property value!"); + } + nIndex += 1; + } + + if ( aType.compareToAscii( STAR_BASIC ) == 0 && aScript.getLength() ) + { + com::sun::star::uno::Any aAny; + SfxMacroLoader::loadMacro( aScript, aAny, pDoc ); + } + else if ( aType.compareToAscii( "Service" ) == 0 || + aType.compareToAscii( "Script" ) == 0 ) + { + if ( aScript.getLength() ) + { + SfxViewFrame* pView = pDoc ? + SfxViewFrame::GetFirst( pDoc ) : + SfxViewFrame::Current(); + + ::com::sun::star::uno::Reference + < ::com::sun::star::util::XURLTransformer > xTrans( + ::comphelper::getProcessServiceFactory()->createInstance( + rtl::OUString::createFromAscii( + "com.sun.star.util.URLTransformer" ) ), + UNO_QUERY ); + + ::com::sun::star::util::URL aURL; + aURL.Complete = aScript; + xTrans->parseStrict( aURL ); + + ::com::sun::star::uno::Reference + < ::com::sun::star::frame::XDispatchProvider > xProv; + + if ( pView != NULL ) + { + xProv = ::com::sun::star::uno::Reference + < ::com::sun::star::frame::XDispatchProvider > ( + pView->GetFrame().GetFrameInterface(), UNO_QUERY ); + } + else + { + xProv = ::com::sun::star::uno::Reference + < ::com::sun::star::frame::XDispatchProvider > ( + ::comphelper::getProcessServiceFactory()->createInstance( + rtl::OUString::createFromAscii( + "com.sun.star.frame.Desktop" ) ), + UNO_QUERY ); + } + + ::com::sun::star::uno::Reference < ::com::sun::star::frame::XDispatch > xDisp; + if ( xProv.is() ) + xDisp = xProv->queryDispatch( aURL, ::rtl::OUString(), 0 ); + + if ( xDisp.is() ) + { + //::com::sun::star::uno::Sequence < ::com::sun::star::beans::PropertyValue > aArgs(1); + //aArgs[0].Name = rtl::OUString::createFromAscii("Referer"); + //aArs[0].Value <<= ::rtl::OUString( pDoc->GetMedium()->GetName() ); + //xDisp->dispatch( aURL, aArgs ); + + css::beans::PropertyValue aEventParam; + aEventParam.Value <<= aTrigger; + css::uno::Sequence< css::beans::PropertyValue > aDispatchArgs( &aEventParam, 1 ); + xDisp->dispatch( aURL, aDispatchArgs ); + } + } + } + else if ( aType.getLength() == 0 ) + { + // Empty type means no active binding for the event. Just ignore do nothing. + } + else + { + DBG_ERRORFILE( "notifyEvent(): Unsupported event type" ); + } + } +} + +//-------------------------------------------------------------------------------------------------------- +// --- ::document::XEventListener --- +//-------------------------------------------------------------------------------------------------------- +void SAL_CALL SfxEvents_Impl::notifyEvent( const DOCEVENTOBJECT& aEvent ) throw( RUNTIMEEXCEPTION ) +{ + ::osl::ClearableMutexGuard aGuard( maMutex ); + + // get the event name, find the coresponding data, execute the data + + OUSTRING aName = aEvent.EventName; + long nCount = maEventNames.getLength(); + long nIndex = 0; + sal_Bool bFound = sal_False; + + while ( !bFound && ( nIndex < nCount ) ) + { + if ( maEventNames[nIndex] == aName ) + bFound = sal_True; + else + nIndex += 1; + } + + if ( !bFound ) + return; + + ANY aEventData = maEventData[ nIndex ]; + aGuard.clear(); + Execute( aEventData, css::document::DocumentEvent(aEvent.Source, aEvent.EventName, NULL, css::uno::Any()), mpObjShell ); +} + +//-------------------------------------------------------------------------------------------------------- +// --- ::lang::XEventListener --- +//-------------------------------------------------------------------------------------------------------- +void SAL_CALL SfxEvents_Impl::disposing( const EVENTOBJECT& /*Source*/ ) throw( RUNTIMEEXCEPTION ) +{ + ::osl::MutexGuard aGuard( maMutex ); + + if ( mxBroadcaster.is() ) + { + mxBroadcaster->removeEventListener( this ); + mxBroadcaster = NULL; + } +} + +//-------------------------------------------------------------------------------------------------------- +// +//-------------------------------------------------------------------------------------------------------- +SfxEvents_Impl::SfxEvents_Impl( SfxObjectShell* pShell, + REFERENCE< XEVENTBROADCASTER > xBroadcaster ) +{ + // get the list of supported events and store it + if ( pShell ) + maEventNames = pShell->GetEventNames(); + else + maEventNames = GlobalEventConfig().getElementNames(); + + maEventData = SEQUENCE < ANY > ( maEventNames.getLength() ); + + mpObjShell = pShell; + mxBroadcaster = xBroadcaster; + + if ( mxBroadcaster.is() ) + mxBroadcaster->addEventListener( this ); +} + +//-------------------------------------------------------------------------------------------------------- +SfxEvents_Impl::~SfxEvents_Impl() +{ +} + +//-------------------------------------------------------------------------------------------------------- +SvxMacro* SfxEvents_Impl::ConvertToMacro( const ANY& rElement, SfxObjectShell* pObjShell, BOOL bBlowUp ) +{ + SvxMacro* pMacro = NULL; + SEQUENCE < PROPERTYVALUE > aProperties; + ANY aAny; + if ( bBlowUp ) + BlowUpMacro( rElement, aAny, pObjShell ); + else + aAny = rElement; + + if ( aAny >>= aProperties ) + { + OUSTRING aType; + OUSTRING aScriptURL; + OUSTRING aLibrary; + OUSTRING aMacroName; + + long nCount = aProperties.getLength(); + long nIndex = 0; + + if ( !nCount ) + return pMacro; + + while ( nIndex < nCount ) + { + if ( aProperties[ nIndex ].Name.compareToAscii( PROP_EVENT_TYPE ) == 0 ) + aProperties[ nIndex ].Value >>= aType; + else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_SCRIPT ) == 0 ) + aProperties[ nIndex ].Value >>= aScriptURL; + else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_LIBRARY ) == 0 ) + aProperties[ nIndex ].Value >>= aLibrary; + else if ( aProperties[ nIndex ].Name.compareToAscii( PROP_MACRO_NAME ) == 0 ) + aProperties[ nIndex ].Value >>= aMacroName; + else { + DBG_ERROR("Unknown propery value!"); + } + nIndex += 1; + } + + // Get the type + ScriptType eType( STARBASIC ); + if ( aType.compareToAscii( STAR_BASIC ) == COMPARE_EQUAL ) + eType = STARBASIC; + else if ( aType.compareToAscii( "Script" ) == COMPARE_EQUAL && aScriptURL.getLength() ) + eType = EXTENDED_STYPE; + else if ( aType.compareToAscii( SVX_MACRO_LANGUAGE_JAVASCRIPT ) == COMPARE_EQUAL ) + eType = JAVASCRIPT; + else { + DBG_ERRORFILE( "ConvertToMacro: Unknown macro type" ); + } + + if ( aMacroName.getLength() ) + { + if ( aLibrary.compareToAscii("application") == 0 ) + aLibrary = SFX_APP()->GetName(); + else + aLibrary = ::rtl::OUString(); + pMacro = new SvxMacro( aMacroName, aLibrary, eType ); + } + else if ( eType == EXTENDED_STYPE ) + pMacro = new SvxMacro( aScriptURL, aType ); + } + + return pMacro; +} + +void SfxEvents_Impl::BlowUpMacro( const ANY& rEvent, ANY& rRet, SfxObjectShell* pDoc ) +{ + if ( !pDoc ) + pDoc = SfxObjectShell::Current(); + + SEQUENCE < PROPERTYVALUE > aInProps; + SEQUENCE < PROPERTYVALUE > aOutProps(2); + + if ( !( rEvent >>= aInProps ) ) + return; + + sal_Int32 nCount = aInProps.getLength(); + + if ( !nCount ) + return; + + OUSTRING aType; + OUSTRING aScript; + OUSTRING aLibrary; + OUSTRING aMacroName; + + sal_Int32 nIndex = 0; + + while ( nIndex < nCount ) + { + if ( aInProps[ nIndex ].Name.compareToAscii( PROP_EVENT_TYPE ) == 0 ) + { + aInProps[nIndex].Value >>= aType; + aOutProps[0] = aInProps[nIndex]; + } + else if ( aInProps[ nIndex ].Name.compareToAscii( PROP_SCRIPT ) == 0 ) + { + aInProps[nIndex].Value >>= aScript; + aOutProps[1] = aInProps[nIndex]; + } + else if ( aInProps[ nIndex ].Name.compareToAscii( PROP_LIBRARY ) == 0 ) + { + aInProps[ nIndex ].Value >>= aLibrary; + } + else if ( aInProps[ nIndex ].Name.compareToAscii( PROP_MACRO_NAME ) == 0 ) + { + aInProps[ nIndex ].Value >>= aMacroName; + } + nIndex += 1; + } + + if ( aType.compareToAscii( STAR_BASIC ) == 0 ) + { + aOutProps.realloc(4); + if ( aScript.getLength() ) + { + if( ! aMacroName.getLength() || ! aLibrary.getLength() ) + { + sal_Int32 nHashPos = aScript.indexOf( '/', 8 ); + sal_Int32 nArgsPos = aScript.indexOf( '(' ); + if ( ( nHashPos != STRING_NOTFOUND ) && ( nHashPos < nArgsPos ) ) + { + OUSTRING aBasMgrName( INetURLObject::decode( aScript.copy( 8, nHashPos-8 ), INET_HEX_ESCAPE, INetURLObject::DECODE_WITH_CHARSET ) ); + if ( aBasMgrName.compareToAscii(".") == 0 ) + aLibrary = pDoc->GetTitle(); +/* + else if ( aBasMgrName.getLength() ) + aLibrary = aBasMgrName; + */ + else + aLibrary = SFX_APP()->GetName(); + + // Get the macro name + aMacroName = aScript.copy( nHashPos+1, nArgsPos - nHashPos - 1 ); + } + else + { + DBG_ERRORFILE( "ConvertToMacro: Unknown macro url format" ); + } + } + } + else if ( aMacroName.getLength() ) + { + aScript = OUSTRING( RTL_CONSTASCII_USTRINGPARAM( MACRO_PRFIX ) ); + if ( aLibrary.compareTo( SFX_APP()->GetName() ) != 0 && aLibrary.compareToAscii("StarDesktop") != 0 && aLibrary.compareToAscii("application") != 0 ) + aScript += String('.'); + + aScript += String('/'); + aScript += aMacroName; + aScript += OUSTRING( RTL_CONSTASCII_USTRINGPARAM( MACRO_POSTFIX ) ); + } + else + // wrong properties + return; + + if ( aLibrary.compareToAscii("document") != 0 ) + { + if ( !aLibrary.getLength() || (pDoc && ( String(aLibrary) == pDoc->GetTitle( SFX_TITLE_APINAME ) || String(aLibrary) == pDoc->GetTitle() )) ) + aLibrary = String::CreateFromAscii("document"); + else + aLibrary = String::CreateFromAscii("application"); + } + + aOutProps[1].Name = OUSTRING::createFromAscii( PROP_SCRIPT ); + aOutProps[1].Value <<= aScript; + aOutProps[2].Name = OUSTRING::createFromAscii( PROP_LIBRARY ); + aOutProps[2].Value <<= aLibrary; + aOutProps[3].Name = OUSTRING::createFromAscii( PROP_MACRO_NAME ); + aOutProps[3].Value <<= aMacroName; + rRet <<= aOutProps; + } + else if ( aType.compareToAscii( SVX_MACRO_LANGUAGE_JAVASCRIPT ) == 0 ) + { + aOutProps[1] = aInProps[1]; + rRet <<= aOutProps; + } + else + { + rRet <<= aOutProps; + } +} + +ModelCollectionEnumeration::ModelCollectionEnumeration(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR) + : ModelCollectionMutexBase( ) + , m_xSMGR (xSMGR ) + , m_pEnumerationIt (m_lModels.begin()) +{ +} + +ModelCollectionEnumeration::~ModelCollectionEnumeration() +{ +} + +void ModelCollectionEnumeration::setModelList(const TModelList& rList) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + m_lModels = rList; + m_pEnumerationIt = m_lModels.begin(); + aLock.clear(); + // <- SAFE +} + +sal_Bool SAL_CALL ModelCollectionEnumeration::hasMoreElements() + throw(css::uno::RuntimeException) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + return (m_pEnumerationIt != m_lModels.end()); + // <- SAFE +} + +css::uno::Any SAL_CALL ModelCollectionEnumeration::nextElement() + throw(css::container::NoSuchElementException, + css::lang::WrappedTargetException , + css::uno::RuntimeException ) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + if (m_pEnumerationIt == m_lModels.end()) + throw css::container::NoSuchElementException( + ::rtl::OUString::createFromAscii("End of model enumeration reached."), + static_cast< css::container::XEnumeration* >(this)); + css::uno::Reference< css::frame::XModel > xModel(*m_pEnumerationIt, UNO_QUERY); + ++m_pEnumerationIt; + aLock.clear(); + // <- SAFE + + return css::uno::makeAny(xModel); +} + +SFX_IMPL_XSERVICEINFO( SfxGlobalEvents_Impl, "com.sun.star.frame.GlobalEventBroadcaster", "com.sun.star.comp.sfx2.GlobalEventBroadcaster" ) +SFX_IMPL_ONEINSTANCEFACTORY( SfxGlobalEvents_Impl ); + +//----------------------------------------------------------------------------- +SfxGlobalEvents_Impl::SfxGlobalEvents_Impl( const com::sun::star::uno::Reference < ::com::sun::star::lang::XMultiServiceFactory >& xSMGR) + : ModelCollectionMutexBase( ) + , m_xSMGR (xSMGR ) + , m_aLegacyListeners (m_aLock) + , m_aDocumentListeners (m_aLock) + , pImp (0 ) +{ + m_refCount++; + SFX_APP(); + pImp = new GlobalEventConfig(); + m_xEvents = pImp; + m_xJobExecutorListener = css::uno::Reference< css::document::XEventListener >( + xSMGR->createInstance(::rtl::OUString::createFromAscii("com.sun.star.task.JobExecutor")), + UNO_QUERY); + m_refCount--; +} + +//----------------------------------------------------------------------------- +SfxGlobalEvents_Impl::~SfxGlobalEvents_Impl() +{ +} + +//----------------------------------------------------------------------------- +css::uno::Reference< css::container::XNameReplace > SAL_CALL SfxGlobalEvents_Impl::getEvents() + throw(css::uno::RuntimeException) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + return m_xEvents; + // <- SAFE +} + +//----------------------------------------------------------------------------- +void SAL_CALL SfxGlobalEvents_Impl::addEventListener(const css::uno::Reference< css::document::XEventListener >& xListener) + throw(css::uno::RuntimeException) +{ + // container is threadsafe + m_aLegacyListeners.addInterface(xListener); +} + +//----------------------------------------------------------------------------- +void SAL_CALL SfxGlobalEvents_Impl::removeEventListener(const css::uno::Reference< css::document::XEventListener >& xListener) + throw(css::uno::RuntimeException) +{ + // container is threadsafe + m_aLegacyListeners.removeInterface(xListener); +} + +//----------------------------------------------------------------------------- +void SAL_CALL SfxGlobalEvents_Impl::addDocumentEventListener( const css::uno::Reference< css::document::XDocumentEventListener >& _Listener ) + throw(css::uno::RuntimeException) +{ + m_aDocumentListeners.addInterface( _Listener ); +} + +//----------------------------------------------------------------------------- +void SAL_CALL SfxGlobalEvents_Impl::removeDocumentEventListener( const css::uno::Reference< css::document::XDocumentEventListener >& _Listener ) + throw(css::uno::RuntimeException) +{ + m_aDocumentListeners.removeInterface( _Listener ); +} + +//----------------------------------------------------------------------------- +void SAL_CALL SfxGlobalEvents_Impl::notifyDocumentEvent( const ::rtl::OUString& /*_EventName*/, + const css::uno::Reference< css::frame::XController2 >& /*_ViewController*/, const css::uno::Any& /*_Supplement*/ ) + throw (css::lang::IllegalArgumentException, css::lang::NoSupportException, css::uno::RuntimeException) +{ + // we're a multiplexer only, no chance to generate artifical events here + throw css::lang::NoSupportException(::rtl::OUString(), *this); +} + +//----------------------------------------------------------------------------- +void SAL_CALL SfxGlobalEvents_Impl::notifyEvent(const css::document::EventObject& aEvent) + throw(css::uno::RuntimeException) +{ + css::document::DocumentEvent aDocEvent(aEvent.Source, aEvent.EventName, NULL, css::uno::Any()); + implts_notifyJobExecution(aEvent); + implts_checkAndExecuteEventBindings(aDocEvent); + implts_notifyListener(aDocEvent); +} + +//----------------------------------------------------------------------------- +void SAL_CALL SfxGlobalEvents_Impl::documentEventOccured( const ::css::document::DocumentEvent& _Event ) + throw (::css::uno::RuntimeException) +{ + implts_notifyJobExecution(css::document::EventObject(_Event.Source, _Event.EventName)); + implts_checkAndExecuteEventBindings(_Event); + implts_notifyListener(_Event); +} + +//----------------------------------------------------------------------------- +void SAL_CALL SfxGlobalEvents_Impl::disposing(const css::lang::EventObject& aEvent) + throw(css::uno::RuntimeException) +{ + css::uno::Reference< css::frame::XModel > xDoc(aEvent.Source, UNO_QUERY); + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + TModelList::iterator pIt = impl_searchDoc(xDoc); + if (pIt != m_lModels.end()) + m_lModels.erase(pIt); + aLock.clear(); + // <- SAFE +} + +//----------------------------------------------------------------------------- +sal_Bool SAL_CALL SfxGlobalEvents_Impl::has(const css::uno::Any& aElement) + throw (css::uno::RuntimeException) +{ + css::uno::Reference< css::frame::XModel > xDoc; + aElement >>= xDoc; + + sal_Bool bHas = sal_False; + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + TModelList::iterator pIt = impl_searchDoc(xDoc); + if (pIt != m_lModels.end()) + bHas = sal_True; + aLock.clear(); + // <- SAFE + + return bHas; +} + +//----------------------------------------------------------------------------- +void SAL_CALL SfxGlobalEvents_Impl::insert( const css::uno::Any& aElement ) + throw (css::lang::IllegalArgumentException , + css::container::ElementExistException, + css::uno::RuntimeException ) +{ + css::uno::Reference< css::frame::XModel > xDoc; + aElement >>= xDoc; + if (!xDoc.is()) + throw css::lang::IllegalArgumentException( + ::rtl::OUString::createFromAscii("Cant locate at least the model parameter."), + static_cast< css::container::XSet* >(this), + 0); + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + TModelList::iterator pIt = impl_searchDoc(xDoc); + if (pIt != m_lModels.end()) + throw css::container::ElementExistException( + ::rtl::OUString(), + static_cast< css::container::XSet* >(this)); + m_lModels.push_back(xDoc); + aLock.clear(); + // <- SAFE + + css::uno::Reference< css::document::XDocumentEventBroadcaster > xDocBroadcaster(xDoc, UNO_QUERY ); + if (xDocBroadcaster.is()) + xDocBroadcaster->addDocumentEventListener(this); + else + { + // try the "legacy version" of XDocumentEventBroadcaster, which is XEventBroadcaster + css::uno::Reference< css::document::XEventBroadcaster > xBroadcaster(xDoc, UNO_QUERY); + if (xBroadcaster.is()) + xBroadcaster->addEventListener(static_cast< css::document::XEventListener* >(this)); + } +} + +//----------------------------------------------------------------------------- +void SAL_CALL SfxGlobalEvents_Impl::remove( const css::uno::Any& aElement ) + throw (css::lang::IllegalArgumentException , + css::container::NoSuchElementException, + css::uno::RuntimeException ) +{ + css::uno::Reference< css::frame::XModel > xDoc; + aElement >>= xDoc; + if (!xDoc.is()) + throw css::lang::IllegalArgumentException( + ::rtl::OUString::createFromAscii("Cant locate at least the model parameter."), + static_cast< css::container::XSet* >(this), + 0); + + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + TModelList::iterator pIt = impl_searchDoc(xDoc); + if (pIt == m_lModels.end()) + throw css::container::NoSuchElementException( + ::rtl::OUString(), + static_cast< css::container::XSet* >(this)); + m_lModels.erase(pIt); + aLock.clear(); + // <- SAFE + + css::uno::Reference< css::document::XDocumentEventBroadcaster > xDocBroadcaster(xDoc, UNO_QUERY ); + if (xDocBroadcaster.is()) + xDocBroadcaster->removeDocumentEventListener(this); + else + { + // try the "legacy version" of XDocumentEventBroadcaster, which is XEventBroadcaster + css::uno::Reference< css::document::XEventBroadcaster > xBroadcaster(xDoc, UNO_QUERY); + if (xBroadcaster.is()) + xBroadcaster->removeEventListener(static_cast< css::document::XEventListener* >(this)); + } +} + +//----------------------------------------------------------------------------- +css::uno::Reference< css::container::XEnumeration > SAL_CALL SfxGlobalEvents_Impl::createEnumeration() + throw (css::uno::RuntimeException) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + ModelCollectionEnumeration* pEnum = new ModelCollectionEnumeration(m_xSMGR); + pEnum->setModelList(m_lModels); + css::uno::Reference< css::container::XEnumeration > xEnum( + static_cast< css::container::XEnumeration* >(pEnum), + UNO_QUERY); + aLock.clear(); + // <- SAFE + + return xEnum; +} + +//----------------------------------------------------------------------------- +css::uno::Type SAL_CALL SfxGlobalEvents_Impl::getElementType() + throw (css::uno::RuntimeException) +{ + return ::getCppuType(static_cast< css::uno::Reference< css::frame::XModel >* >(NULL)); +} + +//----------------------------------------------------------------------------- +sal_Bool SAL_CALL SfxGlobalEvents_Impl::hasElements() + throw (css::uno::RuntimeException) +{ + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + return (m_lModels.size()>0); + // <- SAFE +} + +//----------------------------------------------------------------------------- +void SfxGlobalEvents_Impl::implts_notifyJobExecution(const css::document::EventObject& aEvent) +{ + try + { + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + css::uno::Reference< css::document::XEventListener > xJobExecutor(m_xJobExecutorListener); + aLock.clear(); + // <- SAFE + if (xJobExecutor.is()) + xJobExecutor->notifyEvent(aEvent); + } + catch(const css::uno::RuntimeException& exRun) + { throw exRun; } + catch(const css::uno::Exception&) + {} +} + +//----------------------------------------------------------------------------- +void SfxGlobalEvents_Impl::implts_checkAndExecuteEventBindings(const css::document::DocumentEvent& aEvent) +{ + try + { + // SAFE -> + ::osl::ResettableMutexGuard aLock(m_aLock); + css::uno::Reference< css::container::XNameReplace > xEvents = m_xEvents; + aLock.clear(); + // <- SAFE + + css::uno::Any aAny; + if (xEvents.is()) + aAny = xEvents->getByName(aEvent.EventName); + Execute(aAny, aEvent, 0); + } + catch(const css::uno::RuntimeException& exRun) + { throw exRun; } + catch(const css::uno::Exception&) + {} +} + +//----------------------------------------------------------------------------- +void SfxGlobalEvents_Impl::implts_notifyListener(const css::document::DocumentEvent& aEvent) +{ + // containers are threadsafe + css::document::EventObject aLegacyEvent(aEvent.Source, aEvent.EventName); + m_aLegacyListeners.notifyEach( &css::document::XEventListener::notifyEvent, aLegacyEvent ); + + m_aDocumentListeners.notifyEach( &css::document::XDocumentEventListener::documentEventOccured, aEvent ); +} + +//----------------------------------------------------------------------------- +// not threadsafe ... must be locked from outside! +TModelList::iterator SfxGlobalEvents_Impl::impl_searchDoc(const css::uno::Reference< css::frame::XModel >& xModel) +{ + if (!xModel.is()) + return m_lModels.end(); + + TModelList::iterator pIt; + for ( pIt = m_lModels.begin(); + pIt != m_lModels.end() ; + ++pIt ) + { + css::uno::Reference< css::frame::XModel > xContainerDoc(*pIt, UNO_QUERY); + if (xContainerDoc == xModel) + break; + } + + return pIt; +} + |