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