merge the formfield patch from ooo-build
[ooovba.git] / framework / source / dispatch / interceptionhelper.cxx
blob1bb33a335062d13eac7af83a756b7be322fefe04
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: interceptionhelper.cxx,v $
10 * $Revision: 1.6 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
34 //_______________________________________________
35 // my own includes
37 #ifndef __FRAMEWORK_DISPATCH_INTERCEPTIONHELPER_HXX_
38 #include <dispatch/interceptionhelper.hxx>
39 #endif
41 //_______________________________________________
42 // interface includes
43 #include <com/sun/star/frame/XInterceptorInfo.hpp>
45 //_______________________________________________
46 // includes of other projects
47 #include <vcl/svapp.hxx>
49 //_______________________________________________
50 // namespace
52 namespace framework{
54 //_______________________________________________
55 // non exported const
57 sal_Bool InterceptionHelper::m_bPreferrFirstInterceptor = sal_True;
59 //_______________________________________________
60 // non exported definitions
62 //_______________________________________________
63 // declarations
65 /*-----------------------------------------------------------------------------
66 31.03.2003 09:02
67 -----------------------------------------------------------------------------*/
68 DEFINE_XINTERFACE_3(InterceptionHelper ,
69 OWeakObject ,
70 DIRECT_INTERFACE(css::frame::XDispatchProvider ),
71 DIRECT_INTERFACE(css::frame::XDispatchProviderInterception),
72 DIRECT_INTERFACE(css::lang::XEventListener ))
74 /*-----------------------------------------------------------------------------
75 31.03.2003 09:02
76 -----------------------------------------------------------------------------*/
77 InterceptionHelper::InterceptionHelper(const css::uno::Reference< css::frame::XFrame >& xOwner,
78 const css::uno::Reference< css::frame::XDispatchProvider >& xSlave)
79 // Init baseclasses first
80 : ThreadHelpBase(&Application::GetSolarMutex())
81 , OWeakObject ( )
82 // Init member
83 , m_xOwnerWeak (xOwner )
84 , m_xSlave (xSlave )
88 /*-----------------------------------------------------------------------------
89 31.03.2003 09:02
90 -----------------------------------------------------------------------------*/
91 InterceptionHelper::~InterceptionHelper()
95 /*-----------------------------------------------------------------------------
96 31.03.2003 09:09
97 -----------------------------------------------------------------------------*/
98 css::uno::Reference< css::frame::XDispatch > SAL_CALL InterceptionHelper::queryDispatch(const css::util::URL& aURL ,
99 const ::rtl::OUString& sTargetFrameName,
100 sal_Int32 nSearchFlags )
101 throw(css::uno::RuntimeException)
103 // SAFE {
104 ReadGuard aReadLock(m_aLock);
106 // a) first search an interceptor, which match to this URL by it's URL pattern registration
107 // Note: if it return NULL - it does not mean an empty interceptor list automaticly!
108 css::uno::Reference< css::frame::XDispatchProvider > xInterceptor;
109 InterceptorList::const_iterator pIt = m_lInterceptionRegs.findByPattern(aURL.Complete);
110 if (pIt != m_lInterceptionRegs.end())
111 xInterceptor = pIt->xInterceptor;
113 // b) No match by registration - but a valid interceptor list.
114 // Use first interceptor everytimes.
115 // Note: it doesn't matter, which direction this helper implementation use to ask interceptor objects.
116 // Using of member m_aInterceptorList will starts at the beginning everytimes.
117 // It depends from the filling operation, in which direction it works realy!
118 if (!xInterceptor.is() && m_lInterceptionRegs.size()>0)
120 pIt = m_lInterceptionRegs.begin();
121 xInterceptor = pIt->xInterceptor;
124 // c) No registered interceptor => use our direct slave.
125 // This helper exist by design and must be valid everytimes ...
126 // But to be more feature proof - we should check that .-)
127 if (!xInterceptor.is() && m_xSlave.is())
128 xInterceptor = m_xSlave;
130 aReadLock.unlock();
131 // } SAFE
133 css::uno::Reference< css::frame::XDispatch > xReturn;
134 if (xInterceptor.is())
135 xReturn = xInterceptor->queryDispatch(aURL, sTargetFrameName, nSearchFlags);
136 return xReturn;
139 /*-----------------------------------------------------------------------------
140 31.03.2003 07:58
141 -----------------------------------------------------------------------------*/
142 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL InterceptionHelper::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor )
143 throw(css::uno::RuntimeException)
145 sal_Int32 c = lDescriptor.getLength();
146 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatches (c);
147 css::uno::Reference< css::frame::XDispatch >* pDispatches = lDispatches.getArray();
148 const css::frame::DispatchDescriptor* pDescriptor = lDescriptor.getConstArray();
150 for (sal_Int32 i=0; i<c; ++i)
151 pDispatches[i] = queryDispatch(pDescriptor[i].FeatureURL, pDescriptor[i].FrameName, pDescriptor[i].SearchFlags);
153 return lDispatches;
156 /*-----------------------------------------------------------------------------
157 31.03.2003 10:20
158 -----------------------------------------------------------------------------*/
159 void SAL_CALL InterceptionHelper::registerDispatchProviderInterceptor(const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor)
160 throw(css::uno::RuntimeException)
162 // reject wrong calling of this interface method
163 css::uno::Reference< css::frame::XDispatchProvider > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
164 if (!xInterceptor.is())
165 throw css::uno::RuntimeException(DECLARE_ASCII("NULL references not allowed as in parameter"), xThis);
167 // Fill a new info structure for new interceptor.
168 // Save his reference and try to get an additional URL/pattern list from him.
169 // If no list exist register these interceptor for all dispatch events with "*"!
170 InterceptorInfo aInfo;
172 aInfo.xInterceptor = css::uno::Reference< css::frame::XDispatchProvider >(xInterceptor, css::uno::UNO_QUERY);
173 css::uno::Reference< css::frame::XInterceptorInfo > xInfo(xInterceptor, css::uno::UNO_QUERY);
174 if (xInfo.is())
175 aInfo.lURLPattern = xInfo->getInterceptedURLs();
176 else
178 aInfo.lURLPattern.realloc(1);
179 aInfo.lURLPattern[0] = ::rtl::OUString::createFromAscii("*");
182 // SAFE {
183 WriteGuard aWriteLock(m_aLock);
185 // a) no interceptor at all - set this instance as master for given interceptor
186 // and set our slave as it's slave - and put this interceptor to the list.
187 // It's place there doesn matter. Because this list is currently empty.
188 if (m_lInterceptionRegs.empty())
190 xInterceptor->setMasterDispatchProvider(xThis );
191 xInterceptor->setSlaveDispatchProvider (m_xSlave);
192 m_lInterceptionRegs.push_back(aInfo);
195 // b) OK - there is at least one interceptor already registered.
196 // It's slave and it's master must be valid references ...
197 // because we created it. But we have to look for the static bool which
198 // regulate direction of using of interceptor objects!
200 // b1) If "m_bPreferrFirstInterceptor" is set to true, we have to
201 // insert it behind any other existing interceptor - means at the end of our list.
202 else if (m_bPreferrFirstInterceptor)
204 css::uno::Reference< css::frame::XDispatchProvider > xMasterD = m_lInterceptionRegs.rbegin()->xInterceptor;
205 css::uno::Reference< css::frame::XDispatchProviderInterceptor > xMasterI (xMasterD, css::uno::UNO_QUERY);
207 xInterceptor->setMasterDispatchProvider(xMasterD );
208 xInterceptor->setSlaveDispatchProvider (m_xSlave );
209 xMasterI->setSlaveDispatchProvider (aInfo.xInterceptor);
211 m_lInterceptionRegs.push_back(aInfo);
214 // b2) If "m_bPreferrFirstInterceptor" is set to false, we have to
215 // insert it before any other existing interceptor - means at the beginning of our list.
216 else
218 css::uno::Reference< css::frame::XDispatchProvider > xSlaveD = m_lInterceptionRegs.begin()->xInterceptor;
219 css::uno::Reference< css::frame::XDispatchProviderInterceptor > xSlaveI (xSlaveD , css::uno::UNO_QUERY);
221 xInterceptor->setMasterDispatchProvider(xThis );
222 xInterceptor->setSlaveDispatchProvider (xSlaveD );
223 xSlaveI->setMasterDispatchProvider (aInfo.xInterceptor);
225 m_lInterceptionRegs.push_front(aInfo);
228 css::uno::Reference< css::frame::XFrame > xOwner(m_xOwnerWeak.get(), css::uno::UNO_QUERY);
230 aWriteLock.unlock();
231 // } SAFE
233 // Don't forget to send a frame action event "context changed".
234 // Any cached dispatch objects must be validated now!
235 if (xOwner.is())
236 xOwner->contextChanged();
239 /*-----------------------------------------------------------------------------
240 31.03.2003 10:27
241 -----------------------------------------------------------------------------*/
242 void SAL_CALL InterceptionHelper::releaseDispatchProviderInterceptor(const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor)
243 throw(css::uno::RuntimeException)
245 // reject wrong calling of this interface method
246 css::uno::Reference< css::frame::XDispatchProvider > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
247 if (!xInterceptor.is())
248 throw css::uno::RuntimeException(DECLARE_ASCII("NULL references not allowed as in parameter"), xThis);
250 // SAFE {
251 WriteGuard aWriteLock(m_aLock);
253 // search this interceptor ...
254 // If it could be located inside cache -
255 // use it's slave/master relations to update the interception list;
256 // set empty references for it as new master and slave;
257 // and relase it from out cache.
258 InterceptorList::iterator pIt = m_lInterceptionRegs.findByReference(xInterceptor);
259 if (pIt != m_lInterceptionRegs.end())
261 css::uno::Reference< css::frame::XDispatchProvider > xSlaveD (xInterceptor->getSlaveDispatchProvider() , css::uno::UNO_QUERY);
262 css::uno::Reference< css::frame::XDispatchProvider > xMasterD (xInterceptor->getMasterDispatchProvider(), css::uno::UNO_QUERY);
263 css::uno::Reference< css::frame::XDispatchProviderInterceptor > xSlaveI (xSlaveD , css::uno::UNO_QUERY);
264 css::uno::Reference< css::frame::XDispatchProviderInterceptor > xMasterI (xMasterD , css::uno::UNO_QUERY);
266 if (xMasterI.is())
267 xMasterI->setSlaveDispatchProvider(xSlaveD);
269 if (xSlaveI.is())
270 xSlaveI->setMasterDispatchProvider(xMasterD);
272 xInterceptor->setSlaveDispatchProvider (css::uno::Reference< css::frame::XDispatchProvider >());
273 xInterceptor->setMasterDispatchProvider(css::uno::Reference< css::frame::XDispatchProvider >());
275 m_lInterceptionRegs.erase(pIt);
278 css::uno::Reference< css::frame::XFrame > xOwner(m_xOwnerWeak.get(), css::uno::UNO_QUERY);
280 aWriteLock.unlock();
281 // } SAFE
283 // Don't forget to send a frame action event "context changed".
284 // Any cached dispatch objects must be validated now!
285 if (xOwner.is())
286 xOwner->contextChanged();
289 /*-----------------------------------------------------------------------------
290 31.03.2003 10:31
291 -----------------------------------------------------------------------------*/
292 #define FORCE_DESTRUCTION_OF_INTERCEPTION_CHAIN
293 void SAL_CALL InterceptionHelper::disposing(const css::lang::EventObject& aEvent)
294 throw(css::uno::RuntimeException)
296 #ifdef FORCE_DESTRUCTION_OF_INTERCEPTION_CHAIN
297 // SAFE ->
298 ReadGuard aReadLock(m_aLock);
300 // check calli ... we accept such disposing call's only from our onwer frame.
301 css::uno::Reference< css::frame::XFrame > xOwner(m_xOwnerWeak.get(), css::uno::UNO_QUERY);
302 if (aEvent.Source != xOwner)
303 return;
305 // Because every interceptor hold at least one reference to us ... and we destruct this list
306 // of interception objects ... we should hold ourself alive .-)
307 css::uno::Reference< css::frame::XDispatchProvider > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY_THROW);
309 // We need a full copy of all currently registered interceptor objects.
310 // Otherwhise we cant iterate over this vector without the risk, that our iterator will be invalid.
311 // Because this vetor will be influenced by every deregistered interceptor.
312 InterceptionHelper::InterceptorList aCopy = m_lInterceptionRegs;
314 aReadLock.unlock();
315 // <- SAFE
317 InterceptionHelper::InterceptorList::iterator pIt;
318 for ( pIt = aCopy.begin();
319 pIt != aCopy.end() ;
320 ++pIt )
322 InterceptionHelper::InterceptorInfo& rInfo = *pIt;
323 if (rInfo.xInterceptor.is())
325 css::uno::Reference< css::frame::XDispatchProviderInterceptor > xInterceptor(rInfo.xInterceptor, css::uno::UNO_QUERY_THROW);
326 releaseDispatchProviderInterceptor(xInterceptor);
327 rInfo.xInterceptor.clear();
331 aCopy.clear();
333 #if OSL_DEBUG_LEVEL > 0
334 // SAFE ->
335 aReadLock.lock();
336 if (!m_lInterceptionRegs.empty() )
337 OSL_ENSURE(sal_False, "There are some pending interceptor objects, which seams to be registered during (!) the destruction of a frame.");
338 aReadLock.unlock();
339 // <- SAFE
340 #endif // ODL_DEBUG_LEVEL>0
342 #endif // FORCE_DESTRUCTION_OF_INTERCEPTION_CHAIN
345 } // namespace framework