1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
20 #include "DbAdminImpl.hxx"
23 #include <svl/poolitem.hxx>
24 #include <svl/itempool.hxx>
25 #include <svl/stritem.hxx>
26 #include <svl/intitem.hxx>
27 #include <svl/eitem.hxx>
28 #include <IItemSetHelper.hxx>
29 #include <UITools.hxx>
30 #include <core_resource.hxx>
31 #include <strings.hrc>
32 #include <strings.hxx>
33 #include <dsitems.hxx>
34 #include "dsnItem.hxx"
35 #include "optionalboolitem.hxx"
36 #include <stringlistitem.hxx>
37 #include <OAuthenticationContinuation.hxx>
39 #include <com/sun/star/beans/PropertyAttribute.hpp>
40 #include <com/sun/star/frame/XStorable.hpp>
41 #include <com/sun/star/sdb/DatabaseContext.hpp>
42 #include <com/sun/star/sdb/SQLContext.hpp>
43 #include <com/sun/star/sdbc/ConnectionPool.hpp>
44 #include <com/sun/star/sdbc/XDriver.hpp>
45 #include <com/sun/star/task/InteractionHandler.hpp>
46 #include <com/sun/star/ucb/AuthenticationRequest.hpp>
48 #include <comphelper/interaction.hxx>
49 #include <comphelper/sequence.hxx>
50 #include <connectivity/DriversConfig.hxx>
51 #include <connectivity/dbexception.hxx>
52 #include <osl/file.hxx>
53 #include <comphelper/diagnose_ex.hxx>
54 #include <osl/diagnose.h>
55 #include <sal/log.hxx>
56 #include <typelib/typedescription.hxx>
57 #include <vcl/svapp.hxx>
58 #include <vcl/stdtext.hxx>
59 #include <vcl/weld.hxx>
64 #include <o3tl/functional.hxx>
68 using namespace ::dbtools
;
69 using namespace com::sun::star::uno
;
70 using namespace com::sun::star
;
71 using namespace com::sun::star::ucb
;
72 using namespace com::sun::star::task
;
73 using namespace com::sun::star::sdbc
;
74 using namespace com::sun::star::sdb
;
75 using namespace com::sun::star::lang
;
76 using namespace com::sun::star::beans
;
77 using namespace com::sun::star::util
;
78 using namespace com::sun::star::container
;
79 using namespace com::sun::star::frame
;
83 bool implCheckItemType( SfxItemSet
const & _rSet
, const sal_uInt16 _nId
, const std::function
<bool ( const SfxPoolItem
* )>& isItemType
)
85 bool bCorrectType
= false;
87 SfxItemPool
* pPool
= _rSet
.GetPool();
88 OSL_ENSURE( pPool
, "implCheckItemType: invalid item pool!" );
91 const SfxPoolItem
& rDefItem
= pPool
->GetDefaultItem( _nId
);
92 bCorrectType
= isItemType(&rDefItem
);
97 void lcl_putProperty(const Reference
< XPropertySet
>& _rxSet
, const OUString
& _rName
, const Any
& _rValue
)
102 _rxSet
->setPropertyValue(_rName
, _rValue
);
106 SAL_WARN("dbaccess", "ODbAdminDialog::implTranslateProperty: could not set the property "
112 OUString
lcl_createHostWithPort(const SfxStringItem
* _pHostName
,const SfxInt32Item
* _pPortNumber
)
116 if ( _pHostName
&& _pHostName
->GetValue().getLength() )
117 sNewUrl
= _pHostName
->GetValue();
121 sNewUrl
+= ":" + OUString::number(_pPortNumber
->GetValue());
128 // ODbDataSourceAdministrationHelper
129 ODbDataSourceAdministrationHelper::ODbDataSourceAdministrationHelper(const Reference
< XComponentContext
>& _xORB
, weld::Window
* pParent
, weld::Window
* pTopParent
, IItemSetHelper
* _pItemSetHelper
)
132 , m_pItemSetHelper(_pItemSetHelper
)
134 /// initialize the property translation map
135 // direct properties of a data source
136 m_aDirectPropTranslator
.emplace( DSID_CONNECTURL
, PROPERTY_URL
);
137 m_aDirectPropTranslator
.emplace( DSID_NAME
, PROPERTY_NAME
);
138 m_aDirectPropTranslator
.emplace( DSID_USER
, PROPERTY_USER
);
139 m_aDirectPropTranslator
.emplace( DSID_PASSWORD
, PROPERTY_PASSWORD
);
140 m_aDirectPropTranslator
.emplace( DSID_PASSWORDREQUIRED
, PROPERTY_ISPASSWORDREQUIRED
);
141 m_aDirectPropTranslator
.emplace( DSID_TABLEFILTER
, PROPERTY_TABLEFILTER
);
142 m_aDirectPropTranslator
.emplace( DSID_READONLY
, PROPERTY_ISREADONLY
);
143 m_aDirectPropTranslator
.emplace( DSID_SUPPRESSVERSIONCL
, PROPERTY_SUPPRESSVERSIONCL
);
145 // implicit properties, to be found in the direct property "Info"
146 m_aIndirectPropTranslator
.emplace( DSID_JDBCDRIVERCLASS
, INFO_JDBCDRIVERCLASS
);
147 m_aIndirectPropTranslator
.emplace( DSID_TEXTFILEEXTENSION
, INFO_TEXTFILEEXTENSION
);
148 m_aIndirectPropTranslator
.emplace( DSID_CHARSET
, INFO_CHARSET
);
149 m_aIndirectPropTranslator
.emplace( DSID_TEXTFILEHEADER
, INFO_TEXTFILEHEADER
);
150 m_aIndirectPropTranslator
.emplace( DSID_FIELDDELIMITER
, INFO_FIELDDELIMITER
);
151 m_aIndirectPropTranslator
.emplace( DSID_TEXTDELIMITER
, INFO_TEXTDELIMITER
);
152 m_aIndirectPropTranslator
.emplace( DSID_DECIMALDELIMITER
, INFO_DECIMALDELIMITER
);
153 m_aIndirectPropTranslator
.emplace( DSID_THOUSANDSDELIMITER
, INFO_THOUSANDSDELIMITER
);
154 m_aIndirectPropTranslator
.emplace( DSID_SHOWDELETEDROWS
, INFO_SHOWDELETEDROWS
);
155 m_aIndirectPropTranslator
.emplace( DSID_ALLOWLONGTABLENAMES
, INFO_ALLOWLONGTABLENAMES
);
156 m_aIndirectPropTranslator
.emplace( DSID_ADDITIONALOPTIONS
, INFO_ADDITIONALOPTIONS
);
157 m_aIndirectPropTranslator
.emplace( DSID_SQL92CHECK
, PROPERTY_ENABLESQL92CHECK
);
158 m_aIndirectPropTranslator
.emplace( DSID_AUTOINCREMENTVALUE
, PROPERTY_AUTOINCREMENTCREATION
);
159 m_aIndirectPropTranslator
.emplace( DSID_AUTORETRIEVEVALUE
, INFO_AUTORETRIEVEVALUE
);
160 m_aIndirectPropTranslator
.emplace( DSID_AUTORETRIEVEENABLED
, INFO_AUTORETRIEVEENABLED
);
161 m_aIndirectPropTranslator
.emplace( DSID_APPEND_TABLE_ALIAS
, INFO_APPEND_TABLE_ALIAS
);
162 m_aIndirectPropTranslator
.emplace( DSID_AS_BEFORE_CORRNAME
, INFO_AS_BEFORE_CORRELATION_NAME
);
163 m_aIndirectPropTranslator
.emplace( DSID_CHECK_REQUIRED_FIELDS
, INFO_FORMS_CHECK_REQUIRED_FIELDS
);
164 m_aIndirectPropTranslator
.emplace( DSID_ESCAPE_DATETIME
, INFO_ESCAPE_DATETIME
);
165 m_aIndirectPropTranslator
.emplace( DSID_PRIMARY_KEY_SUPPORT
, OUString("PrimaryKeySupport") );
166 m_aIndirectPropTranslator
.emplace( DSID_PARAMETERNAMESUBST
, INFO_PARAMETERNAMESUBST
);
167 m_aIndirectPropTranslator
.emplace( DSID_IGNOREDRIVER_PRIV
, INFO_IGNOREDRIVER_PRIV
);
168 m_aIndirectPropTranslator
.emplace( DSID_BOOLEANCOMPARISON
, PROPERTY_BOOLEANCOMPARISONMODE
);
169 m_aIndirectPropTranslator
.emplace( DSID_ENABLEOUTERJOIN
, PROPERTY_ENABLEOUTERJOIN
);
170 m_aIndirectPropTranslator
.emplace( DSID_CATALOG
, PROPERTY_USECATALOGINSELECT
);
171 m_aIndirectPropTranslator
.emplace( DSID_SCHEMA
, PROPERTY_USESCHEMAINSELECT
);
172 m_aIndirectPropTranslator
.emplace( DSID_INDEXAPPENDIX
, OUString("AddIndexAppendix") );
173 m_aIndirectPropTranslator
.emplace( DSID_DOSLINEENDS
, OUString("PreferDosLikeLineEnds") );
174 m_aIndirectPropTranslator
.emplace( DSID_CONN_SOCKET
, OUString("LocalSocket") );
175 m_aIndirectPropTranslator
.emplace( DSID_NAMED_PIPE
, OUString("NamedPipe") );
176 m_aIndirectPropTranslator
.emplace( DSID_RESPECTRESULTSETTYPE
, OUString("RespectDriverResultSetType") );
177 m_aIndirectPropTranslator
.emplace( DSID_MAX_ROW_SCAN
, OUString("MaxRowScan") );
179 // extra settings for ODBC
180 m_aIndirectPropTranslator
.emplace( DSID_USECATALOG
, INFO_USECATALOG
);
181 // extra settings for an LDAP address book
182 m_aIndirectPropTranslator
.emplace( DSID_CONN_LDAP_BASEDN
, INFO_CONN_LDAP_BASEDN
);
183 m_aIndirectPropTranslator
.emplace( DSID_CONN_LDAP_ROWCOUNT
, INFO_CONN_LDAP_ROWCOUNT
);
184 m_aIndirectPropTranslator
.emplace( DSID_CONN_LDAP_USESSL
, OUString("UseSSL") );
185 m_aIndirectPropTranslator
.emplace( DSID_DOCUMENT_URL
, PROPERTY_URL
);
188 m_aIndirectPropTranslator
.emplace( DSID_IGNORECURRENCY
, OUString("IgnoreCurrency") );
192 m_xDatabaseContext
= DatabaseContext::create(m_xContext
);
194 catch(const Exception
&)
196 ShowServiceNotAvailableError(pTopParent
, u
"com.sun.star.sdb.DatabaseContext", true);
200 bool ODbDataSourceAdministrationHelper::getCurrentSettings(Sequence
< PropertyValue
>& _rDriverParam
)
202 OSL_ENSURE(m_pItemSetHelper
->getOutputSet(), "ODbDataSourceAdministrationHelper::getCurrentSettings : not to be called without an example set!");
203 if (!m_pItemSetHelper
->getOutputSet())
206 std::vector
< PropertyValue
> aReturn
;
207 // collecting this in a vector because it has a push_back, in opposite to sequences
209 // user: DSID_USER -> "user"
210 const SfxStringItem
* pUser
= m_pItemSetHelper
->getOutputSet()->GetItem
<SfxStringItem
>(DSID_USER
);
211 if (pUser
&& pUser
->GetValue().getLength())
212 aReturn
.emplace_back( "user", 0,
213 Any(pUser
->GetValue()), PropertyState_DIRECT_VALUE
);
215 // check if the connection type requires a password
216 if (hasAuthentication(*m_pItemSetHelper
->getOutputSet()))
218 // password: DSID_PASSWORD -> password
219 const SfxStringItem
* pPassword
= m_pItemSetHelper
->getOutputSet()->GetItem
<SfxStringItem
>(DSID_PASSWORD
);
220 OUString sPassword
= pPassword
? pPassword
->GetValue() : OUString();
221 const SfxBoolItem
* pPasswordRequired
= m_pItemSetHelper
->getOutputSet()->GetItem
<SfxBoolItem
>(DSID_PASSWORDREQUIRED
);
222 // if the set does not contain a password, but the item set says it requires one, ask the user
223 if ((!pPassword
|| !pPassword
->GetValue().getLength()) && (pPasswordRequired
&& pPasswordRequired
->GetValue()))
225 const SfxStringItem
* pName
= m_pItemSetHelper
->getOutputSet()->GetItem
<SfxStringItem
>(DSID_NAME
);
227 Reference
< XModel
> xModel( getDataSourceOrModel( m_xDatasource
), UNO_QUERY_THROW
);
228 ::comphelper::NamedValueCollection
aArgs( xModel
->getArgs() );
229 Reference
< XInteractionHandler
> xHandler( aArgs
.getOrDefault( "InteractionHandler", Reference
< XInteractionHandler
>() ) );
231 if ( !xHandler
.is() )
233 // instantiate the default SDB interaction handler
234 xHandler
= task::InteractionHandler::createWithParent(m_xContext
, m_pParent
->GetXWindow());
237 OUString sName
= pName
? pName
->GetValue() : OUString();
238 OUString
sLoginRequest(DBA_RES(STR_ENTER_CONNECTION_PASSWORD
));
239 OUString sTemp
= sName
;
240 sName
= ::dbaui::getStrippedDatabaseName(nullptr,sTemp
);
241 if ( !sName
.isEmpty() )
242 sLoginRequest
= sLoginRequest
.replaceAll("$name$", sName
);
245 sLoginRequest
= sLoginRequest
.replaceAll("\"$name$\"", "");
246 // ensure that in other languages the string will be deleted
247 sLoginRequest
= sLoginRequest
.replaceAll("$name$", "");
251 AuthenticationRequest aRequest
;
252 aRequest
.ServerName
= sName
;
253 aRequest
.Diagnostic
= sLoginRequest
;
254 aRequest
.HasRealm
= false;
256 aRequest
.HasUserName
= pUser
!= nullptr;
257 aRequest
.UserName
= pUser
? pUser
->GetValue() : OUString();
258 aRequest
.HasPassword
= true;
260 aRequest
.HasAccount
= false;
263 rtl::Reference
<comphelper::OInteractionRequest
> pRequest
= new comphelper::OInteractionRequest(Any(aRequest
));
265 // build an interaction request
266 // two continuations (Ok and Cancel)
267 ::rtl::Reference
< comphelper::OInteractionAbort
> pAbort
= new comphelper::OInteractionAbort
;
268 ::rtl::Reference
< dbaccess::OAuthenticationContinuation
> pAuthenticate
= new dbaccess::OAuthenticationContinuation
;
269 pAuthenticate
->setCanChangeUserName( false );
270 pAuthenticate
->setRememberPassword( RememberAuthentication_SESSION
);
273 pRequest
->addContinuation(pAbort
);
274 pRequest
->addContinuation(pAuthenticate
);
276 // handle the request
279 SolarMutexGuard aSolarGuard
;
280 // release the mutex when calling the handler, it may need to lock the SolarMutex
281 xHandler
->handle(pRequest
);
285 DBG_UNHANDLED_EXCEPTION("dbaccess");
287 if (!pAuthenticate
->wasSelected())
290 sPassword
= pAuthenticate
->getPassword();
291 if (pAuthenticate
->getRememberPassword())
292 m_pItemSetHelper
->getWriteOutputSet()->Put(SfxStringItem(DSID_PASSWORD
, sPassword
));
295 if (!sPassword
.isEmpty())
296 aReturn
.emplace_back( "password", 0,
297 Any(sPassword
), PropertyState_DIRECT_VALUE
);
300 if ( !aReturn
.empty() )
301 _rDriverParam
= comphelper::containerToSequence(aReturn
);
303 // append all the other stuff (charset etc.)
304 fillDatasourceInfo(*m_pItemSetHelper
->getOutputSet(), _rDriverParam
);
309 void ODbDataSourceAdministrationHelper::successfullyConnected()
311 OSL_ENSURE(m_pItemSetHelper
->getOutputSet(), "ODbDataSourceAdministrationHelper::successfullyConnected: not to be called without an example set!");
312 if (!m_pItemSetHelper
->getOutputSet())
315 if (hasAuthentication(*m_pItemSetHelper
->getOutputSet()))
317 const SfxStringItem
* pPassword
= m_pItemSetHelper
->getOutputSet()->GetItem
<SfxStringItem
>(DSID_PASSWORD
);
318 if (pPassword
&& (0 != pPassword
->GetValue().getLength()))
320 OUString sPassword
= pPassword
->GetValue();
322 Reference
< XPropertySet
> xCurrentDatasource
= getCurrentDataSource();
323 lcl_putProperty(xCurrentDatasource
,m_aDirectPropTranslator
[DSID_PASSWORD
], Any(sPassword
));
328 void ODbDataSourceAdministrationHelper::clearPassword()
330 if (m_pItemSetHelper
->getWriteOutputSet())
331 m_pItemSetHelper
->getWriteOutputSet()->ClearItem(DSID_PASSWORD
);
334 std::pair
< Reference
<XConnection
>,bool> ODbDataSourceAdministrationHelper::createConnection()
336 std::pair
< Reference
<XConnection
>,bool> aRet
;
338 Sequence
< PropertyValue
> aConnectionParams
;
339 if ( getCurrentSettings(aConnectionParams
) )
342 // fill the table list with this connection information
343 SQLExceptionInfo aErrorInfo
;
346 weld::WaitObject
aWaitCursor(m_pParent
);
347 aRet
.first
= getDriver()->connect(getConnectionURL(), aConnectionParams
);
350 catch (const SQLContext
& e
) { aErrorInfo
= SQLExceptionInfo(e
); }
351 catch (const SQLWarning
& e
) { aErrorInfo
= SQLExceptionInfo(e
); }
352 catch (const SQLException
& e
) { aErrorInfo
= SQLExceptionInfo(e
); }
354 showError(aErrorInfo
,m_pParent
->GetXWindow(),getORB());
356 if ( aRet
.first
.is() )
357 successfullyConnected();// notify the admindlg to save the password
362 Reference
< XDriver
> ODbDataSourceAdministrationHelper::getDriver()
364 return getDriver(getConnectionURL());
367 Reference
< XDriver
> ODbDataSourceAdministrationHelper::getDriver(const OUString
& _sURL
)
369 // get the global DriverManager
370 Reference
< XConnectionPool
> xDriverManager
;
372 OUString sCurrentActionError
= DBA_RES(STR_COULDNOTCREATE_DRIVERMANAGER
);
373 sCurrentActionError
= sCurrentActionError
.replaceFirst("#servicename#", "com.sun.star.sdbc.ConnectionPool");
377 xDriverManager
.set( ConnectionPool::create( getORB() ) );
379 catch (const Exception
&)
381 css::uno::Any anyEx
= cppu::getCaughtException();
382 // wrap the exception into an SQLException
383 throw SQLException(sCurrentActionError
, getORB(), "S1000", 0, anyEx
);
386 Reference
< XDriver
> xDriver
= xDriverManager
->getDriverByURL(_sURL
);
389 sCurrentActionError
= DBA_RES(STR_NOREGISTEREDDRIVER
);
390 sCurrentActionError
= sCurrentActionError
.replaceFirst("#connurl#", _sURL
);
391 // will be caught and translated into an SQLContext exception
392 throw SQLException(sCurrentActionError
, getORB(), "S1000", 0, Any());
397 Reference
< XPropertySet
> const & ODbDataSourceAdministrationHelper::getCurrentDataSource()
399 if ( !m_xDatasource
.is() )
401 Reference
<XInterface
> xIn(m_aDataSourceOrName
,UNO_QUERY
);
404 OUString sCurrentDatasource
;
405 m_aDataSourceOrName
>>= sCurrentDatasource
;
406 OSL_ENSURE(!sCurrentDatasource
.isEmpty(),"No datasource name given!");
409 if ( m_xDatabaseContext
.is() )
410 m_xDatasource
.set(m_xDatabaseContext
->getByName(sCurrentDatasource
),UNO_QUERY
);
413 catch(const Exception
&)
417 m_xModel
.set(getDataSourceOrModel(xIn
),UNO_QUERY
);
419 m_xDatasource
.set(xIn
,UNO_QUERY
);
422 m_xDatasource
.set(getDataSourceOrModel(xIn
),UNO_QUERY
);
423 m_xModel
.set(xIn
,UNO_QUERY
);
427 OSL_ENSURE(m_xDatasource
.is(), "ODbDataSourceAdministrationHelper::getCurrentDataSource: no data source!");
428 return m_xDatasource
;
431 OUString
ODbDataSourceAdministrationHelper::getDatasourceType( const SfxItemSet
& _rSet
)
433 const SfxStringItem
* pConnectURL
= _rSet
.GetItem
<SfxStringItem
>(DSID_CONNECTURL
);
434 OSL_ENSURE( pConnectURL
, "ODbDataSourceAdministrationHelper::getDatasourceType: invalid items in the source set!" );
435 const DbuTypeCollectionItem
* pTypeCollection
= _rSet
.GetItem
<DbuTypeCollectionItem
>(DSID_TYPECOLLECTION
);
436 OSL_ENSURE(pTypeCollection
, "ODbDataSourceAdministrationHelper::getDatasourceType: invalid items in the source set!");
437 ::dbaccess::ODsnTypeCollection
* pCollection
= pTypeCollection
->getCollection();
438 return pCollection
->getType(pConnectURL
->GetValue());
441 bool ODbDataSourceAdministrationHelper::hasAuthentication(const SfxItemSet
& _rSet
)
443 return DataSourceMetaData::getAuthentication( getDatasourceType( _rSet
) ) != AuthNone
;
446 OUString
ODbDataSourceAdministrationHelper::getConnectionURL() const
450 OUString eType
= getDatasourceType(*m_pItemSetHelper
->getOutputSet());
452 const SfxStringItem
* pUrlItem
= m_pItemSetHelper
->getOutputSet()->GetItem
<SfxStringItem
>(DSID_CONNECTURL
);
453 const DbuTypeCollectionItem
* pTypeCollection
= m_pItemSetHelper
->getOutputSet()->GetItem
<DbuTypeCollectionItem
>(DSID_TYPECOLLECTION
);
455 OSL_ENSURE(pUrlItem
,"Connection URL is NULL. -> GPF!");
456 OSL_ENSURE(pTypeCollection
, "ODbDataSourceAdministrationHelper::getDatasourceType: invalid items in the source set!");
457 ::dbaccess::ODsnTypeCollection
* pCollection
= pTypeCollection
->getCollection();
458 OSL_ENSURE(pCollection
, "ODbDataSourceAdministrationHelper::getDatasourceType: invalid type collection!");
460 switch( pCollection
->determineType(eType
) )
462 case ::dbaccess::DST_DBASE
:
463 case ::dbaccess::DST_FLAT
:
464 case ::dbaccess::DST_CALC
:
465 case ::dbaccess::DST_WRITER
:
467 case ::dbaccess::DST_MSACCESS
:
468 case ::dbaccess::DST_MSACCESS_2007
:
470 OUString sFileName
= pCollection
->cutPrefix(pUrlItem
->GetValue());
471 OUString sNewFileName
;
472 if ( ::osl::FileBase::getSystemPathFromFileURL( sFileName
, sNewFileName
) == ::osl::FileBase::E_None
)
474 sNewUrl
+= sNewFileName
;
478 case ::dbaccess::DST_MYSQL_NATIVE
:
479 case ::dbaccess::DST_MYSQL_JDBC
:
481 const SfxStringItem
* pHostName
= m_pItemSetHelper
->getOutputSet()->GetItem
<SfxStringItem
>(DSID_CONN_HOSTNAME
);
482 const SfxInt32Item
* pPortNumber
= m_pItemSetHelper
->getOutputSet()->GetItem
<SfxInt32Item
>(DSID_MYSQL_PORTNUMBER
);
483 const SfxStringItem
* pDatabaseName
= m_pItemSetHelper
->getOutputSet()->GetItem
<SfxStringItem
>(DSID_DATABASENAME
);
484 sNewUrl
= lcl_createHostWithPort(pHostName
,pPortNumber
);
485 OUString sDatabaseName
= pDatabaseName
? pDatabaseName
->GetValue() : OUString();
486 if ( !sDatabaseName
.getLength() && pUrlItem
)
487 sDatabaseName
= pCollection
->cutPrefix( pUrlItem
->GetValue() );
488 // TODO: what's that? Why is the database name transported via the URL Item?
489 // Huh? Anybody there?
490 // OJ: It is needed when the connection properties are changed. There the URL is used for every type.
492 if ( !sDatabaseName
.isEmpty() )
494 sNewUrl
+= "/" + sDatabaseName
;
498 case ::dbaccess::DST_ORACLE_JDBC
:
500 const SfxStringItem
* pHostName
= m_pItemSetHelper
->getOutputSet()->GetItem
<SfxStringItem
>(DSID_CONN_HOSTNAME
);
501 const SfxInt32Item
* pPortNumber
= m_pItemSetHelper
->getOutputSet()->GetItem
<SfxInt32Item
>(DSID_ORACLE_PORTNUMBER
);
502 const SfxStringItem
* pDatabaseName
= m_pItemSetHelper
->getOutputSet()->GetItem
<SfxStringItem
>(DSID_DATABASENAME
);
503 if ( pHostName
&& pHostName
->GetValue().getLength() )
505 sNewUrl
= "@" + lcl_createHostWithPort(pHostName
,pPortNumber
);
506 OUString sDatabaseName
= pDatabaseName
? pDatabaseName
->GetValue() : OUString();
507 if ( sDatabaseName
.isEmpty() && pUrlItem
)
508 sDatabaseName
= pCollection
->cutPrefix( pUrlItem
->GetValue() );
509 if ( !sDatabaseName
.isEmpty() )
511 sNewUrl
+= ":" + sDatabaseName
;
515 { // here someone entered a JDBC url which looks like oracle, so we have to use the url property
520 case ::dbaccess::DST_LDAP
:
522 const SfxInt32Item
* pPortNumber
= m_pItemSetHelper
->getOutputSet()->GetItem
<SfxInt32Item
>(DSID_CONN_LDAP_PORTNUMBER
);
523 sNewUrl
= pCollection
->cutPrefix(pUrlItem
->GetValue()) + lcl_createHostWithPort(nullptr,pPortNumber
);
526 case ::dbaccess::DST_JDBC
:
531 if ( !sNewUrl
.isEmpty() )
532 sNewUrl
= pCollection
->getPrefix(eType
) + sNewUrl
;
534 sNewUrl
= pUrlItem
->GetValue();
541 struct PropertyValueLess
543 bool operator() (const PropertyValue
& x
, const PropertyValue
& y
) const
544 { return x
.Name
< y
.Name
; } // construct prevents a MSVC6 warning
549 typedef std::set
<PropertyValue
, PropertyValueLess
> PropertyValueSet
;
551 void ODbDataSourceAdministrationHelper::translateProperties(const Reference
< XPropertySet
>& _rxSource
, SfxItemSet
& _rDest
)
555 for (auto const& elem
: m_aDirectPropTranslator
)
557 // get the property value
561 aValue
= _rxSource
->getPropertyValue(elem
.second
);
565 SAL_WARN("dbaccess", "ODbDataSourceAdministrationHelper::translateProperties: could not extract the property "
568 // transfer it into an item
569 implTranslateProperty(_rDest
, elem
.first
, aValue
);
572 // get the additional information
573 Sequence
< PropertyValue
> aAdditionalInfo
;
576 _rxSource
->getPropertyValue(PROPERTY_INFO
) >>= aAdditionalInfo
;
578 catch(Exception
&) { }
580 // collect the names of the additional settings
581 PropertyValueSet aInfos
;
582 for (const PropertyValue
& rAdditionalInfo
: std::as_const(aAdditionalInfo
))
584 if( rAdditionalInfo
.Name
== "JDBCDRV" )
586 PropertyValue
aCompatibility(rAdditionalInfo
);
587 aCompatibility
.Name
= "JavaDriverClass";
588 aInfos
.insert(aCompatibility
);
591 aInfos
.insert(rAdditionalInfo
);
594 // go through all known translations and check if we have such a setting
595 if ( !aInfos
.empty() )
597 PropertyValue aSearchFor
;
598 for (auto const& elem
: m_aIndirectPropTranslator
)
600 aSearchFor
.Name
= elem
.second
;
601 PropertyValueSet::const_iterator aInfoPos
= aInfos
.find(aSearchFor
);
602 if (aInfos
.end() != aInfoPos
)
603 // the property is contained in the info sequence
604 // -> transfer it into an item
605 implTranslateProperty(_rDest
, elem
.first
, aInfoPos
->Value
);
614 Reference
<XStorable
> xStore(getDataSourceOrModel(_rxSource
),UNO_QUERY
);
615 _rDest
.Put(SfxBoolItem(DSID_READONLY
, !xStore
.is() || xStore
->isReadonly() ));
619 TOOLS_WARN_EXCEPTION("dbaccess", "IsReadOnly throws");
623 void ODbDataSourceAdministrationHelper::translateProperties(const SfxItemSet
& _rSource
, const Reference
< XPropertySet
>& _rxDest
)
625 OSL_ENSURE(_rxDest
.is(), "ODbDataSourceAdministrationHelper::translateProperties: invalid property set!");
629 // the property set info
630 Reference
< XPropertySetInfo
> xInfo
;
631 try { xInfo
= _rxDest
->getPropertySetInfo(); }
632 catch(Exception
&) { }
634 static const OUStringLiteral
sUrlProp(u
"URL");
635 // transfer the direct properties
636 for (auto const& elem
: m_aDirectPropTranslator
)
638 const SfxPoolItem
* pCurrentItem
= _rSource
.GetItem(static_cast<sal_uInt16
>(elem
.first
));
641 sal_Int16 nAttributes
= PropertyAttribute::READONLY
;
644 try { nAttributes
= xInfo
->getPropertyByName(elem
.second
).Attributes
; }
645 catch(Exception
&) { }
647 if ((nAttributes
& PropertyAttribute::READONLY
) == 0)
649 if ( sUrlProp
== elem
.second
)
651 Any
aValue(getConnectionURL());
652 // aValue <<= OUString();
653 lcl_putProperty(_rxDest
, elem
.second
,aValue
);
656 implTranslateProperty(_rxDest
, elem
.second
, pCurrentItem
);
661 // now for the indirect properties
663 Sequence
< PropertyValue
> aInfo
;
664 // the original properties
667 _rxDest
->getPropertyValue(PROPERTY_INFO
) >>= aInfo
;
669 catch(Exception
&) { }
671 // overwrite and extend them
672 fillDatasourceInfo(_rSource
, aInfo
);
673 // and propagate the (newly composed) sequence to the set
674 lcl_putProperty(_rxDest
,PROPERTY_INFO
, Any(aInfo
));
677 void ODbDataSourceAdministrationHelper::fillDatasourceInfo(const SfxItemSet
& _rSource
, Sequence
< css::beans::PropertyValue
>& _rInfo
)
679 // within the current "Info" sequence, replace the ones we can examine from the item set
680 // (we don't just fill a completely new sequence with our own items, but we preserve any properties unknown to
683 // first determine which of all the items are relevant for the data source (depends on the connection url)
684 const OUString eType
= getDatasourceType(_rSource
);
685 const ::connectivity::DriversConfig
aDriverConfig(getORB());
686 const ::comphelper::NamedValueCollection
& aProperties
= aDriverConfig
.getProperties(eType
);
688 // collect the translated property values for the relevant items
689 PropertyValueSet aRelevantSettings
;
690 MapInt2String::const_iterator aTranslation
;
691 for (ItemID detailId
= DSID_FIRST_ITEM_ID
; detailId
<= DSID_LAST_ITEM_ID
; ++detailId
)
693 const SfxPoolItem
* pCurrent
= _rSource
.GetItem(static_cast<sal_uInt16
>(detailId
));
694 aTranslation
= m_aIndirectPropTranslator
.find(detailId
);
695 if ( pCurrent
&& (m_aIndirectPropTranslator
.end() != aTranslation
) &&
696 aProperties
.has(aTranslation
->second
) )
698 if ( aTranslation
->second
== INFO_CHARSET
)
701 implTranslateProperty(pCurrent
) >>= sCharSet
;
702 if ( !sCharSet
.isEmpty() )
703 aRelevantSettings
.insert(PropertyValue(aTranslation
->second
, 0, Any(sCharSet
), PropertyState_DIRECT_VALUE
));
706 aRelevantSettings
.insert(PropertyValue(aTranslation
->second
, 0, implTranslateProperty(pCurrent
), PropertyState_DIRECT_VALUE
));
710 // settings to preserve
711 MapInt2String aPreservedSettings
;
713 // now aRelevantSettings contains all the property values relevant for the current data source type,
714 // check the original sequence if it already contains any of these values (which have to be overwritten, then)
715 PropertyValue
* pInfo
= _rInfo
.getArray();
716 PropertyValue aSearchFor
;
717 sal_Int32 nObsoleteSetting
= -1;
718 sal_Int32 nCount
= _rInfo
.getLength();
719 for (sal_Int32 i
= 0; i
< nCount
; ++i
, ++pInfo
)
721 aSearchFor
.Name
= pInfo
->Name
;
722 PropertyValueSet::const_iterator aOverwrittenSetting
= aRelevantSettings
.find(aSearchFor
);
723 if (aRelevantSettings
.end() != aOverwrittenSetting
)
724 { // the setting was present in the original sequence, and it is to be overwritten -> replace it
725 if ( pInfo
->Value
!= aOverwrittenSetting
->Value
)
726 *pInfo
= *aOverwrittenSetting
;
727 aRelevantSettings
.erase(aOverwrittenSetting
);
729 else if( pInfo
->Name
== "JDBCDRV" )
730 { // this is a compatibility setting, remove it from the sequence (it's replaced by JavaDriverClass)
731 nObsoleteSetting
= i
;
734 aPreservedSettings
[i
] = pInfo
->Name
;
736 if (-1 != nObsoleteSetting
)
737 ::comphelper::removeElementAt(_rInfo
, nObsoleteSetting
);
739 if ( !aPreservedSettings
.empty() )
740 { // check if there are settings which
741 // * are known as indirect properties
742 // * but not relevant for the current data source type
743 // These settings have to be removed: If they're not relevant, we have no UI for changing them.
745 // for this, we need a string-controlled quick access to m_aIndirectPropTranslator
746 std::set
<OUString
> aIndirectProps
;
747 std::transform(m_aIndirectPropTranslator
.begin(),
748 m_aIndirectPropTranslator
.end(),
749 std::inserter(aIndirectProps
,aIndirectProps
.begin()),
750 ::o3tl::select2nd
< MapInt2String::value_type
>());
752 // now check the to-be-preserved props
753 std::vector
< sal_Int32
> aRemoveIndexes
;
754 sal_Int32 nPositionCorrector
= 0;
755 for (auto const& preservedSetting
: aPreservedSettings
)
757 if (aIndirectProps
.end() != aIndirectProps
.find(preservedSetting
.second
))
759 aRemoveIndexes
.push_back(preservedSetting
.first
- nPositionCorrector
);
760 ++nPositionCorrector
;
763 // now finally remove all such props
764 for (auto const& removeIndex
: aRemoveIndexes
)
765 ::comphelper::removeElementAt(_rInfo
, removeIndex
);
768 Sequence
< Any
> aTypeSettings
;
769 aTypeSettings
= aProperties
.getOrDefault("TypeInfoSettings",aTypeSettings
);
770 // here we have a special entry for types from oracle
771 if ( aTypeSettings
.hasElements() )
773 aRelevantSettings
.insert(PropertyValue("TypeInfoSettings", 0, Any(aTypeSettings
), PropertyState_DIRECT_VALUE
));
776 // check which values are still left ('cause they were not present in the original sequence, but are to be set)
777 if ( aRelevantSettings
.empty() )
780 sal_Int32 nOldLength
= _rInfo
.getLength();
781 _rInfo
.realloc(nOldLength
+ aRelevantSettings
.size());
782 PropertyValue
* pAppendValues
= _rInfo
.getArray() + nOldLength
;
783 for (auto const& relevantSetting
: aRelevantSettings
)
785 if ( relevantSetting
.Name
== INFO_CHARSET
)
788 relevantSetting
.Value
>>= sCharSet
;
789 if ( !sCharSet
.isEmpty() )
790 *pAppendValues
= relevantSetting
;
793 *pAppendValues
= relevantSetting
;
798 Any
ODbDataSourceAdministrationHelper::implTranslateProperty(const SfxPoolItem
* _pItem
)
800 // translate the SfxPoolItem
803 const SfxStringItem
* pStringItem
= dynamic_cast<const SfxStringItem
*>( _pItem
);
804 const SfxBoolItem
* pBoolItem
= dynamic_cast<const SfxBoolItem
*>( _pItem
);
805 const OptionalBoolItem
* pOptBoolItem
= dynamic_cast<const OptionalBoolItem
*>( _pItem
);
806 const SfxInt32Item
* pInt32Item
= dynamic_cast< const SfxInt32Item
* >( _pItem
);
807 const OStringListItem
* pStringListItem
= dynamic_cast<const OStringListItem
*>( _pItem
);
811 aValue
<<= pStringItem
->GetValue();
813 else if ( pBoolItem
)
815 aValue
<<= pBoolItem
->GetValue();
817 else if ( pOptBoolItem
)
819 if ( !pOptBoolItem
->HasValue() )
822 aValue
<<= pOptBoolItem
->GetValue();
824 else if ( pInt32Item
)
826 aValue
<<= pInt32Item
->GetValue();
828 else if ( pStringListItem
)
830 aValue
<<= pStringListItem
->getList();
834 OSL_FAIL("ODbDataSourceAdministrationHelper::implTranslateProperty: unsupported item type!");
841 void ODbDataSourceAdministrationHelper::implTranslateProperty(const Reference
< XPropertySet
>& _rxSet
, const OUString
& _rName
, const SfxPoolItem
* _pItem
)
843 Any aValue
= implTranslateProperty(_pItem
);
844 lcl_putProperty(_rxSet
, _rName
,aValue
);
847 OString
ODbDataSourceAdministrationHelper::translatePropertyId( sal_Int32 _nId
)
851 MapInt2String::const_iterator aPos
= m_aDirectPropTranslator
.find( _nId
);
852 if ( m_aDirectPropTranslator
.end() != aPos
)
854 aString
= aPos
->second
;
858 MapInt2String::const_iterator indirectPos
= m_aIndirectPropTranslator
.find( _nId
);
859 if ( m_aIndirectPropTranslator
.end() != indirectPos
)
860 aString
= indirectPos
->second
;
863 OString
aReturn( aString
.getStr(), aString
.getLength(), RTL_TEXTENCODING_ASCII_US
);
866 template<class T
> static bool checkItemType(const SfxPoolItem
* pItem
){ return dynamic_cast<const T
*>(pItem
) != nullptr;}
868 void ODbDataSourceAdministrationHelper::implTranslateProperty( SfxItemSet
& _rSet
, sal_Int32 _nId
, const Any
& _rValue
)
870 switch ( _rValue
.getValueType().getTypeClass() )
872 case TypeClass_STRING
:
873 if ( implCheckItemType( _rSet
, _nId
, checkItemType
<SfxStringItem
> ) )
877 _rSet
.Put(SfxStringItem(_nId
, sValue
));
880 SAL_WARN( "dbaccess", "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value ("
881 << translatePropertyId(_nId
) << " should be no string)!");
885 case TypeClass_BOOLEAN
:
886 if ( implCheckItemType( _rSet
, _nId
, checkItemType
<SfxBoolItem
> ) )
890 _rSet
.Put(SfxBoolItem(_nId
, bVal
));
892 else if ( implCheckItemType( _rSet
, _nId
, checkItemType
<OptionalBoolItem
> ) )
894 OptionalBoolItem
aItem( _nId
);
895 if ( _rValue
.hasValue() )
899 aItem
.SetValue( bValue
);
906 SAL_WARN( "dbaccess", "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value ("
907 << translatePropertyId(_nId
)
908 << " should be no boolean)!");
913 if ( implCheckItemType( _rSet
, _nId
, checkItemType
<SfxInt32Item
> ) )
915 sal_Int32 nValue
= 0;
917 _rSet
.Put( SfxInt32Item( _nId
, nValue
) );
920 SAL_WARN( "dbaccess", "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value ("
921 << translatePropertyId(_nId
)
922 << " should be no int)!");
926 case TypeClass_SEQUENCE
:
927 if ( implCheckItemType( _rSet
, _nId
, checkItemType
<OStringListItem
> ) )
929 // determine the element type
930 TypeDescription
aTD(_rValue
.getValueType());
931 typelib_IndirectTypeDescription
* pSequenceTD
=
932 reinterpret_cast< typelib_IndirectTypeDescription
* >(aTD
.get());
933 OSL_ENSURE(pSequenceTD
&& pSequenceTD
->pType
, "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid sequence type!");
935 Type
aElementType(pSequenceTD
->pType
);
936 switch (aElementType
.getTypeClass())
938 case TypeClass_STRING
:
940 Sequence
< OUString
> aStringList
;
941 _rValue
>>= aStringList
;
942 _rSet
.Put(OStringListItem(_nId
, aStringList
));
946 OSL_FAIL("ODbDataSourceAdministrationHelper::implTranslateProperty: unsupported property value type!");
950 SAL_WARN( "dbaccess", "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value ("
951 << translatePropertyId(_nId
)
952 << " should be no string sequence)!");
957 _rSet
.ClearItem(_nId
);
961 OSL_FAIL("ODbDataSourceAdministrationHelper::implTranslateProperty: unsupported property value type!");
965 OUString
ODbDataSourceAdministrationHelper::getDocumentUrl(SfxItemSet
const & _rDest
)
967 const SfxStringItem
* pUrlItem
= _rDest
.GetItem
<SfxStringItem
>(DSID_DOCUMENT_URL
);
968 OSL_ENSURE(pUrlItem
,"Document URL is NULL. -> GPF!");
969 return pUrlItem
->GetValue();
972 void ODbDataSourceAdministrationHelper::convertUrl(SfxItemSet
& _rDest
)
974 OUString eType
= getDatasourceType(_rDest
);
976 const SfxStringItem
* pUrlItem
= _rDest
.GetItem
<SfxStringItem
>(DSID_CONNECTURL
);
977 const DbuTypeCollectionItem
* pTypeCollection
= _rDest
.GetItem
<DbuTypeCollectionItem
>(DSID_TYPECOLLECTION
);
979 OSL_ENSURE(pUrlItem
,"Connection URL is NULL. -> GPF!");
980 OSL_ENSURE(pTypeCollection
, "ODbAdminDialog::getDatasourceType: invalid items in the source set!");
981 ::dbaccess::ODsnTypeCollection
* pCollection
= pTypeCollection
->getCollection();
982 OSL_ENSURE(pCollection
, "ODbAdminDialog::getDatasourceType: invalid type collection!");
984 sal_uInt16 nPortNumberId
= 0;
985 sal_Int32 nPortNumber
= -1;
986 OUString sNewHostName
;
989 pCollection
->extractHostNamePort(pUrlItem
->GetValue(),sUrlPart
,sNewHostName
,nPortNumber
);
990 const ::dbaccess::DATASOURCE_TYPE eTy
= pCollection
->determineType(eType
);
994 case ::dbaccess::DST_MYSQL_NATIVE
:
995 case ::dbaccess::DST_MYSQL_JDBC
:
996 nPortNumberId
= DSID_MYSQL_PORTNUMBER
;
998 case ::dbaccess::DST_ORACLE_JDBC
:
999 nPortNumberId
= DSID_ORACLE_PORTNUMBER
;
1001 case ::dbaccess::DST_LDAP
:
1002 nPortNumberId
= DSID_CONN_LDAP_PORTNUMBER
;
1008 if ( !sUrlPart
.isEmpty() )
1010 if ( eTy
== ::dbaccess::DST_MYSQL_NATIVE
)
1012 _rDest
.Put( SfxStringItem( DSID_DATABASENAME
, sUrlPart
) );
1016 OUString sNewUrl
= pCollection
->getPrefix(eType
) + sUrlPart
;
1017 _rDest
.Put( SfxStringItem( DSID_CONNECTURL
, sNewUrl
) );
1021 if ( !sNewHostName
.isEmpty() )
1022 _rDest
.Put(SfxStringItem(DSID_CONN_HOSTNAME
, sNewHostName
));
1024 if ( nPortNumber
!= -1 && nPortNumberId
!= 0 )
1025 _rDest
.Put(SfxInt32Item(nPortNumberId
, nPortNumber
));
1029 bool ODbDataSourceAdministrationHelper::saveChanges(const SfxItemSet
& _rSource
)
1031 // put the remembered settings into the property set
1032 Reference
<XPropertySet
> xDatasource
= getCurrentDataSource();
1033 if ( !xDatasource
.is() )
1036 translateProperties(_rSource
,xDatasource
);
1041 void ODbDataSourceAdministrationHelper::setDataSourceOrName( const Any
& _rDataSourceOrName
)
1043 OSL_ENSURE( !m_aDataSourceOrName
.hasValue(), "ODbDataSourceAdministrationHelper::setDataSourceOrName: already have one!" );
1044 // hmm. We could reset m_xDatasource/m_xModel, probably, and continue working
1045 m_aDataSourceOrName
= _rDataSourceOrName
;
1048 // DbuTypeCollectionItem
1049 DbuTypeCollectionItem::DbuTypeCollectionItem(sal_Int16 _nWhich
, ::dbaccess::ODsnTypeCollection
* _pCollection
)
1050 :SfxPoolItem(_nWhich
)
1051 ,m_pCollection(_pCollection
)
1055 DbuTypeCollectionItem::DbuTypeCollectionItem(const DbuTypeCollectionItem
& _rSource
)
1056 :SfxPoolItem(_rSource
)
1057 ,m_pCollection(_rSource
.getCollection())
1061 bool DbuTypeCollectionItem::operator==(const SfxPoolItem
& _rItem
) const
1063 return SfxPoolItem::operator==(_rItem
) &&
1064 static_cast<const DbuTypeCollectionItem
&>( _rItem
).getCollection() == getCollection();
1067 DbuTypeCollectionItem
* DbuTypeCollectionItem::Clone(SfxItemPool
* /*_pPool*/) const
1069 return new DbuTypeCollectionItem(*this);
1072 } // namespace dbaui
1074 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */