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 <vector> 32 #include <sortdynres.hxx> 33 #include <cppuhelper/interfacecontainer.hxx> 34 #include <com/sun/star/ucb/ContentResultSetCapability.hpp> 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 #include <com/sun/star/ucb/XSourceInitialization.hpp> 39 40 //----------------------------------------------------------------------------- 41 using namespace com::sun::star::beans; 42 using namespace com::sun::star::lang; 43 using namespace com::sun::star::sdbc; 44 using namespace com::sun::star::ucb; 45 using namespace com::sun::star::uno; 46 using namespace cppu; 47 using namespace rtl; 48 49 //========================================================================= 50 51 // The mutex to synchronize access to containers. 52 static osl::Mutex& getContainerMutex() 53 { 54 static osl::Mutex* pMutex = NULL; 55 if( !pMutex ) 56 { 57 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 58 if( !pMutex ) 59 { 60 static osl::Mutex aMutex; 61 pMutex = &aMutex; 62 } 63 } 64 65 return *pMutex; 66 } 67 68 //========================================================================= 69 // 70 // SortedDynamicResultSet 71 // 72 //========================================================================= 73 74 SortedDynamicResultSet::SortedDynamicResultSet( 75 const Reference < XDynamicResultSet > &xOriginal, 76 const Sequence < NumberedSortingInfo > &aOptions, 77 const Reference < XAnyCompareFactory > &xCompFac, 78 const Reference < XMultiServiceFactory > &xSMgr ) 79 { 80 mpDisposeEventListeners = NULL; 81 mpOwnListener = new SortedDynamicResultSetListener( this ); 82 83 mxOwnListener = Reference< XDynamicResultSetListener >( mpOwnListener ); 84 85 mxOriginal = xOriginal; 86 maOptions = aOptions; 87 mxCompFac = xCompFac; 88 mxSMgr = xSMgr; 89 90 mpOne = NULL; 91 mpTwo = NULL; 92 93 mbGotWelcome = sal_False; 94 mbUseOne = sal_True; 95 mbStatic = sal_False; 96 } 97 98 //-------------------------------------------------------------------------- 99 SortedDynamicResultSet::~SortedDynamicResultSet() 100 { 101 mpOwnListener->impl_OwnerDies(); 102 mxOwnListener.clear(); 103 104 delete mpDisposeEventListeners; 105 106 mxOne.clear(); 107 mxTwo.clear(); 108 mxOriginal.clear(); 109 110 mpOne = NULL; 111 mpTwo = NULL; 112 } 113 114 //-------------------------------------------------------------------------- 115 // XInterface methods. 116 //-------------------------------------------------------------------------- 117 118 XINTERFACE_IMPL_4( SortedDynamicResultSet, 119 XTypeProvider, 120 XServiceInfo, 121 XComponent, /* base class of XDynamicResultSet */ 122 XDynamicResultSet ); 123 124 //-------------------------------------------------------------------------- 125 // XTypeProvider methods. 126 //-------------------------------------------------------------------------- 127 128 XTYPEPROVIDER_IMPL_3( SortedDynamicResultSet, 129 XTypeProvider, 130 XServiceInfo, 131 XDynamicResultSet ); 132 133 //-------------------------------------------------------------------------- 134 // XServiceInfo methods. 135 //-------------------------------------------------------------------------- 136 137 XSERVICEINFO_NOFACTORY_IMPL_1( SortedDynamicResultSet, 138 OUString::createFromAscii( 139 "com.sun.star.comp.ucb.SortedDynamicResultSet" ), 140 OUString::createFromAscii( 141 DYNAMIC_RESULTSET_SERVICE_NAME ) ); 142 143 //-------------------------------------------------------------------------- 144 // XComponent methods. 145 //-------------------------------------------------------------------------- 146 void SAL_CALL SortedDynamicResultSet::dispose() 147 throw( RuntimeException ) 148 { 149 osl::Guard< osl::Mutex > aGuard( maMutex ); 150 151 if ( mpDisposeEventListeners && mpDisposeEventListeners->getLength() ) 152 { 153 EventObject aEvt; 154 aEvt.Source = static_cast< XComponent * >( this ); 155 mpDisposeEventListeners->disposeAndClear( aEvt ); 156 } 157 158 mxOne.clear(); 159 mxTwo.clear(); 160 mxOriginal.clear(); 161 162 mpOne = NULL; 163 mpTwo = NULL; 164 mbUseOne = sal_True; 165 } 166 167 //-------------------------------------------------------------------------- 168 void SAL_CALL SortedDynamicResultSet::addEventListener( 169 const Reference< XEventListener >& Listener ) 170 throw( RuntimeException ) 171 { 172 osl::Guard< osl::Mutex > aGuard( maMutex ); 173 174 if ( !mpDisposeEventListeners ) 175 mpDisposeEventListeners = 176 new OInterfaceContainerHelper( getContainerMutex() ); 177 178 mpDisposeEventListeners->addInterface( Listener ); 179 } 180 181 //-------------------------------------------------------------------------- 182 void SAL_CALL SortedDynamicResultSet::removeEventListener( 183 const Reference< XEventListener >& Listener ) 184 throw( RuntimeException ) 185 { 186 osl::Guard< osl::Mutex > aGuard( maMutex ); 187 188 if ( mpDisposeEventListeners ) 189 mpDisposeEventListeners->removeInterface( Listener ); 190 } 191 192 //-------------------------------------------------------------------------- 193 // XDynamicResultSet methods. 194 // ------------------------------------------------------------------------------ 195 Reference< XResultSet > SAL_CALL 196 SortedDynamicResultSet::getStaticResultSet() 197 throw( ListenerAlreadySetException, RuntimeException ) 198 { 199 osl::Guard< osl::Mutex > aGuard( maMutex ); 200 201 if ( mxListener.is() ) 202 throw ListenerAlreadySetException(); 203 204 mbStatic = sal_True; 205 206 if ( mxOriginal.is() ) 207 { 208 mpOne = new SortedResultSet( mxOriginal->getStaticResultSet() ); 209 mxOne = mpOne; 210 mpOne->Initialize( maOptions, mxCompFac ); 211 } 212 213 return mxOne; 214 } 215 216 // ------------------------------------------------------------------------------ 217 void SAL_CALL 218 SortedDynamicResultSet::setListener( const Reference< XDynamicResultSetListener >& Listener ) 219 throw( ListenerAlreadySetException, RuntimeException ) 220 { 221 osl::Guard< osl::Mutex > aGuard( maMutex ); 222 223 if ( mxListener.is() ) 224 throw ListenerAlreadySetException(); 225 226 addEventListener( Reference< XEventListener >::query( Listener ) ); 227 228 mxListener = Listener; 229 230 if ( mxOriginal.is() ) 231 mxOriginal->setListener( mxOwnListener ); 232 } 233 234 // ------------------------------------------------------------------------------ 235 void SAL_CALL 236 SortedDynamicResultSet::connectToCache( 237 const Reference< XDynamicResultSet > & xCache ) 238 throw( ListenerAlreadySetException, 239 AlreadyInitializedException, 240 ServiceNotFoundException, 241 RuntimeException ) 242 { 243 if( mxListener.is() ) 244 throw ListenerAlreadySetException(); 245 246 if( mbStatic ) 247 throw ListenerAlreadySetException(); 248 249 Reference< XSourceInitialization > xTarget( xCache, UNO_QUERY ); 250 if( xTarget.is() && mxSMgr.is() ) 251 { 252 Reference< XCachedDynamicResultSetStubFactory > xStubFactory; 253 try 254 { 255 xStubFactory = Reference< XCachedDynamicResultSetStubFactory >( 256 mxSMgr->createInstance( 257 OUString::createFromAscii( 258 "com.sun.star.ucb.CachedDynamicResultSetStubFactory" ) ), 259 UNO_QUERY ); 260 } 261 catch ( Exception const & ) 262 { 263 } 264 265 if( xStubFactory.is() ) 266 { 267 xStubFactory->connectToCache( 268 this, xCache, Sequence< NumberedSortingInfo > (), NULL ); 269 return; 270 } 271 } 272 throw ServiceNotFoundException(); 273 } 274 275 // ------------------------------------------------------------------------------ 276 sal_Int16 SAL_CALL 277 SortedDynamicResultSet::getCapabilities() 278 throw( RuntimeException ) 279 { 280 osl::Guard< osl::Mutex > aGuard( maMutex ); 281 282 sal_Int16 nCaps = 0; 283 284 if ( mxOriginal.is() ) 285 nCaps = mxOriginal->getCapabilities(); 286 287 nCaps |= ContentResultSetCapability::SORTED; 288 289 return nCaps; 290 } 291 292 //-------------------------------------------------------------------------- 293 // XDynamicResultSetListener methods. 294 // ------------------------------------------------------------------------------ 295 296 /** In the first notify-call the listener gets the two 297 <type>XResultSet</type>s and has to hold them. The <type>XResultSet</type>s 298 are implementations of the service <type>ContentResultSet</type>. 299 300 <p>The notified new <type>XResultSet</type> will stay valid after returning 301 notification. The old one will become invalid after returning notification. 302 303 <p>While in notify-call the listener is allowed to read old and new version, 304 except in the first call, where only the new Resultset is valid. 305 306 <p>The Listener is allowed to blockade this call, until he really want to go 307 to the new version. The only situation, where the listener has to return the 308 update call at once is, while he disposes his broadcaster or while he is 309 removing himsef as listener (otherwise you deadlock)!!! 310 */ 311 void SAL_CALL 312 SortedDynamicResultSet::impl_notify( const ListEvent& Changes ) 313 throw( RuntimeException ) 314 { 315 osl::Guard< osl::Mutex > aGuard( maMutex ); 316 317 sal_Bool bHasNew = sal_False; 318 sal_Bool bHasModified = sal_False; 319 320 SortedResultSet *pCurSet = NULL; 321 322 // mxNew und mxOld vertauschen und anschliessend die Tabellen von Old 323 // nach New kopieren 324 if ( mbGotWelcome ) 325 { 326 if ( mbUseOne ) 327 { 328 mbUseOne = sal_False; 329 mpTwo->CopyData( mpOne ); 330 pCurSet = mpTwo; 331 } 332 else 333 { 334 mbUseOne = sal_True; 335 mpOne->CopyData( mpTwo ); 336 pCurSet = mpOne; 337 } 338 } 339 340 Any aRet; 341 342 try { 343 aRet = pCurSet->getPropertyValue( OUString::createFromAscii( "IsRowCountFinal" ) ); 344 } 345 catch ( UnknownPropertyException ) {} 346 catch ( WrappedTargetException ) {} 347 348 long nOldCount = pCurSet->GetCount(); 349 sal_Bool bWasFinal = false; 350 351 aRet >>= bWasFinal; 352 353 // handle the actions in the list 354 for ( long i=0; i<Changes.Changes.getLength(); i++ ) 355 { 356 const ListAction aAction = Changes.Changes[i]; 357 switch ( aAction.ListActionType ) 358 { 359 case ListActionType::WELCOME: 360 { 361 WelcomeDynamicResultSetStruct aWelcome; 362 if ( aAction.ActionInfo >>= aWelcome ) 363 { 364 mpTwo = new SortedResultSet( aWelcome.Old ); 365 mxTwo = mpTwo; 366 mpOne = new SortedResultSet( aWelcome.New ); 367 mxOne = mpOne; 368 mpOne->Initialize( maOptions, mxCompFac ); 369 mbGotWelcome = sal_True; 370 mbUseOne = sal_True; 371 pCurSet = mpOne; 372 373 aWelcome.Old = mxTwo; 374 aWelcome.New = mxOne; 375 376 ListAction *pWelcomeAction = new ListAction; 377 pWelcomeAction->ActionInfo <<= aWelcome; 378 pWelcomeAction->Position = 0; 379 pWelcomeAction->Count = 0; 380 pWelcomeAction->ListActionType = ListActionType::WELCOME; 381 382 maActions.Insert( pWelcomeAction ); 383 } 384 else 385 { 386 // throw RuntimeException(); 387 } 388 break; 389 } 390 case ListActionType::INSERTED: 391 { 392 pCurSet->InsertNew( aAction.Position, aAction.Count ); 393 bHasNew = sal_True; 394 break; 395 } 396 case ListActionType::REMOVED: 397 { 398 pCurSet->Remove( aAction.Position, 399 aAction.Count, 400 &maActions ); 401 break; 402 } 403 case ListActionType::MOVED: 404 { 405 long nOffset = 0; 406 if ( aAction.ActionInfo >>= nOffset ) 407 { 408 pCurSet->Move( aAction.Position, 409 aAction.Count, 410 nOffset ); 411 } 412 break; 413 } 414 case ListActionType::PROPERTIES_CHANGED: 415 { 416 pCurSet->SetChanged( aAction.Position, aAction.Count ); 417 bHasModified = sal_True; 418 break; 419 } 420 default: break; 421 } 422 } 423 424 if ( bHasModified ) 425 pCurSet->ResortModified( &maActions ); 426 427 if ( bHasNew ) 428 pCurSet->ResortNew( &maActions ); 429 430 // send the new actions with a notify to the listeners 431 SendNotify(); 432 433 // check for propertyChangeEvents 434 pCurSet->CheckProperties( nOldCount, bWasFinal ); 435 } 436 437 //----------------------------------------------------------------- 438 // XEventListener 439 //----------------------------------------------------------------- 440 void SAL_CALL 441 SortedDynamicResultSet::impl_disposing( const EventObject& ) 442 throw( RuntimeException ) 443 { 444 mxListener.clear(); 445 mxOriginal.clear(); 446 } 447 448 // ------------------------------------------------------------------------------ 449 // private methods 450 // ------------------------------------------------------------------------------ 451 void SortedDynamicResultSet::SendNotify() 452 { 453 long nCount = maActions.Count(); 454 455 if ( nCount && mxListener.is() ) 456 { 457 Sequence< ListAction > aActionList( maActions.Count() ); 458 ListAction *pActionList = aActionList.getArray(); 459 460 for ( long i=0; i<nCount; i++ ) 461 { 462 pActionList[ i ] = *(maActions.GetAction( i )); 463 } 464 465 ListEvent aNewEvent; 466 aNewEvent.Changes = aActionList; 467 468 mxListener->notify( aNewEvent ); 469 } 470 471 // clean up 472 maActions.Clear(); 473 } 474 475 //========================================================================= 476 // 477 // SortedDynamicResultSetFactory 478 // 479 //========================================================================= 480 SortedDynamicResultSetFactory::SortedDynamicResultSetFactory( 481 const Reference< XMultiServiceFactory > & rSMgr ) 482 { 483 mxSMgr = rSMgr; 484 } 485 486 //-------------------------------------------------------------------------- 487 SortedDynamicResultSetFactory::~SortedDynamicResultSetFactory() 488 { 489 } 490 491 //-------------------------------------------------------------------------- 492 // XInterface methods. 493 //-------------------------------------------------------------------------- 494 495 XINTERFACE_IMPL_3( SortedDynamicResultSetFactory, 496 XTypeProvider, 497 XServiceInfo, 498 XSortedDynamicResultSetFactory ); 499 500 //-------------------------------------------------------------------------- 501 // XTypeProvider methods. 502 //-------------------------------------------------------------------------- 503 504 XTYPEPROVIDER_IMPL_3( SortedDynamicResultSetFactory, 505 XTypeProvider, 506 XServiceInfo, 507 XSortedDynamicResultSetFactory ); 508 509 //-------------------------------------------------------------------------- 510 // XServiceInfo methods. 511 //-------------------------------------------------------------------------- 512 513 XSERVICEINFO_IMPL_1( SortedDynamicResultSetFactory, 514 OUString::createFromAscii( 515 "com.sun.star.comp.ucb.SortedDynamicResultSetFactory" ), 516 OUString::createFromAscii( 517 DYNAMIC_RESULTSET_FACTORY_NAME ) ); 518 519 //-------------------------------------------------------------------------- 520 // Service factory implementation. 521 //-------------------------------------------------------------------------- 522 523 ONE_INSTANCE_SERVICE_FACTORY_IMPL( SortedDynamicResultSetFactory ); 524 525 //-------------------------------------------------------------------------- 526 // SortedDynamicResultSetFactory methods. 527 //-------------------------------------------------------------------------- 528 Reference< XDynamicResultSet > SAL_CALL 529 SortedDynamicResultSetFactory::createSortedDynamicResultSet( 530 const Reference< XDynamicResultSet > & Source, 531 const Sequence< NumberedSortingInfo > & Info, 532 const Reference< XAnyCompareFactory > & CompareFactory ) 533 throw( RuntimeException ) 534 { 535 Reference< XDynamicResultSet > xRet; 536 xRet = new SortedDynamicResultSet( Source, Info, CompareFactory, mxSMgr ); 537 return xRet; 538 } 539 540 //========================================================================= 541 // 542 // EventList 543 // 544 //========================================================================= 545 546 void EventList::Clear() 547 { 548 for ( std::deque< LISTACTION* >::size_type i = 0; 549 i < maData.size(); ++i ) 550 { 551 delete maData[i]; 552 } 553 554 maData.clear(); 555 } 556 557 //-------------------------------------------------------------------------- 558 void EventList::AddEvent( long nType, long nPos, long nCount ) 559 { 560 ListAction *pAction = new ListAction; 561 pAction->Position = nPos; 562 pAction->Count = nCount; 563 pAction->ListActionType = nType; 564 565 Insert( pAction ); 566 } 567 568 //================================================================= 569 // 570 // SortedDynamicResultSetListener 571 // 572 //================================================================= 573 574 SortedDynamicResultSetListener::SortedDynamicResultSetListener( 575 SortedDynamicResultSet *mOwner ) 576 { 577 mpOwner = mOwner; 578 } 579 580 //----------------------------------------------------------------- 581 SortedDynamicResultSetListener::~SortedDynamicResultSetListener() 582 { 583 } 584 585 //----------------------------------------------------------------- 586 // XInterface methods. 587 //----------------------------------------------------------------- 588 589 XINTERFACE_IMPL_2( SortedDynamicResultSetListener, 590 XEventListener, /* base class of XDynamicResultSetListener */ 591 XDynamicResultSetListener ); 592 593 //----------------------------------------------------------------- 594 // XEventListener ( base of XDynamicResultSetListener ) 595 //----------------------------------------------------------------- 596 void SAL_CALL 597 SortedDynamicResultSetListener::disposing( const EventObject& Source ) 598 throw( RuntimeException ) 599 { 600 osl::Guard< osl::Mutex > aGuard( maMutex ); 601 602 if ( mpOwner ) 603 mpOwner->impl_disposing( Source ); 604 } 605 606 //----------------------------------------------------------------- 607 // XDynamicResultSetListener 608 //----------------------------------------------------------------- 609 void SAL_CALL 610 SortedDynamicResultSetListener::notify( const ListEvent& Changes ) 611 throw( RuntimeException ) 612 { 613 osl::Guard< osl::Mutex > aGuard( maMutex ); 614 615 if ( mpOwner ) 616 mpOwner->impl_notify( Changes ); 617 } 618 619 //----------------------------------------------------------------- 620 // own methods: 621 //----------------------------------------------------------------- 622 void SAL_CALL 623 SortedDynamicResultSetListener::impl_OwnerDies() 624 { 625 osl::Guard< osl::Mutex > aGuard( maMutex ); 626 mpOwner = NULL; 627 } 628 629