| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_framework.hxx" |
| |
| //_________________________________________________________________________________________________________________ |
| // my own includes |
| //_________________________________________________________________________________________________________________ |
| |
| #include <stdio.h> |
| #include <dispatch/dispatchprovider.hxx> |
| #include <loadenv/loadenv.hxx> |
| #include <dispatch/loaddispatcher.hxx> |
| #include <dispatch/closedispatcher.hxx> |
| #include <dispatch/menudispatcher.hxx> |
| #include <dispatch/helpagentdispatcher.hxx> |
| #include <dispatch/startmoduledispatcher.hxx> |
| |
| #include <pattern/window.hxx> |
| #include <threadhelp/transactionguard.hxx> |
| #include <threadhelp/readguard.hxx> |
| #include <threadhelp/writeguard.hxx> |
| #include <dispatchcommands.h> |
| #include <protocols.h> |
| #include <services.h> |
| #include <targets.h> |
| #include <general.h> |
| |
| //_________________________________________________________________________________________________________________ |
| // interface includes |
| //_________________________________________________________________________________________________________________ |
| #include <com/sun/star/frame/FrameSearchFlag.hpp> |
| #include <com/sun/star/uno/Exception.hpp> |
| #include <com/sun/star/ucb/XContentProviderManager.hpp> |
| #include <com/sun/star/document/XTypeDetection.hpp> |
| #include <com/sun/star/lang/XInitialization.hpp> |
| |
| //_________________________________________________________________________________________________________________ |
| // includes of other projects |
| //_________________________________________________________________________________________________________________ |
| #include <osl/diagnose.h> |
| #include <rtl/string.h> |
| #include <rtl/ustring.hxx> |
| #include <vcl/svapp.hxx> |
| #include <rtl/ustrbuf.hxx> |
| //_________________________________________________________________________________________________________________ |
| // namespace |
| //_________________________________________________________________________________________________________________ |
| |
| namespace framework{ |
| |
| //_________________________________________________________________________________________________________________ |
| // non exported const |
| //_________________________________________________________________________________________________________________ |
| |
| //_________________________________________________________________________________________________________________ |
| // non exported definitions |
| //_________________________________________________________________________________________________________________ |
| |
| //_________________________________________________________________________________________________________________ |
| // declarations |
| //_________________________________________________________________________________________________________________ |
| |
| //***************************************************************************************************************** |
| // XInterface, XTypeProvider |
| //***************************************************************************************************************** |
| DEFINE_XINTERFACE_2( DispatchProvider , |
| OWeakObject , |
| DIRECT_INTERFACE(css::lang::XTypeProvider ), |
| DIRECT_INTERFACE(css::frame::XDispatchProvider) |
| ) |
| |
| DEFINE_XTYPEPROVIDER_2( DispatchProvider , |
| css::lang::XTypeProvider , |
| css::frame::XDispatchProvider |
| ) |
| |
| //_________________________________________________________________________________________________________________ |
| |
| /** |
| @short standard ctor/dtor |
| @descr These initialize a new instance of this class with needed informations for work. |
| We hold a weakreference to our owner frame which start dispatches at us. |
| We can't use a normal reference because he hold a reference of us too ... |
| nobody can die so ...! |
| |
| @seealso using at owner |
| |
| @param xFactory |
| reference to servicemanager to create new services. |
| @param xFrame |
| reference to our owner frame. |
| |
| @modified 17.05.2002 10:07, as96863 |
| */ |
| DispatchProvider::DispatchProvider( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory , |
| const css::uno::Reference< css::frame::XFrame >& xFrame ) |
| // Init baseclasses first |
| : ThreadHelpBase( &Application::GetSolarMutex() ) |
| , OWeakObject ( ) |
| // Init member |
| , m_xFactory ( xFactory ) |
| , m_xFrame ( xFrame ) |
| { |
| } |
| |
| //_________________________________________________________________________________________________________________ |
| |
| /** |
| @short protected(!) dtor for deinitializing |
| @descr We made it protected to prevent using of us as base class instead as a member. |
| |
| @modified 17.05.2002 10:05, as96863 |
| */ |
| DispatchProvider::~DispatchProvider() |
| { |
| } |
| |
| //_________________________________________________________________________________________________________________ |
| |
| /** |
| @interface XDispatchProvider |
| @short search a dispatcher for given URL |
| @descr If no interceptor is set on owner, we search for right frame and dispatch URL to it. |
| If no frame was found, we do nothing. |
| But we doesn't do it directly here. We detect the type of our owner frame and calls |
| specialized queryDispatch() helper dependen from that. Because a Desktop handle some |
| requests in another way then a normal frame. |
| |
| @param aURL |
| URL to dispatch. |
| @param sTargetFrameName |
| name of searched frame. |
| @param nSearchFlags |
| flags for searching. |
| @return A reference to a dispatch object for this URL (if someone was found!). |
| |
| @threadsafe yes |
| @modified 17.05.2002 10:59, as96863 |
| */ |
| css::uno::Reference< css::frame::XDispatch > SAL_CALL DispatchProvider::queryDispatch( const css::util::URL& aURL , |
| const ::rtl::OUString& sTargetFrameName , |
| sal_Int32 nSearchFlags ) throw( css::uno::RuntimeException ) |
| { |
| css::uno::Reference< css::frame::XDispatch > xDispatcher; |
| |
| /* SAFE { */ |
| ReadGuard aReadLock( m_aLock ); |
| css::uno::Reference< css::frame::XFrame > xOwner( m_xFrame.get(), css::uno::UNO_QUERY ); |
| aReadLock.unlock(); |
| /* } SAFE */ |
| |
| css::uno::Reference< css::frame::XDesktop > xDesktopCheck( xOwner, css::uno::UNO_QUERY ); |
| |
| if (xDesktopCheck.is()) |
| xDispatcher = implts_queryDesktopDispatch(xOwner, aURL, sTargetFrameName, nSearchFlags); |
| else |
| xDispatcher = implts_queryFrameDispatch(xOwner, aURL, sTargetFrameName, nSearchFlags); |
| |
| return xDispatcher; |
| } |
| |
| //_________________________________________________________________________________________________________________ |
| |
| /** |
| @interface XDispatchProvider |
| @short do the same like queryDispatch() ... but handle multiple dispatches at the same time |
| @descr It's an optimism. User give us a list of queries ... and we return a list of dispatcher. |
| If one of given queries couldn't be solved to a real existing dispatcher ... |
| we return a list with empty references in it! Order of both lists will be retained! |
| |
| @seealso method queryDispatch() |
| |
| @param lDescriptions |
| a list of all dispatch parameters for multiple requests |
| @return A reference a list of dispatch objects for these URLs - may with some <NULL/> values inside. |
| |
| @threadsafe yes |
| @modified 17.05.2002 09:55, as96863 |
| */ |
| 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 ) |
| { |
| // Create return list - which must have same size then the given descriptor |
| // It's not allowed to pack it! |
| sal_Int32 nCount = lDescriptions.getLength(); |
| css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount ); |
| |
| // Step over all descriptors and try to get any dispatcher for it. |
| for( sal_Int32 i=0; i<nCount; ++i ) |
| { |
| lDispatcher[i] = queryDispatch( lDescriptions[i].FeatureURL , |
| lDescriptions[i].FrameName , |
| lDescriptions[i].SearchFlags ); |
| } |
| |
| return lDispatcher; |
| } |
| |
| //_________________________________________________________________________________________________________________ |
| |
| ::sal_Bool lcl_isStartModuleDispatch (const css::util::URL& aURL) |
| { |
| return (aURL.Complete.equals(CMD_UNO_SHOWSTARTMODULE)); |
| } |
| |
| //_________________________________________________________________________________________________________________ |
| |
| /** |
| @short helper for queryDispatch() |
| @descr Every member of the frame tree (frame, desktop) must handle such request |
| in another way. So we implement different specialized metods for every one. |
| |
| @threadsafe yes |
| @modified 20.08.2003 08:32, as96863 |
| */ |
| css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_queryDesktopDispatch( const css::uno::Reference< css::frame::XFrame > xDesktop , |
| const css::util::URL& aURL , |
| const ::rtl::OUString& sTargetFrameName , |
| sal_Int32 nSearchFlags ) |
| { |
| css::uno::Reference< css::frame::XDispatch > xDispatcher; |
| |
| // ignore wrong requests which are not supported |
| if ( |
| (sTargetFrameName==SPECIALTARGET_MENUBAR ) || // valid for frame dispatches - not for desktop |
| (sTargetFrameName==SPECIALTARGET_HELPAGENT) || // valid for frame dispatches - not for desktop |
| (sTargetFrameName==SPECIALTARGET_PARENT ) || // we have no parent by definition |
| (sTargetFrameName==SPECIALTARGET_BEAMER ) // beamer frames are allowed as child of tasks only - |
| // and they exist more then ones. We have no idea which our sub tasks is the right one |
| ) |
| { |
| return NULL; |
| } |
| |
| //----------------------------------------------------------------------------------------------------- |
| // I) handle special cases which not right for using findFrame() first |
| //----------------------------------------------------------------------------------------------------- |
| |
| //----------------------------------------------------------------------------------------------------- |
| // I.I) "_blank" |
| // It's not the right place to create a new task here - because we are queried for a dispatch object |
| // only, which can handle such request. Such dispatcher should create the required task on demand. |
| // Normaly the functionality for "_blank" is provided by findFrame() - but that would create it directly |
| // here. Thats why we must "intercept" here. |
| //----------------------------------------------------------------------------------------------------- |
| if (sTargetFrameName==SPECIALTARGET_BLANK) |
| { |
| if (implts_isLoadableContent(aURL)) |
| xDispatcher = implts_getOrCreateDispatchHelper( E_BLANKDISPATCHER, xDesktop ); |
| } |
| |
| //----------------------------------------------------------------------------------------------------- |
| // I.II) "_default" |
| // This is a combination of search an empty task for recycling - or create a new one. |
| //----------------------------------------------------------------------------------------------------- |
| else |
| if (sTargetFrameName==SPECIALTARGET_DEFAULT) |
| { |
| if (implts_isLoadableContent(aURL)) |
| xDispatcher = implts_getOrCreateDispatchHelper( E_DEFAULTDISPATCHER, xDesktop ); |
| |
| if (lcl_isStartModuleDispatch(aURL)) |
| xDispatcher = implts_getOrCreateDispatchHelper( E_STARTMODULEDISPATCHER, xDesktop ); |
| } |
| |
| //----------------------------------------------------------------------------------------------------- |
| // I.III) "_self", "", "_top" |
| // The desktop can't load any document - but he can handle some special protocols like "uno", "slot" ... |
| // Why is "top" here handled too? Because the desktop is the topest frame. Normaly it's superflous |
| // to use this target - but we can handle it in the same manner then "_self". |
| //----------------------------------------------------------------------------------------------------- |
| else |
| if ( |
| (sTargetFrameName==SPECIALTARGET_SELF) || |
| (sTargetFrameName==SPECIALTARGET_TOP ) || |
| (sTargetFrameName.getLength()<1 ) |
| ) |
| { |
| xDispatcher = implts_searchProtocolHandler(aURL); |
| } |
| |
| //----------------------------------------------------------------------------------------------------- |
| // I.IV) no further special targets exist |
| // Now we have to search for the right target frame by calling findFrame() - but should provide our code |
| // against creation of a new task if no frame could be found. |
| // I said it b efore - it's allowed for dispatch() only. |
| //----------------------------------------------------------------------------------------------------- |
| else |
| { |
| sal_Int32 nRightFlags = nSearchFlags; |
| nRightFlags &= ~css::frame::FrameSearchFlag::CREATE; |
| |
| // try to find any existing target and ask him for his dispatcher |
| css::uno::Reference< css::frame::XFrame > xFoundFrame = xDesktop->findFrame(sTargetFrameName, nRightFlags); |
| if (xFoundFrame.is()) |
| { |
| css::uno::Reference< css::frame::XDispatchProvider > xProvider( xFoundFrame, css::uno::UNO_QUERY ); |
| xDispatcher = xProvider->queryDispatch(aURL,SPECIALTARGET_SELF,0); |
| } |
| else |
| // if it couldn't be found - but creation was allowed |
| // use special dispatcher for creatio or froward it to the browser |
| if (nSearchFlags & css::frame::FrameSearchFlag::CREATE) |
| xDispatcher = implts_getOrCreateDispatchHelper( E_CREATEDISPATCHER, xDesktop, sTargetFrameName, nSearchFlags ); |
| } |
| |
| return xDispatcher; |
| } |
| |
| //_________________________________________________________________________________________________________________ |
| |
| css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_queryFrameDispatch( const css::uno::Reference< css::frame::XFrame > xFrame , |
| const css::util::URL& aURL , |
| const ::rtl::OUString& sTargetFrameName , |
| sal_Int32 nSearchFlags ) |
| { |
| css::uno::Reference< css::frame::XDispatch > xDispatcher; |
| |
| //----------------------------------------------------------------------------------------------------- |
| // 0) Some URLs are dispatched in a generic way (e.g. by the menu) using the default target "". |
| // But they are specified to use her own fix target. Detect such URLs here and use the correct target. |
| //----------------------------------------------------------------------------------------------------- |
| |
| ::rtl::OUString sTargetName = sTargetFrameName; |
| |
| //----------------------------------------------------------------------------------------------------- |
| // I) handle special cases which not right for using findFrame() first |
| //----------------------------------------------------------------------------------------------------- |
| |
| //----------------------------------------------------------------------------------------------------- |
| // I.I) "_blank", "_default" |
| // It's not the right place to create a new task here. Only the desktop can do that. |
| // Normaly the functionality for "_blank" is provided by findFrame() - but that would create it directly |
| // here. Thats why we must "intercept" here. |
| //----------------------------------------------------------------------------------------------------- |
| if ( |
| (sTargetName==SPECIALTARGET_BLANK ) || |
| (sTargetName==SPECIALTARGET_DEFAULT) |
| ) |
| { |
| css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY ); |
| if (xParent.is()) |
| xDispatcher = xParent->queryDispatch(aURL, sTargetName, 0); // its a special target - ignore search flags |
| } |
| |
| //----------------------------------------------------------------------------------------------------- |
| // I.II) "_menubar" |
| // Special mode on frame or task to receive the local menu. Not supported by findFrame() |
| //----------------------------------------------------------------------------------------------------- |
| else |
| if (sTargetName==SPECIALTARGET_MENUBAR) |
| { |
| xDispatcher = implts_getOrCreateDispatchHelper( E_MENUDISPATCHER, xFrame ); |
| } |
| |
| //----------------------------------------------------------------------------------------------------- |
| // I.III) "_helpagent" |
| // Special mode on frame or task to start the help agent. |
| // It's defined for top level frames only. |
| //----------------------------------------------------------------------------------------------------- |
| else |
| if (sTargetName==SPECIALTARGET_HELPAGENT) |
| { |
| if (WindowHelper::isTopWindow(xFrame->getContainerWindow())) |
| xDispatcher = implts_getOrCreateDispatchHelper( E_HELPAGENTDISPATCHER, xFrame ); |
| else |
| { |
| // Don''t use findFrame() here - because it's not possible to find |
| // a top lebel frame without knowing his name. And a frame with name |
| // "" can't be really searched! That's why forward query to any parent |
| // explicitly. |
| css::uno::Reference< css::frame::XDispatchProvider > xProvider( xFrame->getCreator(), css::uno::UNO_QUERY ); |
| if (xProvider.is()) |
| xDispatcher = xProvider->queryDispatch(aURL,SPECIALTARGET_HELPAGENT,0); |
| } |
| } |
| |
| //----------------------------------------------------------------------------------------------------- |
| // I.IV) "_helpagent" |
| // Special sub frame of a top frame only. Search or create it. ... OK it's currently a little bit HACKI. |
| // Only the sfx (means the controller) can create it it. |
| //----------------------------------------------------------------------------------------------------- |
| else |
| if (sTargetName==SPECIALTARGET_BEAMER) |
| { |
| css::uno::Reference< css::frame::XDispatchProvider > xBeamer( xFrame->findFrame( SPECIALTARGET_BEAMER, css::frame::FrameSearchFlag::CHILDREN | css::frame::FrameSearchFlag::SELF ), css::uno::UNO_QUERY ); |
| if (xBeamer.is()) |
| { |
| xDispatcher = xBeamer->queryDispatch(aURL, SPECIALTARGET_SELF, 0); |
| } |
| else |
| { |
| css::uno::Reference< css::frame::XDispatchProvider > xController( xFrame->getController(), css::uno::UNO_QUERY ); |
| if (xController.is()) |
| // force using of special target - but use original search flags |
| // May the caller used the CREATE flag or not! |
| xDispatcher = xController->queryDispatch(aURL, SPECIALTARGET_BEAMER, nSearchFlags); |
| } |
| } |
| |
| //----------------------------------------------------------------------------------------------------- |
| // I.V) "_parent" |
| // Our parent frame (if it exist) should handle this URL. |
| //----------------------------------------------------------------------------------------------------- |
| else |
| if (sTargetName==SPECIALTARGET_PARENT) |
| { |
| css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY ); |
| if (xParent.is()) |
| // SELF => we must address the parent directly... and not his parent or any other parent! |
| xDispatcher = xParent->queryDispatch(aURL, SPECIALTARGET_SELF, 0); |
| } |
| |
| //----------------------------------------------------------------------------------------------------- |
| // I.VI) "_top" |
| // This request must be forwarded to any parent frame, till we reach a top frame. |
| // If no parent exist, we can handle itself. |
| //----------------------------------------------------------------------------------------------------- |
| else |
| if (sTargetName==SPECIALTARGET_TOP) |
| { |
| if (xFrame->isTop()) |
| { |
| // If we are this top frame itself (means our owner frame) |
| // we should call ourself recursiv with a better target "_self". |
| // So we can share the same code! (see reaction for "_self" inside this method too.) |
| xDispatcher = this->queryDispatch(aURL,SPECIALTARGET_SELF,0); |
| } |
| else |
| { |
| css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY ); |
| // Normaly if isTop() returned sal_False ... the parent frame MUST(!) exist ... |
| // But it seams to be better to check that here to prevent us against an access violation. |
| if (xParent.is()) |
| xDispatcher = xParent->queryDispatch(aURL, SPECIALTARGET_TOP, 0); |
| } |
| } |
| |
| //----------------------------------------------------------------------------------------------------- |
| // I.VII) "_self", "" |
| // Our owner frame should handle this URL. But we can't do it for all of them. |
| // So we ask the internal setted controller first. If he disagree we try to find a registered |
| // protocol handler. If this failed too - we check for a loadable content and in case of true |
| // we load it into the frame by returning specilized dispatch object. |
| //----------------------------------------------------------------------------------------------------- |
| else |
| if ( |
| (sTargetName==SPECIALTARGET_SELF) || |
| (sTargetName.getLength()<1 ) |
| ) |
| { |
| // There exist a hard coded interception for special URLs. |
| if ( |
| (aURL.Complete.equalsAscii(".uno:CloseDoc" )) || |
| (aURL.Complete.equalsAscii(".uno:CloseWin" )) |
| ) |
| { |
| css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY ); |
| // In case the frame is not a top one, is not based on system window and has a parent, |
| // the parent frame should to be queried for the correct dispatcher. |
| // See i93473 |
| if ( |
| !WindowHelper::isTopWindow(xFrame->getContainerWindow()) && |
| !VCLUnoHelper::GetWindow(xFrame->getContainerWindow())->IsSystemWindow() && |
| xParent.is() |
| ) |
| xDispatcher = xParent->queryDispatch(aURL, SPECIALTARGET_SELF, 0); |
| else |
| xDispatcher = implts_getOrCreateDispatchHelper( E_CLOSEDISPATCHER, xFrame ); |
| } |
| else if (aURL.Complete.equalsAscii(".uno:CloseFrame")) |
| xDispatcher = implts_getOrCreateDispatchHelper( E_CLOSEDISPATCHER, xFrame ); |
| |
| if ( ! xDispatcher.is()) |
| { |
| // Ask our controller for his agreement for these dispatched URL ... |
| // because some URLs are internal and can be handled faster by SFX - which most is the current controller! |
| // But in case of e.g. the bibliography not all queries will be handled successfully here. |
| css::uno::Reference< css::frame::XDispatchProvider > xController( xFrame->getController(), css::uno::UNO_QUERY ); |
| if (xController.is()) |
| xDispatcher = xController->queryDispatch(aURL, SPECIALTARGET_SELF, 0); |
| } |
| |
| // If controller has no fun to dispatch these URL - we must search another right dispatcher. |
| // Search for any registered protocol handler first. |
| if (!xDispatcher.is()) |
| xDispatcher = implts_searchProtocolHandler(aURL); |
| |
| // Not for controller - not for protocol handler |
| // It should be a loadable content - may be a file. Check it ... |
| // This check is necessary to found out, that |
| // support for some protocols isn't installed by user. May be |
| // "ftp" isn't available. So we suppress creation of our self dispatcher. |
| // The result will be clear. He can't handle it - but he would try it. |
| if ( |
| ( ! xDispatcher.is() ) && |
| ( implts_isLoadableContent(aURL) ) |
| ) |
| { |
| xDispatcher = implts_getOrCreateDispatchHelper( E_SELFDISPATCHER, xFrame ); |
| } |
| } |
| |
| //----------------------------------------------------------------------------------------------------- |
| // I.VI) no further special handlings exist |
| // Now we have to search for the right target frame by calling findFrame() - but should provide our code |
| // against creation of a new task if no frame could be found. |
| // I said it before - it's allowed for dispatch() only. |
| //----------------------------------------------------------------------------------------------------- |
| else |
| { |
| sal_Int32 nRightFlags = nSearchFlags; |
| nRightFlags &= ~css::frame::FrameSearchFlag::CREATE; |
| |
| // try to find any existing target and ask him for his dispatcher |
| css::uno::Reference< css::frame::XFrame > xFoundFrame = xFrame->findFrame(sTargetName, nRightFlags); |
| if (xFoundFrame.is()) |
| { |
| // Attention: Found target is our own owner frame! |
| // Don't ask him for his dispatcher. We know it already - it's our self dispatch helper. |
| // Otherwhise we can start a never ending recursiv call. Why? |
| // Somewere called our owner frame - he called some interceptor objects - and may by this dispatch provider |
| // is called. If wa use queryDispatch() on our owner frame again - we start this call stack again ... and again. |
| if (xFoundFrame==xFrame) |
| xDispatcher = implts_getOrCreateDispatchHelper( E_SELFDISPATCHER, xFrame ); |
| else |
| { |
| css::uno::Reference< css::frame::XDispatchProvider > xProvider( xFoundFrame, css::uno::UNO_QUERY ); |
| xDispatcher = xProvider->queryDispatch(aURL,SPECIALTARGET_SELF,0); |
| } |
| } |
| else |
| // if it couldn't be found - but creation was allowed |
| // forward request to the desktop. |
| // Note: The given target name must be used to set the name on new created task! |
| // Don't forward request by changing it to a special one e.g _blank. |
| // Use the CREATE flag only to prevent call against further searches. |
| // We already know it - the target must be created new. |
| if (nSearchFlags & css::frame::FrameSearchFlag::CREATE) |
| { |
| css::uno::Reference< css::frame::XDispatchProvider > xParent( xFrame->getCreator(), css::uno::UNO_QUERY ); |
| if (xParent.is()) |
| xDispatcher = xParent->queryDispatch(aURL, sTargetName, css::frame::FrameSearchFlag::CREATE); |
| } |
| } |
| |
| return xDispatcher; |
| } |
| |
| //_________________________________________________________________________________________________________________ |
| |
| /** |
| @short search for a registered protocol handler and ask him for a dispatch object |
| @descr Wes earch a suitable handler inside our cfg package org.openoffice.Office.ProtocolHandler. |
| If we found anyone, we create and initialize it. Initialize means: we set our owner frame on it |
| as context information. He can use it or leave it. Of course - we are aware of handler implementations, |
| which doesn't support initialization. It's an optional feature. |
| |
| @param aURL |
| the dispatch URL for which may a handler is registered |
| |
| @return A dispatch object if a handler was found and agree with the given URL or <NULL/> otherwhise. |
| |
| @threadsafe yes |
| @modified 05.09.2002 13:43, as96863 |
| */ |
| css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_searchProtocolHandler( const css::util::URL& aURL ) |
| { |
| css::uno::Reference< css::frame::XDispatch > xDispatcher; |
| ProtocolHandler aHandler ; |
| |
| // This member is threadsafe by himself and lives if we live - we doesn't need any mutex here. |
| if (m_aProtocolHandlerCache.search(aURL,&aHandler)) |
| { |
| /* SAFE { */ |
| ReadGuard aReadLock( m_aLock ); |
| |
| // create it |
| css::uno::Reference< css::frame::XDispatchProvider > xHandler; |
| try |
| { |
| xHandler = css::uno::Reference< css::frame::XDispatchProvider >( |
| m_xFactory->createInstance(aHandler.m_sUNOName), |
| css::uno::UNO_QUERY); |
| } |
| catch(css::uno::Exception&) {} |
| |
| // look if initialization is necessary |
| css::uno::Reference< css::lang::XInitialization > xInit( xHandler, css::uno::UNO_QUERY ); |
| if (xInit.is()) |
| { |
| css::uno::Reference< css::frame::XFrame > xOwner( m_xFrame.get(), css::uno::UNO_QUERY ); |
| 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.") |
| if (xOwner.is()) |
| { |
| try |
| { |
| // but do it only, if all context informations are OK |
| css::uno::Sequence< css::uno::Any > lContext(1); |
| lContext[0] <<= xOwner; |
| xInit->initialize(lContext); |
| } |
| catch(css::uno::Exception&) {} |
| } |
| } |
| |
| aReadLock.unlock(); |
| /* } SAFE */ |
| |
| // ask for his (sub)dispatcher for the given URL |
| if (xHandler.is()) |
| xDispatcher = xHandler->queryDispatch(aURL,SPECIALTARGET_SELF,0); |
| } |
| |
| return xDispatcher; |
| } |
| |
| //_________________________________________________________________________________________________________________ |
| |
| /** |
| @short get or create new dispatch helper |
| @descr Sometimes we need some helper implementations to support dispatching of special URLs or commands. |
| But it's not a good idea to hold these services for the whole life time of this provider instance. |
| We should create it on demand ... |
| Thats why we implement this method. It return an already existing helper or create a new one otherwise. |
| |
| @attention The parameter sTarget and nSearchFlags are defaulted to "" and 0! |
| Please use it only, if you can be sure, that the really given by the outside calli! |
| Mostly it depends from the parameter eHelper is they are required or not. |
| |
| @param eHelper |
| specify the requested dispatch helper |
| @param xOwner |
| the target of possible dispatch() call on created dispatch helper |
| @param sTarget |
| the target parameter of the original queryDispatch() request |
| @param nSearchFlags |
| the flags parameter of the original queryDispatch() request |
| @return A reference to a dispatch helper. |
| |
| @threadsafe yes |
| @modified 20.08.2003 10:22, as96863 |
| */ |
| css::uno::Reference< css::frame::XDispatch > DispatchProvider::implts_getOrCreateDispatchHelper( EDispatchHelper eHelper , |
| const css::uno::Reference< css::frame::XFrame >& xOwner , |
| const ::rtl::OUString& sTarget , |
| sal_Int32 nSearchFlags) |
| { |
| css::uno::Reference< css::frame::XDispatch > xDispatchHelper; |
| |
| /* SAFE { */ |
| ReadGuard aReadLock( m_aLock ); |
| css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory; |
| aReadLock.unlock(); |
| /* } SAFE */ |
| |
| switch (eHelper) |
| { |
| case E_MENUDISPATCHER : |
| { |
| // Attention: Such menue dispatcher must be a singleton for this frame - means our owner frame. |
| // Otherwhise he can make some trouble. |
| /* SAFE { */ |
| WriteGuard aWriteLock( m_aLock ); |
| if ( ! m_xMenuDispatcher.is() ) |
| { |
| MenuDispatcher* pDispatcher = new MenuDispatcher( xFactory, xOwner ); |
| m_xMenuDispatcher = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY ); |
| } |
| xDispatchHelper = m_xMenuDispatcher; |
| aWriteLock.unlock(); |
| /* } SAFE */ |
| } |
| break; |
| |
| case E_HELPAGENTDISPATCHER : |
| { |
| // Attention: It's not a good idea to create this help agent twice for the same frame (window) |
| // May it will be shown twice too - and user activate the first one. Then he get the corresponding |
| // help window ... but there exist another help agent window on bottom side of the frame window. |
| // It's superflous. Create it on demand - but hold it alive till this provider dies. |
| /* SAFE { */ |
| WriteGuard aWriteLock( m_aLock ); |
| if ( ! m_xHelpAgentDispatcher.is() ) |
| { |
| HelpAgentDispatcher* pDispatcher = new HelpAgentDispatcher( xOwner ); |
| m_xHelpAgentDispatcher = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY ); |
| } |
| xDispatchHelper = m_xHelpAgentDispatcher; |
| aWriteLock.unlock(); |
| /* } SAFE */ |
| } |
| break; |
| |
| case E_CREATEDISPATCHER : |
| { |
| LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, sTarget, nSearchFlags); |
| xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY ); |
| } |
| break; |
| |
| case E_BLANKDISPATCHER : |
| { |
| css::uno::Reference< css::frame::XFrame > xDesktop( xOwner, css::uno::UNO_QUERY ); |
| if (xDesktop.is()) |
| { |
| LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, SPECIALTARGET_BLANK, 0); |
| xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY ); |
| } |
| } |
| break; |
| |
| case E_DEFAULTDISPATCHER : |
| { |
| css::uno::Reference< css::frame::XFrame > xDesktop( xOwner, css::uno::UNO_QUERY ); |
| if (xDesktop.is()) |
| { |
| LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, SPECIALTARGET_DEFAULT, 0); |
| xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY ); |
| } |
| } |
| break; |
| |
| case E_SELFDISPATCHER : |
| { |
| LoadDispatcher* pDispatcher = new LoadDispatcher(xFactory, xOwner, SPECIALTARGET_SELF, 0); |
| xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY ); |
| } |
| break; |
| |
| case E_CLOSEDISPATCHER : |
| { |
| CloseDispatcher* pDispatcher = new CloseDispatcher( xFactory, xOwner, sTarget ); |
| xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY ); |
| } |
| break; |
| |
| case E_STARTMODULEDISPATCHER : |
| { |
| StartModuleDispatcher* pDispatcher = new StartModuleDispatcher( xFactory, xOwner, sTarget ); |
| xDispatchHelper = css::uno::Reference< css::frame::XDispatch >( static_cast< ::cppu::OWeakObject* >(pDispatcher), css::uno::UNO_QUERY ); |
| } |
| break; |
| } |
| |
| return xDispatchHelper; |
| } |
| |
| //_________________________________________________________________________________________________________________ |
| |
| /** |
| @short check URL for support by our used loader or handler |
| @descr If we must return our own dispatch helper implementations (self, blank, create dispatcher!) |
| we should be shure, that URL describe any loadable content. Otherwise slot/uno URLs |
| will be detected ... but there exist nothing for ral loading into a target frame! |
| |
| @param aURL |
| URL which should be "detected" |
| @return <TRUE/> if somewhere could handle that - <FALSE/> otherwise. |
| |
| @threadsafe yes |
| @modified 17.05.2002 09:47, as96863 |
| */ |
| sal_Bool DispatchProvider::implts_isLoadableContent( const css::util::URL& aURL ) |
| { |
| LoadEnv::EContentType eType = LoadEnv::classifyContent(aURL.Complete, css::uno::Sequence< css::beans::PropertyValue >()); |
| return ( eType == LoadEnv::E_CAN_BE_LOADED ); |
| } |
| |
| } // namespace framework |