1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_framework.hxx"
26
27 //_________________________________________________________________________________________________________________
28 // my own includes
29 //_________________________________________________________________________________________________________________
30 #include <dispatch/servicehandler.hxx>
31 #include <threadhelp/readguard.hxx>
32 #include <general.h>
33 #include <services.h>
34
35 //_________________________________________________________________________________________________________________
36 // interface includes
37 //_________________________________________________________________________________________________________________
38 #include <com/sun/star/frame/DispatchResultState.hpp>
39 #include <com/sun/star/task/XJobExecutor.hpp>
40
41 //_________________________________________________________________________________________________________________
42 // includes of other projects
43 //_________________________________________________________________________________________________________________
44
45 #include <vcl/svapp.hxx>
46
47 //_________________________________________________________________________________________________________________
48 // namespace
49 //_________________________________________________________________________________________________________________
50
51 namespace framework{
52
53 //_________________________________________________________________________________________________________________
54 // non exported const
55 //_________________________________________________________________________________________________________________
56
57 #define PROTOCOL_VALUE "service:"
58 #define PROTOCOL_LENGTH 8
59
60 //_________________________________________________________________________________________________________________
61 // non exported definitions
62 //_________________________________________________________________________________________________________________
63
64 //_________________________________________________________________________________________________________________
65 // declarations
66 //_________________________________________________________________________________________________________________
67
68 //_________________________________________________________________________________________________________________
69 // XInterface, XTypeProvider, XServiceInfo
70
DEFINE_XINTERFACE_5(ServiceHandler,OWeakObject,DIRECT_INTERFACE (css::lang::XTypeProvider),DIRECT_INTERFACE (css::lang::XServiceInfo),DIRECT_INTERFACE (css::frame::XDispatchProvider),DIRECT_INTERFACE (css::frame::XNotifyingDispatch),DIRECT_INTERFACE (css::frame::XDispatch))71 DEFINE_XINTERFACE_5(ServiceHandler ,
72 OWeakObject ,
73 DIRECT_INTERFACE(css::lang::XTypeProvider ),
74 DIRECT_INTERFACE(css::lang::XServiceInfo ),
75 DIRECT_INTERFACE(css::frame::XDispatchProvider ),
76 DIRECT_INTERFACE(css::frame::XNotifyingDispatch),
77 DIRECT_INTERFACE(css::frame::XDispatch ))
78
79 DEFINE_XTYPEPROVIDER_5(ServiceHandler ,
80 css::lang::XTypeProvider ,
81 css::lang::XServiceInfo ,
82 css::frame::XDispatchProvider ,
83 css::frame::XNotifyingDispatch,
84 css::frame::XDispatch )
85
86 DEFINE_XSERVICEINFO_MULTISERVICE(ServiceHandler ,
87 ::cppu::OWeakObject ,
88 SERVICENAME_PROTOCOLHANDLER ,
89 IMPLEMENTATIONNAME_SERVICEHANDLER)
90
91 DEFINE_INIT_SERVICE(ServiceHandler,
92 {
93 /*Attention
94 I think we don't need any mutex or lock here ... because we are called by our own static method impl_createInstance()
95 to create a new instance of this class by our own supported service factory.
96 see macro DEFINE_XSERVICEINFO_MULTISERVICE and "impl_initService()" for further informations!
97 */
98 }
99 )
100
101 //_________________________________________________________________________________________________________________
102
103 /**
104 @short standard ctor
105 @descr These initialize a new instance of this class with needed informations for work.
106
107 @param xFactory
108 reference to uno servicemanager for creation of new services
109
110 @modified 02.05.2002 08:16, as96863
111 */
112 ServiceHandler::ServiceHandler( const css::uno::Reference< css::lang::XMultiServiceFactory >& xFactory )
113 // Init baseclasses first
114 : ThreadHelpBase( &Application::GetSolarMutex() )
115 , OWeakObject ( )
116 // Init member
117 , m_xFactory ( xFactory )
118 {
119 }
120
121 //_________________________________________________________________________________________________________________
122
123 /**
124 @short standard dtor
125 @descr -
126
127 @modified 02.05.2002 08:16, as96863
128 */
~ServiceHandler()129 ServiceHandler::~ServiceHandler()
130 {
131 m_xFactory = NULL;
132 }
133
134 //_________________________________________________________________________________________________________________
135
136 /**
137 @short decide if this dispatch implementation can be used for requested URL or not
138 @descr A protocol handler is registerd for an URL pattern inside configuration and will
139 be asked by the generic dispatch mechanism inside framework, if he can handle this
140 special URL which match his registration. He can agree by returning of a valid dispatch
141 instance or disagree by returning <NULL/>.
142 We don't create new dispatch instances here really - we return THIS as result to handle it
143 at the same implementation.
144
145 @modified 02.05.2002 15:25, as96863
146 */
queryDispatch(const css::util::URL & aURL,const::rtl::OUString &,sal_Int32)147 css::uno::Reference< css::frame::XDispatch > SAL_CALL ServiceHandler::queryDispatch( const css::util::URL& aURL ,
148 const ::rtl::OUString& /*sTarget*/ ,
149 sal_Int32 /*nFlags*/ ) throw( css::uno::RuntimeException )
150 {
151 css::uno::Reference< css::frame::XDispatch > xDispatcher;
152 if (aURL.Complete.compareToAscii(PROTOCOL_VALUE,PROTOCOL_LENGTH)==0)
153 xDispatcher = this;
154 return xDispatcher;
155 }
156
157 //_________________________________________________________________________________________________________________
158
159 /**
160 @short do the same like dispatch() but for multiple requests at the same time
161 @descr -
162
163 @modified 02.05.2002 15:27, as96863
164 */
queryDispatches(const css::uno::Sequence<css::frame::DispatchDescriptor> & lDescriptor)165 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 )
166 {
167 sal_Int32 nCount = lDescriptor.getLength();
168 css::uno::Sequence< css::uno::Reference< css::frame::XDispatch > > lDispatcher( nCount );
169 for( sal_Int32 i=0; i<nCount; ++i )
170 {
171 lDispatcher[i] = this->queryDispatch(
172 lDescriptor[i].FeatureURL,
173 lDescriptor[i].FrameName,
174 lDescriptor[i].SearchFlags);
175 }
176 return lDispatcher;
177 }
178
179 //_________________________________________________________________________________________________________________
180
181 /**
182 @short dispatch URL with arguments
183 @descr We use threadsafe internal method to do so. It returns a state value - but we ignore it.
184 Because we doesn't support status listener notifications here.
185
186 @param aURL
187 uno URL which should be executed
188 @param lArguments
189 list of optional arguments for this request
190
191 @modified 02.05.2002 08:19, as96863
192 */
dispatch(const css::util::URL & aURL,const css::uno::Sequence<css::beans::PropertyValue> & lArguments)193 void SAL_CALL ServiceHandler::dispatch( const css::util::URL& aURL ,
194 const css::uno::Sequence< css::beans::PropertyValue >& lArguments ) throw( css::uno::RuntimeException )
195 {
196 // dispatch() is an [oneway] call ... and may our user release his reference to us immediately.
197 // So we should hold us self alive till this call ends.
198 css::uno::Reference< css::frame::XNotifyingDispatch > xSelfHold(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
199 implts_dispatch(aURL,lArguments);
200 // No notification for status listener!
201 }
202
203 //_________________________________________________________________________________________________________________
204
205 /**
206 @short dispatch with guaranteed notifications about success
207 @descr We use threadsafe internal method to do so. Return state of this function will be used
208 for notification if an optional listener is given.
209
210 @param aURL
211 uno URL which should be executed
212 @param lArguments
213 list of optional arguments for this request
214 @param xListener
215 optional listener for state events
216
217 @modified 30.04.2002 14:49, as96863
218 */
dispatchWithNotification(const css::util::URL & aURL,const css::uno::Sequence<css::beans::PropertyValue> & lArguments,const css::uno::Reference<css::frame::XDispatchResultListener> & xListener)219 void SAL_CALL ServiceHandler::dispatchWithNotification( const css::util::URL& aURL ,
220 const css::uno::Sequence< css::beans::PropertyValue >& lArguments,
221 const css::uno::Reference< css::frame::XDispatchResultListener >& xListener ) throw( css::uno::RuntimeException )
222 {
223 // This class was designed to die by reference. And if user release his reference to us immediately after calling this method
224 // we can run into some problems. So we hold us self alive till this method ends.
225 // Another reason: We can use this reference as source of sending event at the end too.
226 css::uno::Reference< css::frame::XNotifyingDispatch > xThis(static_cast< ::cppu::OWeakObject* >(this), css::uno::UNO_QUERY);
227
228 css::uno::Reference< css::uno::XInterface > xService = implts_dispatch(aURL,lArguments);
229 if (xListener.is())
230 {
231 css::frame::DispatchResultEvent aEvent;
232 if (xService.is())
233 aEvent.State = css::frame::DispatchResultState::SUCCESS;
234 else
235 aEvent.State = css::frame::DispatchResultState::FAILURE;
236 aEvent.Result <<= xService; // may NULL for state=FAILED!
237 aEvent.Source = xThis;
238
239 xListener->dispatchFinished( aEvent );
240 }
241 }
242
243 //_________________________________________________________________________________________________________________
244
245 /**
246 @short threadsafe helper for dispatch calls
247 @descr We support two interfaces for the same process - dispatch URLs. That the reason for this internal
248 function. It implements the real dispatch operation and returns a state value which inform caller
249 about success. He can notify listener then by using this return value.
250
251 @param aURL
252 uno URL which should be executed
253 @param lArguments
254 list of optional arguments for this request
255
256 @return <NULL/> if requested service couldn't be created successullfy;
257 a valid reference otherwise. This return value can be used to indicate,
258 if dispatch was successfully or not.
259
260 @modified 02.05.2002 10:51, as96863
261 */
implts_dispatch(const css::util::URL & aURL,const css::uno::Sequence<css::beans::PropertyValue> &)262 css::uno::Reference< css::uno::XInterface > ServiceHandler::implts_dispatch( const css::util::URL& aURL ,
263 const css::uno::Sequence< css::beans::PropertyValue >& /*lArguments*/ ) throw( css::uno::RuntimeException )
264 {
265 /* SAFE */
266 ReadGuard aReadLock( m_aLock );
267 css::uno::Reference< css::lang::XMultiServiceFactory > xFactory = m_xFactory;
268 aReadLock.unlock();
269 /* SAFE */
270
271 if (!xFactory.is())
272 return css::uno::Reference< css::uno::XInterface >();
273
274 // extract service name and may optional given parameters from given URL
275 // and use it to create and start the component
276 ::rtl::OUString sServiceAndArguments = aURL.Complete.copy(PROTOCOL_LENGTH);
277 ::rtl::OUString sServiceName;
278 ::rtl::OUString sArguments ;
279
280 sal_Int32 nArgStart = sServiceAndArguments.indexOf('?',0);
281 if (nArgStart!=-1)
282 {
283 sServiceName = sServiceAndArguments.copy(0,nArgStart);
284 ++nArgStart; // ignore '?'!
285 sArguments = sServiceAndArguments.copy(nArgStart);
286 }
287 else
288 {
289 sServiceName = sServiceAndArguments;
290 }
291
292 if (!sServiceName.getLength())
293 return css::uno::Reference< css::uno::XInterface >();
294
295 // If a service doesn't support an optional job executor interface - he can't get
296 // any given parameters!
297 // Because we can't know if we must call createInstanceWithArguments() or XJobExecutor::trigger() ...
298
299 css::uno::Reference< css::uno::XInterface > xService;
300 try
301 {
302 // => a) a service starts running inside his own ctor and we create it only
303 xService = xFactory->createInstance(sServiceName);
304 // or b) he implements the right interface and starts there (may with optional parameters)
305 css::uno::Reference< css::task::XJobExecutor > xExecuteable(xService, css::uno::UNO_QUERY);
306 if (xExecuteable.is())
307 xExecuteable->trigger(sArguments);
308 }
309 // ignore all errors - inclusive runtime errors!
310 // E.g. a script based service (written in phyton) could not be executed
311 // because it contains syntax errors, which was detected at runtime ...
312 catch(const css::uno::Exception&)
313 { xService.clear(); }
314
315 return xService;
316 }
317
318 //_________________________________________________________________________________________________________________
319
320 /**
321 @short add/remove listener for state events
322 @descr We use an internal container to hold such registered listener. This container lives if we live.
323 And if call pas registration as non breakable transaction - we can accept the request without
324 any explicit lock. Because we share our mutex with this container.
325
326 @param xListener
327 reference to a valid listener for state events
328 @param aURL
329 URL about listener will be informed, if something occurred
330
331 @modified 30.04.2002 14:49, as96863
332 */
addStatusListener(const css::uno::Reference<css::frame::XStatusListener> &,const css::util::URL &)333 void SAL_CALL ServiceHandler::addStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/ ,
334 const css::util::URL& /*aURL*/ ) throw( css::uno::RuntimeException )
335 {
336 // not suported yet
337 }
338
339 //_________________________________________________________________________________________________________________
340
removeStatusListener(const css::uno::Reference<css::frame::XStatusListener> &,const css::util::URL &)341 void SAL_CALL ServiceHandler::removeStatusListener( const css::uno::Reference< css::frame::XStatusListener >& /*xListener*/ ,
342 const css::util::URL& /*aURL*/ ) throw( css::uno::RuntimeException )
343 {
344 // not suported yet
345 }
346
347 } // namespace framework
348