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