1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
29 #include <vcl/threadex.hxx>
30 #include <cppuhelper/supportsservice.hxx>
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" };
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
))
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.
71 describes the requested feature.
73 @param sTargetFrameName
74 points to the frame, which must be used (or may be created) for this dispatch.
77 in case the <var>sTargetFrameName</var> isn't unique, these flags regulate further searches.
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();
96 css::uno::Reference
<css::util::XURLTransformer
> xParser
;
99 std::scoped_lock
aReadLock(m_mutex
);
100 xParser
= css::util::URLTransformer::create(m_xContext
);
105 aURL
.Complete
= sURL
;
106 xParser
->parseStrict(aURL
);
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);
116 return vcl::solarthread::syncExecute([this, &xDispatch
, &aURL
, &lArguments
]() {
117 return executeDispatch(xDispatch
, aURL
, true, lArguments
);
120 return executeDispatch(xDispatch
, aURL
, true, lArguments
);
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
);
133 // check for valid parameters
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
);
155 std::scoped_lock
aWriteLock(m_mutex
);
156 m_xBroadcaster
= xNotifyDispatch
;
157 m_aBlockFlag
= false;
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
170 // dispatch it without any chance to get a result
171 xDispatch
->dispatch(aURL
, aArguments
);
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.
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
;
192 m_aBlock
.notify_one();
193 m_xBroadcaster
.clear();
196 /** we have to release our broadcaster reference.
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
);
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: */