LibreOffice Module framework (master) 1
dispatchhelper.cxx
Go to the documentation of this file.
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
21
22#include <com/sun/star/frame/XNotifyingDispatch.hpp>
23#include <com/sun/star/util/URLTransformer.hpp>
24#include <com/sun/star/util/XURLTransformer.hpp>
25
28#include <utility>
29#include <vcl/threadex.hxx>
31
32namespace framework
33{
34// XInterface, XTypeProvider, XServiceInfo
35
36OUString SAL_CALL DispatchHelper::getImplementationName()
37{
38 return "com.sun.star.comp.framework.services.DispatchHelper";
39}
40
41sal_Bool SAL_CALL DispatchHelper::supportsService(const OUString& sServiceName)
42{
43 return cppu::supportsService(this, sServiceName);
44}
45
46css::uno::Sequence<OUString> SAL_CALL DispatchHelper::getSupportedServiceNames()
47{
48 return { "com.sun.star.frame.DispatchHelper" };
49}
50
55DispatchHelper::DispatchHelper(css::uno::Reference<css::uno::XComponentContext> xContext)
56 : m_xContext(std::move(xContext))
57 , m_aBlockFlag(false)
58{
59}
60
63DispatchHelper::~DispatchHelper() {}
64
84css::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)
88{
89 // check for valid parameters
90 if ((!xDispatchProvider.is()) || (!m_xContext.is()) || (sURL.isEmpty()))
91 {
92 return css::uno::Any();
93 }
94
95 // parse given URL
96 css::uno::Reference<css::util::XURLTransformer> xParser;
97 /* SAFE { */
98 {
99 std::scoped_lock aReadLock(m_mutex);
100 xParser = css::util::URLTransformer::create(m_xContext);
101 }
102 /* } SAFE */
103
104 css::util::URL aURL;
105 aURL.Complete = sURL;
106 xParser->parseStrict(aURL);
107
108 // search dispatcher
109 css::uno::Reference<css::frame::XDispatch> xDispatch
110 = xDispatchProvider->queryDispatch(aURL, sTargetFrameName, nSearchFlags);
111
112 utl::MediaDescriptor aDescriptor(lArguments);
113 bool bOnMainThread = aDescriptor.getUnpackedValueOrDefault("OnMainThread", false);
114
115 if (bOnMainThread)
116 return vcl::solarthread::syncExecute([this, &xDispatch, &aURL, &lArguments]() {
117 return executeDispatch(xDispatch, aURL, true, lArguments);
118 });
119 else
120 return executeDispatch(xDispatch, aURL, true, lArguments);
121}
122
123const css::uno::Any&
124DispatchHelper::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)
127{
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();
132
133 // check for valid parameters
134 if (xDispatch.is())
135 {
136 css::uno::Reference<css::frame::XNotifyingDispatch> xNotifyDispatch(xDispatch,
137 css::uno::UNO_QUERY);
138
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;
146
147 if (xNotifyDispatch.is())
148 {
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 { */
154 {
155 std::scoped_lock aWriteLock(m_mutex);
156 m_xBroadcaster = xNotifyDispatch;
157 m_aBlockFlag = false;
158 }
159 /* } SAFE */
160
161 // dispatch it and wait for a notification
162 // TODO/MBA: waiting in main thread?!
163 xNotifyDispatch->dispatchWithNotification(aURL, aArguments, xListener);
164
165 std::unique_lock aWriteLock(m_mutex);
166 m_aBlock.wait(aWriteLock, [this] { return m_aBlockFlag; }); // wait for result
167 }
168 else
169 {
170 // dispatch it without any chance to get a result
171 xDispatch->dispatch(aURL, aArguments);
172 }
173 }
174
175 return m_aResult;
176}
177
187void SAL_CALL DispatchHelper::dispatchFinished(const css::frame::DispatchResultEvent& aResult)
188{
189 std::scoped_lock g(m_mutex);
190 m_aResult <<= aResult;
191 m_aBlockFlag = true;
192 m_aBlock.notify_one();
193 m_xBroadcaster.clear();
194}
195
201void SAL_CALL DispatchHelper::disposing(const css::lang::EventObject&)
202{
203 std::scoped_lock g(m_mutex);
204 m_aResult.clear();
205 m_aBlockFlag = true;
206 m_aBlock.notify_one();
207 m_xBroadcaster.clear();
208}
209}
210
211extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
212framework_DispatchHelper_get_implementation(css::uno::XComponentContext* context,
213 css::uno::Sequence<css::uno::Any> const&)
214{
215 return cppu::acquire(new framework::DispatchHelper(context));
216}
217
218/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * framework_DispatchHelper_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
Reference< XDispatch > xDispatch
URL aURL
css::uno::Reference< css::uno::XComponentContext > m_xContext
Sequence< PropertyValue > aArguments
std::mutex m_mutex
Definition: loadenv.cxx:108
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
auto syncExecute(FuncT const &func) -> decltype(func())
unsigned char sal_Bool
Any m_aResult
sal_Int32 nLength