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