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