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_extensions.hxx" 30 31 #include "abpresid.hrc" 32 #include "abptypes.hxx" 33 #include "componentmodule.hxx" 34 #include "datasourcehandling.hxx" 35 36 #include <com/sun/star/beans/XPropertySet.hpp> 37 #include <com/sun/star/container/XNameAccess.hpp> 38 #include <com/sun/star/frame/XStorable.hpp> 39 #include <com/sun/star/lang/XComponent.hpp> 40 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 41 #include <com/sun/star/lang/XSingleServiceFactory.hpp> 42 #include <com/sun/star/sdb/SQLContext.hpp> 43 #include <com/sun/star/sdb/XCompletedConnection.hpp> 44 #include <com/sun/star/sdb/XDatabaseRegistrations.hpp> 45 #include <com/sun/star/sdb/XDocumentDataSource.hpp> 46 #include <com/sun/star/sdbc/XConnection.hpp> 47 #include <com/sun/star/sdbcx/XTablesSupplier.hpp> 48 #include <com/sun/star/task/XInteractionHandler.hpp> 49 #include <com/sun/star/uno/XNamingService.hpp> 50 51 #include <comphelper/interaction.hxx> 52 #include <comphelper/componentcontext.hxx> 53 #include <tools/debug.hxx> 54 #include <tools/diagnose_ex.h> 55 #include <unotools/confignode.hxx> 56 #include <unotools/sharedunocomponent.hxx> 57 #include <vcl/stdtext.hxx> 58 59 //......................................................................... 60 namespace abp 61 { 62 //......................................................................... 63 64 using namespace ::utl; 65 using namespace ::comphelper; 66 using namespace ::com::sun::star::uno; 67 using namespace ::com::sun::star::lang; 68 using namespace ::com::sun::star::sdb; 69 using namespace ::com::sun::star::sdbc; 70 using namespace ::com::sun::star::task; 71 using namespace ::com::sun::star::beans; 72 using namespace ::com::sun::star::sdbcx; 73 using namespace ::com::sun::star::container; 74 using namespace ::com::sun::star::frame; 75 76 //===================================================================== 77 struct PackageAccessControl { }; 78 79 //===================================================================== 80 //--------------------------------------------------------------------- 81 static Reference< XNameAccess > lcl_getDataSourceContext( const Reference< XMultiServiceFactory >& _rxORB ) SAL_THROW (( Exception )) 82 { 83 Reference< XNameAccess > xContext( _rxORB->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.sdb.DatabaseContext" ) ), UNO_QUERY ); 84 DBG_ASSERT(xContext.is(), "lcl_getDataSourceContext: could not access the data source context!"); 85 return xContext; 86 } 87 88 //--------------------------------------------------------------------- 89 /// creates a new data source and inserts it into the context 90 static void lcl_implCreateAndInsert( 91 const Reference< XMultiServiceFactory >& _rxORB, const ::rtl::OUString& _rName, 92 Reference< XPropertySet >& /* [out] */ _rxNewDataSource ) SAL_THROW (( ::com::sun::star::uno::Exception )) 93 { 94 //............................................................. 95 // get the data source context 96 Reference< XNameAccess > xContext = lcl_getDataSourceContext( _rxORB ); 97 98 DBG_ASSERT( !xContext->hasByName( _rName ), "lcl_implCreateAndInsert: name already used!" ); 99 (void)_rName; 100 101 //............................................................. 102 // create a new data source 103 Reference< XSingleServiceFactory > xFactory( xContext, UNO_QUERY ); 104 Reference< XPropertySet > xNewDataSource; 105 if (xFactory.is()) 106 xNewDataSource = Reference< XPropertySet >( xFactory->createInstance(), UNO_QUERY ); 107 DBG_ASSERT( xNewDataSource.is(), "lcl_implCreateAndInsert: could not create a new data source!" ); 108 109 //............................................................. 110 // insert the data source into the context 111 Reference< XNamingService > xDynamicContext( xContext, UNO_QUERY ); 112 DBG_ASSERT( xDynamicContext.is(), "lcl_implCreateAndInsert: missing an interface on the context (XNamingService)!" ); 113 if (xDynamicContext.is()) 114 { 115 // xDynamicContext->registerObject( _rName, xNewDataSource ); 116 _rxNewDataSource = xNewDataSource; 117 } 118 } 119 120 //--------------------------------------------------------------------- 121 /// creates and inserts a data source, and sets it's URL property to the string given 122 static ODataSource lcl_implCreateAndSetURL( 123 const Reference< XMultiServiceFactory >& _rxORB, const ::rtl::OUString& _rName, 124 const sal_Char* _pInitialAsciiURL ) SAL_THROW (( )) 125 { 126 ODataSource aReturn( _rxORB ); 127 try 128 { 129 // create the new data source 130 Reference< XPropertySet > xNewDataSource; 131 lcl_implCreateAndInsert( _rxORB, _rName, xNewDataSource ); 132 133 //............................................................. 134 // set the URL property 135 if (xNewDataSource.is()) 136 { 137 xNewDataSource->setPropertyValue( 138 ::rtl::OUString::createFromAscii( "URL" ), 139 makeAny( ::rtl::OUString::createFromAscii( _pInitialAsciiURL ) ) 140 ); 141 } 142 143 aReturn.setDataSource( xNewDataSource, _rName,PackageAccessControl() ); 144 } 145 catch(const Exception&) 146 { 147 DBG_ERROR( "lcl_implCreateAndSetURL: caught an exception while creating the data source!" ); 148 } 149 150 return aReturn; 151 } 152 //--------------------------------------------------------------------- 153 void lcl_registerDataSource( 154 const Reference< XMultiServiceFactory >& _rxORB, const ::rtl::OUString& _sName, 155 const ::rtl::OUString& _sURL ) SAL_THROW (( ::com::sun::star::uno::Exception )) 156 { 157 OSL_ENSURE( _sName.getLength(), "lcl_registerDataSource: invalid name!" ); 158 OSL_ENSURE( _sURL.getLength(), "lcl_registerDataSource: invalid URL!" ); 159 try 160 { 161 162 ::comphelper::ComponentContext aContext( _rxORB ); 163 Reference< XDatabaseRegistrations > xRegistrations( 164 aContext.createComponent( "com.sun.star.sdb.DatabaseContext" ), UNO_QUERY_THROW ); 165 166 if ( xRegistrations->hasRegisteredDatabase( _sName ) ) 167 xRegistrations->changeDatabaseLocation( _sName, _sURL ); 168 else 169 xRegistrations->registerDatabaseLocation( _sName, _sURL ); 170 } 171 catch( const Exception& ) 172 { 173 DBG_UNHANDLED_EXCEPTION(); 174 } 175 } 176 177 //===================================================================== 178 //= ODataSourceContextImpl 179 //===================================================================== 180 struct ODataSourceContextImpl 181 { 182 Reference< XMultiServiceFactory > xORB; 183 Reference< XNameAccess > xContext; /// the UNO data source context 184 StringBag aDataSourceNames; /// for quicker name checks (without the UNO overhead) 185 186 ODataSourceContextImpl( const Reference< XMultiServiceFactory >& _rxORB ) : xORB( _rxORB ) { } 187 ODataSourceContextImpl( const ODataSourceContextImpl& _rSource ) 188 :xORB ( _rSource.xORB ) 189 ,xContext ( _rSource.xContext ) 190 { 191 } 192 }; 193 194 //===================================================================== 195 //= ODataSourceContext 196 //===================================================================== 197 //--------------------------------------------------------------------- 198 ODataSourceContext::ODataSourceContext(const Reference< XMultiServiceFactory >& _rxORB) 199 :m_pImpl( new ODataSourceContextImpl( _rxORB ) ) 200 { 201 try 202 { 203 // create the UNO context 204 m_pImpl->xContext = lcl_getDataSourceContext( _rxORB ); 205 206 if (m_pImpl->xContext.is()) 207 { 208 // collect the data source names 209 Sequence< ::rtl::OUString > aDSNames = m_pImpl->xContext->getElementNames(); 210 const ::rtl::OUString* pDSNames = aDSNames.getConstArray(); 211 const ::rtl::OUString* pDSNamesEnd = pDSNames + aDSNames.getLength(); 212 213 for ( ;pDSNames != pDSNamesEnd; ++pDSNames ) 214 m_pImpl->aDataSourceNames.insert( *pDSNames ); 215 } 216 } 217 catch( const Exception& ) 218 { 219 DBG_ERROR( "ODataSourceContext::ODataSourceContext: caught an exception!" ); 220 } 221 } 222 223 //--------------------------------------------------------------------- 224 ::rtl::OUString& ODataSourceContext::disambiguate(::rtl::OUString& _rDataSourceName) 225 { 226 ::rtl::OUString sCheck( _rDataSourceName ); 227 ConstStringBagIterator aPos = m_pImpl->aDataSourceNames.find( sCheck ); 228 229 sal_Int32 nPostFix = 1; 230 while ( ( m_pImpl->aDataSourceNames.end() != aPos ) && ( nPostFix < 65535 ) ) 231 { // there already is a data source with this name 232 sCheck = _rDataSourceName; 233 sCheck += ::rtl::OUString::valueOf( nPostFix++ ); 234 235 aPos = m_pImpl->aDataSourceNames.find( sCheck ); 236 } 237 238 _rDataSourceName = sCheck; 239 return _rDataSourceName; 240 } 241 242 //--------------------------------------------------------------------- 243 void ODataSourceContext::getDataSourceNames( StringBag& _rNames ) const SAL_THROW (( )) 244 { 245 _rNames = m_pImpl->aDataSourceNames; 246 } 247 248 //--------------------------------------------------------------------- 249 ODataSource ODataSourceContext::createNewLDAP( const ::rtl::OUString& _rName) SAL_THROW (( )) 250 { 251 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:ldap:" ); 252 } 253 254 //--------------------------------------------------------------------- 255 ODataSource ODataSourceContext::createNewMORK( const ::rtl::OUString& _rName) SAL_THROW (( )) 256 { 257 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:mozilla" ); 258 } 259 260 //--------------------------------------------------------------------- 261 ODataSource ODataSourceContext::createNewThunderbird( const ::rtl::OUString& _rName ) SAL_THROW (( )) 262 { 263 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:thunderbird" ); 264 } 265 266 //--------------------------------------------------------------------- 267 ODataSource ODataSourceContext::createNewEvolutionLdap( const ::rtl::OUString& _rName) SAL_THROW (( )) 268 { 269 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:evolution:ldap" ); 270 } 271 //--------------------------------------------------------------------- 272 ODataSource ODataSourceContext::createNewEvolutionGroupwise( const ::rtl::OUString& _rName) SAL_THROW (( )) 273 { 274 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:evolution:groupwise" ); 275 } 276 //--------------------------------------------------------------------- 277 ODataSource ODataSourceContext::createNewEvolution( const ::rtl::OUString& _rName) SAL_THROW (( )) 278 { 279 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:evolution:local" ); 280 } 281 282 //--------------------------------------------------------------------- 283 ODataSource ODataSourceContext::createNewKab( const ::rtl::OUString& _rName) SAL_THROW (( )) 284 { 285 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:kab" ); 286 } 287 288 //--------------------------------------------------------------------- 289 ODataSource ODataSourceContext::createNewMacab( const ::rtl::OUString& _rName) SAL_THROW (( )) 290 { 291 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:macab" ); 292 } 293 294 //--------------------------------------------------------------------- 295 ODataSource ODataSourceContext::createNewOutlook( const ::rtl::OUString& _rName) SAL_THROW (( )) 296 { 297 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:outlook" ); 298 } 299 300 //--------------------------------------------------------------------- 301 ODataSource ODataSourceContext::createNewOE( const ::rtl::OUString& _rName) SAL_THROW (( )) 302 { 303 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:outlookexp" ); 304 } 305 306 //--------------------------------------------------------------------- 307 ODataSource ODataSourceContext::createNewDBase( const ::rtl::OUString& _rName) SAL_THROW (( )) 308 { 309 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:dbase:" ); 310 } 311 312 //===================================================================== 313 //= ODataSourceImpl 314 //===================================================================== 315 struct ODataSourceImpl 316 { 317 public: 318 Reference< XMultiServiceFactory > xORB; /// the service factory 319 Reference< XPropertySet > xDataSource; /// the UNO data source 320 ::utl::SharedUNOComponent< XConnection > 321 xConnection; 322 StringBag aTables; // the cached table names 323 ::rtl::OUString sName; 324 sal_Bool bTablesUpToDate; // table name cache up-to-date? 325 326 ODataSourceImpl( const Reference< XMultiServiceFactory >& _rxORB ) 327 :xORB( _rxORB ) 328 ,bTablesUpToDate( sal_False ) 329 { 330 } 331 332 ODataSourceImpl( const ODataSourceImpl& _rSource ); 333 }; 334 335 //--------------------------------------------------------------------- 336 ODataSourceImpl::ODataSourceImpl( const ODataSourceImpl& _rSource ) 337 :xORB( _rSource.xORB ) 338 ,xDataSource( _rSource.xDataSource ) 339 ,xConnection( _rSource.xConnection ) 340 ,aTables( _rSource.aTables ) 341 ,sName( _rSource.sName ) 342 ,bTablesUpToDate( _rSource.bTablesUpToDate ) 343 { 344 } 345 346 //===================================================================== 347 //= ODataSource 348 //===================================================================== 349 //--------------------------------------------------------------------- 350 ODataSource::ODataSource( const ODataSource& _rSource ) 351 :m_pImpl( NULL ) 352 { 353 *this = _rSource; 354 } 355 356 //--------------------------------------------------------------------- 357 ODataSource& ODataSource::operator=( const ODataSource& _rSource ) 358 { 359 delete m_pImpl; 360 m_pImpl = new ODataSourceImpl( *_rSource.m_pImpl ); 361 362 return *this; 363 } 364 365 //--------------------------------------------------------------------- 366 ODataSource::ODataSource( const Reference< XMultiServiceFactory >& _rxORB ) 367 :m_pImpl(new ODataSourceImpl(_rxORB)) 368 { 369 } 370 371 //--------------------------------------------------------------------- 372 ODataSource::~ODataSource( ) 373 { 374 delete m_pImpl; 375 } 376 377 //--------------------------------------------------------------------- 378 void ODataSource::store() SAL_THROW (( )) 379 { 380 if (!isValid()) 381 // nothing to do 382 return; 383 try 384 { 385 Reference< XDocumentDataSource > xDocAccess( m_pImpl->xDataSource, UNO_QUERY ); 386 Reference< XStorable > xStorable; 387 if ( xDocAccess.is() ) 388 xStorable = xStorable.query( xDocAccess->getDatabaseDocument() ); 389 OSL_ENSURE( xStorable.is(),"DataSource is no XStorable!" ); 390 if ( xStorable.is() ) 391 xStorable->storeAsURL(m_pImpl->sName,Sequence<PropertyValue>()); 392 } 393 catch(const Exception&) 394 { 395 DBG_ERROR( "ODataSource::registerDataSource: caught an exception while creating the data source!" ); 396 } 397 } 398 //--------------------------------------------------------------------- 399 void ODataSource::registerDataSource( const ::rtl::OUString& _sRegisteredDataSourceName) SAL_THROW (( )) 400 { 401 if (!isValid()) 402 // nothing to do 403 return; 404 405 try 406 { 407 // invalidate ourself 408 lcl_registerDataSource(m_pImpl->xORB,_sRegisteredDataSourceName,m_pImpl->sName); 409 } 410 catch(const Exception&) 411 { 412 DBG_ERROR( "ODataSource::registerDataSource: caught an exception while creating the data source!" ); 413 } 414 } 415 416 //--------------------------------------------------------------------- 417 void ODataSource::setDataSource( const Reference< XPropertySet >& _rxDS,const ::rtl::OUString& _sName, PackageAccessControl ) 418 { 419 if (m_pImpl->xDataSource.get() == _rxDS.get()) 420 // nothing to do 421 return; 422 423 if ( isConnected() ) 424 disconnect(); 425 426 m_pImpl->sName = _sName; 427 m_pImpl->xDataSource = _rxDS; 428 } 429 430 //--------------------------------------------------------------------- 431 void ODataSource::remove() SAL_THROW (( )) 432 { 433 if (!isValid()) 434 // nothing to do 435 return; 436 437 try 438 { 439 // invalidate ourself 440 m_pImpl->xDataSource.clear(); 441 } 442 catch(const Exception&) 443 { 444 DBG_ERROR( "ODataSource::remove: caught an exception while creating the data source!" ); 445 } 446 } 447 448 //--------------------------------------------------------------------- 449 sal_Bool ODataSource::rename( const ::rtl::OUString& _rName ) SAL_THROW (( )) 450 { 451 if (!isValid()) 452 // nothing to do 453 return sal_False; 454 455 m_pImpl->sName = _rName; 456 return sal_True; 457 } 458 459 //--------------------------------------------------------------------- 460 ::rtl::OUString ODataSource::getName() const SAL_THROW (( )) 461 { 462 if ( !isValid() ) 463 return ::rtl::OUString(); 464 return m_pImpl->sName; 465 } 466 467 //--------------------------------------------------------------------- 468 bool ODataSource::hasTable( const ::rtl::OUString& _rTableName ) const 469 { 470 if ( !isConnected() ) 471 return false; 472 473 const StringBag& aTables( getTableNames() ); 474 return aTables.find( _rTableName ) != aTables.end(); 475 } 476 477 //--------------------------------------------------------------------- 478 const StringBag& ODataSource::getTableNames() const SAL_THROW (( )) 479 { 480 m_pImpl->aTables.clear(); 481 if ( !isConnected() ) 482 { 483 DBG_ERROR( "ODataSource::getTableNames: not connected!" ); 484 } 485 else 486 { 487 try 488 { 489 // get the tables container from the connection 490 Reference< XTablesSupplier > xSuppTables( m_pImpl->xConnection.getTyped(), UNO_QUERY ); 491 Reference< XNameAccess > xTables; 492 if ( xSuppTables.is( ) ) 493 xTables = xSuppTables->getTables(); 494 DBG_ASSERT( xTables.is(), "ODataSource::getTableNames: could not retrieve the tables container!" ); 495 496 // get the names 497 Sequence< ::rtl::OUString > aTableNames; 498 if ( xTables.is( ) ) 499 aTableNames = xTables->getElementNames( ); 500 501 // copy the names 502 const ::rtl::OUString* pTableNames = aTableNames.getConstArray(); 503 const ::rtl::OUString* pTableNamesEnd = pTableNames + aTableNames.getLength(); 504 for (;pTableNames < pTableNamesEnd; ++pTableNames) 505 m_pImpl->aTables.insert( *pTableNames ); 506 } 507 catch(const Exception&) 508 { 509 } 510 } 511 512 // now the table cache is up-to-date 513 m_pImpl->bTablesUpToDate = sal_True; 514 return m_pImpl->aTables; 515 } 516 517 //--------------------------------------------------------------------- 518 sal_Bool ODataSource::connect( Window* _pMessageParent ) SAL_THROW (( )) 519 { 520 if ( isConnected( ) ) 521 // nothing to do 522 return sal_True; 523 524 // ................................................................ 525 // create the interaction handler (needed for authentication and error handling) 526 static ::rtl::OUString s_sInteractionHandlerServiceName = ::rtl::OUString::createFromAscii("com.sun.star.task.InteractionHandler"); 527 Reference< XInteractionHandler > xInteractions; 528 try 529 { 530 xInteractions = Reference< XInteractionHandler >( 531 m_pImpl->xORB->createInstance( s_sInteractionHandlerServiceName ), 532 UNO_QUERY 533 ); 534 } 535 catch(const Exception&) 536 { 537 } 538 539 // ................................................................ 540 // failure to create the interaction handler is a serious issue ... 541 if (!xInteractions.is()) 542 { 543 if ( _pMessageParent ) 544 ShowServiceNotAvailableError( _pMessageParent, s_sInteractionHandlerServiceName, sal_True ); 545 return sal_False; 546 } 547 548 // ................................................................ 549 // open the connection 550 Any aError; 551 Reference< XConnection > xConnection; 552 try 553 { 554 Reference< XCompletedConnection > xComplConn( m_pImpl->xDataSource, UNO_QUERY ); 555 DBG_ASSERT( xComplConn.is(), "ODataSource::connect: missing the XCompletedConnection interface on the data source!" ); 556 if ( xComplConn.is() ) 557 xConnection = xComplConn->connectWithCompletion( xInteractions ); 558 } 559 catch( const SQLContext& e ) { aError <<= e; } 560 catch( const SQLWarning& e ) { aError <<= e; } 561 catch( const SQLException& e ) { aError <<= e; } 562 catch( const Exception& ) 563 { 564 DBG_ERROR( "ODataSource::connect: caught a generic exception!" ); 565 } 566 567 // ................................................................ 568 // handle errors 569 if ( aError.hasValue() && _pMessageParent ) 570 { 571 try 572 { 573 SQLException aException; 574 aError >>= aException; 575 if ( !aException.Message.getLength() ) 576 { 577 // prepend some context info 578 SQLContext aDetailedError; 579 aDetailedError.Message = String( ModuleRes( RID_STR_NOCONNECTION ) ); 580 aDetailedError.Details = String( ModuleRes( RID_STR_PLEASECHECKSETTINGS ) ); 581 aDetailedError.NextException = aError; 582 // handle (aka display) the new context info 583 xInteractions->handle( new OInteractionRequest( makeAny( aDetailedError ) ) ); 584 } 585 else 586 { 587 // handle (aka display) the original error 588 xInteractions->handle( new OInteractionRequest( makeAny( aException ) ) ); 589 } 590 } 591 catch( const Exception& ) 592 { 593 DBG_ERROR( "ODataSource::connect: caught an exception while trying to display the error!" ); 594 } 595 } 596 597 if ( !xConnection.is() ) 598 return sal_False; 599 600 // ................................................................ 601 // success 602 m_pImpl->xConnection.reset( xConnection ); 603 m_pImpl->aTables.clear(); 604 m_pImpl->bTablesUpToDate = sal_False; 605 606 return sal_True; 607 } 608 609 //--------------------------------------------------------------------- 610 void ODataSource::disconnect( ) SAL_THROW (( )) 611 { 612 m_pImpl->xConnection.clear(); 613 m_pImpl->aTables.clear(); 614 m_pImpl->bTablesUpToDate = sal_False; 615 } 616 617 //--------------------------------------------------------------------- 618 sal_Bool ODataSource::isConnected( ) const SAL_THROW (( )) 619 { 620 return m_pImpl->xConnection.is(); 621 } 622 623 //--------------------------------------------------------------------- 624 sal_Bool ODataSource::isValid() const SAL_THROW (( )) 625 { 626 return m_pImpl && m_pImpl->xDataSource.is(); 627 } 628 //--------------------------------------------------------------------- 629 Reference< XPropertySet > ODataSource::getDataSource() const SAL_THROW (( )) 630 { 631 return m_pImpl ? m_pImpl->xDataSource : Reference< XPropertySet >(); 632 } 633 634 //......................................................................... 635 } // namespace abp 636 //......................................................................... 637 638