Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <dispatch/servicehandler.hxx>
30 : : #include <threadhelp/readguard.hxx>
31 : : #include <general.h>
32 : : #include <services.h>
33 : :
34 : : #include <com/sun/star/frame/DispatchResultState.hpp>
35 : : #include <com/sun/star/task/XJobExecutor.hpp>
36 : :
37 : : #include <vcl/svapp.hxx>
38 : :
39 : : namespace framework{
40 : :
41 : : #define PROTOCOL_VALUE "service:"
42 : : #define PROTOCOL_LENGTH 8
43 : :
44 : : //_________________________________________________________________________________________________________________
45 : : // XInterface, XTypeProvider, XServiceInfo
46 : :
47 [ + + ][ + - ]: 92 : DEFINE_XINTERFACE_5(ServiceHandler ,
48 : : OWeakObject ,
49 : : DIRECT_INTERFACE(css::lang::XTypeProvider ),
50 : : DIRECT_INTERFACE(css::lang::XServiceInfo ),
51 : : DIRECT_INTERFACE(css::frame::XDispatchProvider ),
52 : : DIRECT_INTERFACE(css::frame::XNotifyingDispatch),
53 : : DIRECT_INTERFACE(css::frame::XDispatch ))
54 : :
55 [ # # ][ # # ]: 0 : DEFINE_XTYPEPROVIDER_5(ServiceHandler ,
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
56 : : css::lang::XTypeProvider ,
57 : : css::lang::XServiceInfo ,
58 : : css::frame::XDispatchProvider ,
59 : : css::frame::XNotifyingDispatch,
60 : : css::frame::XDispatch )
61 : :
62 [ + - ][ + - ]: 39 : DEFINE_XSERVICEINFO_MULTISERVICE(ServiceHandler ,
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ # # ][ # # ]
63 : : ::cppu::OWeakObject ,
64 : : SERVICENAME_PROTOCOLHANDLER ,
65 : : IMPLEMENTATIONNAME_SERVICEHANDLER)
66 : :
67 : 2 : DEFINE_INIT_SERVICE(ServiceHandler,
68 : : {
69 : : /*Attention
70 : : I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
71 : : to create a new instance of this class by our own supported service factory.
72 : : see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
73 : : */
74 : : }
75 : : )
76 : :
77 : : //_________________________________________________________________________________________________________________
78 : :
79 : : /**
80 : : @short standard ctor
81 : : @descr These initialize a new instance of ths class with needed informations for work.
82 : :
83 : : @param xFactory
84 : : reference to uno servicemanager for creation of new services
85 : : */
86 : 2 : ServiceHandler::ServiceHandler( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
87 : : // Init baseclasses first
88 [ + - ]: 2 : : ThreadHelpBase( &Application::GetSolarMutex() )
89 : : , OWeakObject ( )
90 : : // Init member
91 [ + - ]: 4 : , m_xFactory ( xFactory )
92 : : {
93 : 2 : }
94 : :
95 : : //_________________________________________________________________________________________________________________
96 : :
97 : : /**
98 : : @short standard dtor
99 : : @descr -
100 : : */
101 [ + - ][ + - ]: 2 : ServiceHandler::~ServiceHandler()
102 : : {
103 [ + - ]: 2 : m_xFactory = NULL;
104 [ - + ]: 4 : }
105 : :
106 : : //_________________________________________________________________________________________________________________
107 : :
108 : : /**
109 : : @short decide if this dispatch implementation can be used for requested URL or not
110 : : @descr A protocol handler is registerd for an URL pattern inside configuration and will
111 : : be asked by the generic dispatch mechanism inside framework, if he can handle this
112 : : special URL wich match his registration. He can agree by returning of a valid dispatch
113 : : instance or disagree by returning <NULL/>.
114 : : We don't create new dispatch instances here realy - we return THIS as result to handle it
115 : : at the same implementation.
116 : : */
117 : 6 : css::uno::Reference< css::frame::XDispatch > SAL_CALL ServiceHandler::queryDispatch( const css::util::URL& aURL ,
118 : : const ::rtl::OUString& /*sTarget*/ ,
119 : : sal_Int32 /*nFlags*/ ) throw( css::uno::RuntimeException )
120 : : {
121 : 6 : css::uno::Reference< css::frame::XDispatch > xDispatcher;
122 [ + - ]: 6 : if (aURL.Complete.compareToAscii(PROTOCOL_VALUE,PROTOCOL_LENGTH)==0)
123 [ + - ]: 6 : xDispatcher = this;
124 : 6 : return xDispatcher;
125 : : }
126 : :
127 : : //_________________________________________________________________________________________________________________
128 : :
129 : : /**
130 : : @short do the same like dispatch() but for multiple requests at the same time
131 : : @descr -
132 : : */
133 : 2 : css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > SAL_CALL ServiceHandler::queryDispatches( const css::uno::Sequence< css::frame::DispatchDescriptor >& lDescriptor ) throw( css::uno::RuntimeException )
134 : : {
135 : 2 : sal_Int32 nCount = lDescriptor.getLength();
136 : 2 : css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
137 [ + + ]: 6 : for( sal_Int32 i=0; i<nCount; ++i )
138 : : {
139 [ + - ]: 4 : lDispatcher[i] = this->queryDispatch(
140 : 4 : lDescriptor[i].FeatureURL,
141 : 4 : lDescriptor[i].FrameName,
142 [ + - ][ + - ]: 12 : lDescriptor[i].SearchFlags);
143 : : }
144 : 2 : return lDispatcher;
145 : : }
146 : :
147 : : //_________________________________________________________________________________________________________________
148 : :
149 : : /**
150 : : @short dispatch URL with arguments
151 : : @descr We use threadsafe internal method to do so. It returns a state value - but we ignore it.
152 : : Because we doesn't support status listener notifications here.
153 : :
154 : : @param aURL
155 : : uno URL which should be executed
156 : : @param lArguments
157 : : list of optional arguments for this request
158 : : */
159 : 0 : void SAL_CALL ServiceHandler::dispatch( const css::util::URL& aURL ,
160 : : const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) throw( css::uno::RuntimeException )
161 : : {
162 : : // dispatch() is an [oneway] call ... and may our user release his reference to us immediatly.
163 : : // So we should hold us self alive till this call ends.
164 [ # # ]: 0 : css::uno::Reference< css::frame::XNotifyingDispatch > xSelfHold(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
165 [ # # ]: 0 : implts_dispatch(aURL,lArguments);
166 : : // No notification for status listener!
167 : 0 : }
168 : :
169 : : //_________________________________________________________________________________________________________________
170 : :
171 : : /**
172 : : @short dispatch with guaranteed notifications about success
173 : : @descr We use threadsafe internal method to do so. Return state of this function will be used
174 : : for notification if an optional listener is given.
175 : :
176 : : @param aURL
177 : : uno URL which should be executed
178 : : @param lArguments
179 : : list of optional arguments for this request
180 : : @param xListener
181 : : optional listener for state events
182 : : */
183 : 0 : void SAL_CALL ServiceHandler::dispatchWithNotification( const css::util::URL& aURL ,
184 : : const css::uno::Sequence< css::beans::PropertyValue >& lArguments,
185 : : const css::uno::Reference< css::frame::XDispatchResultListener >& xListener ) throw( css::uno::RuntimeException )
186 : : {
187 : : // This class was designed to die by reference. And if user release his reference to us immediatly after calling this method
188 : : // we can run into some problems. So we hold us self alive till this method ends.
189 : : // Another reason: We can use this reference as source of sending event at the end too.
190 [ # # ]: 0 : css::uno::Reference< css::frame::XNotifyingDispatch > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
191 : :
192 [ # # ]: 0 : css::uno::Reference< css::uno::XInterface > xService = implts_dispatch(aURL,lArguments);
193 [ # # ]: 0 : if (xListener.is())
194 : : {
195 [ # # ]: 0 : css::frame::DispatchResultEvent aEvent;
196 [ # # ]: 0 : if (xService.is())
197 : 0 : aEvent.State = css::frame::DispatchResultState::SUCCESS;
198 : : else
199 : 0 : aEvent.State = css::frame::DispatchResultState::FAILURE;
200 [ # # ]: 0 : aEvent.Result <<= xService; // may NULL for state=FAILED!
201 [ # # ]: 0 : aEvent.Source = xThis;
202 : :
203 [ # # ][ # # ]: 0 : xListener->dispatchFinished( aEvent );
[ # # ]
204 : 0 : }
205 : 0 : }
206 : :
207 : : //_________________________________________________________________________________________________________________
208 : :
209 : : /**
210 : : @short threadsafe helper for dispatch calls
211 : : @descr We support two interfaces for the same process - dispatch URLs. That the reason for this internal
212 : : function. It implements the real dispatch operation and returns a state value which inform caller
213 : : about success. He can notify listener then by using this return value.
214 : :
215 : : @param aURL
216 : : uno URL which should be executed
217 : : @param lArguments
218 : : list of optional arguments for this request
219 : :
220 : : @return <NULL/> if requested service couldn't be created successullfy;
221 : : a valid reference otherwise. This return value can be used to indicate,
222 : : if dispatch was successfully or not.
223 : : */
224 : 0 : css::uno::Reference< css::uno::XInterface > ServiceHandler::implts_dispatch( const css::util::URL& aURL ,
225 : : const css::uno::Sequence< css::beans::PropertyValue >& /*lArguments*/ ) throw( css::uno::RuntimeException )
226 : : {
227 : : /* SAFE */
228 [ # # ]: 0 : ReadGuard aReadLock( m_aLock );
229 : 0 : css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory;
230 [ # # ]: 0 : aReadLock.unlock();
231 : : /* SAFE */
232 : :
233 [ # # ]: 0 : if (!xFactory.is())
234 : 0 : return css::uno::Reference< css::uno::XInterface >();
235 : :
236 : : // extract service name and may optional given parameters from given URL
237 : : // and use it to create and start the component
238 : 0 : ::rtl::OUString sServiceAndArguments = aURL.Complete.copy(PROTOCOL_LENGTH);
239 : 0 : ::rtl::OUString sServiceName;
240 : 0 : ::rtl::OUString sArguments ;
241 : :
242 : 0 : sal_Int32 nArgStart = sServiceAndArguments.indexOf('?',0);
243 [ # # ]: 0 : if (nArgStart!=-1)
244 : : {
245 : 0 : sServiceName = sServiceAndArguments.copy(0,nArgStart);
246 : 0 : ++nArgStart; // ignore '?'!
247 : 0 : sArguments = sServiceAndArguments.copy(nArgStart);
248 : : }
249 : : else
250 : : {
251 : 0 : sServiceName = sServiceAndArguments;
252 : : }
253 : :
254 [ # # ]: 0 : if (sServiceName.isEmpty())
255 : 0 : return css::uno::Reference< css::uno::XInterface >();
256 : :
257 : : // If a service doesnt support an optional job executor interface - he can't get
258 : : // any given parameters!
259 : : // Because we can't know if we must call createInstanceWithArguments() or XJobExecutor::trigger() ...
260 : :
261 : 0 : css::uno::Reference< css::uno::XInterface > xService;
262 : : try
263 : : {
264 : : // => a) a service starts running inside his own ctor and we create it only
265 [ # # ][ # # ]: 0 : xService = xFactory->createInstance(sServiceName);
[ # # ]
266 : : // or b) he implements the right interface and starts there (may with optional parameters)
267 [ # # ]: 0 : css::uno::Reference< css::task::XJobExecutor > xExecuteable(xService, css::uno::UNO_QUERY);
268 [ # # ]: 0 : if (xExecuteable.is())
269 [ # # ][ # # ]: 0 : xExecuteable->trigger(sArguments);
[ # # ]
270 : : }
271 : : // ignore all errors - inclusive runtime errors!
272 : : // E.g. a script based service (written in phyton) could not be executed
273 : : // because it contains syntax errors, which was detected at runtime ...
274 [ # # ]: 0 : catch(const css::uno::Exception&)
275 : 0 : { xService.clear(); }
276 : :
277 [ # # ]: 0 : return xService;
278 : : }
279 : :
280 : : //_________________________________________________________________________________________________________________
281 : :
282 : : /**
283 : : @short add/remove listener for state events
284 : : @descr We use an internal container to hold such registered listener. This container lives if we live.
285 : : And if call pas registration as non breakable transaction - we can accept the request without
286 : : any explicit lock. Because we share our mutex with this container.
287 : :
288 : : @param xListener
289 : : reference to a valid listener for state events
290 : : @param aURL
291 : : URL about listener will be informed, if something occurred
292 : : */
293 : 0 : void SAL_CALL ServiceHandler::addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/ ,
294 : : const css::util::URL& /*aURL*/ ) throw( css::uno::RuntimeException )
295 : : {
296 : : // not suported yet
297 : 0 : }
298 : :
299 : : //_________________________________________________________________________________________________________________
300 : :
301 : 0 : void SAL_CALL ServiceHandler::removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/ ,
302 : : const css::util::URL& /*aURL*/ ) throw( css::uno::RuntimeException )
303 : : {
304 : : // not suported yet
305 : 0 : }
306 : :
307 : : } // namespace framework
308 : :
309 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|