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