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