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_ucb.hxx" 30 31 #include <dynamicresultsetwrapper.hxx> 32 #include <ucbhelper/macros.hxx> 33 #include <osl/diagnose.h> 34 #include <rtl/ustring.hxx> 35 #include <com/sun/star/ucb/ListActionType.hpp> 36 #include <com/sun/star/ucb/WelcomeDynamicResultSetStruct.hpp> 37 #include <com/sun/star/ucb/XCachedDynamicResultSetStubFactory.hpp> 38 39 using namespace com::sun::star::lang; 40 using namespace com::sun::star::sdbc; 41 using namespace com::sun::star::ucb; 42 using namespace com::sun::star::uno; 43 using namespace cppu; 44 using namespace rtl; 45 46 //-------------------------------------------------------------------------- 47 //-------------------------------------------------------------------------- 48 // class DynamicResultSetWrapper 49 //-------------------------------------------------------------------------- 50 //-------------------------------------------------------------------------- 51 52 DynamicResultSetWrapper::DynamicResultSetWrapper( 53 Reference< XDynamicResultSet > xOrigin 54 , const Reference< XMultiServiceFactory > & xSMgr ) 55 56 : m_bDisposed( sal_False ) 57 , m_bInDispose( sal_False ) 58 , m_pDisposeEventListeners( NULL ) 59 , m_xSMgr( xSMgr ) 60 , m_bStatic( sal_False ) 61 , m_bGotWelcome( sal_False ) 62 , m_xSource( xOrigin ) 63 , m_xSourceResultOne( NULL ) 64 , m_xSourceResultTwo( NULL ) 65 // , m_xSourceResultCurrent( NULL ) 66 // , m_bUseOne( NULL ) 67 , m_xMyResultOne( NULL ) 68 , m_xMyResultTwo( NULL ) 69 , m_xListener( NULL ) 70 { 71 m_pMyListenerImpl = new DynamicResultSetWrapperListener( this ); 72 m_xMyListenerImpl = Reference< XDynamicResultSetListener >( m_pMyListenerImpl ); 73 //call impl_init() at the end of constructor of derived class 74 }; 75 76 void SAL_CALL DynamicResultSetWrapper::impl_init() 77 { 78 //call this at the end of constructor of derived class 79 // 80 81 Reference< XDynamicResultSet > xSource = NULL; 82 { 83 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 84 xSource = m_xSource; 85 m_xSource = NULL; 86 } 87 if( xSource.is() ) 88 setSource( xSource ); 89 } 90 91 DynamicResultSetWrapper::~DynamicResultSetWrapper() 92 { 93 //call impl_deinit() at start of destructor of derived class 94 95 delete m_pDisposeEventListeners; 96 }; 97 98 void SAL_CALL DynamicResultSetWrapper::impl_deinit() 99 { 100 //call this at start of destructor of derived class 101 // 102 m_pMyListenerImpl->impl_OwnerDies(); 103 } 104 105 void SAL_CALL DynamicResultSetWrapper 106 ::impl_EnsureNotDisposed() 107 throw( DisposedException, RuntimeException ) 108 { 109 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 110 if( m_bDisposed ) 111 throw DisposedException(); 112 } 113 114 //virtual 115 void SAL_CALL DynamicResultSetWrapper 116 ::impl_InitResultSetOne( const Reference< XResultSet >& xResultSet ) 117 { 118 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 119 OSL_ENSURE( !m_xSourceResultOne.is(), "Source ResultSet One is set already" ); 120 m_xSourceResultOne = xResultSet; 121 m_xMyResultOne = xResultSet; 122 } 123 124 //virtual 125 void SAL_CALL DynamicResultSetWrapper 126 ::impl_InitResultSetTwo( const Reference< XResultSet >& xResultSet ) 127 { 128 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 129 OSL_ENSURE( !m_xSourceResultTwo.is(), "Source ResultSet Two is set already" ); 130 m_xSourceResultTwo = xResultSet; 131 m_xMyResultTwo = xResultSet; 132 } 133 134 //-------------------------------------------------------------------------- 135 // XInterface methods. 136 //-------------------------------------------------------------------------- 137 //list all interfaces inclusive baseclasses of interfaces 138 QUERYINTERFACE_IMPL_START( DynamicResultSetWrapper ) 139 SAL_STATIC_CAST( XComponent*, this ) //base of XDynamicResultSet 140 , SAL_STATIC_CAST( XDynamicResultSet*, this ) 141 , SAL_STATIC_CAST( XSourceInitialization*, this ) 142 QUERYINTERFACE_IMPL_END 143 144 //-------------------------------------------------------------------------- 145 // XComponent methods. 146 //-------------------------------------------------------------------------- 147 // virtual 148 void SAL_CALL DynamicResultSetWrapper 149 ::dispose() throw( RuntimeException ) 150 { 151 impl_EnsureNotDisposed(); 152 153 Reference< XComponent > xSourceComponent; 154 { 155 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex ); 156 if( m_bInDispose || m_bDisposed ) 157 return; 158 m_bInDispose = sal_True; 159 160 xSourceComponent = Reference< XComponent >(m_xSource, UNO_QUERY); 161 162 if( m_pDisposeEventListeners && m_pDisposeEventListeners->getLength() ) 163 { 164 EventObject aEvt; 165 aEvt.Source = static_cast< XComponent * >( this ); 166 167 aGuard.clear(); 168 m_pDisposeEventListeners->disposeAndClear( aEvt ); 169 } 170 } 171 172 /* //@todo ?? ( only if java collection needs to long ) 173 if( xSourceComponent.is() ) 174 xSourceComponent->dispose(); 175 */ 176 177 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 178 m_bDisposed = sal_True; 179 m_bInDispose = sal_False; 180 } 181 182 //-------------------------------------------------------------------------- 183 // virtual 184 void SAL_CALL DynamicResultSetWrapper 185 ::addEventListener( const Reference< XEventListener >& Listener ) 186 throw( RuntimeException ) 187 { 188 impl_EnsureNotDisposed(); 189 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 190 191 if ( !m_pDisposeEventListeners ) 192 m_pDisposeEventListeners = 193 new OInterfaceContainerHelper( m_aContainerMutex ); 194 195 m_pDisposeEventListeners->addInterface( Listener ); 196 } 197 198 //-------------------------------------------------------------------------- 199 // virtual 200 void SAL_CALL DynamicResultSetWrapper 201 ::removeEventListener( const Reference< XEventListener >& Listener ) 202 throw( RuntimeException ) 203 { 204 impl_EnsureNotDisposed(); 205 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 206 207 if ( m_pDisposeEventListeners ) 208 m_pDisposeEventListeners->removeInterface( Listener ); 209 } 210 211 //-------------------------------------------------------------------------- 212 // own methods 213 //-------------------------------------------------------------------------- 214 215 //virtual 216 void SAL_CALL DynamicResultSetWrapper 217 ::impl_disposing( const EventObject& ) 218 throw( RuntimeException ) 219 { 220 impl_EnsureNotDisposed(); 221 222 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 223 224 if( !m_xSource.is() ) 225 return; 226 227 //release all references to the broadcaster: 228 m_xSource.clear(); 229 m_xSourceResultOne.clear();//?? or only when not static?? 230 m_xSourceResultTwo.clear();//?? 231 //@todo m_xMyResultOne.clear(); ??? 232 //@todo m_xMyResultTwo.clear(); ??? 233 } 234 235 //virtual 236 void SAL_CALL DynamicResultSetWrapper 237 ::impl_notify( const ListEvent& Changes ) 238 throw( RuntimeException ) 239 { 240 impl_EnsureNotDisposed(); 241 //@todo 242 /* 243 <p>The Listener is allowed to blockade this call, until he really want to go 244 to the new version. The only situation, where the listener has to return the 245 update call at once is, while he disposes his broadcaster or while he is 246 removing himsef as listener (otherwise you deadlock)!!! 247 */ 248 // handle the actions in the list 249 250 ListEvent aNewEvent; 251 aNewEvent.Source = static_cast< XDynamicResultSet * >( this ); 252 aNewEvent.Changes = Changes.Changes; 253 254 { 255 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 256 for( long i=0; !m_bGotWelcome && i<Changes.Changes.getLength(); i++ ) 257 { 258 ListAction& rAction = aNewEvent.Changes[i]; 259 switch( rAction.ListActionType ) 260 { 261 case ListActionType::WELCOME: 262 { 263 WelcomeDynamicResultSetStruct aWelcome; 264 if( rAction.ActionInfo >>= aWelcome ) 265 { 266 impl_InitResultSetOne( aWelcome.Old ); 267 impl_InitResultSetTwo( aWelcome.New ); 268 m_bGotWelcome = sal_True; 269 270 aWelcome.Old = m_xMyResultOne; 271 aWelcome.New = m_xMyResultTwo; 272 273 rAction.ActionInfo <<= aWelcome; 274 } 275 else 276 { 277 OSL_ENSURE( sal_False, "ListActionType was WELCOME but ActionInfo didn't contain a WelcomeDynamicResultSetStruct" ); 278 //throw RuntimeException(); 279 } 280 break; 281 } 282 } 283 } 284 OSL_ENSURE( m_bGotWelcome, "first notification was without WELCOME" ); 285 } 286 287 if( !m_xListener.is() ) 288 m_aListenerSet.wait(); 289 m_xListener->notify( aNewEvent ); 290 291 /* 292 m_bUseOne = !m_bUseOne; 293 if( m_bUseOne ) 294 m_xSourceResultCurrent = m_xSourceResultOne; 295 else 296 m_xSourceResultCurrent = m_xSourceResultTwo; 297 */ 298 } 299 300 //-------------------------------------------------------------------------- 301 // XSourceInitialization 302 //-------------------------------------------------------------------------- 303 //virtual 304 void SAL_CALL DynamicResultSetWrapper 305 ::setSource( const Reference< XInterface > & Source ) 306 throw( AlreadyInitializedException, RuntimeException ) 307 { 308 impl_EnsureNotDisposed(); 309 { 310 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 311 if( m_xSource.is() ) 312 { 313 throw AlreadyInitializedException(); 314 } 315 } 316 317 Reference< XDynamicResultSet > xSourceDynamic( Source, UNO_QUERY ); 318 OSL_ENSURE( xSourceDynamic.is(), 319 "the given source is not of required type XDynamicResultSet" ); 320 321 Reference< XDynamicResultSetListener > xListener = NULL; 322 Reference< XDynamicResultSetListener > xMyListenerImpl = NULL; 323 324 sal_Bool bStatic = sal_False; 325 { 326 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 327 m_xSource = xSourceDynamic; 328 xListener = m_xListener; 329 bStatic = m_bStatic; 330 xMyListenerImpl = m_xMyListenerImpl; 331 } 332 if( xListener.is() ) 333 xSourceDynamic->setListener( m_xMyListenerImpl ); 334 else if( bStatic ) 335 { 336 Reference< XComponent > xSourceComponent( Source, UNO_QUERY ); 337 xSourceComponent->addEventListener( Reference< XEventListener > ::query( xMyListenerImpl ) ); 338 } 339 m_aSourceSet.set(); 340 } 341 342 //-------------------------------------------------------------------------- 343 // XDynamicResultSet 344 //-------------------------------------------------------------------------- 345 //virtual 346 Reference< XResultSet > SAL_CALL DynamicResultSetWrapper 347 ::getStaticResultSet() 348 throw( ListenerAlreadySetException, RuntimeException ) 349 { 350 impl_EnsureNotDisposed(); 351 352 Reference< XDynamicResultSet > xSource = NULL; 353 Reference< XEventListener > xMyListenerImpl = NULL; 354 { 355 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 356 if( m_xListener.is() ) 357 throw ListenerAlreadySetException(); 358 359 xSource = m_xSource; 360 m_bStatic = sal_True; 361 xMyListenerImpl = Reference< XEventListener > ::query( m_xMyListenerImpl ); 362 } 363 364 if( xSource.is() ) 365 { 366 Reference< XComponent > xSourceComponent( xSource, UNO_QUERY ); 367 xSourceComponent->addEventListener( xMyListenerImpl ); 368 } 369 if( !xSource.is() ) 370 m_aSourceSet.wait(); 371 372 373 Reference< XResultSet > xResultSet = xSource->getStaticResultSet(); 374 impl_InitResultSetOne( xResultSet ); 375 return m_xMyResultOne; 376 } 377 378 //virtual 379 void SAL_CALL DynamicResultSetWrapper 380 ::setListener( const Reference< 381 XDynamicResultSetListener > & Listener ) 382 throw( ListenerAlreadySetException, RuntimeException ) 383 { 384 impl_EnsureNotDisposed(); 385 386 Reference< XDynamicResultSet > xSource = NULL; 387 Reference< XDynamicResultSetListener > xMyListenerImpl = NULL; 388 { 389 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 390 if( m_xListener.is() ) 391 throw ListenerAlreadySetException(); 392 if( m_bStatic ) 393 throw ListenerAlreadySetException(); 394 395 m_xListener = Listener; 396 addEventListener( Reference< XEventListener >::query( Listener ) ); 397 398 xSource = m_xSource; 399 xMyListenerImpl = m_xMyListenerImpl; 400 } 401 if ( xSource.is() ) 402 xSource->setListener( xMyListenerImpl ); 403 404 m_aListenerSet.set(); 405 } 406 407 //virtual 408 void SAL_CALL DynamicResultSetWrapper 409 ::connectToCache( const Reference< XDynamicResultSet > & xCache ) 410 throw( ListenerAlreadySetException, AlreadyInitializedException, ServiceNotFoundException, RuntimeException ) 411 { 412 impl_EnsureNotDisposed(); 413 414 if( m_xListener.is() ) 415 throw ListenerAlreadySetException(); 416 if( m_bStatic ) 417 throw ListenerAlreadySetException(); 418 419 Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY ); 420 OSL_ENSURE( xTarget.is(), "The given Target dosn't have the required interface 'XSourceInitialization'" ); 421 if( xTarget.is() && m_xSMgr.is() ) 422 { 423 //@todo m_aSourceSet.wait();? 424 425 Reference< XCachedDynamicResultSetStubFactory > xStubFactory; 426 try 427 { 428 xStubFactory = Reference< XCachedDynamicResultSetStubFactory >( 429 m_xSMgr->createInstance( 430 OUString::createFromAscii( 431 "com.sun.star.ucb.CachedDynamicResultSetStubFactory" ) ), 432 UNO_QUERY ); 433 } 434 catch ( Exception const & ) 435 { 436 } 437 438 if( xStubFactory.is() ) 439 { 440 xStubFactory->connectToCache( 441 this, xCache, Sequence< NumberedSortingInfo > (), NULL ); 442 return; 443 } 444 } 445 OSL_ENSURE( sal_False, "could not connect to cache" ); 446 throw ServiceNotFoundException(); 447 } 448 449 //virtual 450 sal_Int16 SAL_CALL DynamicResultSetWrapper 451 ::getCapabilities() 452 throw( RuntimeException ) 453 { 454 impl_EnsureNotDisposed(); 455 456 m_aSourceSet.wait(); 457 Reference< XDynamicResultSet > xSource = NULL; 458 { 459 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 460 xSource = m_xSource; 461 } 462 return xSource->getCapabilities(); 463 } 464 465 //-------------------------------------------------------------------------- 466 //-------------------------------------------------------------------------- 467 // class DynamicResultSetWrapperListener 468 //-------------------------------------------------------------------------- 469 //-------------------------------------------------------------------------- 470 471 DynamicResultSetWrapperListener::DynamicResultSetWrapperListener( 472 DynamicResultSetWrapper* pOwner ) 473 : m_pOwner( pOwner ) 474 { 475 476 } 477 478 DynamicResultSetWrapperListener::~DynamicResultSetWrapperListener() 479 { 480 481 } 482 483 //-------------------------------------------------------------------------- 484 // XInterface methods. 485 //-------------------------------------------------------------------------- 486 //list all interfaces inclusive baseclasses of interfaces 487 XINTERFACE_IMPL_2( DynamicResultSetWrapperListener 488 , XDynamicResultSetListener 489 , XEventListener //base of XDynamicResultSetListener 490 ); 491 492 //-------------------------------------------------------------------------- 493 // XDynamicResultSetListener methods: 494 //-------------------------------------------------------------------------- 495 //virtual 496 void SAL_CALL DynamicResultSetWrapperListener 497 ::disposing( const EventObject& rEventObject ) 498 throw( RuntimeException ) 499 { 500 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 501 502 if( m_pOwner ) 503 m_pOwner->impl_disposing( rEventObject ); 504 } 505 506 //virtual 507 void SAL_CALL DynamicResultSetWrapperListener 508 ::notify( const ListEvent& Changes ) 509 throw( RuntimeException ) 510 { 511 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 512 513 if( m_pOwner ) 514 m_pOwner->impl_notify( Changes ); 515 } 516 517 //-------------------------------------------------------------------------- 518 // own methods: 519 //-------------------------------------------------------------------------- 520 521 void SAL_CALL DynamicResultSetWrapperListener 522 ::impl_OwnerDies() 523 { 524 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 525 526 m_pOwner = NULL; 527 } 528 529