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