Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <dispatch/interceptionhelper.hxx>
30 : :
31 : : #include <com/sun/star/frame/XInterceptorInfo.hpp>
32 : :
33 : : #include <vcl/svapp.hxx>
34 : :
35 : :
36 : : namespace framework{
37 : :
38 : :
39 : : sal_Bool InterceptionHelper::m_bPreferrFirstInterceptor = sal_True;
40 : :
41 : :
42 : :
43 [ + + ][ + - ]: 49571 : DEFINE_XINTERFACE_3(InterceptionHelper ,
44 : : OWeakObject ,
45 : : DIRECT_INTERFACE(css::frame::XDispatchProvider ),
46 : : DIRECT_INTERFACE(css::frame::XDispatchProviderInterception),
47 : : DIRECT_INTERFACE(css::lang::XEventListener ))
48 : :
49 : 1983 : InterceptionHelper::InterceptionHelper(const css::uno::Reference< css::frame::XFrame >& xOwner,
50 : : const css::uno::Reference< css::frame::XDispatchProvider >& xSlave)
51 : : // Init baseclasses first
52 [ + - ]: 1983 : : ThreadHelpBase(&Application::GetSolarMutex())
53 : : , OWeakObject ( )
54 : : // Init member
55 : : , m_xOwnerWeak (xOwner )
56 [ + - ][ + - ]: 3966 : , m_xSlave (xSlave )
[ + - ]
57 : : {
58 : 1983 : }
59 : :
60 [ + - ][ + - ]: 1892 : InterceptionHelper::~InterceptionHelper()
[ + - ]
61 : : {
62 [ - + ]: 3784 : }
63 : :
64 : 205665 : css::uno::Reference< css::frame::XDispatch > SAL_CALL InterceptionHelper::queryDispatch(const css::util::URL& aURL ,
65 : : const ::rtl::OUString& sTargetFrameName,
66 : : sal_Int32 nSearchFlags )
67 : : throw(css::uno::RuntimeException)
68 : : {
69 : : // SAFE {
70 [ + - ]: 205665 : ReadGuard aReadLock(m_aLock);
71 : :
72 : : // a) first search an interceptor, which match to this URL by it's URL pattern registration
73 : : // Note: if it return NULL - it does not mean an empty interceptor list automaticly!
74 : 205665 : css::uno::Reference< css::frame::XDispatchProvider > xInterceptor;
75 [ + - ]: 205665 : InterceptorList::const_iterator pIt = m_lInterceptionRegs.findByPattern(aURL.Complete);
76 [ + + ][ + - ]: 205665 : if (pIt != m_lInterceptionRegs.end())
77 [ + - ]: 180575 : xInterceptor = pIt->xInterceptor;
78 : :
79 : : // b) No match by registration - but a valid interceptor list.
80 : : // Use first interceptor everytimes.
81 : : // Note: it doesn't matter, which direction this helper implementation use to ask interceptor objects.
82 : : // Using of member m_aInterceptorList will starts at the beginning everytimes.
83 : : // It depends from the filling operation, in which direction it works realy!
84 [ + + ][ - + ]: 205665 : if (!xInterceptor.is() && m_lInterceptionRegs.size()>0)
[ - + ]
85 : : {
86 : 0 : pIt = m_lInterceptionRegs.begin();
87 [ # # ]: 0 : xInterceptor = pIt->xInterceptor;
88 : : }
89 : :
90 : : // c) No registered interceptor => use our direct slave.
91 : : // This helper exist by design and must be valid everytimes ...
92 : : // But to be more feature proof - we should check that .-)
93 [ + + ][ + - ]: 205665 : if (!xInterceptor.is() && m_xSlave.is())
[ + + ]
94 [ + - ]: 25090 : xInterceptor = m_xSlave;
95 : :
96 [ + - ]: 205665 : aReadLock.unlock();
97 : : // } SAFE
98 : :
99 : 205665 : css::uno::Reference< css::frame::XDispatch > xReturn;
100 [ + - ]: 205665 : if (xInterceptor.is())
101 [ + - ][ + - ]: 205665 : xReturn = xInterceptor->queryDispatch(aURL, sTargetFrameName, nSearchFlags);
[ + - ]
102 [ + - ]: 205665 : return xReturn;
103 : : }
104 : :
105 : 2 : css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL InterceptionHelper::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor )
106 : : throw(css::uno::RuntimeException)
107 : : {
108 : 2 : sal_Int32 c = lDescriptor.getLength();
109 : 2 : css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatches (c);
110 [ + - ]: 2 : css::uno::Reference< css::frame::XDispatch >* pDispatches = lDispatches.getArray();
111 : 2 : const css::frame::DispatchDescriptor* pDescriptor = lDescriptor.getConstArray();
112 : :
113 [ + + ]: 6 : for (sal_Int32 i=0; i<c; ++i)
114 [ + - ][ + - ]: 4 : pDispatches[i] = queryDispatch(pDescriptor[i].FeatureURL, pDescriptor[i].FrameName, pDescriptor[i].SearchFlags);
115 : :
116 : 2 : return lDispatches;
117 : : }
118 : :
119 : 1549 : void SAL_CALL InterceptionHelper::registerDispatchProviderInterceptor(const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor)
120 : : throw(css::uno::RuntimeException)
121 : : {
122 : : // reject wrong calling of this interface method
123 [ + - ]: 1549 : css::uno::Reference< css::frame::XDispatchProvider > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
124 [ - + ]: 1549 : if (!xInterceptor.is())
125 [ # # ][ # # ]: 0 : throw css::uno::RuntimeException(DECLARE_ASCII("NULL references not allowed as in parameter"), xThis);
126 : :
127 : : // Fill a new info structure for new interceptor.
128 : : // Save his reference and try to get an additional URL/pattern list from him.
129 : : // If no list exist register these interceptor for all dispatch events with "*"!
130 [ + - ]: 1549 : InterceptorInfo aInfo;
131 : :
132 [ + - ][ + - ]: 1549 : aInfo.xInterceptor = css::uno::Reference< css::frame::XDispatchProvider >(xInterceptor, css::uno::UNO_QUERY);
133 [ + - ]: 1549 : css::uno::Reference< css::frame::XInterceptorInfo > xInfo(xInterceptor, css::uno::UNO_QUERY);
134 [ - + ]: 1549 : if (xInfo.is())
135 [ # # ][ # # ]: 0 : aInfo.lURLPattern = xInfo->getInterceptedURLs();
[ # # ][ # # ]
136 : : else
137 : : {
138 [ + - ]: 1549 : aInfo.lURLPattern.realloc(1);
139 [ + - ]: 1549 : aInfo.lURLPattern[0] = ::rtl::OUString("*");
140 : : }
141 : :
142 : : // SAFE {
143 [ + - ]: 1549 : WriteGuard aWriteLock(m_aLock);
144 : :
145 : : // a) no interceptor at all - set this instance as master for given interceptor
146 : : // and set our slave as it's slave - and put this interceptor to the list.
147 : : // It's place there doesn matter. Because this list is currently empty.
148 [ + - ]: 1549 : if (m_lInterceptionRegs.empty())
149 : : {
150 [ + - ][ + - ]: 1549 : xInterceptor->setMasterDispatchProvider(xThis );
151 [ + - ][ + - ]: 1549 : xInterceptor->setSlaveDispatchProvider (m_xSlave);
152 [ + - ]: 1549 : m_lInterceptionRegs.push_back(aInfo);
153 : : }
154 : :
155 : : // b) OK - there is at least one interceptor already registered.
156 : : // It's slave and it's master must be valid references ...
157 : : // because we created it. But we have to look for the static bool which
158 : : // regulate direction of using of interceptor objects!
159 : :
160 : : // b1) If "m_bPreferrFirstInterceptor" is set to true, we have to
161 : : // insert it behind any other existing interceptor - means at the end of our list.
162 [ # # ]: 0 : else if (m_bPreferrFirstInterceptor)
163 : : {
164 [ # # ]: 0 : css::uno::Reference< css::frame::XDispatchProvider > xMasterD = m_lInterceptionRegs.rbegin()->xInterceptor;
165 [ # # ]: 0 : css::uno::Reference< css::frame::XDispatchProviderInterceptor > xMasterI (xMasterD, css::uno::UNO_QUERY);
166 : :
167 [ # # ][ # # ]: 0 : xInterceptor->setMasterDispatchProvider(xMasterD );
168 [ # # ][ # # ]: 0 : xInterceptor->setSlaveDispatchProvider (m_xSlave );
169 [ # # ][ # # ]: 0 : xMasterI->setSlaveDispatchProvider (aInfo.xInterceptor);
170 : :
171 [ # # ]: 0 : m_lInterceptionRegs.push_back(aInfo);
172 : : }
173 : :
174 : : // b2) If "m_bPreferrFirstInterceptor" is set to false, we have to
175 : : // insert it before any other existing interceptor - means at the beginning of our list.
176 : : else
177 : : {
178 : 0 : css::uno::Reference< css::frame::XDispatchProvider > xSlaveD = m_lInterceptionRegs.begin()->xInterceptor;
179 [ # # ]: 0 : css::uno::Reference< css::frame::XDispatchProviderInterceptor > xSlaveI (xSlaveD , css::uno::UNO_QUERY);
180 : :
181 [ # # ][ # # ]: 0 : xInterceptor->setMasterDispatchProvider(xThis );
182 [ # # ][ # # ]: 0 : xInterceptor->setSlaveDispatchProvider (xSlaveD );
183 [ # # ][ # # ]: 0 : xSlaveI->setMasterDispatchProvider (aInfo.xInterceptor);
184 : :
185 [ # # ]: 0 : m_lInterceptionRegs.push_front(aInfo);
186 : : }
187 : :
188 [ + - ][ + - ]: 1549 : css::uno::Reference< css::frame::XFrame > xOwner(m_xOwnerWeak.get(), css::uno::UNO_QUERY);
189 : :
190 [ + - ]: 1549 : aWriteLock.unlock();
191 : : // } SAFE
192 : :
193 : : // Don't forget to send a frame action event "context changed".
194 : : // Any cached dispatch objects must be validated now!
195 [ + - ]: 1549 : if (xOwner.is())
196 [ + - ][ + - ]: 1549 : xOwner->contextChanged();
[ + - ][ + - ]
197 : 1549 : }
198 : :
199 : 1458 : void SAL_CALL InterceptionHelper::releaseDispatchProviderInterceptor(const css::uno::Reference< css::frame::XDispatchProviderInterceptor >& xInterceptor)
200 : : throw(css::uno::RuntimeException)
201 : : {
202 : : // reject wrong calling of this interface method
203 [ + - ]: 1458 : css::uno::Reference< css::frame::XDispatchProvider > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
204 [ - + ]: 1458 : if (!xInterceptor.is())
205 [ # # ][ # # ]: 0 : throw css::uno::RuntimeException(DECLARE_ASCII("NULL references not allowed as in parameter"), xThis);
206 : :
207 : : // SAFE {
208 [ + - ]: 1458 : WriteGuard aWriteLock(m_aLock);
209 : :
210 : : // search this interceptor ...
211 : : // If it could be located inside cache -
212 : : // use it's slave/master relations to update the interception list;
213 : : // set empty references for it as new master and slave;
214 : : // and relase it from out cache.
215 [ + - ]: 1458 : InterceptorList::iterator pIt = m_lInterceptionRegs.findByReference(xInterceptor);
216 [ + - ][ + - ]: 1458 : if (pIt != m_lInterceptionRegs.end())
217 : : {
218 [ + - ][ + - ]: 1458 : css::uno::Reference< css::frame::XDispatchProvider > xSlaveD (xInterceptor->getSlaveDispatchProvider() , css::uno::UNO_QUERY);
[ + - ]
219 [ + - ][ + - ]: 1458 : css::uno::Reference< css::frame::XDispatchProvider > xMasterD (xInterceptor->getMasterDispatchProvider(), css::uno::UNO_QUERY);
[ + - ]
220 [ + - ]: 1458 : css::uno::Reference< css::frame::XDispatchProviderInterceptor > xSlaveI (xSlaveD , css::uno::UNO_QUERY);
221 [ + - ]: 1458 : css::uno::Reference< css::frame::XDispatchProviderInterceptor > xMasterI (xMasterD , css::uno::UNO_QUERY);
222 : :
223 [ - + ]: 1458 : if (xMasterI.is())
224 [ # # ][ # # ]: 0 : xMasterI->setSlaveDispatchProvider(xSlaveD);
225 : :
226 [ - + ]: 1458 : if (xSlaveI.is())
227 [ # # ][ # # ]: 0 : xSlaveI->setMasterDispatchProvider(xMasterD);
228 : :
229 [ + - ][ + - ]: 1458 : xInterceptor->setSlaveDispatchProvider (css::uno::Reference< css::frame::XDispatchProvider >());
230 [ + - ][ + - ]: 1458 : xInterceptor->setMasterDispatchProvider(css::uno::Reference< css::frame::XDispatchProvider >());
231 : :
232 [ + - ]: 1458 : m_lInterceptionRegs.erase(pIt);
233 : : }
234 : :
235 [ + - ][ + - ]: 1458 : css::uno::Reference< css::frame::XFrame > xOwner(m_xOwnerWeak.get(), css::uno::UNO_QUERY);
236 : :
237 [ + - ]: 1458 : aWriteLock.unlock();
238 : : // } SAFE
239 : :
240 : : // Don't forget to send a frame action event "context changed".
241 : : // Any cached dispatch objects must be validated now!
242 [ + - ]: 1458 : if (xOwner.is())
243 [ + - ][ + - ]: 1458 : xOwner->contextChanged();
[ + - ]
244 : 1458 : }
245 : :
246 : : #define FORCE_DESTRUCTION_OF_INTERCEPTION_CHAIN
247 : 1656 : void SAL_CALL InterceptionHelper::disposing(const css::lang::EventObject& aEvent)
248 : : throw(css::uno::RuntimeException)
249 : : {
250 : : #ifdef FORCE_DESTRUCTION_OF_INTERCEPTION_CHAIN
251 : : // SAFE ->
252 [ + - ]: 1656 : ReadGuard aReadLock(m_aLock);
253 : :
254 : : // check calli ... we accept such disposing call's only from our onwer frame.
255 [ + - ][ + - ]: 1656 : css::uno::Reference< css::frame::XFrame > xOwner(m_xOwnerWeak.get(), css::uno::UNO_QUERY);
256 [ - + ][ + - ]: 1656 : if (aEvent.Source != xOwner)
257 : 1656 : return;
258 : :
259 : : // Because every interceptor hold at least one reference to us ... and we destruct this list
260 : : // of interception objects ... we should hold ourself alive .-)
261 [ + - ]: 1656 : css::uno::Reference< css::frame::XDispatchProvider > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY_THROW);
262 : :
263 : : // We need a full copy of all currently registered interceptor objects.
264 : : // Otherwhise we cant iterate over this vector without the risk, that our iterator will be invalid.
265 : : // Because this vetor will be influenced by every deregistered interceptor.
266 [ + - ]: 1656 : InterceptionHelper::InterceptorList aCopy = m_lInterceptionRegs;
267 : :
268 [ + - ]: 1656 : aReadLock.unlock();
269 : : // <- SAFE
270 : :
271 : 1656 : InterceptionHelper::InterceptorList::iterator pIt;
272 [ # # + - ]: 3312 : for ( pIt = aCopy.begin();
[ - + ]
273 : 1656 : pIt != aCopy.end() ;
274 : : ++pIt )
275 : : {
276 : 0 : InterceptionHelper::InterceptorInfo& rInfo = *pIt;
277 [ # # ]: 0 : if (rInfo.xInterceptor.is())
278 : : {
279 [ # # ]: 0 : css::uno::Reference< css::frame::XDispatchProviderInterceptor > xInterceptor(rInfo.xInterceptor, css::uno::UNO_QUERY_THROW);
280 [ # # ]: 0 : releaseDispatchProviderInterceptor(xInterceptor);
281 : 0 : rInfo.xInterceptor.clear();
282 : : }
283 : : }
284 : :
285 [ - + ][ + - ]: 1656 : aCopy.clear();
[ + - ]
286 : :
287 : : #if OSL_DEBUG_LEVEL > 0
288 : : // SAFE ->
289 : : aReadLock.lock();
290 : : if (!m_lInterceptionRegs.empty() )
291 : : OSL_FAIL("There are some pending interceptor objects, which seams to be registered during (!) the destruction of a frame.");
292 : : aReadLock.unlock();
293 : : // <- SAFE
294 : : #endif // ODL_DEBUG_LEVEL>0
295 : :
296 : : #endif // FORCE_DESTRUCTION_OF_INTERCEPTION_CHAIN
297 : : }
298 : :
299 : : } // namespace framework
300 : :
301 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|