LibreOffice Module framework (master) 1
servicehandler.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#include <services.h>
22
23#include <com/sun/star/frame/DispatchResultState.hpp>
24#include <com/sun/star/task/XJobExecutor.hpp>
25#include <com/sun/star/lang/XMultiServiceFactory.hpp>
26
29#include <utility>
30
31namespace framework{
32
33constexpr OUStringLiteral PROTOCOL_VALUE = u"service:";
34
35// XInterface, XTypeProvider, XServiceInfo
36
38{
39 return "com.sun.star.comp.framework.ServiceHandler";
40}
41
42sal_Bool SAL_CALL ServiceHandler::supportsService( const OUString& sServiceName )
43{
45}
46
47css::uno::Sequence< OUString > SAL_CALL ServiceHandler::getSupportedServiceNames()
48{
50}
51
52
60ServiceHandler::ServiceHandler( css::uno::Reference< css::uno::XComponentContext > xContext )
61 : m_xContext (std::move( xContext ))
62{
63}
64
69{
70}
71
81css::uno::Reference< css::frame::XDispatch > SAL_CALL ServiceHandler::queryDispatch( const css::util::URL& aURL ,
82 const OUString& /*sTarget*/ ,
83 sal_Int32 /*nFlags*/ )
84{
85 css::uno::Reference< css::frame::XDispatch > xDispatcher;
86 if (aURL.Complete.startsWith(PROTOCOL_VALUE))
87 xDispatcher = this;
88 return xDispatcher;
89}
90
94css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL ServiceHandler::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor )
95{
96 sal_Int32 nCount = lDescriptor.getLength();
97 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
98 auto lDispatcherRange = asNonConstRange(lDispatcher);
99 for( sal_Int32 i=0; i<nCount; ++i )
100 {
101 lDispatcherRange[i] = queryDispatch(
102 lDescriptor[i].FeatureURL,
103 lDescriptor[i].FrameName,
104 lDescriptor[i].SearchFlags);
105 }
106 return lDispatcher;
107}
108
119void SAL_CALL ServiceHandler::dispatch( const css::util::URL& aURL ,
120 const css::uno::Sequence< css::beans::PropertyValue >& /*lArguments*/ )
121{
122 // dispatch() is an [oneway] call ... and may our user release his reference to us immediately.
123 // So we should hold us self alive till this call ends.
124 css::uno::Reference< css::frame::XNotifyingDispatch > xSelfHold(this);
126 // No notification for status listener!
127}
128
141void SAL_CALL ServiceHandler::dispatchWithNotification( const css::util::URL& aURL ,
142 const css::uno::Sequence< css::beans::PropertyValue >& /*lArguments*/,
143 const css::uno::Reference< css::frame::XDispatchResultListener >& xListener )
144{
145 // This class was designed to die by reference. And if user release his reference to us immediately after calling this method
146 // we can run into some problems. So we hold us self alive till this method ends.
147 // Another reason: We can use this reference as source of sending event at the end too.
148 css::uno::Reference< css::frame::XNotifyingDispatch > xThis(this);
149
150 css::uno::Reference< css::uno::XInterface > xService = implts_dispatch(aURL);
151 if (xListener.is())
152 {
153 css::frame::DispatchResultEvent aEvent;
154 if (xService.is())
155 aEvent.State = css::frame::DispatchResultState::SUCCESS;
156 else
157 aEvent.State = css::frame::DispatchResultState::FAILURE;
158 aEvent.Result <<= xService; // may NULL for state=FAILED!
159 aEvent.Source = xThis;
160
161 xListener->dispatchFinished( aEvent );
162 }
163}
164
178css::uno::Reference< css::uno::XInterface > ServiceHandler::implts_dispatch( const css::util::URL& aURL )
179{
180 // extract service name and may optional given parameters from given URL
181 // and use it to create and start the component
182 OUString sServiceAndArguments = aURL.Complete.copy(PROTOCOL_VALUE.getLength());
183 OUString sServiceName;
184 OUString sArguments;
185
186 sal_Int32 nArgStart = sServiceAndArguments.indexOf('?');
187 if (nArgStart!=-1)
188 {
189 sServiceName = sServiceAndArguments.copy(0,nArgStart);
190 ++nArgStart; // ignore '?'!
191 sArguments = sServiceAndArguments.copy(nArgStart);
192 }
193 else
194 {
195 sServiceName = sServiceAndArguments;
196 }
197
198 if (sServiceName.isEmpty())
199 return css::uno::Reference< css::uno::XInterface >();
200
201 // If a service doesn't support an optional job executor interface - he can't get
202 // any given parameters!
203 // Because we can't know if we must call createInstanceWithArguments() or XJobExecutor::trigger() ...
204
205 css::uno::Reference< css::uno::XInterface > xService;
206 try
207 {
208 // => a) a service starts running inside his own ctor and we create it only
209 xService = m_xContext->getServiceManager()->createInstanceWithContext(sServiceName, m_xContext);
210 // or b) he implements the right interface and starts there (may with optional parameters)
211 css::uno::Reference< css::task::XJobExecutor > xExecutable(xService, css::uno::UNO_QUERY);
212 if (xExecutable.is())
213 xExecutable->trigger(sArguments);
214 }
215 // ignore all errors - inclusive runtime errors!
216 // E.g. a script based service (written in Python) could not be executed
217 // because it contains syntax errors, which was detected at runtime...
218 catch(const css::uno::Exception&)
219 {
220 TOOLS_WARN_EXCEPTION("fwk.dispatch", "ignored");
221 xService.clear();
222 }
223
224 return xService;
225}
226
238void SAL_CALL ServiceHandler::addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/ ,
239 const css::util::URL& /*aURL*/ )
240{
241 // not supported yet
242}
243
244void SAL_CALL ServiceHandler::removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/ ,
245 const css::util::URL& /*aURL*/ )
246{
247 // not supported yet
248}
249
250} // namespace framework
251
252
253extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
255 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
256{
257 return cppu::acquire(new framework::ServiceHandler(context));
258}
259
260/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
constexpr OUStringLiteral sServiceName
AnyEventRef aEvent
protocol handler for "service:*" URLs @descr It's a special dispatch/provider object which is registe...
virtual void SAL_CALL dispatch(const css::util::URL &aURL, const css::uno::Sequence< css::beans::PropertyValue > &lArguments) override
dispatch URL with arguments @descr We use threadsafe internal method to do so.
virtual sal_Bool SAL_CALL supportsService(const OUString &sServiceName) override
virtual OUString SAL_CALL getImplementationName() override
virtual ~ServiceHandler() override
standard dtor
css::uno::Reference< css::uno::XComponentContext > m_xContext
reference to global uno service manager which had created us
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual void SAL_CALL removeStatusListener(const css::uno::Reference< css::frame::XStatusListener > &xListener, const css::util::URL &aURL) override
virtual void SAL_CALL dispatchWithNotification(const css::util::URL &aURL, const css::uno::Sequence< css::beans::PropertyValue > &lArguments, const css::uno::Reference< css::frame::XDispatchResultListener > &xListener) override
dispatch with guaranteed notifications about success @descr We use threadsafe internal method to do s...
virtual void SAL_CALL addStatusListener(const css::uno::Reference< css::frame::XStatusListener > &xListener, const css::util::URL &aURL) override
add/remove listener for state events @descr We use an internal container to hold such registered list...
virtual css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL queryDispatches(const css::uno::Sequence< css::frame::DispatchDescriptor > &lDescriptor) override
do the same like dispatch() but for multiple requests at the same time
virtual css::uno::Reference< css::frame::XDispatch > SAL_CALL queryDispatch(const css::util::URL &aURL, const OUString &sTarget, sal_Int32 nFlags) override
decide if this dispatch implementation can be used for requested URL or not @descr A protocol handler...
ServiceHandler(css::uno::Reference< css::uno::XComponentContext >)
standard ctor @descr This initializes a new instance of this class with needed information for work.
css::uno::Reference< css::uno::XInterface > implts_dispatch(const css::util::URL &aURL)
threadsafe helper for dispatch calls @descr We support two interfaces for the same process - dispatch...
int nCount
#define TOOLS_WARN_EXCEPTION(area, stream)
URL aURL
float u
css::uno::Reference< css::uno::XComponentContext > m_xContext
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
constexpr OUStringLiteral PROTOCOL_VALUE
constexpr OUStringLiteral SERVICENAME_PROTOCOLHANDLER
Definition: services.h:32
int i
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * framework_ServiceHandler_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
unsigned char sal_Bool