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