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 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 */ 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 wich 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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