xref: /trunk/main/extensions/source/abpilot/datasourcehandling.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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