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_dbaccess.hxx" 26 27 #include "intercept.hxx" 28 #include "dbastrings.hrc" 29 30 #include <com/sun/star/embed/EmbedStates.hpp> 31 #include <com/sun/star/document/XEventBroadcaster.hpp> 32 #include <com/sun/star/util/XModifiable.hpp> 33 #include <cppuhelper/weak.hxx> 34 35 #include <comphelper/types.hxx> 36 #include <tools/debug.hxx> 37 #include <tools/diagnose_ex.h> 38 39 40 namespace dbaccess 41 { 42 using namespace ::com::sun::star::uno; 43 using namespace ::com::sun::star::util; 44 using namespace ::com::sun::star::ucb; 45 using namespace ::com::sun::star::beans; 46 using namespace ::com::sun::star::lang; 47 using namespace ::com::sun::star::sdbc; 48 using namespace ::com::sun::star::frame; 49 using namespace ::com::sun::star::io; 50 using namespace ::com::sun::star::embed; 51 using namespace ::com::sun::star::container; 52 using namespace ::comphelper; 53 using namespace ::cppu; 54 55 #define DISPATCH_SAVEAS 0 56 #define DISPATCH_SAVE 1 57 #define DISPATCH_CLOSEDOC 2 58 #define DISPATCH_CLOSEWIN 3 59 #define DISPATCH_CLOSEFRAME 4 60 #define DISPATCH_RELOAD 5 61 // the OSL_ENSURE in CTOR has to be changed too, when adding new defines 62 63 void SAL_CALL OInterceptor::dispose() 64 throw( RuntimeException ) 65 { 66 EventObject aEvt( *this ); 67 68 osl::MutexGuard aGuard(m_aMutex); 69 70 if ( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() ) 71 m_pDisposeEventListeners->disposeAndClear( aEvt ); 72 73 if ( m_pStatCL ) 74 m_pStatCL->disposeAndClear( aEvt ); 75 76 m_xSlaveDispatchProvider.clear(); 77 m_xMasterDispatchProvider.clear(); 78 79 m_pContentHolder = NULL; 80 } 81 82 83 DBG_NAME(OInterceptor) 84 85 OInterceptor::OInterceptor( ODocumentDefinition* _pContentHolder,sal_Bool _bAllowEditDoc ) 86 :m_pContentHolder( _pContentHolder ) 87 ,m_aInterceptedURL(7) 88 ,m_pDisposeEventListeners(0) 89 ,m_pStatCL(0) 90 ,m_bAllowEditDoc(_bAllowEditDoc) 91 { 92 DBG_CTOR(OInterceptor,NULL); 93 94 OSL_ENSURE(DISPATCH_RELOAD < m_aInterceptedURL.getLength(),"Illegal size."); 95 96 m_aInterceptedURL[DISPATCH_SAVEAS] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:SaveAs")); 97 m_aInterceptedURL[DISPATCH_SAVE] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:Save")); 98 m_aInterceptedURL[DISPATCH_CLOSEDOC] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:CloseDoc")); 99 m_aInterceptedURL[DISPATCH_CLOSEWIN] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:CloseWin")); 100 m_aInterceptedURL[DISPATCH_CLOSEFRAME] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:CloseFrame")); 101 m_aInterceptedURL[DISPATCH_RELOAD] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(".uno:Reload")); 102 } 103 104 105 OInterceptor::~OInterceptor() 106 { 107 if( m_pDisposeEventListeners ) 108 delete m_pDisposeEventListeners; 109 110 if(m_pStatCL) 111 delete m_pStatCL; 112 113 DBG_DTOR(OInterceptor,NULL); 114 } 115 116 struct DispatchHelper 117 { 118 URL aURL; 119 Sequence<PropertyValue > aArguments; 120 }; 121 122 //XDispatch 123 void SAL_CALL OInterceptor::dispatch( const URL& _URL,const Sequence<PropertyValue >& Arguments ) throw (RuntimeException) 124 { 125 ::osl::MutexGuard aGuard( m_aMutex ); 126 if ( !m_pContentHolder ) 127 return; 128 129 if ( _URL.Complete == m_aInterceptedURL[ DISPATCH_SAVE ] ) 130 { 131 m_pContentHolder->save( sal_False ); 132 return; 133 } 134 135 if ( _URL.Complete == m_aInterceptedURL[ DISPATCH_RELOAD ] ) 136 { 137 ODocumentDefinition::fillReportData( 138 m_pContentHolder->getContext(), 139 m_pContentHolder->getComponent(), 140 m_pContentHolder->getConnection() 141 ); 142 return; 143 } 144 145 if( _URL.Complete == m_aInterceptedURL[ DISPATCH_SAVEAS ] ) 146 { 147 if ( m_pContentHolder->isNewReport() ) 148 { 149 m_pContentHolder->saveAs(); 150 } 151 else if ( m_xSlaveDispatchProvider.is() ) 152 { 153 Sequence< PropertyValue > aNewArgs = Arguments; 154 sal_Int32 nInd = 0; 155 156 while( nInd < aNewArgs.getLength() ) 157 { 158 if ( aNewArgs[nInd].Name.equalsAscii( "SaveTo" ) ) 159 { 160 aNewArgs[nInd].Value <<= sal_True; 161 break; 162 } 163 nInd++; 164 } 165 166 if ( nInd == aNewArgs.getLength() ) 167 { 168 aNewArgs.realloc( nInd + 1 ); 169 aNewArgs[nInd].Name = ::rtl::OUString::createFromAscii( "SaveTo" ); 170 aNewArgs[nInd].Value <<= sal_True; 171 } 172 173 Reference< XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch( 174 _URL, ::rtl::OUString::createFromAscii( "_self" ), 0 ); 175 if ( xDispatch.is() ) 176 xDispatch->dispatch( _URL, aNewArgs ); 177 } 178 return; 179 } 180 181 if ( _URL.Complete == m_aInterceptedURL[ DISPATCH_CLOSEDOC ] 182 || _URL.Complete == m_aInterceptedURL[ DISPATCH_CLOSEWIN ] 183 || _URL.Complete == m_aInterceptedURL[ DISPATCH_CLOSEFRAME ] 184 ) 185 { 186 DispatchHelper* pHelper = new DispatchHelper; 187 pHelper->aArguments = Arguments; 188 pHelper->aURL = _URL; 189 Application::PostUserEvent( LINK( this, OInterceptor, OnDispatch ), reinterpret_cast< void* >( pHelper ) ); 190 return; 191 } 192 } 193 194 IMPL_LINK( OInterceptor, OnDispatch, void*, _pDispatcher ) 195 { 196 ::std::auto_ptr<DispatchHelper> pHelper( reinterpret_cast< DispatchHelper* >( _pDispatcher ) ); 197 try 198 { 199 if ( m_pContentHolder && m_pContentHolder->prepareClose() && m_xSlaveDispatchProvider.is() ) 200 { 201 Reference< XDispatch > xDispatch = m_xSlaveDispatchProvider->queryDispatch( 202 pHelper->aURL, ::rtl::OUString::createFromAscii( "_self" ), 0 ); 203 if ( xDispatch.is() ) 204 { 205 Reference< ::com::sun::star::document::XEventBroadcaster> xEvtB(m_pContentHolder->getComponent(),UNO_QUERY); 206 if ( xEvtB.is() ) 207 xEvtB->removeEventListener(this); 208 209 Reference< XInterface > xKeepContentHolderAlive( *m_pContentHolder ); 210 xDispatch->dispatch( pHelper->aURL,pHelper->aArguments); 211 } 212 } 213 } 214 catch ( const Exception& ) 215 { 216 DBG_UNHANDLED_EXCEPTION(); 217 } 218 219 return 0L; 220 } 221 222 void SAL_CALL OInterceptor::addStatusListener( 223 const Reference< 224 XStatusListener >& Control, 225 const URL& _URL ) 226 throw ( 227 RuntimeException 228 ) 229 { 230 if(!Control.is()) 231 return; 232 233 if ( m_pContentHolder && _URL.Complete == m_aInterceptedURL[DISPATCH_SAVEAS] ) 234 { // SaveAs 235 236 if ( !m_pContentHolder->isNewReport() ) 237 { 238 FeatureStateEvent aStateEvent; 239 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[DISPATCH_SAVEAS]; 240 aStateEvent.FeatureDescriptor = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SaveCopyTo")); 241 aStateEvent.IsEnabled = sal_True; 242 aStateEvent.Requery = sal_False; 243 aStateEvent.State <<= (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("($3)"))); 244 Control->statusChanged(aStateEvent); 245 } 246 247 { 248 osl::MutexGuard aGuard(m_aMutex); 249 if(!m_pStatCL) 250 m_pStatCL = new PropertyChangeListenerContainer(m_aMutex); 251 } 252 253 m_pStatCL->addInterface(_URL.Complete,Control); 254 } 255 else if ( m_pContentHolder && _URL.Complete == m_aInterceptedURL[DISPATCH_SAVE] ) 256 { // Save 257 FeatureStateEvent aStateEvent; 258 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[DISPATCH_SAVE]; 259 aStateEvent.FeatureDescriptor = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Update")); 260 aStateEvent.IsEnabled = m_pContentHolder != NULL && m_pContentHolder->isModified(); 261 aStateEvent.Requery = sal_False; 262 263 Control->statusChanged(aStateEvent); 264 { 265 osl::MutexGuard aGuard(m_aMutex); 266 if(!m_pStatCL) 267 m_pStatCL = new PropertyChangeListenerContainer(m_aMutex); 268 } 269 270 m_pStatCL->addInterface(_URL.Complete,Control); 271 Reference< ::com::sun::star::document::XEventBroadcaster> xEvtB(m_pContentHolder->getComponent(),UNO_QUERY); 272 if ( xEvtB.is() ) 273 xEvtB->addEventListener(this); 274 } 275 else 276 { 277 sal_Int32 i = 2; 278 if(_URL.Complete == m_aInterceptedURL[i] || 279 _URL.Complete == m_aInterceptedURL[++i] || 280 _URL.Complete == m_aInterceptedURL[++i] || 281 _URL.Complete == m_aInterceptedURL[i = DISPATCH_RELOAD] ) 282 { // Close and return 283 FeatureStateEvent aStateEvent; 284 aStateEvent.FeatureURL.Complete = m_aInterceptedURL[i]; 285 aStateEvent.FeatureDescriptor = rtl::OUString( 286 RTL_CONSTASCII_USTRINGPARAM("Close and Return")); 287 aStateEvent.IsEnabled = sal_True; 288 aStateEvent.Requery = sal_False; 289 Control->statusChanged(aStateEvent); 290 291 292 { 293 osl::MutexGuard aGuard(m_aMutex); 294 if(!m_pStatCL) 295 m_pStatCL = new PropertyChangeListenerContainer(m_aMutex); 296 } 297 298 m_pStatCL->addInterface(_URL.Complete,Control); 299 return; 300 } 301 } 302 } 303 304 305 void SAL_CALL OInterceptor::removeStatusListener( 306 const Reference< 307 XStatusListener >& Control, 308 const URL& _URL ) 309 throw ( 310 RuntimeException 311 ) 312 { 313 if(!(Control.is() && m_pStatCL)) 314 return; 315 else 316 { 317 m_pStatCL->removeInterface(_URL.Complete,Control); 318 return; 319 } 320 } 321 322 323 //XInterceptorInfo 324 Sequence< ::rtl::OUString > SAL_CALL OInterceptor::getInterceptedURLs( ) throw ( RuntimeException ) 325 { 326 // now implemented as update 327 return m_aInterceptedURL; 328 } 329 330 331 // XDispatchProvider 332 333 Reference< XDispatch > SAL_CALL OInterceptor::queryDispatch( const URL& _URL,const ::rtl::OUString& TargetFrameName,sal_Int32 SearchFlags ) 334 throw (RuntimeException) 335 { 336 osl::MutexGuard aGuard(m_aMutex); 337 const ::rtl::OUString* pIter = m_aInterceptedURL.getConstArray(); 338 const ::rtl::OUString* pEnd = pIter + m_aInterceptedURL.getLength(); 339 for(;pIter != pEnd;++pIter) 340 { 341 if ( _URL.Complete == *pIter ) 342 return (XDispatch*)this; 343 } 344 345 if(m_xSlaveDispatchProvider.is()) 346 return m_xSlaveDispatchProvider->queryDispatch(_URL,TargetFrameName,SearchFlags); 347 else 348 return Reference<XDispatch>(); 349 } 350 351 Sequence< Reference< XDispatch > > SAL_CALL OInterceptor::queryDispatches( const Sequence<DispatchDescriptor >& Requests ) throw ( RuntimeException ) 352 { 353 Sequence< Reference< XDispatch > > aRet; 354 osl::MutexGuard aGuard(m_aMutex); 355 if(m_xSlaveDispatchProvider.is()) 356 aRet = m_xSlaveDispatchProvider->queryDispatches(Requests); 357 else 358 aRet.realloc(Requests.getLength()); 359 360 for(sal_Int32 i = 0; i < Requests.getLength(); ++i) 361 { 362 const ::rtl::OUString* pIter = m_aInterceptedURL.getConstArray(); 363 const ::rtl::OUString* pEnd = pIter + m_aInterceptedURL.getLength(); 364 for(;pIter != pEnd;++pIter) 365 { 366 if ( Requests[i].FeatureURL.Complete == *pIter ) 367 { 368 aRet[i] = (XDispatch*) this; 369 break; 370 } 371 } 372 } 373 374 return aRet; 375 } 376 377 378 379 //XDispatchProviderInterceptor 380 381 Reference< XDispatchProvider > SAL_CALL OInterceptor::getSlaveDispatchProvider( ) throw ( RuntimeException ) 382 { 383 osl::MutexGuard aGuard(m_aMutex); 384 return m_xSlaveDispatchProvider; 385 } 386 387 void SAL_CALL 388 OInterceptor::setSlaveDispatchProvider( const Reference< XDispatchProvider >& NewDispatchProvider ) 389 throw ( RuntimeException ) 390 { 391 osl::MutexGuard aGuard(m_aMutex); 392 m_xSlaveDispatchProvider = NewDispatchProvider; 393 } 394 395 396 Reference< XDispatchProvider > SAL_CALL OInterceptor::getMasterDispatchProvider( ) 397 throw ( 398 RuntimeException 399 ) 400 { 401 osl::MutexGuard aGuard(m_aMutex); 402 return m_xMasterDispatchProvider; 403 } 404 405 406 void SAL_CALL OInterceptor::setMasterDispatchProvider( 407 const Reference< XDispatchProvider >& NewSupplier ) 408 throw ( 409 RuntimeException 410 ) 411 { 412 osl::MutexGuard aGuard(m_aMutex); 413 m_xMasterDispatchProvider = NewSupplier; 414 } 415 // ----------------------------------------------------------------------------- 416 void SAL_CALL OInterceptor::notifyEvent( const ::com::sun::star::document::EventObject& Event ) throw (::com::sun::star::uno::RuntimeException) 417 { 418 osl::ResettableMutexGuard _rGuard(m_aMutex); 419 if ( m_pStatCL && Event.EventName == ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OnModifyChanged")) ) 420 { 421 OInterfaceContainerHelper* pListener = m_pStatCL->getContainer(m_aInterceptedURL[DISPATCH_SAVE]); 422 if ( pListener ) 423 { 424 FeatureStateEvent aEvt; 425 aEvt.FeatureURL.Complete = m_aInterceptedURL[DISPATCH_SAVE]; 426 aEvt.FeatureDescriptor = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Update")); 427 Reference<XModifiable> xModel(Event.Source,UNO_QUERY); 428 aEvt.IsEnabled = xModel.is() && xModel->isModified(); 429 aEvt.Requery = sal_False; 430 431 NOTIFY_LISTERNERS((*pListener),XStatusListener,statusChanged) 432 } 433 } 434 } 435 // ----------------------------------------------------------------------------- 436 void SAL_CALL OInterceptor::disposing( const ::com::sun::star::lang::EventObject& /*Source*/ ) throw (::com::sun::star::uno::RuntimeException) 437 { 438 } 439 440 //........................................................................ 441 } // namespace dbaccess 442 //........................................................................ 443 444