| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_framework.hxx" |
| |
| //_______________________________________________ |
| // my own includes |
| |
| #ifndef __FRAMEWORK_DISPATCH_INTERCEPTIONHELPER_HXX_ |
| #include <dispatch/interceptionhelper.hxx> |
| #endif |
| |
| //_______________________________________________ |
| // interface includes |
| #include <com/sun/star/frame/XInterceptorInfo.hpp> |
| |
| //_______________________________________________ |
| // includes of other projects |
| #include <vcl/svapp.hxx> |
| |
| //_______________________________________________ |
| // namespace |
| |
| namespace framework{ |
| |
| //_______________________________________________ |
| // non exported const |
| |
| sal_Bool InterceptionHelper::m_bPreferrFirstInterceptor = sal_True; |
| |
| //_______________________________________________ |
| // non exported definitions |
| |
| //_______________________________________________ |
| // declarations |
| |
| /*----------------------------------------------------------------------------- |
| 31.03.2003 09:02 |
| -----------------------------------------------------------------------------*/ |
| DEFINE_XINTERFACE_3(InterceptionHelper , |
| OWeakObject , |
| DIRECT_INTERFACE(css::frame::XDispatchProvider ), |
| DIRECT_INTERFACE(css::frame::XDispatchProviderInterception), |
| DIRECT_INTERFACE(css::lang::XEventListener )) |
| |
| /*----------------------------------------------------------------------------- |
| 31.03.2003 09:02 |
| -----------------------------------------------------------------------------*/ |
| InterceptionHelper::InterceptionHelper(const css::uno::Reference< css::frame::XFrame >& xOwner, |
| const css::uno::Reference< css::frame::XDispatchProvider >& xSlave) |
| // Init baseclasses first |
| : ThreadHelpBase(&Application::GetSolarMutex()) |
| , OWeakObject ( ) |
| // Init member |
| , m_xOwnerWeak (xOwner ) |
| , m_xSlave (xSlave ) |
| { |
| } |
| |
| /*----------------------------------------------------------------------------- |
| 31.03.2003 09:02 |
| -----------------------------------------------------------------------------*/ |
| InterceptionHelper::~InterceptionHelper() |
| { |
| } |
| |
| /*----------------------------------------------------------------------------- |
| 31.03.2003 09:09 |
| -----------------------------------------------------------------------------*/ |
| css::uno::Reference< css::frame::XDispatch > SAL_CALL InterceptionHelper::queryDispatch(const css::util::URL& aURL , |
| const ::rtl::OUString& sTargetFrameName, |
| sal_Int32 nSearchFlags ) |
| throw(css::uno::RuntimeException) |
| { |
| // SAFE { |
| ReadGuard aReadLock(m_aLock); |
| |
| // a) first search an interceptor, which match to this URL by it's URL pattern registration |
| // Note: if it return NULL - it does not mean an empty interceptor list automaticly! |
| css::uno::Reference< css::frame::XDispatchProvider > xInterceptor; |
| InterceptorList::const_iterator pIt = m_lInterceptionRegs.findByPattern(aURL.Complete); |
| if (pIt != m_lInterceptionRegs.end()) |
| xInterceptor = pIt->xInterceptor; |
| |
| // b) No match by registration - but a valid interceptor list. |
| // Use first interceptor everytimes. |
| // Note: it doesn't matter, which direction this helper implementation use to ask interceptor objects. |
| // Using of member m_aInterceptorList will starts at the beginning everytimes. |
| // It depends from the filling operation, in which direction it works realy! |
| if (!xInterceptor.is() && m_lInterceptionRegs.size()>0) |
| { |
| pIt = m_lInterceptionRegs.begin(); |
| xInterceptor = pIt->xInterceptor; |
| } |
| |
| // c) No registered interceptor => use our direct slave. |
| // This helper exist by design and must be valid everytimes ... |
| // But to be more feature proof - we should check that .-) |
| if (!xInterceptor.is() && m_xSlave.is()) |
| xInterceptor = m_xSlave; |
| |
| aReadLock.unlock(); |
| // } SAFE |
| |
| css::uno::Reference< css::frame::XDispatch > xReturn; |
| if (xInterceptor.is()) |
| xReturn = xInterceptor->queryDispatch(aURL, sTargetFrameName, nSearchFlags); |
| return xReturn; |
| } |
| |
| /*----------------------------------------------------------------------------- |
| 31.03.2003 07:58 |
| -----------------------------------------------------------------------------*/ |
| css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL InterceptionHelper::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor ) |
| throw(css::uno::RuntimeException) |
| { |
| sal_Int32 c = lDescriptor.getLength(); |
| css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatches (c); |
| css::uno::Reference< css::frame::XDispatch >* pDispatches = lDispatches.getArray(); |
| const css::frame::DispatchDescriptor* pDescriptor = lDescriptor.getConstArray(); |
| |
| for (sal_Int32 i=0; i<c; ++i) |
| pDispatches[i] = queryDispatch(pDescriptor[i].FeatureURL, pDescriptor[i].FrameName, pDescriptor[i].SearchFlags); |
| |
| return lDispatches; |
| } |
| |
| /*----------------------------------------------------------------------------- |
| 31.03.2003 10:20 |
| -----------------------------------------------------------------------------*/ |
| void SAL_CALL InterceptionHelper::registerDispatchProviderInterceptor(const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor) |
| throw(css::uno::RuntimeException) |
| { |
| // reject wrong calling of this interface method |
| css::uno::Reference< css::frame::XDispatchProvider > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY); |
| if (!xInterceptor.is()) |
| throw css::uno::RuntimeException(DECLARE_ASCII("NULL references not allowed as in parameter"), xThis); |
| |
| // Fill a new info structure for new interceptor. |
| // Save his reference and try to get an additional URL/pattern list from him. |
| // If no list exist register these interceptor for all dispatch events with "*"! |
| InterceptorInfo aInfo; |
| |
| aInfo.xInterceptor = css::uno::Reference< css::frame::XDispatchProvider >(xInterceptor, css::uno::UNO_QUERY); |
| css::uno::Reference< css::frame::XInterceptorInfo > xInfo(xInterceptor, css::uno::UNO_QUERY); |
| if (xInfo.is()) |
| aInfo.lURLPattern = xInfo->getInterceptedURLs(); |
| else |
| { |
| aInfo.lURLPattern.realloc(1); |
| aInfo.lURLPattern[0] = ::rtl::OUString::createFromAscii("*"); |
| } |
| |
| // SAFE { |
| WriteGuard aWriteLock(m_aLock); |
| |
| // a) no interceptor at all - set this instance as master for given interceptor |
| // and set our slave as it's slave - and put this interceptor to the list. |
| // It's place there doesn matter. Because this list is currently empty. |
| if (m_lInterceptionRegs.empty()) |
| { |
| xInterceptor->setMasterDispatchProvider(xThis ); |
| xInterceptor->setSlaveDispatchProvider (m_xSlave); |
| m_lInterceptionRegs.push_back(aInfo); |
| } |
| |
| // b) OK - there is at least one interceptor already registered. |
| // It's slave and it's master must be valid references ... |
| // because we created it. But we have to look for the static bool which |
| // regulate direction of using of interceptor objects! |
| |
| // b1) If "m_bPreferrFirstInterceptor" is set to true, we have to |
| // insert it behind any other existing interceptor - means at the end of our list. |
| else if (m_bPreferrFirstInterceptor) |
| { |
| css::uno::Reference< css::frame::XDispatchProvider > xMasterD = m_lInterceptionRegs.rbegin()->xInterceptor; |
| css::uno::Reference< css::frame::XDispatchProviderInterceptor > xMasterI (xMasterD, css::uno::UNO_QUERY); |
| |
| xInterceptor->setMasterDispatchProvider(xMasterD ); |
| xInterceptor->setSlaveDispatchProvider (m_xSlave ); |
| xMasterI->setSlaveDispatchProvider (aInfo.xInterceptor); |
| |
| m_lInterceptionRegs.push_back(aInfo); |
| } |
| |
| // b2) If "m_bPreferrFirstInterceptor" is set to false, we have to |
| // insert it before any other existing interceptor - means at the beginning of our list. |
| else |
| { |
| css::uno::Reference< css::frame::XDispatchProvider > xSlaveD = m_lInterceptionRegs.begin()->xInterceptor; |
| css::uno::Reference< css::frame::XDispatchProviderInterceptor > xSlaveI (xSlaveD , css::uno::UNO_QUERY); |
| |
| xInterceptor->setMasterDispatchProvider(xThis ); |
| xInterceptor->setSlaveDispatchProvider (xSlaveD ); |
| xSlaveI->setMasterDispatchProvider (aInfo.xInterceptor); |
| |
| m_lInterceptionRegs.push_front(aInfo); |
| } |
| |
| css::uno::Reference< css::frame::XFrame > xOwner(m_xOwnerWeak.get(), css::uno::UNO_QUERY); |
| |
| aWriteLock.unlock(); |
| // } SAFE |
| |
| // Don't forget to send a frame action event "context changed". |
| // Any cached dispatch objects must be validated now! |
| if (xOwner.is()) |
| xOwner->contextChanged(); |
| } |
| |
| /*----------------------------------------------------------------------------- |
| 31.03.2003 10:27 |
| -----------------------------------------------------------------------------*/ |
| void SAL_CALL InterceptionHelper::releaseDispatchProviderInterceptor(const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor) |
| throw(css::uno::RuntimeException) |
| { |
| // reject wrong calling of this interface method |
| css::uno::Reference< css::frame::XDispatchProvider > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY); |
| if (!xInterceptor.is()) |
| throw css::uno::RuntimeException(DECLARE_ASCII("NULL references not allowed as in parameter"), xThis); |
| |
| // SAFE { |
| WriteGuard aWriteLock(m_aLock); |
| |
| // search this interceptor ... |
| // If it could be located inside cache - |
| // use it's slave/master relations to update the interception list; |
| // set empty references for it as new master and slave; |
| // and relase it from out cache. |
| InterceptorList::iterator pIt = m_lInterceptionRegs.findByReference(xInterceptor); |
| if (pIt != m_lInterceptionRegs.end()) |
| { |
| css::uno::Reference< css::frame::XDispatchProvider > xSlaveD (xInterceptor->getSlaveDispatchProvider() , css::uno::UNO_QUERY); |
| css::uno::Reference< css::frame::XDispatchProvider > xMasterD (xInterceptor->getMasterDispatchProvider(), css::uno::UNO_QUERY); |
| css::uno::Reference< css::frame::XDispatchProviderInterceptor > xSlaveI (xSlaveD , css::uno::UNO_QUERY); |
| css::uno::Reference< css::frame::XDispatchProviderInterceptor > xMasterI (xMasterD , css::uno::UNO_QUERY); |
| |
| if (xMasterI.is()) |
| xMasterI->setSlaveDispatchProvider(xSlaveD); |
| |
| if (xSlaveI.is()) |
| xSlaveI->setMasterDispatchProvider(xMasterD); |
| |
| xInterceptor->setSlaveDispatchProvider (css::uno::Reference< css::frame::XDispatchProvider >()); |
| xInterceptor->setMasterDispatchProvider(css::uno::Reference< css::frame::XDispatchProvider >()); |
| |
| m_lInterceptionRegs.erase(pIt); |
| } |
| |
| css::uno::Reference< css::frame::XFrame > xOwner(m_xOwnerWeak.get(), css::uno::UNO_QUERY); |
| |
| aWriteLock.unlock(); |
| // } SAFE |
| |
| // Don't forget to send a frame action event "context changed". |
| // Any cached dispatch objects must be validated now! |
| if (xOwner.is()) |
| xOwner->contextChanged(); |
| } |
| |
| /*----------------------------------------------------------------------------- |
| 31.03.2003 10:31 |
| -----------------------------------------------------------------------------*/ |
| #define FORCE_DESTRUCTION_OF_INTERCEPTION_CHAIN |
| void SAL_CALL InterceptionHelper::disposing(const css::lang::EventObject& aEvent) |
| throw(css::uno::RuntimeException) |
| { |
| #ifdef FORCE_DESTRUCTION_OF_INTERCEPTION_CHAIN |
| // SAFE -> |
| ReadGuard aReadLock(m_aLock); |
| |
| // check calli ... we accept such disposing call's only from our onwer frame. |
| css::uno::Reference< css::frame::XFrame > xOwner(m_xOwnerWeak.get(), css::uno::UNO_QUERY); |
| if (aEvent.Source != xOwner) |
| return; |
| |
| // Because every interceptor hold at least one reference to us ... and we destruct this list |
| // of interception objects ... we should hold ourself alive .-) |
| css::uno::Reference< css::frame::XDispatchProvider > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY_THROW); |
| |
| // We need a full copy of all currently registered interceptor objects. |
| // Otherwhise we cant iterate over this vector without the risk, that our iterator will be invalid. |
| // Because this vetor will be influenced by every deregistered interceptor. |
| InterceptionHelper::InterceptorList aCopy = m_lInterceptionRegs; |
| |
| aReadLock.unlock(); |
| // <- SAFE |
| |
| InterceptionHelper::InterceptorList::iterator pIt; |
| for ( pIt = aCopy.begin(); |
| pIt != aCopy.end() ; |
| ++pIt ) |
| { |
| InterceptionHelper::InterceptorInfo& rInfo = *pIt; |
| if (rInfo.xInterceptor.is()) |
| { |
| css::uno::Reference< css::frame::XDispatchProviderInterceptor > xInterceptor(rInfo.xInterceptor, css::uno::UNO_QUERY_THROW); |
| releaseDispatchProviderInterceptor(xInterceptor); |
| rInfo.xInterceptor.clear(); |
| } |
| } |
| |
| aCopy.clear(); |
| |
| #if OSL_DEBUG_LEVEL > 0 |
| // SAFE -> |
| aReadLock.lock(); |
| if (!m_lInterceptionRegs.empty() ) |
| OSL_ENSURE(sal_False, "There are some pending interceptor objects, which seams to be registered during (!) the destruction of a frame."); |
| aReadLock.unlock(); |
| // <- SAFE |
| #endif // ODL_DEBUG_LEVEL>0 |
| |
| #endif // FORCE_DESTRUCTION_OF_INTERCEPTION_CHAIN |
| } |
| |
| } // namespace framework |