Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / framework / source / services / dispatchhelper.cxx
blob8f3d77d322baa50a55a44d106b8c8662aebb22c2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <framework/dispatchhelper.hxx>
22 #include <com/sun/star/frame/XNotifyingDispatch.hpp>
23 #include <com/sun/star/util/URLTransformer.hpp>
24 #include <com/sun/star/util/XURLTransformer.hpp>
26 #include <comphelper/profilezone.hxx>
27 #include <unotools/mediadescriptor.hxx>
28 #include <utility>
29 #include <vcl/threadex.hxx>
30 #include <cppuhelper/supportsservice.hxx>
32 namespace framework
34 // XInterface, XTypeProvider, XServiceInfo
36 OUString SAL_CALL DispatchHelper::getImplementationName()
38 return "com.sun.star.comp.framework.services.DispatchHelper";
41 sal_Bool SAL_CALL DispatchHelper::supportsService(const OUString& sServiceName)
43 return cppu::supportsService(this, sServiceName);
46 css::uno::Sequence<OUString> SAL_CALL DispatchHelper::getSupportedServiceNames()
48 return { "com.sun.star.frame.DispatchHelper" };
51 /** ctor.
53 @param xSMGR the global uno service manager, which can be used to create own needed services.
55 DispatchHelper::DispatchHelper(css::uno::Reference<css::uno::XComponentContext> xContext)
56 : m_xContext(std::move(xContext))
57 , m_aBlockFlag(false)
61 /** dtor.
63 DispatchHelper::~DispatchHelper() {}
65 /** capsulate all steps of a dispatch request and provide so an easy way for dispatches.
67 @param xDispatchProvider
68 identifies the object, which provides may be valid dispatch objects for this execute.
70 @param sURL
71 describes the requested feature.
73 @param sTargetFrameName
74 points to the frame, which must be used (or may be created) for this dispatch.
76 @param nSearchFlags
77 in case the <var>sTargetFrameName</var> isn't unique, these flags regulate further searches.
79 @param lArguments
80 optional arguments for this request.
82 @return An Any which capsulate a possible result of the internal wrapped dispatch.
84 css::uno::Any SAL_CALL DispatchHelper::executeDispatch(
85 const css::uno::Reference<css::frame::XDispatchProvider>& xDispatchProvider,
86 const OUString& sURL, const OUString& sTargetFrameName, sal_Int32 nSearchFlags,
87 const css::uno::Sequence<css::beans::PropertyValue>& lArguments)
89 // check for valid parameters
90 if ((!xDispatchProvider.is()) || (!m_xContext.is()) || (sURL.isEmpty()))
92 return css::uno::Any();
95 // parse given URL
96 css::uno::Reference<css::util::XURLTransformer> xParser;
97 /* SAFE { */
99 std::scoped_lock aReadLock(m_mutex);
100 xParser = css::util::URLTransformer::create(m_xContext);
102 /* } SAFE */
104 css::util::URL aURL;
105 aURL.Complete = sURL;
106 xParser->parseStrict(aURL);
108 // search dispatcher
109 css::uno::Reference<css::frame::XDispatch> xDispatch
110 = xDispatchProvider->queryDispatch(aURL, sTargetFrameName, nSearchFlags);
112 utl::MediaDescriptor aDescriptor(lArguments);
113 bool bOnMainThread = aDescriptor.getUnpackedValueOrDefault("OnMainThread", false);
115 if (bOnMainThread)
116 return vcl::solarthread::syncExecute([this, &xDispatch, &aURL, &lArguments]() {
117 return executeDispatch(xDispatch, aURL, true, lArguments);
119 else
120 return executeDispatch(xDispatch, aURL, true, lArguments);
123 const css::uno::Any&
124 DispatchHelper::executeDispatch(const css::uno::Reference<css::frame::XDispatch>& xDispatch,
125 const css::util::URL& aURL, bool SyncronFlag,
126 const css::uno::Sequence<css::beans::PropertyValue>& lArguments)
128 comphelper::ProfileZone aZone("executeDispatch");
129 css::uno::Reference<css::uno::XInterface> xTHIS(static_cast<::cppu::OWeakObject*>(this),
130 css::uno::UNO_QUERY);
131 m_aResult.clear();
133 // check for valid parameters
134 if (xDispatch.is())
136 css::uno::Reference<css::frame::XNotifyingDispatch> xNotifyDispatch(xDispatch,
137 css::uno::UNO_QUERY);
139 // make sure that synchronous execution is used (if possible)
140 css::uno::Sequence<css::beans::PropertyValue> aArguments(lArguments);
141 sal_Int32 nLength = lArguments.getLength();
142 aArguments.realloc(nLength + 1);
143 auto pArguments = aArguments.getArray();
144 pArguments[nLength].Name = "SynchronMode";
145 pArguments[nLength].Value <<= SyncronFlag;
147 if (xNotifyDispatch.is())
149 // dispatch it with guaranteed notification
150 // Here we can hope for a result ... instead of the normal dispatch.
151 css::uno::Reference<css::frame::XDispatchResultListener> xListener(xTHIS,
152 css::uno::UNO_QUERY);
153 /* SAFE { */
155 std::scoped_lock aWriteLock(m_mutex);
156 m_xBroadcaster = xNotifyDispatch;
157 m_aBlockFlag = false;
159 /* } SAFE */
161 // dispatch it and wait for a notification
162 // TODO/MBA: waiting in main thread?!
163 xNotifyDispatch->dispatchWithNotification(aURL, aArguments, xListener);
165 std::unique_lock aWriteLock(m_mutex);
166 m_aBlock.wait(aWriteLock, [this] { return m_aBlockFlag; }); // wait for result
168 else
170 // dispatch it without any chance to get a result
171 xDispatch->dispatch(aURL, aArguments);
175 return m_aResult;
178 /** callback for started dispatch with guaranteed notifications.
180 We must save the result, so the method executeDispatch() can return it.
181 Further we must release the broadcaster (otherwise it can't die)
182 and unblock the waiting executeDispatch() request.
184 @param aResult
185 describes the result of the dispatch operation
187 void SAL_CALL DispatchHelper::dispatchFinished(const css::frame::DispatchResultEvent& aResult)
189 std::scoped_lock g(m_mutex);
190 m_aResult <<= aResult;
191 m_aBlockFlag = true;
192 m_aBlock.notify_one();
193 m_xBroadcaster.clear();
196 /** we have to release our broadcaster reference.
198 @param aEvent
199 describe the source of this event and MUST be our save broadcaster!
201 void SAL_CALL DispatchHelper::disposing(const css::lang::EventObject&)
203 std::scoped_lock g(m_mutex);
204 m_aResult.clear();
205 m_aBlockFlag = true;
206 m_aBlock.notify_one();
207 m_xBroadcaster.clear();
211 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
212 framework_DispatchHelper_get_implementation(css::uno::XComponentContext* context,
213 css::uno::Sequence<css::uno::Any> const&)
215 return cppu::acquire(new framework::DispatchHelper(context));
218 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */