bump product version to 4.1.6.2
[LibreOffice.git] / extensions / source / abpilot / datasourcehandling.cxx
blob9c94c01858a3792877c217120f5a9aa58fa458d4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include "abpresid.hrc"
22 #include "abptypes.hxx"
23 #include "componentmodule.hxx"
24 #include "datasourcehandling.hxx"
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <com/sun/star/container/XNameAccess.hpp>
28 #include <com/sun/star/frame/XStorable.hpp>
29 #include <com/sun/star/lang/XComponent.hpp>
30 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
31 #include <com/sun/star/sdb/DatabaseContext.hpp>
32 #include <com/sun/star/sdb/SQLContext.hpp>
33 #include <com/sun/star/sdb/XCompletedConnection.hpp>
34 #include <com/sun/star/sdb/XDatabaseRegistrations.hpp>
35 #include <com/sun/star/sdb/XDocumentDataSource.hpp>
36 #include <com/sun/star/sdbc/XConnection.hpp>
37 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
38 #include <com/sun/star/task/InteractionHandler.hpp>
39 #include <com/sun/star/uno/XNamingService.hpp>
41 #include <comphelper/interaction.hxx>
42 #include <comphelper/processfactory.hxx>
43 #include <tools/debug.hxx>
44 #include <tools/diagnose_ex.h>
45 #include <unotools/confignode.hxx>
46 #include <unotools/sharedunocomponent.hxx>
47 #include <vcl/stdtext.hxx>
49 //.........................................................................
50 namespace abp
52 //.........................................................................
54 using namespace ::utl;
55 using namespace ::comphelper;
56 using namespace ::com::sun::star::uno;
57 using namespace ::com::sun::star::lang;
58 using namespace ::com::sun::star::sdb;
59 using namespace ::com::sun::star::sdbc;
60 using namespace ::com::sun::star::task;
61 using namespace ::com::sun::star::beans;
62 using namespace ::com::sun::star::sdbcx;
63 using namespace ::com::sun::star::container;
64 using namespace ::com::sun::star::frame;
66 //=====================================================================
67 struct PackageAccessControl { };
69 //=====================================================================
70 //---------------------------------------------------------------------
71 static Reference< XDatabaseContext > lcl_getDataSourceContext( const Reference< XComponentContext >& _rxContext ) SAL_THROW (( Exception ))
73 Reference<XDatabaseContext> xContext = DatabaseContext::create(_rxContext);
74 return xContext;
77 //---------------------------------------------------------------------
78 /// creates a new data source and inserts it into the context
79 static void lcl_implCreateAndInsert(
80 const Reference< XComponentContext >& _rxContext, const OUString& _rName,
81 Reference< XPropertySet >& /* [out] */ _rxNewDataSource ) SAL_THROW (( ::com::sun::star::uno::Exception ))
83 //.............................................................
84 // get the data source context
85 Reference< XDatabaseContext > xContext = lcl_getDataSourceContext( _rxContext );
87 DBG_ASSERT( !xContext->hasByName( _rName ), "lcl_implCreateAndInsert: name already used!" );
88 (void)_rName;
90 //.............................................................
91 // create a new data source
92 Reference< XSingleServiceFactory > xFactory( xContext, UNO_QUERY );
93 Reference< XPropertySet > xNewDataSource;
94 if (xFactory.is())
95 xNewDataSource = Reference< XPropertySet >( xFactory->createInstance(), UNO_QUERY );
96 DBG_ASSERT( xNewDataSource.is(), "lcl_implCreateAndInsert: could not create a new data source!" );
98 //.............................................................
99 // insert the data source into the context
100 Reference< XNamingService > xDynamicContext( xContext, UNO_QUERY );
101 DBG_ASSERT( xDynamicContext.is(), "lcl_implCreateAndInsert: missing an interface on the context (XNamingService)!" );
102 if (xDynamicContext.is())
104 // xDynamicContext->registerObject( _rName, xNewDataSource );
105 _rxNewDataSource = xNewDataSource;
109 //---------------------------------------------------------------------
110 /// creates and inserts a data source, and sets it's URL property to the string given
111 static ODataSource lcl_implCreateAndSetURL(
112 const Reference< XComponentContext >& _rxORB, const OUString& _rName,
113 const sal_Char* _pInitialAsciiURL ) SAL_THROW (( ))
115 ODataSource aReturn( _rxORB );
118 // create the new data source
119 Reference< XPropertySet > xNewDataSource;
120 lcl_implCreateAndInsert( _rxORB, _rName, xNewDataSource );
122 //.............................................................
123 // set the URL property
124 if (xNewDataSource.is())
126 xNewDataSource->setPropertyValue(
127 OUString( "URL" ),
128 makeAny( OUString::createFromAscii( _pInitialAsciiURL ) )
132 aReturn.setDataSource( xNewDataSource, _rName,PackageAccessControl() );
134 catch(const Exception&)
136 OSL_FAIL( "lcl_implCreateAndSetURL: caught an exception while creating the data source!" );
139 return aReturn;
141 //---------------------------------------------------------------------
142 void lcl_registerDataSource(
143 const Reference< XComponentContext >& _rxORB, const OUString& _sName,
144 const OUString& _sURL ) SAL_THROW (( ::com::sun::star::uno::Exception ))
146 OSL_ENSURE( !_sName.isEmpty(), "lcl_registerDataSource: invalid name!" );
147 OSL_ENSURE( !_sURL.isEmpty(), "lcl_registerDataSource: invalid URL!" );
150 Reference< XDatabaseContext > xRegistrations( DatabaseContext::create(_rxORB) );
151 if ( xRegistrations->hasRegisteredDatabase( _sName ) )
152 xRegistrations->changeDatabaseLocation( _sName, _sURL );
153 else
154 xRegistrations->registerDatabaseLocation( _sName, _sURL );
156 catch( const Exception& )
158 DBG_UNHANDLED_EXCEPTION();
162 //=====================================================================
163 //= ODataSourceContextImpl
164 //=====================================================================
165 struct ODataSourceContextImpl
167 Reference< XComponentContext > xORB;
168 Reference< XNameAccess > xContext; /// the UNO data source context
169 StringBag aDataSourceNames; /// for quicker name checks (without the UNO overhead)
171 ODataSourceContextImpl( const Reference< XComponentContext >& _rxORB ) : xORB( _rxORB ) { }
172 ODataSourceContextImpl( const ODataSourceContextImpl& _rSource )
173 :xORB ( _rSource.xORB )
174 ,xContext ( _rSource.xContext )
179 //=====================================================================
180 //= ODataSourceContext
181 //=====================================================================
182 //---------------------------------------------------------------------
183 ODataSourceContext::ODataSourceContext(const Reference< XComponentContext >& _rxORB)
184 :m_pImpl( new ODataSourceContextImpl( _rxORB ) )
188 // create the UNO context
189 m_pImpl->xContext = Reference<XNameAccess>(
190 lcl_getDataSourceContext( _rxORB ),
191 UNO_QUERY_THROW);
193 if (m_pImpl->xContext.is())
195 // collect the data source names
196 Sequence< OUString > aDSNames = m_pImpl->xContext->getElementNames();
197 const OUString* pDSNames = aDSNames.getConstArray();
198 const OUString* pDSNamesEnd = pDSNames + aDSNames.getLength();
200 for ( ;pDSNames != pDSNamesEnd; ++pDSNames )
201 m_pImpl->aDataSourceNames.insert( *pDSNames );
204 catch( const Exception& )
206 OSL_FAIL( "ODataSourceContext::ODataSourceContext: caught an exception!" );
209 ODataSourceContext::~ODataSourceContext()
211 delete(m_pImpl);
214 //---------------------------------------------------------------------
215 OUString& ODataSourceContext::disambiguate(OUString& _rDataSourceName)
217 OUString sCheck( _rDataSourceName );
218 ConstStringBagIterator aPos = m_pImpl->aDataSourceNames.find( sCheck );
220 sal_Int32 nPostFix = 1;
221 while ( ( m_pImpl->aDataSourceNames.end() != aPos ) && ( nPostFix < 65535 ) )
222 { // there already is a data source with this name
223 sCheck = _rDataSourceName;
224 sCheck += OUString::valueOf( nPostFix++ );
226 aPos = m_pImpl->aDataSourceNames.find( sCheck );
229 _rDataSourceName = sCheck;
230 return _rDataSourceName;
233 //---------------------------------------------------------------------
234 void ODataSourceContext::getDataSourceNames( StringBag& _rNames ) const SAL_THROW (( ))
236 _rNames = m_pImpl->aDataSourceNames;
239 //---------------------------------------------------------------------
240 ODataSource ODataSourceContext::createNewLDAP( const OUString& _rName) SAL_THROW (( ))
242 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:ldap:" );
245 //---------------------------------------------------------------------
246 ODataSource ODataSourceContext::createNewMORK( const OUString& _rName) SAL_THROW (( ))
248 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:mozilla" );
251 //---------------------------------------------------------------------
252 ODataSource ODataSourceContext::createNewThunderbird( const OUString& _rName ) SAL_THROW (( ))
254 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:thunderbird" );
257 //---------------------------------------------------------------------
258 ODataSource ODataSourceContext::createNewEvolutionLdap( const OUString& _rName) SAL_THROW (( ))
260 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:evolution:ldap" );
262 //---------------------------------------------------------------------
263 ODataSource ODataSourceContext::createNewEvolutionGroupwise( const OUString& _rName) SAL_THROW (( ))
265 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:evolution:groupwise" );
267 //---------------------------------------------------------------------
268 ODataSource ODataSourceContext::createNewEvolution( const OUString& _rName) SAL_THROW (( ))
270 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:evolution:local" );
273 //---------------------------------------------------------------------
274 ODataSource ODataSourceContext::createNewKab( const OUString& _rName) SAL_THROW (( ))
276 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:kab" );
279 //---------------------------------------------------------------------
280 ODataSource ODataSourceContext::createNewMacab( const OUString& _rName) SAL_THROW (( ))
282 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:macab" );
285 //---------------------------------------------------------------------
286 ODataSource ODataSourceContext::createNewOutlook( const OUString& _rName) SAL_THROW (( ))
288 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:outlook" );
291 //---------------------------------------------------------------------
292 ODataSource ODataSourceContext::createNewOE( const OUString& _rName) SAL_THROW (( ))
294 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:address:outlookexp" );
297 //---------------------------------------------------------------------
298 ODataSource ODataSourceContext::createNewDBase( const OUString& _rName) SAL_THROW (( ))
300 return lcl_implCreateAndSetURL( m_pImpl->xORB, _rName, "sdbc:dbase:" );
303 //=====================================================================
304 //= ODataSourceImpl
305 //=====================================================================
306 struct ODataSourceImpl
308 public:
309 Reference< XComponentContext > xORB; /// the service factory
310 Reference< XPropertySet > xDataSource; /// the UNO data source
311 ::utl::SharedUNOComponent< XConnection >
312 xConnection;
313 StringBag aTables; // the cached table names
314 OUString sName;
315 sal_Bool bTablesUpToDate; // table name cache up-to-date?
317 ODataSourceImpl( const Reference< XComponentContext >& _rxORB )
318 :xORB( _rxORB )
319 ,bTablesUpToDate( sal_False )
323 ODataSourceImpl( const ODataSourceImpl& _rSource );
326 //---------------------------------------------------------------------
327 ODataSourceImpl::ODataSourceImpl( const ODataSourceImpl& _rSource )
328 :xORB( _rSource.xORB )
329 ,xDataSource( _rSource.xDataSource )
330 ,xConnection( _rSource.xConnection )
331 ,aTables( _rSource.aTables )
332 ,sName( _rSource.sName )
333 ,bTablesUpToDate( _rSource.bTablesUpToDate )
337 //=====================================================================
338 //= ODataSource
339 //=====================================================================
340 //---------------------------------------------------------------------
341 ODataSource::ODataSource( const ODataSource& _rSource )
342 :m_pImpl( NULL )
344 *this = _rSource;
347 //---------------------------------------------------------------------
348 ODataSource& ODataSource::operator=( const ODataSource& _rSource )
350 if( this != &_rSource )
352 delete m_pImpl;
353 m_pImpl = new ODataSourceImpl( *_rSource.m_pImpl );
355 return *this;
358 //---------------------------------------------------------------------
359 ODataSource::ODataSource( const Reference< XComponentContext >& _rxORB )
360 :m_pImpl(new ODataSourceImpl(_rxORB))
364 //---------------------------------------------------------------------
365 ODataSource::~ODataSource( )
367 delete m_pImpl;
370 //---------------------------------------------------------------------
371 void ODataSource::store() SAL_THROW (( ))
373 if (!isValid())
374 // nothing to do
375 return;
378 Reference< XDocumentDataSource > xDocAccess( m_pImpl->xDataSource, UNO_QUERY );
379 Reference< XStorable > xStorable;
380 if ( xDocAccess.is() )
381 xStorable = xStorable.query( xDocAccess->getDatabaseDocument() );
382 OSL_ENSURE( xStorable.is(),"DataSource is no XStorable!" );
383 if ( xStorable.is() )
384 xStorable->storeAsURL(m_pImpl->sName,Sequence<PropertyValue>());
386 catch(const Exception&)
388 OSL_FAIL( "ODataSource::registerDataSource: caught an exception while creating the data source!" );
391 //---------------------------------------------------------------------
392 void ODataSource::registerDataSource( const OUString& _sRegisteredDataSourceName) SAL_THROW (( ))
394 if (!isValid())
395 // nothing to do
396 return;
400 // invalidate ourself
401 lcl_registerDataSource(m_pImpl->xORB,_sRegisteredDataSourceName,m_pImpl->sName);
403 catch(const Exception&)
405 OSL_FAIL( "ODataSource::registerDataSource: caught an exception while creating the data source!" );
409 //---------------------------------------------------------------------
410 void ODataSource::setDataSource( const Reference< XPropertySet >& _rxDS,const OUString& _sName, PackageAccessControl )
412 if (m_pImpl->xDataSource.get() == _rxDS.get())
413 // nothing to do
414 return;
416 if ( isConnected() )
417 disconnect();
419 m_pImpl->sName = _sName;
420 m_pImpl->xDataSource = _rxDS;
423 //---------------------------------------------------------------------
424 void ODataSource::remove() SAL_THROW (( ))
426 if (!isValid())
427 // nothing to do
428 return;
432 // invalidate ourself
433 m_pImpl->xDataSource.clear();
435 catch(const Exception&)
437 OSL_FAIL( "ODataSource::remove: caught an exception while creating the data source!" );
441 //---------------------------------------------------------------------
442 sal_Bool ODataSource::rename( const OUString& _rName ) SAL_THROW (( ))
444 if (!isValid())
445 // nothing to do
446 return sal_False;
448 m_pImpl->sName = _rName;
449 return sal_True;
452 //---------------------------------------------------------------------
453 OUString ODataSource::getName() const SAL_THROW (( ))
455 if ( !isValid() )
456 return OUString();
457 return m_pImpl->sName;
460 //---------------------------------------------------------------------
461 bool ODataSource::hasTable( const OUString& _rTableName ) const
463 if ( !isConnected() )
464 return false;
466 const StringBag& aTables( getTableNames() );
467 return aTables.find( _rTableName ) != aTables.end();
470 //---------------------------------------------------------------------
471 const StringBag& ODataSource::getTableNames() const SAL_THROW (( ))
473 m_pImpl->aTables.clear();
474 if ( !isConnected() )
476 OSL_FAIL( "ODataSource::getTableNames: not connected!" );
478 else
482 // get the tables container from the connection
483 Reference< XTablesSupplier > xSuppTables( m_pImpl->xConnection.getTyped(), UNO_QUERY );
484 Reference< XNameAccess > xTables;
485 if ( xSuppTables.is( ) )
486 xTables = xSuppTables->getTables();
487 DBG_ASSERT( xTables.is(), "ODataSource::getTableNames: could not retrieve the tables container!" );
489 // get the names
490 Sequence< OUString > aTableNames;
491 if ( xTables.is( ) )
492 aTableNames = xTables->getElementNames( );
494 // copy the names
495 const OUString* pTableNames = aTableNames.getConstArray();
496 const OUString* pTableNamesEnd = pTableNames + aTableNames.getLength();
497 for (;pTableNames < pTableNamesEnd; ++pTableNames)
498 m_pImpl->aTables.insert( *pTableNames );
500 catch(const Exception&)
505 // now the table cache is up-to-date
506 m_pImpl->bTablesUpToDate = sal_True;
507 return m_pImpl->aTables;
510 //---------------------------------------------------------------------
511 sal_Bool ODataSource::connect( Window* _pMessageParent ) SAL_THROW (( ))
513 if ( isConnected( ) )
514 // nothing to do
515 return sal_True;
517 // ................................................................
518 // create the interaction handler (needed for authentication and error handling)
519 Reference< XInteractionHandler > xInteractions;
522 xInteractions.set(
523 InteractionHandler::createWithParent(m_pImpl->xORB, 0),
524 UNO_QUERY);
526 catch(const Exception&)
530 // ................................................................
531 // failure to create the interaction handler is a serious issue ...
532 if (!xInteractions.is())
534 OUString s_sInteractionHandlerServiceName("com.sun.star.task.InteractionHandler");
535 if ( _pMessageParent )
536 ShowServiceNotAvailableError( _pMessageParent, s_sInteractionHandlerServiceName, sal_True );
537 return sal_False;
540 // ................................................................
541 // open the connection
542 Any aError;
543 Reference< XConnection > xConnection;
546 Reference< XCompletedConnection > xComplConn( m_pImpl->xDataSource, UNO_QUERY );
547 DBG_ASSERT( xComplConn.is(), "ODataSource::connect: missing the XCompletedConnection interface on the data source!" );
548 if ( xComplConn.is() )
549 xConnection = xComplConn->connectWithCompletion( xInteractions );
551 catch( const SQLContext& e ) { aError <<= e; }
552 catch( const SQLWarning& e ) { aError <<= e; }
553 catch( const SQLException& e ) { aError <<= e; }
554 catch( const Exception& )
556 OSL_FAIL( "ODataSource::connect: caught a generic exception!" );
559 // ................................................................
560 // handle errors
561 if ( aError.hasValue() && _pMessageParent )
565 SQLException aException;
566 aError >>= aException;
567 if ( aException.Message.isEmpty() )
569 // prepend some context info
570 SQLContext aDetailedError;
571 aDetailedError.Message = String( ModuleRes( RID_STR_NOCONNECTION ) );
572 aDetailedError.Details = String( ModuleRes( RID_STR_PLEASECHECKSETTINGS ) );
573 aDetailedError.NextException = aError;
574 // handle (aka display) the new context info
575 xInteractions->handle( new OInteractionRequest( makeAny( aDetailedError ) ) );
577 else
579 // handle (aka display) the original error
580 xInteractions->handle( new OInteractionRequest( makeAny( aException ) ) );
583 catch( const Exception& )
585 OSL_FAIL( "ODataSource::connect: caught an exception while trying to display the error!" );
589 if ( !xConnection.is() )
590 return sal_False;
592 // ................................................................
593 // success
594 m_pImpl->xConnection.reset( xConnection );
595 m_pImpl->aTables.clear();
596 m_pImpl->bTablesUpToDate = sal_False;
598 return sal_True;
601 //---------------------------------------------------------------------
602 void ODataSource::disconnect( ) SAL_THROW (( ))
604 m_pImpl->xConnection.clear();
605 m_pImpl->aTables.clear();
606 m_pImpl->bTablesUpToDate = sal_False;
609 //---------------------------------------------------------------------
610 sal_Bool ODataSource::isConnected( ) const SAL_THROW (( ))
612 return m_pImpl->xConnection.is();
615 //---------------------------------------------------------------------
616 sal_Bool ODataSource::isValid() const SAL_THROW (( ))
618 return m_pImpl && m_pImpl->xDataSource.is();
620 //---------------------------------------------------------------------
621 Reference< XPropertySet > ODataSource::getDataSource() const SAL_THROW (( ))
623 return m_pImpl ? m_pImpl->xDataSource : Reference< XPropertySet >();
626 //.........................................................................
627 } // namespace abp
628 //.........................................................................
630 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */