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 <cachedcontentresultsetstub.hxx> 32 #include <com/sun/star/sdbc/FetchDirection.hpp> 33 #include <com/sun/star/ucb/FetchError.hpp> 34 #include <osl/diagnose.h> 35 36 using namespace com::sun::star::beans; 37 using namespace com::sun::star::lang; 38 using namespace com::sun::star::sdbc; 39 using namespace com::sun::star::ucb; 40 using namespace com::sun::star::uno; 41 using namespace com::sun::star::util; 42 using namespace cppu; 43 using namespace rtl; 44 45 CachedContentResultSetStub::CachedContentResultSetStub( Reference< XResultSet > xOrigin ) 46 : ContentResultSetWrapper( xOrigin ) 47 , m_nColumnCount( 0 ) 48 , m_bColumnCountCached( sal_False ) 49 , m_bNeedToPropagateFetchSize( sal_True ) 50 , m_bFirstFetchSizePropagationDone( sal_False ) 51 , m_nLastFetchSize( 1 )//this value is not important at all 52 , m_bLastFetchDirection( sal_True )//this value is not important at all 53 , m_aPropertyNameForFetchSize( OUString::createFromAscii( "FetchSize" ) ) 54 , m_aPropertyNameForFetchDirection( OUString::createFromAscii( "FetchDirection" ) ) 55 { 56 impl_init(); 57 } 58 59 CachedContentResultSetStub::~CachedContentResultSetStub() 60 { 61 impl_deinit(); 62 } 63 64 //-------------------------------------------------------------------------- 65 // XInterface methods. 66 //-------------------------------------------------------------------------- 67 XINTERFACE_COMMON_IMPL( CachedContentResultSetStub ) 68 69 Any SAL_CALL CachedContentResultSetStub 70 ::queryInterface( const Type& rType ) 71 throw ( RuntimeException ) 72 { 73 //list all interfaces inclusive baseclasses of interfaces 74 75 Any aRet = ContentResultSetWrapper::queryInterface( rType ); 76 if( aRet.hasValue() ) 77 return aRet; 78 79 aRet = cppu::queryInterface( rType 80 , static_cast< XTypeProvider* >( this ) 81 , static_cast< XServiceInfo* >( this ) 82 , static_cast< XFetchProvider* >( this ) 83 , static_cast< XFetchProviderForContentAccess* >( this ) 84 ); 85 86 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType ); 87 } 88 89 //-------------------------------------------------------------------------- 90 // own methods. ( inherited ) 91 //-------------------------------------------------------------------------- 92 93 //virtual 94 void SAL_CALL CachedContentResultSetStub 95 ::impl_propertyChange( const PropertyChangeEvent& rEvt ) 96 throw( RuntimeException ) 97 { 98 impl_EnsureNotDisposed(); 99 100 //don't notify events on fetchsize and fetchdirection to the above CachedContentResultSet 101 //because it will ignore them anyway and we can save this remote calls 102 if( rEvt.PropertyName == m_aPropertyNameForFetchSize 103 || rEvt.PropertyName == m_aPropertyNameForFetchDirection ) 104 return; 105 106 PropertyChangeEvent aEvt( rEvt ); 107 aEvt.Source = static_cast< XPropertySet * >( this ); 108 aEvt.Further = sal_False; 109 110 impl_notifyPropertyChangeListeners( aEvt ); 111 } 112 113 114 //virtual 115 void SAL_CALL CachedContentResultSetStub 116 ::impl_vetoableChange( const PropertyChangeEvent& rEvt ) 117 throw( PropertyVetoException, 118 RuntimeException ) 119 { 120 impl_EnsureNotDisposed(); 121 122 //don't notify events on fetchsize and fetchdirection to the above CachedContentResultSet 123 //because it will ignore them anyway and we can save this remote calls 124 if( rEvt.PropertyName == m_aPropertyNameForFetchSize 125 || rEvt.PropertyName == m_aPropertyNameForFetchDirection ) 126 return; 127 128 PropertyChangeEvent aEvt( rEvt ); 129 aEvt.Source = static_cast< XPropertySet * >( this ); 130 aEvt.Further = sal_False; 131 132 impl_notifyVetoableChangeListeners( aEvt ); 133 } 134 135 //-------------------------------------------------------------------------- 136 // XTypeProvider methods. 137 //-------------------------------------------------------------------------- 138 139 XTYPEPROVIDER_COMMON_IMPL( CachedContentResultSetStub ) 140 //list all interfaces exclusive baseclasses 141 Sequence< Type > SAL_CALL CachedContentResultSetStub 142 ::getTypes() 143 throw( RuntimeException ) 144 { 145 static Sequence< Type >* pTypes = NULL; 146 if( !pTypes ) 147 { 148 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); 149 if( !pTypes ) 150 { 151 pTypes = new Sequence< Type >(13); 152 (*pTypes)[0] = CPPU_TYPE_REF( XTypeProvider ); 153 (*pTypes)[1] = CPPU_TYPE_REF( XServiceInfo ); 154 (*pTypes)[2] = CPPU_TYPE_REF( XComponent ); 155 (*pTypes)[3] = CPPU_TYPE_REF( XCloseable ); 156 (*pTypes)[4] = CPPU_TYPE_REF( XResultSetMetaDataSupplier ); 157 (*pTypes)[5] = CPPU_TYPE_REF( XPropertySet ); 158 (*pTypes)[6] = CPPU_TYPE_REF( XPropertyChangeListener ); 159 (*pTypes)[7] = CPPU_TYPE_REF( XVetoableChangeListener ); 160 (*pTypes)[8] = CPPU_TYPE_REF( XResultSet ); 161 (*pTypes)[9] = CPPU_TYPE_REF( XContentAccess ); 162 (*pTypes)[10] = CPPU_TYPE_REF( XRow ); 163 (*pTypes)[11] = CPPU_TYPE_REF( XFetchProvider ); 164 (*pTypes)[12] = CPPU_TYPE_REF( XFetchProviderForContentAccess ); 165 } 166 } 167 return *pTypes; 168 /* 169 static cppu::OTypeCollection * pCollection = 0; 170 if (!pCollection) 171 { 172 osl::MutexGuard aGuard(osl::Mutex::getGlobalMutex()); 173 if (!pCollection) 174 { 175 static cppu::OTypeCollection 176 aTheCollection( 177 getCppuType( 178 static_cast< Reference< XTypeProvider > 179 const * >( 180 0)), 181 getCppuType( 182 static_cast< Reference< XServiceInfo > 183 const * >( 184 0)), 185 getCppuType( 186 static_cast< Reference< XComponent > 187 const * >( 188 0)), 189 getCppuType( 190 static_cast< Reference< XCloseable > 191 const * >( 192 0)), 193 getCppuType( 194 static_cast< Reference< XResultSetMetaDataSupplier > 195 const * >( 196 0)), 197 getCppuType( 198 static_cast< Reference< XPropertySet > 199 const * >( 200 0)), 201 getCppuType( 202 static_cast< Reference< XPropertyChangeListener > 203 const * >( 204 0)), 205 getCppuType( 206 static_cast< Reference< XVetoableChangeListener > 207 const * >( 208 0)), 209 getCppuType( 210 static_cast< Reference< XResultSet > 211 const * >( 212 0)), 213 getCppuType( 214 static_cast< Reference< XContentAccess > 215 const * >( 216 0)), 217 getCppuType( 218 static_cast< Reference< XRow > 219 const * >( 220 0)), 221 getCppuType( 222 static_cast< Reference< XFetchProvider > 223 const * >( 224 0)), 225 getCppuType( 226 static_cast< Reference< XFetchProviderForContentAccess > 227 const * >( 228 0)) 229 ); 230 pCollection = &aTheCollection; 231 } 232 } 233 return pCollection->getTypes(); 234 */ 235 } 236 237 //-------------------------------------------------------------------------- 238 // XServiceInfo methods. 239 //-------------------------------------------------------------------------- 240 241 XSERVICEINFO_NOFACTORY_IMPL_1( CachedContentResultSetStub, 242 OUString::createFromAscii( 243 "com.sun.star.comp.ucb.CachedContentResultSetStub" ), 244 OUString::createFromAscii( 245 CACHED_CRS_STUB_SERVICE_NAME ) ); 246 247 //----------------------------------------------------------------- 248 // XFetchProvider methods. 249 //----------------------------------------------------------------- 250 251 #define FETCH_XXX( impl_loadRow, loadInterface ) \ 252 impl_EnsureNotDisposed(); \ 253 if( !m_xResultSetOrigin.is() ) \ 254 { \ 255 OSL_ENSURE( sal_False, "broadcaster was disposed already" ); \ 256 throw RuntimeException(); \ 257 } \ 258 impl_propagateFetchSizeAndDirection( nRowCount, bDirection ); \ 259 FetchResult aRet; \ 260 aRet.StartIndex = nRowStartPosition; \ 261 aRet.Orientation = bDirection; \ 262 aRet.FetchError = FetchError::SUCCESS; /*ENDOFDATA, EXCEPTION*/ \ 263 sal_Int32 nOldOriginal_Pos = m_xResultSetOrigin->getRow(); \ 264 if( impl_isForwardOnly() ) \ 265 { \ 266 if( nOldOriginal_Pos != nRowStartPosition ) \ 267 { \ 268 /*@todo*/ \ 269 aRet.FetchError = FetchError::EXCEPTION; \ 270 return aRet; \ 271 } \ 272 if( nRowCount != 1 ) \ 273 aRet.FetchError = FetchError::EXCEPTION; \ 274 \ 275 aRet.Rows.realloc( 1 ); \ 276 \ 277 try \ 278 { \ 279 impl_loadRow( aRet.Rows[0], loadInterface ); \ 280 } \ 281 catch( SQLException& ) \ 282 { \ 283 aRet.Rows.realloc( 0 ); \ 284 aRet.FetchError = FetchError::EXCEPTION; \ 285 return aRet; \ 286 } \ 287 return aRet; \ 288 } \ 289 aRet.Rows.realloc( nRowCount ); \ 290 sal_Bool bOldOriginal_AfterLast = sal_False; \ 291 if( !nOldOriginal_Pos ) \ 292 bOldOriginal_AfterLast = m_xResultSetOrigin->isAfterLast(); \ 293 sal_Int32 nN = 1; \ 294 sal_Bool bValidNewPos = sal_False; \ 295 try \ 296 { \ 297 try \ 298 { \ 299 /*if( nOldOriginal_Pos != nRowStartPosition )*/ \ 300 bValidNewPos = m_xResultSetOrigin->absolute( nRowStartPosition ); \ 301 } \ 302 catch( SQLException& ) \ 303 { \ 304 aRet.Rows.realloc( 0 ); \ 305 aRet.FetchError = FetchError::EXCEPTION; \ 306 return aRet; \ 307 } \ 308 if( !bValidNewPos ) \ 309 { \ 310 aRet.Rows.realloc( 0 ); \ 311 aRet.FetchError = FetchError::EXCEPTION; \ 312 \ 313 /*restore old position*/ \ 314 if( nOldOriginal_Pos ) \ 315 m_xResultSetOrigin->absolute( nOldOriginal_Pos ); \ 316 else if( bOldOriginal_AfterLast ) \ 317 m_xResultSetOrigin->afterLast(); \ 318 else \ 319 m_xResultSetOrigin->beforeFirst(); \ 320 \ 321 return aRet; \ 322 } \ 323 for( ; nN <= nRowCount; ) \ 324 { \ 325 impl_loadRow( aRet.Rows[nN-1], loadInterface ); \ 326 nN++; \ 327 if( nN <= nRowCount ) \ 328 { \ 329 if( bDirection ) \ 330 { \ 331 if( !m_xResultSetOrigin->next() ) \ 332 { \ 333 aRet.Rows.realloc( nN-1 ); \ 334 aRet.FetchError = FetchError::ENDOFDATA; \ 335 break; \ 336 } \ 337 } \ 338 else \ 339 { \ 340 if( !m_xResultSetOrigin->previous() ) \ 341 { \ 342 aRet.Rows.realloc( nN-1 ); \ 343 aRet.FetchError = FetchError::ENDOFDATA; \ 344 break; \ 345 } \ 346 } \ 347 } \ 348 } \ 349 } \ 350 catch( SQLException& ) \ 351 { \ 352 aRet.Rows.realloc( nN-1 ); \ 353 aRet.FetchError = FetchError::EXCEPTION; \ 354 } \ 355 /*restore old position*/ \ 356 if( nOldOriginal_Pos ) \ 357 m_xResultSetOrigin->absolute( nOldOriginal_Pos ); \ 358 else if( bOldOriginal_AfterLast ) \ 359 m_xResultSetOrigin->afterLast(); \ 360 else \ 361 m_xResultSetOrigin->beforeFirst(); \ 362 return aRet; 363 364 FetchResult SAL_CALL CachedContentResultSetStub 365 ::fetch( sal_Int32 nRowStartPosition 366 , sal_Int32 nRowCount, sal_Bool bDirection ) 367 throw( RuntimeException ) 368 { 369 impl_init_xRowOrigin(); 370 FETCH_XXX( impl_getCurrentRowContent, m_xRowOrigin ); 371 } 372 373 sal_Int32 SAL_CALL CachedContentResultSetStub 374 ::impl_getColumnCount() 375 { 376 sal_Int32 nCount; 377 sal_Bool bCached; 378 { 379 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 380 nCount = m_nColumnCount; 381 bCached = m_bColumnCountCached; 382 } 383 if( !bCached ) 384 { 385 try 386 { 387 Reference< XResultSetMetaData > xMetaData = getMetaData(); 388 if( xMetaData.is() ) 389 nCount = xMetaData->getColumnCount(); 390 } 391 catch( SQLException& ) 392 { 393 OSL_ENSURE( sal_False, "couldn't determine the column count" ); 394 nCount = 0; 395 } 396 } 397 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 398 m_nColumnCount = nCount; 399 m_bColumnCountCached = sal_True; 400 return m_nColumnCount; 401 } 402 403 void SAL_CALL CachedContentResultSetStub 404 ::impl_getCurrentRowContent( Any& rRowContent 405 , Reference< XRow > xRow ) 406 throw ( SQLException, RuntimeException ) 407 { 408 sal_Int32 nCount = impl_getColumnCount(); 409 410 Sequence< Any > aContent( nCount ); 411 for( sal_Int32 nN = 1; nN <= nCount; nN++ ) 412 { 413 aContent[nN-1] = xRow->getObject( nN, NULL ); 414 } 415 416 rRowContent <<= aContent; 417 } 418 419 void SAL_CALL CachedContentResultSetStub 420 ::impl_propagateFetchSizeAndDirection( sal_Int32 nFetchSize, sal_Bool bFetchDirection ) 421 throw ( RuntimeException ) 422 { 423 //this is done only for the case, that there is another CachedContentResultSet in the chain of underlying ResulSets 424 425 //we do not propagate the property 'FetchSize' or 'FetchDirection' via 'setPropertyValue' from the above CachedContentResultSet to save remote calls 426 427 //if the underlying ResultSet has a property FetchSize and FetchDirection, 428 //we will set these properties, if the new given parameters are different from the last ones 429 430 if( !m_bNeedToPropagateFetchSize ) 431 return; 432 433 sal_Bool bNeedAction; 434 sal_Int32 nLastSize; 435 sal_Bool bLastDirection; 436 sal_Bool bFirstPropagationDone; 437 { 438 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 439 bNeedAction = m_bNeedToPropagateFetchSize; 440 nLastSize = m_nLastFetchSize; 441 bLastDirection = m_bLastFetchDirection; 442 bFirstPropagationDone = m_bFirstFetchSizePropagationDone; 443 } 444 if( bNeedAction ) 445 { 446 if( nLastSize == nFetchSize 447 && bLastDirection == bFetchDirection 448 && bFirstPropagationDone == sal_True ) 449 return; 450 451 if(!bFirstPropagationDone) 452 { 453 //check wether the properties 'FetchSize' and 'FetchDirection' do exist 454 455 Reference< XPropertySetInfo > xPropertySetInfo = getPropertySetInfo(); 456 sal_Bool bHasSize = xPropertySetInfo->hasPropertyByName( m_aPropertyNameForFetchSize ); 457 sal_Bool bHasDirection = xPropertySetInfo->hasPropertyByName( m_aPropertyNameForFetchDirection ); 458 459 if(!bHasSize || !bHasDirection) 460 { 461 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 462 m_bNeedToPropagateFetchSize = sal_False; 463 return; 464 } 465 } 466 467 sal_Bool bSetSize = ( nLastSize !=nFetchSize ) || !bFirstPropagationDone; 468 sal_Bool bSetDirection = ( bLastDirection !=bFetchDirection ) || !bFirstPropagationDone; 469 470 { 471 osl::Guard< osl::Mutex > aGuard( m_aMutex ); 472 m_bFirstFetchSizePropagationDone = sal_True; 473 m_nLastFetchSize = nFetchSize; 474 m_bLastFetchDirection = bFetchDirection; 475 } 476 477 if( bSetSize ) 478 { 479 Any aValue; 480 aValue <<= nFetchSize; 481 try 482 { 483 setPropertyValue( m_aPropertyNameForFetchSize, aValue ); 484 } 485 catch( com::sun::star::uno::Exception& ) {} 486 } 487 if( bSetDirection ) 488 { 489 sal_Int32 nFetchDirection = FetchDirection::FORWARD; 490 if( !bFetchDirection ) 491 nFetchDirection = FetchDirection::REVERSE; 492 Any aValue; 493 aValue <<= nFetchDirection; 494 try 495 { 496 setPropertyValue( m_aPropertyNameForFetchDirection, aValue ); 497 } 498 catch( com::sun::star::uno::Exception& ) {} 499 } 500 501 } 502 } 503 504 //----------------------------------------------------------------- 505 // XFetchProviderForContentAccess methods. 506 //----------------------------------------------------------------- 507 508 void SAL_CALL CachedContentResultSetStub 509 ::impl_getCurrentContentIdentifierString( Any& rAny 510 , Reference< XContentAccess > xContentAccess ) 511 throw ( RuntimeException ) 512 { 513 rAny <<= xContentAccess->queryContentIdentifierString(); 514 } 515 516 void SAL_CALL CachedContentResultSetStub 517 ::impl_getCurrentContentIdentifier( Any& rAny 518 , Reference< XContentAccess > xContentAccess ) 519 throw ( RuntimeException ) 520 { 521 rAny <<= xContentAccess->queryContentIdentifier(); 522 } 523 524 void SAL_CALL CachedContentResultSetStub 525 ::impl_getCurrentContent( Any& rAny 526 , Reference< XContentAccess > xContentAccess ) 527 throw ( RuntimeException ) 528 { 529 rAny <<= xContentAccess->queryContent(); 530 } 531 532 //virtual 533 FetchResult SAL_CALL CachedContentResultSetStub 534 ::fetchContentIdentifierStrings( sal_Int32 nRowStartPosition 535 , sal_Int32 nRowCount, sal_Bool bDirection ) 536 throw( com::sun::star::uno::RuntimeException ) 537 { 538 impl_init_xContentAccessOrigin(); 539 FETCH_XXX( impl_getCurrentContentIdentifierString, m_xContentAccessOrigin ); 540 } 541 542 //virtual 543 FetchResult SAL_CALL CachedContentResultSetStub 544 ::fetchContentIdentifiers( sal_Int32 nRowStartPosition 545 , sal_Int32 nRowCount, sal_Bool bDirection ) 546 throw( com::sun::star::uno::RuntimeException ) 547 { 548 impl_init_xContentAccessOrigin(); 549 FETCH_XXX( impl_getCurrentContentIdentifier, m_xContentAccessOrigin ); 550 } 551 552 //virtual 553 FetchResult SAL_CALL CachedContentResultSetStub 554 ::fetchContents( sal_Int32 nRowStartPosition 555 , sal_Int32 nRowCount, sal_Bool bDirection ) 556 throw( com::sun::star::uno::RuntimeException ) 557 { 558 impl_init_xContentAccessOrigin(); 559 FETCH_XXX( impl_getCurrentContent, m_xContentAccessOrigin ); 560 } 561 562 //-------------------------------------------------------------------------- 563 //-------------------------------------------------------------------------- 564 // class CachedContentResultSetStubFactory 565 //-------------------------------------------------------------------------- 566 //-------------------------------------------------------------------------- 567 568 CachedContentResultSetStubFactory::CachedContentResultSetStubFactory( 569 const Reference< XMultiServiceFactory > & rSMgr ) 570 { 571 m_xSMgr = rSMgr; 572 } 573 574 CachedContentResultSetStubFactory::~CachedContentResultSetStubFactory() 575 { 576 } 577 578 //-------------------------------------------------------------------------- 579 // CachedContentResultSetStubFactory XInterface methods. 580 //-------------------------------------------------------------------------- 581 582 XINTERFACE_IMPL_3( CachedContentResultSetStubFactory, 583 XTypeProvider, 584 XServiceInfo, 585 XCachedContentResultSetStubFactory ); 586 587 //-------------------------------------------------------------------------- 588 // CachedContentResultSetStubFactory XTypeProvider methods. 589 //-------------------------------------------------------------------------- 590 591 XTYPEPROVIDER_IMPL_3( CachedContentResultSetStubFactory, 592 XTypeProvider, 593 XServiceInfo, 594 XCachedContentResultSetStubFactory ); 595 596 //-------------------------------------------------------------------------- 597 // CachedContentResultSetStubFactory XServiceInfo methods. 598 //-------------------------------------------------------------------------- 599 600 XSERVICEINFO_IMPL_1( CachedContentResultSetStubFactory, 601 OUString::createFromAscii( 602 "com.sun.star.comp.ucb.CachedContentResultSetStubFactory" ), 603 OUString::createFromAscii( 604 CACHED_CRS_STUB_FACTORY_NAME ) ); 605 606 //-------------------------------------------------------------------------- 607 // Service factory implementation. 608 //-------------------------------------------------------------------------- 609 610 ONE_INSTANCE_SERVICE_FACTORY_IMPL( CachedContentResultSetStubFactory ); 611 612 //-------------------------------------------------------------------------- 613 // CachedContentResultSetStubFactory XCachedContentResultSetStubFactory methods. 614 //-------------------------------------------------------------------------- 615 616 //virtual 617 Reference< XResultSet > SAL_CALL CachedContentResultSetStubFactory 618 ::createCachedContentResultSetStub( 619 const Reference< XResultSet > & xSource ) 620 throw( RuntimeException ) 621 { 622 if( xSource.is() ) 623 { 624 Reference< XResultSet > xRet; 625 xRet = new CachedContentResultSetStub( xSource ); 626 return xRet; 627 } 628 return NULL; 629 } 630 631 632