Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <stdio.h>
21 : #include <dispatch/dispatchprovider.hxx>
22 : #include <loadenv/loadenv.hxx>
23 : #include <dispatch/loaddispatcher.hxx>
24 : #include <dispatch/closedispatcher.hxx>
25 : #include <dispatch/menudispatcher.hxx>
26 : #include <dispatch/startmoduledispatcher.hxx>
27 :
28 : #include <pattern/window.hxx>
29 : #include <threadhelp/transactionguard.hxx>
30 : #include <threadhelp/readguard.hxx>
31 : #include <threadhelp/writeguard.hxx>
32 : #include <dispatchcommands.h>
33 : #include <protocols.h>
34 : #include <services.h>
35 : #include <targets.h>
36 : #include <general.h>
37 :
38 : #include <com/sun/star/frame/FrameSearchFlag.hpp>
39 : #include <com/sun/star/uno/Exception.hpp>
40 : #include <com/sun/star/ucb/XContentProviderManager.hpp>
41 : #include <com/sun/star/document/XTypeDetection.hpp>
42 : #include <com/sun/star/lang/XInitialization.hpp>
43 :
44 : #include <osl/diagnose.h>
45 : #include <rtl/string.h>
46 : #include <rtl/ustring.hxx>
47 : #include <vcl/svapp.hxx>
48 : #include <rtl/ustrbuf.hxx>
49 :
50 : namespace framework{
51 :
52 : //*****************************************************************************************************************
53 : // XInterface, XTypeProvider
54 : //*****************************************************************************************************************
55 1800 : DEFINE_XINTERFACE_2( DispatchProvider ,
56 : OWeakObject ,
57 : DIRECT_INTERFACE(css::lang::XTypeProvider ),
58 : DIRECT_INTERFACE(css::frame::XDispatchProvider)
59 : )
60 :
61 0 : DEFINE_XTYPEPROVIDER_2( DispatchProvider ,
62 : css::lang::XTypeProvider ,
63 : css::frame::XDispatchProvider
64 : )
65 :
66 : /**
67 : @short standard ctor/dtor
68 : @descr These initialize a new instance of tihs class with needed informations for work.
69 : We hold a weakreference to our owner frame which start dispatches at us.
70 : We can't use a normal reference because he hold a reference of us too ...
71 : nobody can die so ...!
72 :
73 : @seealso using at owner
74 :
75 : @param xFactory
76 : reference to servicemanager to create new services.
77 : @param xFrame
78 : reference to our owner frame.
79 : */
80 260 : DispatchProvider::DispatchProvider( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory ,
81 : const css::uno::Reference< css::frame::XFrame >& xFrame )
82 : // Init baseclasses first
83 260 : : ThreadHelpBase( &Application::GetSolarMutex() )
84 : , OWeakObject ( )
85 : // Init member
86 : , m_xFactory ( xFactory )
87 520 : , m_xFrame ( xFrame )
88 : {
89 260 : }
90 :
91 : /**
92 : @short protected(!) dtor for deinitializing
93 : @descr We made it protected to prevent using of us as base class instead as a member.
94 : */
95 166 : DispatchProvider::~DispatchProvider()
96 : {
97 166 : }
98 :
99 : /**
100 : @interface XDispatchProvider
101 : @short search a dispatcher for given URL
102 : @descr If no interceptor is set on owner, we search for right frame and dispatch URL to it.
103 : If no frame was found, we do nothing.
104 : But we doesn't do it directly here. We detect the type of our owner frame and calls
105 : specialized queryDispatch() helper dependen from that. Because a Desktop handle some
106 : requests in another way then a normal frame.
107 :
108 : @param aURL
109 : URL to dispatch.
110 : @param sTargetFrameName
111 : name of searched frame.
112 : @param nSearchFlags
113 : flags for searching.
114 : @return A reference to a dispatch object for this URL (if someone was found!).
115 :
116 : @threadsafe yes
117 : */
118 3995 : css::uno::Reference< css::frame::XDispatch > SAL_CALL DispatchProvider::queryDispatch( const css::util::URL& aURL ,
119 : const ::rtl::OUString& sTargetFrameName ,
120 : sal_Int32 nSearchFlags ) throw( css::uno::RuntimeException )
121 : {
122 3995 : css::uno::Reference< css::frame::XDispatch > xDispatcher;
123 :
124 : /* SAFE { */
125 3995 : ReadGuard aReadLock( m_aLock );
126 3995 : css::uno::Reference< css::frame::XFrame > xOwner( m_xFrame.get(), css::uno::UNO_QUERY );
127 3995 : aReadLock.unlock();
128 : /* } SAFE */
129 :
130 3995 : css::uno::Reference< css::frame::XDesktop > xDesktopCheck( xOwner, css::uno::UNO_QUERY );
131 :
132 3995 : if (xDesktopCheck.is())
133 0 : xDispatcher = implts_queryDesktopDispatch(xOwner, aURL, sTargetFrameName, nSearchFlags);
134 : else
135 3995 : xDispatcher = implts_queryFrameDispatch(xOwner, aURL, sTargetFrameName, nSearchFlags);
136 :
137 3995 : return xDispatcher;
138 : }
139 :
140 : /**
141 : @interface XDispatchProvider
142 : @short do the same like queryDispatch() ... but handle multiple dispatches at the same time
143 : @descr It's an optimism. User give us a list of queries ... and we return a list of dispatcher.
144 : If one of given queries couldn't be solved to a real existing dispatcher ...
145 : we return a list with empty references in it! Order of both lists will be retained!
146 :
147 : @seealso method queryDispatch()
148 :
149 : @param lDescriptions
150 : a list of all dispatch parameters for multiple requests
151 : @return A reference a list of dispatch objects for these URLs - may with some <NULL/> values inside.
152 :
153 : @threadsafe yes
154 : */
155 0 : css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL DispatchProvider::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptions ) throw( css::uno::RuntimeException )
156 : {
157 : // Create return list - which must have same size then the given descriptor
158 : // It's not allowed to pack it!
159 0 : sal_Int32 nCount = lDescriptions.getLength();
160 0 : css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
161 :
162 : // Step over all descriptors and try to get any dispatcher for it.
163 0 : for( sal_Int32 i=0; i<nCount; ++i )
164 : {
165 0 : lDispatcher[i] = queryDispatch( lDescriptions[i].FeatureURL ,
166 0 : lDescriptions[i].FrameName ,
167 0 : lDescriptions[i].SearchFlags );
168 : }
169 :
170 0 : return lDispatcher;
171 : }
172 :
173 0 : ::sal_Bool lcl_isStartModuleDispatch (const css::util::URL& aURL)
174 : {
175 0 : return aURL.Complete == CMD_UNO_SHOWSTARTMODULE;
176 : }
177 :
178 : /**
179 : @short helper for queryDispatch()
180 : @descr Every member of the frame tree (frame, desktop) must handle such request
181 : in another way. So we implement different specialized metods for every one.
182 :
183 : @threadsafe yes
184 : */
185 0 : css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_queryDesktopDispatch( const css::uno::Reference< css::frame::XFrame > xDesktop ,
186 : const css::util::URL& aURL ,
187 : const ::rtl::OUString& sTargetFrameName ,
188 : sal_Int32 nSearchFlags )
189 : {
190 0 : css::uno::Reference< css::frame::XDispatch > xDispatcher;
191 :
192 : // ignore wrong requests which are not supported
193 0 : if (
194 0 : (sTargetFrameName==SPECIALTARGET_MENUBAR ) || // valid for frame dispatches - not for desktop
195 0 : (sTargetFrameName==SPECIALTARGET_PARENT ) || // we have no parent by definition
196 0 : (sTargetFrameName==SPECIALTARGET_BEAMER ) // beamer frames are allowed as child of tasks only -
197 : // and they exist more then ones. We have no idea which our sub tasks is the right one
198 : )
199 : {
200 0 : return NULL;
201 : }
202 :
203 : //-----------------------------------------------------------------------------------------------------
204 : // I) handle special cases which not right for using findFrame() first
205 : //-----------------------------------------------------------------------------------------------------
206 :
207 : //-----------------------------------------------------------------------------------------------------
208 : // I.I) "_blank"
209 : // It's not the right place to create a new task here - because we are queried for a dispatch object
210 : // only, which can handle such request. Such dispatcher should create the required task on demand.
211 : // Normaly the functionality for "_blank" is provided by findFrame() - but that would create it directly
212 : // here. Thats why we must "intercept" here.
213 : //-----------------------------------------------------------------------------------------------------
214 0 : if (sTargetFrameName==SPECIALTARGET_BLANK)
215 : {
216 0 : if (implts_isLoadableContent(aURL))
217 0 : xDispatcher = implts_getOrCreateDispatchHelper( E_BLANKDISPATCHER, xDesktop );
218 : }
219 :
220 : //-----------------------------------------------------------------------------------------------------
221 : // I.II) "_default"
222 : // This is a combination of search an empty task for recycling - or create a new one.
223 : //-----------------------------------------------------------------------------------------------------
224 0 : else if (sTargetFrameName==SPECIALTARGET_DEFAULT)
225 : {
226 0 : if (implts_isLoadableContent(aURL))
227 0 : xDispatcher = implts_getOrCreateDispatchHelper( E_DEFAULTDISPATCHER, xDesktop );
228 :
229 0 : if (lcl_isStartModuleDispatch(aURL))
230 0 : xDispatcher = implts_getOrCreateDispatchHelper( E_STARTMODULEDISPATCHER, xDesktop );
231 : }
232 :
233 : //-----------------------------------------------------------------------------------------------------
234 : // I.III) "_self", "", "_top"
235 : // The desktop can't load any document - but he can handle some special protocols like "uno", "slot" ...
236 : // Why is "top" here handled too? Because the desktop is the topest frame. Normaly it's superflous
237 : // to use this target - but we can handle it in the same manner then "_self".
238 : //-----------------------------------------------------------------------------------------------------
239 0 : else if (
240 0 : (sTargetFrameName==SPECIALTARGET_SELF) ||
241 0 : (sTargetFrameName==SPECIALTARGET_TOP ) ||
242 0 : (sTargetFrameName.isEmpty())
243 : )
244 : {
245 0 : xDispatcher = implts_searchProtocolHandler(aURL);
246 : }
247 :
248 : //-----------------------------------------------------------------------------------------------------
249 : // I.IV) no further special targets exist
250 : // Now we have to search for the right target frame by calling findFrame() - but should provide our code
251 : // against creation of a new task if no frame could be found.
252 : // I said it b efore - it's allowed for dispatch() only.
253 : //-----------------------------------------------------------------------------------------------------
254 : else
255 : {
256 0 : sal_Int32 nRightFlags = nSearchFlags;
257 0 : nRightFlags &= ~css::frame::FrameSearchFlag::CREATE;
258 :
259 : // try to find any existing target and ask him for his dispatcher
260 0 : css::uno::Reference< css::frame::XFrame > xFoundFrame = xDesktop->findFrame(sTargetFrameName, nRightFlags);
261 0 : if (xFoundFrame.is())
262 : {
263 0 : css::uno::Reference< css::frame::XDispatchProvider > xProvider( xFoundFrame, css::uno::UNO_QUERY );
264 0 : xDispatcher = xProvider->queryDispatch(aURL,SPECIALTARGET_SELF,0);
265 : }
266 : // if it couldn't be found - but creation was allowed
267 : // use special dispatcher for creatio or froward it to the browser
268 0 : else if (nSearchFlags & css::frame::FrameSearchFlag::CREATE)
269 0 : xDispatcher = implts_getOrCreateDispatchHelper( E_CREATEDISPATCHER, xDesktop, sTargetFrameName, nSearchFlags );
270 : }
271 :
272 0 : return xDispatcher;
273 : }
274 :
275 : //_________________________________________________________________________________________________________________
276 :
277 3995 : css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_queryFrameDispatch( const css::uno::Reference< css::frame::XFrame > xFrame ,
278 : const css::util::URL& aURL ,
279 : const ::rtl::OUString& sTargetFrameName ,
280 : sal_Int32 nSearchFlags )
281 : {
282 3995 : css::uno::Reference< css::frame::XDispatch > xDispatcher;
283 :
284 : //-----------------------------------------------------------------------------------------------------
285 : // 0) Some URLs are dispatched in a generic way (e.g. by the menu) using the default target "".
286 : // But they are specified to use her own fix target. Detect such URLs here and use the correct target.
287 : //-----------------------------------------------------------------------------------------------------
288 :
289 3995 : ::rtl::OUString sTargetName = sTargetFrameName;
290 :
291 : //-----------------------------------------------------------------------------------------------------
292 : // I) handle special cases which not right for using findFrame() first
293 : //-----------------------------------------------------------------------------------------------------
294 :
295 : //-----------------------------------------------------------------------------------------------------
296 : // I.I) "_blank", "_default"
297 : // It's not the right place to create a new task here. Only the desktop can do that.
298 : // Normaly the functionality for "_blank" is provided by findFrame() - but that would create it directly
299 : // here. Thats why we must "intercept" here.
300 : //-----------------------------------------------------------------------------------------------------
301 23970 : if (
302 11985 : (sTargetName==SPECIALTARGET_BLANK ) ||
303 11985 : (sTargetName==SPECIALTARGET_DEFAULT)
304 : )
305 : {
306 0 : css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY );
307 0 : if (xParent.is())
308 0 : xDispatcher = xParent->queryDispatch(aURL, sTargetName, 0); // its a special target - ignore search flags
309 : }
310 :
311 : //-----------------------------------------------------------------------------------------------------
312 : // I.II) "_menubar"
313 : // Special mode on frame or task to receive the local menu. Not supported by findFrame()
314 : //-----------------------------------------------------------------------------------------------------
315 3995 : else if (sTargetName==SPECIALTARGET_MENUBAR)
316 : {
317 0 : xDispatcher = implts_getOrCreateDispatchHelper( E_MENUDISPATCHER, xFrame );
318 : }
319 :
320 : //-----------------------------------------------------------------------------------------------------
321 : // I.IV) "_helpagent"
322 : // Special sub frame of a top frame only. Search or create it. ... OK it's currently a little bit HACKI.
323 : // Only the sfx (means the controller) can create it it.
324 : //-----------------------------------------------------------------------------------------------------
325 3995 : else if (sTargetName==SPECIALTARGET_BEAMER)
326 : {
327 0 : css::uno::Reference< css::frame::XDispatchProvider > xBeamer( xFrame->findFrame( SPECIALTARGET_BEAMER, css::frame::FrameSearchFlag::CHILDREN | css::frame::FrameSearchFlag::SELF ), css::uno::UNO_QUERY );
328 0 : if (xBeamer.is())
329 : {
330 0 : xDispatcher = xBeamer->queryDispatch(aURL, SPECIALTARGET_SELF, 0);
331 : }
332 : else
333 : {
334 0 : css::uno::Reference< css::frame::XDispatchProvider > xController( xFrame->getController(), css::uno::UNO_QUERY );
335 0 : if (xController.is())
336 : // force using of special target - but use original search flags
337 : // May the caller used the CREATE flag or not!
338 0 : xDispatcher = xController->queryDispatch(aURL, SPECIALTARGET_BEAMER, nSearchFlags);
339 0 : }
340 : }
341 :
342 : //-----------------------------------------------------------------------------------------------------
343 : // I.V) "_parent"
344 : // Our parent frame (if it exist) should handle this URL.
345 : //-----------------------------------------------------------------------------------------------------
346 3995 : else if (sTargetName==SPECIALTARGET_PARENT)
347 : {
348 0 : css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY );
349 0 : if (xParent.is())
350 : // SELF => we must address the parent directly... and not his parent or any other parent!
351 0 : xDispatcher = xParent->queryDispatch(aURL, SPECIALTARGET_SELF, 0);
352 : }
353 :
354 : //-----------------------------------------------------------------------------------------------------
355 : // I.VI) "_top"
356 : // This request must be forwarded to any parent frame, till we reach a top frame.
357 : // If no parent exist, we can handle itself.
358 : //-----------------------------------------------------------------------------------------------------
359 3995 : else if (sTargetName==SPECIALTARGET_TOP)
360 : {
361 0 : if (xFrame->isTop())
362 : {
363 : // If we are this top frame itself (means our owner frame)
364 : // we should call ourself recursiv with a better target "_self".
365 : // So we can share the same code! (see reaction for "_self" inside this method too.)
366 0 : xDispatcher = this->queryDispatch(aURL,SPECIALTARGET_SELF,0);
367 : }
368 : else
369 : {
370 0 : css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY );
371 : // Normaly if isTop() returned sal_False ... the parent frame MUST(!) exist ...
372 : // But it seams to be better to check that here to prevent us against an access violation.
373 0 : if (xParent.is())
374 0 : xDispatcher = xParent->queryDispatch(aURL, SPECIALTARGET_TOP, 0);
375 : }
376 : }
377 :
378 : //-----------------------------------------------------------------------------------------------------
379 : // I.VII) "_self", ""
380 : // Our owner frame should handle this URL. But we can't do it for all of them.
381 : // So we ask the internal setted controller first. If he disagree we try to find a registered
382 : // protocol handler. If this failed too - we check for a loadable content and in case of true
383 : // we load it into the frame by returning specilized dispatch object.
384 : //-----------------------------------------------------------------------------------------------------
385 19975 : else if (
386 11985 : (sTargetName==SPECIALTARGET_SELF) ||
387 3995 : (sTargetName.isEmpty())
388 : )
389 : {
390 : // There exist a hard coded interception for special URLs.
391 3995 : if ( aURL.Complete == ".uno:CloseDoc" || aURL.Complete == ".uno:CloseWin" )
392 : {
393 0 : css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY );
394 : // In case the frame is not a top one, is not based on system window and has a parent,
395 : // the parent frame should to be queried for the correct dispatcher.
396 : // See i93473
397 0 : if (
398 0 : !WindowHelper::isTopWindow(xFrame->getContainerWindow()) &&
399 0 : !VCLUnoHelper::GetWindow(xFrame->getContainerWindow())->IsSystemWindow() &&
400 0 : xParent.is()
401 : )
402 0 : xDispatcher = xParent->queryDispatch(aURL, SPECIALTARGET_SELF, 0);
403 : else
404 0 : xDispatcher = implts_getOrCreateDispatchHelper( E_CLOSEDISPATCHER, xFrame );
405 : }
406 3995 : else if ( aURL.Complete == ".uno:CloseFrame" )
407 0 : xDispatcher = implts_getOrCreateDispatchHelper( E_CLOSEDISPATCHER, xFrame );
408 :
409 3995 : if ( ! xDispatcher.is())
410 : {
411 : // Ask our controller for his agreement for these dispatched URL ...
412 : // because some URLs are internal and can be handled faster by SFX - which most is the current controller!
413 : // But in case of e.g. the bibliography not all queries will be handled successfully here.
414 3995 : css::uno::Reference< css::frame::XDispatchProvider > xController( xFrame->getController(), css::uno::UNO_QUERY );
415 3995 : if (xController.is())
416 3995 : xDispatcher = xController->queryDispatch(aURL, SPECIALTARGET_SELF, 0);
417 : }
418 :
419 : // If controller has no fun to dispatch these URL - we must search another right dispatcher.
420 : // Search for any registered protocol handler first.
421 3995 : if (!xDispatcher.is())
422 2360 : xDispatcher = implts_searchProtocolHandler(aURL);
423 :
424 : // Not for controller - not for protocol handler
425 : // It should be a loadable content - may be a file. Check it ...
426 : // This check is neccessary to found out, that
427 : // support for some protocols isn't installed by user. May be
428 : // "ftp" isn't available. So we suppress creation of our self dispatcher.
429 : // The result will be clear. He can't handle it - but he would try it.
430 6355 : if (
431 3995 : ( ! xDispatcher.is() ) &&
432 2360 : ( implts_isLoadableContent(aURL) )
433 : )
434 : {
435 0 : xDispatcher = implts_getOrCreateDispatchHelper( E_SELFDISPATCHER, xFrame );
436 : }
437 : }
438 :
439 : //-----------------------------------------------------------------------------------------------------
440 : // I.VI) no further special handlings exist
441 : // Now we have to search for the right target frame by calling findFrame() - but should provide our code
442 : // against creation of a new task if no frame could be found.
443 : // I said it before - it's allowed for dispatch() only.
444 : //-----------------------------------------------------------------------------------------------------
445 : else
446 : {
447 0 : sal_Int32 nRightFlags = nSearchFlags;
448 0 : nRightFlags &= ~css::frame::FrameSearchFlag::CREATE;
449 :
450 : // try to find any existing target and ask him for his dispatcher
451 0 : css::uno::Reference< css::frame::XFrame > xFoundFrame = xFrame->findFrame(sTargetName, nRightFlags);
452 0 : if (xFoundFrame.is())
453 : {
454 : // Attention: Found target is our own owner frame!
455 : // Don't ask him for his dispatcher. We know it already - it's our self dispatch helper.
456 : // Otherwhise we can start a never ending recursiv call. Why?
457 : // Somewere called our owner frame - he called some interceptor objects - and may by this dispatch provider
458 : // is called. If wa use queryDispatch() on our owner frame again - we start this call stack again ... and again.
459 0 : if (xFoundFrame==xFrame)
460 0 : xDispatcher = implts_getOrCreateDispatchHelper( E_SELFDISPATCHER, xFrame );
461 : else
462 : {
463 0 : css::uno::Reference< css::frame::XDispatchProvider > xProvider( xFoundFrame, css::uno::UNO_QUERY );
464 0 : xDispatcher = xProvider->queryDispatch(aURL,SPECIALTARGET_SELF,0);
465 : }
466 : }
467 : else
468 : // if it couldn't be found - but creation was allowed
469 : // forward request to the desktop.
470 : // Note: The given target name must be used to set the name on new created task!
471 : // Don't forward request by changing it to a special one e.g _blank.
472 : // Use the CREATE flag only to prevent call against further searches.
473 : // We already know it - the target must be created new.
474 0 : if (nSearchFlags & css::frame::FrameSearchFlag::CREATE)
475 : {
476 0 : css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY );
477 0 : if (xParent.is())
478 0 : xDispatcher = xParent->queryDispatch(aURL, sTargetName, css::frame::FrameSearchFlag::CREATE);
479 0 : }
480 : }
481 :
482 3995 : return xDispatcher;
483 : }
484 :
485 : //_________________________________________________________________________________________________________________
486 :
487 : /**
488 : @short search for a registered protocol handler and ask him for a dispatch object
489 : @descr Wes earch a suitable handler inside our cfg package org.openoffice.Office.ProtocolHandler.
490 : If we found anyone, we create and initialize it. Initialize means: we set our owner frame on it
491 : as context information. He can use it or leave it. Of course - we are aware of handler implementations,
492 : which doesn't support initialization. It's an optional feature.
493 :
494 : @param aURL
495 : the dispatch URL for which may a handler is registered
496 :
497 : @return A dispatch object if a handler was found and agree with the given URL or <NULL/> otherwhise.
498 :
499 : @threadsafe yes
500 : */
501 2360 : css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_searchProtocolHandler( const css::util::URL& aURL )
502 : {
503 2360 : css::uno::Reference< css::frame::XDispatch > xDispatcher;
504 2360 : ProtocolHandler aHandler ;
505 :
506 : // This member is threadsafe by himself and lives if we live - we doesn't need any mutex here.
507 2360 : if (m_aProtocolHandlerCache.search(aURL,&aHandler))
508 : {
509 : /* SAFE { */
510 2360 : ReadGuard aReadLock( m_aLock );
511 :
512 : // create it
513 2360 : css::uno::Reference< css::frame::XDispatchProvider > xHandler;
514 : try
515 : {
516 : xHandler = css::uno::Reference< css::frame::XDispatchProvider >(
517 2360 : m_xFactory->createInstance(aHandler.m_sUNOName),
518 2360 : css::uno::UNO_QUERY);
519 : }
520 0 : catch(const css::uno::Exception&) {}
521 :
522 : // look if initialization is neccessary
523 2360 : css::uno::Reference< css::lang::XInitialization > xInit( xHandler, css::uno::UNO_QUERY );
524 2360 : if (xInit.is())
525 : {
526 0 : css::uno::Reference< css::frame::XFrame > xOwner( m_xFrame.get(), css::uno::UNO_QUERY );
527 : LOG_ASSERT(xOwner.is(), "DispatchProvider::implts_searchProtocolHandler()\nCouldn't get reference to my owner frame. So I can't set may needed context information for this protocol handler.")
528 0 : if (xOwner.is())
529 : {
530 : try
531 : {
532 : // but do it only, if all context informations are OK
533 0 : css::uno::Sequence< css::uno::Any > lContext(1);
534 0 : lContext[0] <<= xOwner;
535 0 : xInit->initialize(lContext);
536 : }
537 0 : catch(const css::uno::Exception&) {}
538 0 : }
539 : }
540 :
541 2360 : aReadLock.unlock();
542 : /* } SAFE */
543 :
544 : // ask for his (sub)dispatcher for the given URL
545 2360 : if (xHandler.is())
546 0 : xDispatcher = xHandler->queryDispatch(aURL,SPECIALTARGET_SELF,0);
547 : }
548 :
549 2360 : return xDispatcher;
550 : }
551 :
552 : //_________________________________________________________________________________________________________________
553 :
554 : /**
555 : @short get or create new dispatch helper
556 : @descr Sometimes we need some helper implementations to support dispatching of special URLs or commands.
557 : But it's not a good idea to hold these services for the whole life time of this provider instance.
558 : We should create it on demand ...
559 : Thats why we implement this method. It return an already existing helper or create a new one otherwise.
560 :
561 : @attention The parameter sTarget and nSearchFlags are defaulted to "" and 0!
562 : Please use it only, if you can be shure, that the realy given by the outside calli!
563 : Mostly it depends from the parameter eHelper is they are required or not.
564 :
565 : @param eHelper
566 : specify the requested dispatch helper
567 : @param xOwner
568 : the target of possible dispatch() call on created dispatch helper
569 : @param sTarget
570 : the target parameter of the original queryDispatch() request
571 : @param nSearchFlags
572 : the flags parameter of the original queryDispatch() request
573 : @return A reference to a dispatch helper.
574 :
575 : @threadsafe yes
576 : */
577 0 : css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_getOrCreateDispatchHelper( EDispatchHelper eHelper ,
578 : const css::uno::Reference< css::frame::XFrame >& xOwner ,
579 : const ::rtl::OUString& sTarget ,
580 : sal_Int32 nSearchFlags)
581 : {
582 0 : css::uno::Reference< css::frame::XDispatch > xDispatchHelper;
583 :
584 : /* SAFE { */
585 0 : ReadGuard aReadLock( m_aLock );
586 0 : css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory;
587 0 : aReadLock.unlock();
588 : /* } SAFE */
589 :
590 0 : switch (eHelper)
591 : {
592 : case E_MENUDISPATCHER :
593 : {
594 : // Attention: Such menue dispatcher must be a singleton for this frame - means our owner frame.
595 : // Otherwhise he can make some trouble.
596 : /* SAFE { */
597 0 : WriteGuard aWriteLock( m_aLock );
598 0 : if ( ! m_xMenuDispatcher.is() )
599 : {
600 0 : MenuDispatcher* pDispatcher = new MenuDispatcher( xFactory, xOwner );
601 0 : m_xMenuDispatcher = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
602 : }
603 0 : xDispatchHelper = m_xMenuDispatcher;
604 0 : aWriteLock.unlock();
605 : /* } SAFE */
606 : }
607 0 : break;
608 :
609 : case E_CREATEDISPATCHER :
610 : {
611 0 : LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, sTarget, nSearchFlags);
612 0 : xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
613 : }
614 0 : break;
615 :
616 : case E_BLANKDISPATCHER :
617 : {
618 0 : css::uno::Reference< css::frame::XFrame > xDesktop( xOwner, css::uno::UNO_QUERY );
619 0 : if (xDesktop.is())
620 : {
621 0 : LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, SPECIALTARGET_BLANK, 0);
622 0 : xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
623 0 : }
624 : }
625 0 : break;
626 :
627 : case E_DEFAULTDISPATCHER :
628 : {
629 0 : css::uno::Reference< css::frame::XFrame > xDesktop( xOwner, css::uno::UNO_QUERY );
630 0 : if (xDesktop.is())
631 : {
632 0 : LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, SPECIALTARGET_DEFAULT, 0);
633 0 : xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
634 0 : }
635 : }
636 0 : break;
637 :
638 : case E_SELFDISPATCHER :
639 : {
640 0 : LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, SPECIALTARGET_SELF, 0);
641 0 : xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
642 : }
643 0 : break;
644 :
645 : case E_CLOSEDISPATCHER :
646 : {
647 0 : CloseDispatcher* pDispatcher = new CloseDispatcher( xFactory, xOwner, sTarget );
648 0 : xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
649 : }
650 0 : break;
651 :
652 : case E_STARTMODULEDISPATCHER :
653 : {
654 0 : StartModuleDispatcher* pDispatcher = new StartModuleDispatcher( xFactory, xOwner, sTarget );
655 0 : xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY );
656 : }
657 0 : break;
658 : }
659 :
660 0 : return xDispatchHelper;
661 : }
662 :
663 : //_________________________________________________________________________________________________________________
664 :
665 : /**
666 : @short check URL for support by our used loader or handler
667 : @descr If we must return our own dispatch helper implementations (self, blank, create dispatcher!)
668 : we should be shure, that URL describe any loadable content. Otherwise slot/uno URLs
669 : will be detected ... but there exist nothing for ral loading into a target frame!
670 :
671 : @param aURL
672 : URL which should be "detected"
673 : @return <TRUE/> if somewhere could handle that - <FALSE/> otherwise.
674 :
675 : @threadsafe yes
676 : */
677 2360 : sal_Bool DispatchProvider::implts_isLoadableContent( const css::util::URL& aURL )
678 : {
679 2360 : LoadEnv::EContentType eType = LoadEnv::classifyContent(aURL.Complete, css::uno::Sequence< css::beans::PropertyValue >());
680 2360 : return ( eType == LoadEnv::E_CAN_BE_LOADED );
681 : }
682 :
683 : } // namespace framework
684 :
685 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|