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_dbaccess.hxx"
26 
27 #include "DbAdminImpl.hxx"
28 #include "dsmeta.hxx"
29 
30 #include <svl/poolitem.hxx>
31 #include <svl/itempool.hxx>
32 #include <svl/stritem.hxx>
33 #include <svl/intitem.hxx>
34 #include <svl/eitem.hxx>
35 #include "DriverSettings.hxx"
36 #include "IItemSetHelper.hxx"
37 #include "UITools.hxx"
38 #include "dbu_dlg.hrc"
39 #include "dbustrings.hrc"
40 #include "dsitems.hxx"
41 #include "dsnItem.hxx"
42 #include "moduledbu.hxx"
43 #include "optionalboolitem.hxx"
44 #include "propertysetitem.hxx"
45 #include "stringlistitem.hxx"
46 #include "OAuthenticationContinuation.hxx"
47 
48 /** === begin UNO includes === **/
49 #include <com/sun/star/beans/PropertyAttribute.hpp>
50 #include <com/sun/star/frame/XStorable.hpp>
51 #include <com/sun/star/sdb/SQLContext.hpp>
52 #include <com/sun/star/sdbc/XDriver.hpp>
53 #include <com/sun/star/sdbc/XDriverAccess.hpp>
54 #include <com/sun/star/task/XInteractionHandler.hpp>
55 #include <com/sun/star/task/XInteractionRequest.hpp>
56 #include <com/sun/star/ucb/XInteractionSupplyAuthentication2.hpp>
57 #include <com/sun/star/ucb/AuthenticationRequest.hpp>
58 /** === end UNO includes === **/
59 
60 #include <comphelper/interaction.hxx>
61 #include <comphelper/property.hxx>
62 #include <comphelper/sequence.hxx>
63 #include <comphelper/guarding.hxx>
64 #include <connectivity/DriversConfig.hxx>
65 #include <connectivity/dbexception.hxx>
66 #include <osl/file.hxx>
67 #include <svl/eitem.hxx>
68 #include <svl/intitem.hxx>
69 #include <svl/itempool.hxx>
70 #include <svl/poolitem.hxx>
71 #include <svl/stritem.hxx>
72 #include <tools/urlobj.hxx>
73 #include <tools/diagnose_ex.h>
74 #include <typelib/typedescription.hxx>
75 #include <vcl/svapp.hxx>
76 #include <vcl/msgbox.hxx>
77 #include <vcl/stdtext.hxx>
78 #include <vcl/waitobj.hxx>
79 #include <vos/mutex.hxx>
80 
81 #include <algorithm>
82 #include <functional>
83 //.........................................................................
84 namespace dbaui
85 {
86 //.........................................................................
87 using namespace ::dbtools;
88 using namespace com::sun::star::uno;
89 using namespace com::sun::star;
90 using namespace com::sun::star::ucb;
91 using namespace com::sun::star::task;
92 using namespace com::sun::star::sdbc;
93 using namespace com::sun::star::sdb;
94 using namespace com::sun::star::lang;
95 using namespace com::sun::star::beans;
96 using namespace com::sun::star::util;
97 using namespace com::sun::star::container;
98 using namespace com::sun::star::frame;
99 
100 //-------------------------------------------------------------------------
101 namespace
102 {
103 	sal_Bool implCheckItemType( SfxItemSet& _rSet, const sal_uInt16 _nId, const TypeId _nExpectedItemType )
104 	{
105 		sal_Bool bCorrectType = sal_False;
106 
107 		SfxItemPool* pPool = _rSet.GetPool();
108 		DBG_ASSERT( pPool, "implCheckItemType: invalid item pool!" );
109 		if ( pPool )
110 		{
111 			const SfxPoolItem& rDefItem = pPool->GetDefaultItem( _nId );
112 			bCorrectType = rDefItem.IsA( _nExpectedItemType );
113 		}
114 		return bCorrectType;
115 	}
116 
117 	void lcl_putProperty(const Reference< XPropertySet >& _rxSet, const ::rtl::OUString& _rName, const Any& _rValue)
118 	{
119 		try
120 		{
121 			if ( _rxSet.is() )
122 				_rxSet->setPropertyValue(_rName, _rValue);
123 		}
124 		catch(Exception&)
125 		{
126 	#ifdef DBG_UTIL
127 			::rtl::OString sMessage("ODbAdminDialog::implTranslateProperty: could not set the property ");
128 			sMessage += ::rtl::OString(_rName.getStr(), _rName.getLength(), RTL_TEXTENCODING_ASCII_US);
129 			sMessage += ::rtl::OString("!");
130 			DBG_ERROR(sMessage.getStr());
131 	#endif
132 		}
133 
134 	}
135 
136 	String lcl_createHostWithPort(const SfxStringItem* _pHostName,const SfxInt32Item* _pPortNumber)
137 	{
138 		String sNewUrl;
139 
140 		if ( _pHostName && _pHostName->GetValue().Len() )
141 			sNewUrl = _pHostName->GetValue();
142 
143 		if ( _pPortNumber )
144 		{
145 			sNewUrl += String::CreateFromAscii(":");
146 			sNewUrl += String::CreateFromInt32(_pPortNumber->GetValue());
147 		}
148 
149 		return sNewUrl;
150 	}
151 }
152 
153 	//========================================================================
154 	//= ODbDataSourceAdministrationHelper
155 	//========================================================================
156 ODbDataSourceAdministrationHelper::ODbDataSourceAdministrationHelper(const Reference< XMultiServiceFactory >& _xORB,Window* _pParent,IItemSetHelper* _pItemSetHelper)
157 		: m_xORB(_xORB)
158 		, m_pParent(_pParent)
159 		, m_pItemSetHelper(_pItemSetHelper)
160 {
161 	/// initialize the property translation map
162 	// direct properties of a data source
163 	m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_CONNECTURL, PROPERTY_URL));
164 	m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_NAME, PROPERTY_NAME));
165 	m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_USER, PROPERTY_USER));
166 	m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_PASSWORD, PROPERTY_PASSWORD));
167 	m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_PASSWORDREQUIRED, PROPERTY_ISPASSWORDREQUIRED));
168 	m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_TABLEFILTER, PROPERTY_TABLEFILTER));
169 	m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_READONLY, PROPERTY_ISREADONLY));
170 	m_aDirectPropTranslator.insert(MapInt2String::value_type(DSID_SUPPRESSVERSIONCL, PROPERTY_SUPPRESSVERSIONCL));
171 
172 	// implicit properties, to be found in the direct property "Info"
173 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_JDBCDRIVERCLASS, INFO_JDBCDRIVERCLASS));
174 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_TEXTFILEEXTENSION, INFO_TEXTFILEEXTENSION));
175 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CHARSET, INFO_CHARSET));
176 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_TEXTFILEHEADER, INFO_TEXTFILEHEADER));
177 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_FIELDDELIMITER, INFO_FIELDDELIMITER));
178 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_TEXTDELIMITER, INFO_TEXTDELIMITER));
179 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_DECIMALDELIMITER, INFO_DECIMALDELIMITER));
180 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_THOUSANDSDELIMITER, INFO_THOUSANDSDELIMITER));
181 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_SHOWDELETEDROWS, INFO_SHOWDELETEDROWS));
182 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_ALLOWLONGTABLENAMES, INFO_ALLOWLONGTABLENAMES));
183 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_ADDITIONALOPTIONS, INFO_ADDITIONALOPTIONS));
184 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_SQL92CHECK, PROPERTY_ENABLESQL92CHECK));
185 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_AUTOINCREMENTVALUE, PROPERTY_AUTOINCREMENTCREATION));
186 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_AUTORETRIEVEVALUE, INFO_AUTORETRIEVEVALUE));
187 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_AUTORETRIEVEENABLED, INFO_AUTORETRIEVEENABLED));
188 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_APPEND_TABLE_ALIAS, INFO_APPEND_TABLE_ALIAS));
189 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_AS_BEFORE_CORRNAME, INFO_AS_BEFORE_CORRELATION_NAME ) );
190     m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CHECK_REQUIRED_FIELDS, INFO_FORMS_CHECK_REQUIRED_FIELDS ) );
191     m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_ESCAPE_DATETIME, INFO_ESCAPE_DATETIME ) );
192     m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_PRIMARY_KEY_SUPPORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrimaryKeySupport" ) ) ) );
193 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_PARAMETERNAMESUBST, INFO_PARAMETERNAMESUBST));
194 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_IGNOREDRIVER_PRIV, INFO_IGNOREDRIVER_PRIV));
195 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_BOOLEANCOMPARISON, PROPERTY_BOOLEANCOMPARISONMODE));
196 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_ENABLEOUTERJOIN, PROPERTY_ENABLEOUTERJOIN));
197 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CATALOG, PROPERTY_USECATALOGINSELECT));
198 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_SCHEMA, PROPERTY_USESCHEMAINSELECT));
199 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_INDEXAPPENDIX, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AddIndexAppendix"))));
200 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_DOSLINEENDS, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PreferDosLikeLineEnds" ) ) ) );
201     m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CONN_SOCKET, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "LocalSocket" ) ) ) );
202     m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_NAMED_PIPE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NamedPipe" ) ) ) );
203     m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_RESPECTRESULTSETTYPE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "RespectDriverResultSetType" ) ) ) );
204     m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_MAX_ROW_SCAN, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MaxRowScan" ) ) ) );
205 
206 	// special settings for adabas
207 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CONN_SHUTSERVICE, ::rtl::OUString::createFromAscii("ShutdownDatabase")));
208 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CONN_DATAINC, ::rtl::OUString::createFromAscii("DataCacheSizeIncrement")));
209 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CONN_CACHESIZE, ::rtl::OUString::createFromAscii("DataCacheSize")));
210 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CONN_CTRLUSER, ::rtl::OUString::createFromAscii("ControlUser")));
211 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CONN_CTRLPWD, ::rtl::OUString::createFromAscii("ControlPassword")));
212 
213 	// extra settings for odbc
214 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_USECATALOG, INFO_USECATALOG));
215 	// extra settings for a ldap address book
216 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CONN_LDAP_BASEDN, INFO_CONN_LDAP_BASEDN));
217 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CONN_LDAP_ROWCOUNT, INFO_CONN_LDAP_ROWCOUNT));
218 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_CONN_LDAP_USESSL, ::rtl::OUString::createFromAscii("UseSSL")));
219 	m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_DOCUMENT_URL, PROPERTY_URL));
220 
221     // oracle
222     m_aIndirectPropTranslator.insert(MapInt2String::value_type(DSID_IGNORECURRENCY, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IgnoreCurrency"))));
223 
224 	try
225 	{
226 		m_xDatabaseContext = Reference< XNameAccess >(m_xORB->createInstance(SERVICE_SDB_DATABASECONTEXT), UNO_QUERY);
227 		m_xDynamicContext.set(m_xDatabaseContext,UNO_QUERY);
228 	}
229 	catch(Exception&)
230 	{
231 	}
232 
233 	if ( !m_xDatabaseContext.is() )
234 	{
235 		ShowServiceNotAvailableError(_pParent->GetParent(), String(SERVICE_SDB_DATABASECONTEXT), sal_True);
236 	}
237 
238 	DBG_ASSERT(m_xDynamicContext.is(), "ODbAdminDialog::ODbAdminDialog : no XNamingService interface !");
239 }
240 	//-------------------------------------------------------------------------
241 sal_Bool ODbDataSourceAdministrationHelper::getCurrentSettings(Sequence< PropertyValue >& _rDriverParam)
242 {
243 	DBG_ASSERT(m_pItemSetHelper->getOutputSet(), "ODbDataSourceAdministrationHelper::getCurrentSettings : not to be called without an example set!");
244 	if (!m_pItemSetHelper->getOutputSet())
245 		return sal_False;
246 
247 	::std::vector< PropertyValue > aReturn;
248 		// collecting this in a vector because it has a push_back, in opposite to sequences
249 
250 	// user: DSID_USER -> "user"
251 	SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pUser, SfxStringItem, DSID_USER, sal_True);
252 	if (pUser && pUser->GetValue().Len())
253 		aReturn.push_back(
254 			PropertyValue(	::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("user")), 0,
255 							makeAny(::rtl::OUString(pUser->GetValue())), PropertyState_DIRECT_VALUE));
256 
257 	// check if the connection type requires a password
258 	if (hasAuthentication(*m_pItemSetHelper->getOutputSet()))
259 	{
260 		// password: DSID_PASSWORD -> "password"
261 		SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pPassword, SfxStringItem, DSID_PASSWORD, sal_True);
262 		String sPassword = pPassword ? pPassword->GetValue() : String();
263 		SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pPasswordRequired, SfxBoolItem, DSID_PASSWORDREQUIRED, sal_True);
264 		// if the set does not contain a password, but the item set says it requires one, ask the user
265 		if ((!pPassword || !pPassword->GetValue().Len()) && (pPasswordRequired && pPasswordRequired->GetValue()))
266 		{
267 			SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pName, SfxStringItem, DSID_NAME, sal_True);
268 
269             Reference< XModel > xModel( getDataSourceOrModel( m_xDatasource ), UNO_QUERY_THROW );
270             ::comphelper::NamedValueCollection aArgs( xModel->getArgs() );
271             Reference< XInteractionHandler > xHandler( aArgs.getOrDefault( "InteractionHandler", Reference< XInteractionHandler >() ) );
272 
273             if ( !xHandler.is() )
274             {
275                 // instantiate the default SDB interaction handler
276                 xHandler = Reference< XInteractionHandler >( m_xORB->createInstance( SERVICE_TASK_INTERACTION_HANDLER ), UNO_QUERY );
277                 if ( !xHandler.is() )
278 				    ShowServiceNotAvailableError(m_pParent->GetParent(), String(SERVICE_TASK_INTERACTION_HANDLER), sal_True);
279             }
280 
281             String sName = pName ? pName->GetValue() : String();
282             String sLoginRequest(ModuleRes(STR_ENTER_CONNECTION_PASSWORD));
283             ::rtl::OUString sTemp = sName;
284             sName = ::dbaui::getStrippedDatabaseName(NULL,sTemp);
285             if ( sName.Len() )
286                 sLoginRequest.SearchAndReplaceAscii("$name$", sName);
287             else
288             {
289                 sLoginRequest.SearchAndReplaceAscii("\"$name$\"", String());
290                 sLoginRequest.SearchAndReplaceAscii("$name$", String()); // just to be sure that in other languages the string will be deleted
291             }
292 
293             // the request
294             AuthenticationRequest aRequest;
295             aRequest.ServerName = sName;
296             aRequest.Diagnostic = sLoginRequest;
297             aRequest.HasRealm   = aRequest.HasAccount = sal_False;
298             // aRequest.Realm
299             aRequest.HasUserName = pUser != 0;
300             aRequest.UserName    = pUser ? rtl::OUString(pUser->GetValue()) : ::rtl::OUString();
301             aRequest.HasPassword = sal_True;
302             //aRequest.Password
303             aRequest.HasAccount  = sal_False;
304             // aRequest.Account
305 
306             comphelper::OInteractionRequest* pRequest = new comphelper::OInteractionRequest(makeAny(aRequest));
307             uno::Reference< XInteractionRequest > xRequest(pRequest);
308 
309             // build an interaction request
310             // two continuations (Ok and Cancel)
311             ::rtl::Reference< comphelper::OInteractionAbort > pAbort = new comphelper::OInteractionAbort;
312             ::rtl::Reference< dbaccess::OAuthenticationContinuation > pAuthenticate = new dbaccess::OAuthenticationContinuation;
313             pAuthenticate->setCanChangeUserName( sal_False );
314             pAuthenticate->setRememberPassword( RememberAuthentication_SESSION );
315 
316             // some knittings
317             pRequest->addContinuation(pAbort.get());
318             pRequest->addContinuation(pAuthenticate.get());
319 
320             // handle the request
321             try
322             {
323                 ::vos::OGuard aSolarGuard(Application::GetSolarMutex());
324                 // release the mutex when calling the handler, it may need to lock the SolarMutex
325                 xHandler->handle(xRequest);
326             }
327             catch(Exception&)
328             {
329                 DBG_UNHANDLED_EXCEPTION();
330             }
331             if (!pAuthenticate->wasSelected())
332                 return sal_False;
333 
334             sPassword = pAuthenticate->getPassword();
335             if (pAuthenticate->getRememberPassword())
336                 m_pItemSetHelper->getWriteOutputSet()->Put(SfxStringItem(DSID_PASSWORD, sPassword));
337 		}
338 
339         if (sPassword.Len())
340 			aReturn.push_back(
341 				PropertyValue(	::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("password")), 0,
342 								makeAny(::rtl::OUString(sPassword)), PropertyState_DIRECT_VALUE));
343 	}
344 
345     if ( !aReturn.empty() )
346 	    _rDriverParam = Sequence< PropertyValue >(&(*aReturn.begin()), aReturn.size());
347 
348 	// append all the other stuff (charset etc.)
349 	fillDatasourceInfo(*m_pItemSetHelper->getOutputSet(), _rDriverParam);
350 
351 	return sal_True;
352 }
353 //-------------------------------------------------------------------------
354 void ODbDataSourceAdministrationHelper::successfullyConnected()
355 {
356 	DBG_ASSERT(m_pItemSetHelper->getOutputSet(), "ODbDataSourceAdministrationHelper::successfullyConnected: not to be called without an example set!");
357 	if (!m_pItemSetHelper->getOutputSet())
358 		return;
359 
360 	if (hasAuthentication(*m_pItemSetHelper->getOutputSet()))
361 	{
362 		SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pPassword, SfxStringItem, DSID_PASSWORD, sal_True);
363 		if (pPassword && (0 != pPassword->GetValue().Len()))
364 		{
365 			::rtl::OUString sPassword = pPassword->GetValue();
366 
367 			Reference< XPropertySet > xCurrentDatasource = getCurrentDataSource();
368 			lcl_putProperty(xCurrentDatasource,m_aDirectPropTranslator[DSID_PASSWORD], makeAny(sPassword));
369 		}
370 	}
371 }
372 //-------------------------------------------------------------------------
373 void ODbDataSourceAdministrationHelper::clearPassword()
374 {
375 	if (m_pItemSetHelper->getWriteOutputSet())
376 		m_pItemSetHelper->getWriteOutputSet()->ClearItem(DSID_PASSWORD);
377 }
378 // -----------------------------------------------------------------------------
379 ::std::pair< Reference<XConnection>,sal_Bool> ODbDataSourceAdministrationHelper::createConnection()
380 {
381 	::std::pair< Reference<XConnection>,sal_Bool> aRet;
382 	aRet.second = sal_False;
383 	Sequence< PropertyValue > aConnectionParams;
384 	if ( getCurrentSettings(aConnectionParams) )
385 	{
386 		// the current DSN
387 		// fill the table list with this connection information
388 		SQLExceptionInfo aErrorInfo;
389 		try
390 		{
391 			WaitObject aWaitCursor(m_pParent);
392 			aRet.first = getDriver()->connect(getConnectionURL(), aConnectionParams);
393 			aRet.second = sal_True;
394 		}
395 		catch (SQLContext& e) { aErrorInfo = SQLExceptionInfo(e); }
396 		catch (SQLWarning& e) { aErrorInfo = SQLExceptionInfo(e); }
397 		catch (SQLException& e) { aErrorInfo = SQLExceptionInfo(e); }
398 
399 		showError(aErrorInfo,m_pParent,getORB());
400 	}
401 	if ( aRet.first.is() )
402 		successfullyConnected();// notify the admindlg to save the password
403 
404 	return aRet;
405 }
406 // -----------------------------------------------------------------------------
407 Reference< XDriver > ODbDataSourceAdministrationHelper::getDriver()
408 {
409     return getDriver(getConnectionURL());
410 }
411 // -----------------------------------------------------------------------------
412 Reference< XDriver > ODbDataSourceAdministrationHelper::getDriver(const ::rtl::OUString& _sURL)
413 {
414 	// get the global DriverManager
415 	Reference< XDriverAccess > xDriverManager;
416 	String sCurrentActionError = String(ModuleRes(STR_COULDNOTCREATE_DRIVERMANAGER));
417 		// in case an error occures
418 	sCurrentActionError.SearchAndReplaceAscii("#servicename#", (::rtl::OUString)SERVICE_SDBC_CONNECTIONPOOL);
419 	try
420 	{
421 		xDriverManager = Reference< XDriverAccess >(getORB()->createInstance(SERVICE_SDBC_CONNECTIONPOOL), UNO_QUERY);
422 		DBG_ASSERT(xDriverManager.is(), "ODbDataSourceAdministrationHelper::getDriver: could not instantiate the driver manager, or it does not provide the necessary interface!");
423 	}
424 	catch (Exception& e)
425 	{
426 		// wrap the exception into an SQLException
427 		SQLException aSQLWrapper(e.Message, getORB(), ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("S1000")), 0, Any());
428 		throw SQLException(sCurrentActionError, getORB(), ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("S1000")), 0, makeAny(aSQLWrapper));
429 	}
430 	if (!xDriverManager.is())
431 		throw SQLException(sCurrentActionError, getORB(), ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("S1000")), 0, Any());
432 
433 
434 	Reference< XDriver > xDriver = xDriverManager->getDriverByURL(_sURL);
435 	if (!xDriver.is())
436 	{
437 		sCurrentActionError = String(ModuleRes(STR_NOREGISTEREDDRIVER));
438 		sCurrentActionError.SearchAndReplaceAscii("#connurl#", _sURL);
439 		// will be caught and translated into an SQLContext exception
440 		throw SQLException(sCurrentActionError, getORB(), ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("S1000")), 0, Any());
441 	}
442 	return xDriver;
443 }
444 
445 // -----------------------------------------------------------------------------
446 Reference< XPropertySet > ODbDataSourceAdministrationHelper::getCurrentDataSource()
447 {
448 	if ( !m_xDatasource.is() )
449 	{
450 		Reference<XInterface> xIn(m_aDataSourceOrName,UNO_QUERY);
451 		if ( !xIn.is() )
452 		{
453 			::rtl::OUString sCurrentDatasource;
454 			m_aDataSourceOrName >>= sCurrentDatasource;
455 			OSL_ENSURE(sCurrentDatasource.getLength(),"No datasource name given!");
456 			try
457 			{
458 				if ( m_xDatabaseContext.is() )
459 					m_xDatasource.set(m_xDatabaseContext->getByName(sCurrentDatasource),UNO_QUERY);
460 				xIn = m_xDatasource;
461 			}
462 			catch(const Exception&)
463 			{
464 			}
465 		}
466     	m_xModel.set(getDataSourceOrModel(xIn),UNO_QUERY);
467 		if ( m_xModel.is() )
468 	    	m_xDatasource.set(xIn,UNO_QUERY);
469 		else
470 		{
471     		m_xDatasource.set(getDataSourceOrModel(xIn),UNO_QUERY);
472 	    	m_xModel.set(xIn,UNO_QUERY);
473 		}
474 	}
475 
476 
477 	DBG_ASSERT(m_xDatasource.is(), "ODbDataSourceAdministrationHelper::getCurrentDataSource: no data source!");
478 	return m_xDatasource;
479 }
480 //-------------------------------------------------------------------------
481 ::rtl::OUString ODbDataSourceAdministrationHelper::getDatasourceType( const SfxItemSet& _rSet )
482 {
483 	SFX_ITEMSET_GET( _rSet, pConnectURL, SfxStringItem, DSID_CONNECTURL, sal_True );
484 	DBG_ASSERT( pConnectURL , "ODbDataSourceAdministrationHelper::getDatasourceType: invalid items in the source set!" );
485     SFX_ITEMSET_GET(_rSet, pTypeCollection, DbuTypeCollectionItem, DSID_TYPECOLLECTION, sal_True);
486 	DBG_ASSERT(pTypeCollection, "ODbDataSourceAdministrationHelper::getDatasourceType: invalid items in the source set!");
487 	::dbaccess::ODsnTypeCollection* pCollection = pTypeCollection->getCollection();
488 	return pCollection->getType(pConnectURL->GetValue());
489 }
490 
491 //-------------------------------------------------------------------------
492 sal_Bool ODbDataSourceAdministrationHelper::hasAuthentication(const SfxItemSet& _rSet) const
493 {
494     return DataSourceMetaData::getAuthentication( getDatasourceType( _rSet ) ) != AuthNone;
495 }
496 // -----------------------------------------------------------------------------
497 String ODbDataSourceAdministrationHelper::getConnectionURL() const
498 {
499 	String sNewUrl;
500 
501 	::rtl::OUString eType = getDatasourceType(*m_pItemSetHelper->getOutputSet());
502 
503 	SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pUrlItem, SfxStringItem, DSID_CONNECTURL, sal_True);
504 	SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pTypeCollection, DbuTypeCollectionItem, DSID_TYPECOLLECTION, sal_True);
505 
506 	OSL_ENSURE(pUrlItem,"Connection URL is NULL. -> GPF!");
507 	DBG_ASSERT(pTypeCollection, "ODbDataSourceAdministrationHelper::getDatasourceType: invalid items in the source set!");
508 	::dbaccess::ODsnTypeCollection* pCollection = pTypeCollection->getCollection();
509 	DBG_ASSERT(pCollection, "ODbDataSourceAdministrationHelper::getDatasourceType: invalid type collection!");
510 
511 	switch( pCollection->determineType(eType) )
512 	{
513 		case  ::dbaccess::DST_DBASE:
514 		case  ::dbaccess::DST_FLAT:
515 		case  ::dbaccess::DST_CALC:
516 			break;
517 		case  ::dbaccess::DST_ADABAS:
518 			{
519 				SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pHostName, SfxStringItem, DSID_CONN_HOSTNAME, sal_True);
520 				sNewUrl = lcl_createHostWithPort(pHostName,NULL);
521 				String sUrl = pCollection->cutPrefix(pUrlItem->GetValue());
522 				if ( sUrl.GetTokenCount(':') == 1 )
523 					sNewUrl += String::CreateFromAscii(":");
524 
525 				sNewUrl += sUrl;
526 			}
527 			break;
528 		case  ::dbaccess::DST_MSACCESS:
529         case  ::dbaccess::DST_MSACCESS_2007:
530 			{
531 				::rtl::OUString sFileName = pCollection->cutPrefix(pUrlItem->GetValue());
532 				::rtl::OUString sNewFileName;
533 				if ( ::osl::FileBase::getSystemPathFromFileURL( sFileName, sNewFileName ) == ::osl::FileBase::E_None )
534 				{
535 					sNewUrl += String(sNewFileName);
536 				}
537 			}
538             break;
539         case  ::dbaccess::DST_MYSQL_NATIVE:
540 		case  ::dbaccess::DST_MYSQL_JDBC:
541 			{
542 				SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pHostName, SfxStringItem, DSID_CONN_HOSTNAME, sal_True);
543 				SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pPortNumber, SfxInt32Item, DSID_MYSQL_PORTNUMBER, sal_True);
544 				SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pDatabaseName, SfxStringItem, DSID_DATABASENAME, sal_True);
545 				sNewUrl = lcl_createHostWithPort(pHostName,pPortNumber);
546                 String sDatabaseName = pDatabaseName ? pDatabaseName->GetValue() : String();
547                 if ( !sDatabaseName.Len() && pUrlItem )
548                     sDatabaseName = pCollection->cutPrefix( pUrlItem->GetValue() );
549                     // TODO: what's that? Why is the database name transported via the URL Item?
550                     // Huh? Anybody there?
551 					// OJ: It is needed when the connection properties are changed. There the URL is used for every type.
552 
553                 if ( sDatabaseName.Len() )
554                 {
555 					sNewUrl += String::CreateFromAscii("/");
556 					sNewUrl += sDatabaseName;
557                 }
558 			}
559 			break;
560 		case  ::dbaccess::DST_ORACLE_JDBC:
561 			{
562 				SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pHostName, SfxStringItem, DSID_CONN_HOSTNAME, sal_True);
563 				SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pPortNumber, SfxInt32Item, DSID_ORACLE_PORTNUMBER, sal_True);
564 				SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pDatabaseName, SfxStringItem, DSID_DATABASENAME, sal_True);
565                 if ( pHostName && pHostName->GetValue().Len() )
566                 {
567 				    sNewUrl = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("@"));
568 				    sNewUrl += lcl_createHostWithPort(pHostName,pPortNumber);
569 				    String sDatabaseName = pDatabaseName ? pDatabaseName->GetValue() : String();
570                     if ( !sDatabaseName.Len() && pUrlItem )
571                         sDatabaseName = pCollection->cutPrefix( pUrlItem->GetValue() );
572 				    if ( sDatabaseName.Len() )
573 				    {
574 					    sNewUrl += String::CreateFromAscii(":");
575 					    sNewUrl += sDatabaseName;
576 				    }
577                 }
578                 else
579                 { // here someone entered a JDBC url which looks like oracle, so we have to use the url property
580 
581                 }
582 			}
583 			break;
584 		case  ::dbaccess::DST_LDAP:
585 			{
586 				//	SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pHostName, SfxStringItem, DSID_CONN_HOSTNAME, sal_True);
587 				SFX_ITEMSET_GET(*m_pItemSetHelper->getOutputSet(), pPortNumber, SfxInt32Item, DSID_CONN_LDAP_PORTNUMBER, sal_True);
588 				sNewUrl = pCollection->cutPrefix(pUrlItem->GetValue());
589 				sNewUrl += lcl_createHostWithPort(NULL,pPortNumber);
590 			}
591 			break;
592 		case  ::dbaccess::DST_JDBC:
593 			// run through
594 		default:
595 			break;
596 	}
597 	if ( sNewUrl.Len() )
598 	{
599 		String sUrl = pCollection->getPrefix(eType);
600 		sUrl += sNewUrl;
601 		sNewUrl = sUrl;
602 	}
603 	else
604 		sNewUrl = pUrlItem->GetValue();
605 
606 	return sNewUrl;
607 }
608 //-------------------------------------------------------------------------
609 struct PropertyValueLess
610 {
611 	bool operator() (const PropertyValue& x, const PropertyValue& y) const
612 		{ return x.Name < y.Name ? true : false; }		// construct prevents a MSVC6 warning
613 };
614 DECLARE_STL_SET( PropertyValue, PropertyValueLess, PropertyValueSet);
615 
616 //........................................................................
617 void ODbDataSourceAdministrationHelper::translateProperties(const Reference< XPropertySet >& _rxSource, SfxItemSet& _rDest)
618 {
619 	::rtl::OUString sNewConnectURL, sName, sUid, sPwd;
620 	Sequence< ::rtl::OUString > aTableFitler;
621 
622 	if (_rxSource.is())
623 	{
624 		for	(	ConstMapInt2StringIterator aDirect = m_aDirectPropTranslator.begin();
625 				aDirect != m_aDirectPropTranslator.end();
626 				++aDirect
627 			)
628 		{
629 			// get the property value
630 			Any aValue;
631 			try
632 			{
633 				aValue = _rxSource->getPropertyValue(aDirect->second);
634 			}
635 			catch(Exception&)
636 			{
637 #ifdef DBG_UTIL
638 				::rtl::OString aMessage("ODbDataSourceAdministrationHelper::translateProperties: could not extract the property ");
639 				aMessage += ::rtl::OString(aDirect->second.getStr(), aDirect->second.getLength(), RTL_TEXTENCODING_ASCII_US);
640 				aMessage += ::rtl::OString("!");
641 				DBG_ERROR(aMessage.getStr());
642 #endif
643 			}
644 			// transfer it into an item
645 			implTranslateProperty(_rDest, aDirect->first, aValue);
646 		}
647 
648 		// get the additional informations
649 		Sequence< PropertyValue > aAdditionalInfo;
650 		try
651 		{
652 			_rxSource->getPropertyValue(PROPERTY_INFO) >>= aAdditionalInfo;
653 		}
654 		catch(Exception&) { }
655 
656 		// collect the names of the additional settings
657 		const PropertyValue* pAdditionalInfo = aAdditionalInfo.getConstArray();
658 		PropertyValueSet aInfos;
659 		for (sal_Int32 i=0; i<aAdditionalInfo.getLength(); ++i, ++pAdditionalInfo)
660 		{
661 			if (0 == pAdditionalInfo->Name.compareToAscii("JDBCDRV"))
662 			{	// compatibility
663 				PropertyValue aCompatibility(*pAdditionalInfo);
664 				aCompatibility.Name = ::rtl::OUString::createFromAscii("JavaDriverClass");
665 				aInfos.insert(aCompatibility);
666 			}
667 			else
668 				aInfos.insert(*pAdditionalInfo);
669 		}
670 
671 		// go through all known translations and check if we have such a setting
672         if ( !aInfos.empty() )
673         {
674 		    PropertyValue aSearchFor;
675             ConstMapInt2StringIterator aEnd = m_aIndirectPropTranslator.end();
676 		    for	(	ConstMapInt2StringIterator aIndirect = m_aIndirectPropTranslator.begin();
677 				    aIndirect != aEnd;
678 				    ++aIndirect)
679 		    {
680 			    aSearchFor.Name = aIndirect->second;
681 			    ConstPropertyValueSetIterator aInfoPos = aInfos.find(aSearchFor);
682 			    if (aInfos.end() != aInfoPos)
683 				    // the property is contained in the info sequence
684 				    // -> transfer it into an item
685 				    implTranslateProperty(_rDest, aIndirect->first, aInfoPos->Value);
686 		    }
687         }
688 
689 		convertUrl(_rDest);
690 	}
691 
692 	try
693 	{
694 		_rDest.Put(OPropertySetItem(DSID_DATASOURCE_UNO, _rxSource));
695 		Reference<XStorable> xStore(getDataSourceOrModel(_rxSource),UNO_QUERY);
696 		_rDest.Put(SfxBoolItem(DSID_READONLY, !xStore.is() || xStore->isReadonly() ));
697 	}
698 	catch(Exception&)
699 	{
700 		OSL_ENSURE(0,"IsReadOnly throws an exception!");
701 	}
702 }
703 
704 //-------------------------------------------------------------------------
705 void ODbDataSourceAdministrationHelper::translateProperties(const SfxItemSet& _rSource, const Reference< XPropertySet >& _rxDest)
706 {
707 	DBG_ASSERT(_rxDest.is(), "ODbDataSourceAdministrationHelper::translateProperties: invalid property set!");
708 	if (!_rxDest.is())
709 		return;
710 
711 	// the property set info
712 	Reference< XPropertySetInfo > xInfo;
713 	try { xInfo = _rxDest->getPropertySetInfo(); }
714 	catch(Exception&) { }
715 
716 	const ::rtl::OUString sUrlProp(RTL_CONSTASCII_USTRINGPARAM("URL"));
717 	// -----------------------------
718 	// transfer the direct properties
719 	for	(	ConstMapInt2StringIterator aDirect = m_aDirectPropTranslator.begin();
720 			aDirect != m_aDirectPropTranslator.end();
721 			++aDirect
722 		)
723 	{
724 		const SfxPoolItem* pCurrentItem = _rSource.GetItem((sal_uInt16)aDirect->first);
725 		if (pCurrentItem)
726 		{
727 			sal_Int16 nAttributes = PropertyAttribute::READONLY;
728 			if (xInfo.is())
729 			{
730 				try { nAttributes = xInfo->getPropertyByName(aDirect->second).Attributes; }
731 				catch(Exception&) { }
732 			}
733 			if ((nAttributes & PropertyAttribute::READONLY) == 0)
734 			{
735 				if ( sUrlProp == aDirect->second )
736 				{
737 					Any aValue(makeAny(::rtl::OUString(getConnectionURL())));
738 					//	aValue <<= ::rtl::OUString();
739 					lcl_putProperty(_rxDest, aDirect->second,aValue);
740 				}
741 				else
742 					implTranslateProperty(_rxDest, aDirect->second, pCurrentItem);
743 			}
744 		}
745 	}
746 
747 	// -------------------------------
748 	// now for the indirect properties
749 
750 	Sequence< PropertyValue > aInfo;
751 	// the original properties
752 	try
753 	{
754 		_rxDest->getPropertyValue(PROPERTY_INFO) >>= aInfo;
755 	}
756 	catch(Exception&) { }
757 
758 	// overwrite and extend them
759 	fillDatasourceInfo(_rSource, aInfo);
760 	// and propagate the (newly composed) sequence to the set
761 	lcl_putProperty(_rxDest,PROPERTY_INFO, makeAny(aInfo));
762 }
763 
764 
765 //-------------------------------------------------------------------------
766 void ODbDataSourceAdministrationHelper::fillDatasourceInfo(const SfxItemSet& _rSource, Sequence< ::com::sun::star::beans::PropertyValue >& _rInfo)
767 {
768 	// within the current "Info" sequence, replace the ones we can examine from the item set
769 	// (we don't just fill a completely new sequence with our own items, but we preserve any properties unknown to
770 	// us)
771 
772 	// first determine which of all the items are relevant for the data source (depends on the connection url)
773 	::rtl::OUString eType = getDatasourceType(_rSource);
774 	::std::vector< sal_Int32> aDetailIds;
775 	ODriversSettings::getSupportedIndirectSettings(eType,getORB(),aDetailIds);
776 
777     // collect the translated property values for the relevant items
778 	PropertyValueSet aRelevantSettings;
779 	ConstMapInt2StringIterator aTranslation;
780 	::std::vector< sal_Int32>::iterator aDetailsEnd = aDetailIds.end();
781 	for (::std::vector< sal_Int32>::iterator aIter = aDetailIds.begin();aIter != aDetailsEnd ; ++aIter)
782 	{
783 		const SfxPoolItem* pCurrent = _rSource.GetItem((sal_uInt16)*aIter);
784 		aTranslation = m_aIndirectPropTranslator.find(*aIter);
785 		if ( pCurrent && (m_aIndirectPropTranslator.end() != aTranslation) )
786 		{
787 			if ( aTranslation->second == INFO_CHARSET )
788 			{
789 				::rtl::OUString sCharSet;
790 				implTranslateProperty(pCurrent) >>= sCharSet;
791 				if ( sCharSet.getLength() )
792 					aRelevantSettings.insert(PropertyValue(aTranslation->second, 0, makeAny(sCharSet), PropertyState_DIRECT_VALUE));
793 			}
794 			else
795 				aRelevantSettings.insert(PropertyValue(aTranslation->second, 0, implTranslateProperty(pCurrent), PropertyState_DIRECT_VALUE));
796 		}
797 	}
798 
799 	// settings to preserve
800 	MapInt2String	aPreservedSettings;
801 
802 	// now aRelevantSettings contains all the property values relevant for the current data source type,
803 	// check the original sequence if it already contains any of these values (which have to be overwritten, then)
804 	PropertyValue* pInfo = _rInfo.getArray();
805 	PropertyValue aSearchFor;
806 	sal_Int32 nObsoleteSetting = -1;
807 	sal_Int32 nCount = _rInfo.getLength();
808 	for (sal_Int32 i = 0; i < nCount; ++i, ++pInfo)
809 	{
810 		aSearchFor.Name = pInfo->Name;
811 		PropertyValueSetIterator aOverwrittenSetting = aRelevantSettings.find(aSearchFor);
812 		if (aRelevantSettings.end() != aOverwrittenSetting)
813 		{	// the setting was present in the original sequence, and it is to be overwritten -> replace it
814 			if ( !::comphelper::compare(pInfo->Value,aOverwrittenSetting->Value) )
815 				*pInfo = *aOverwrittenSetting;
816 			aRelevantSettings.erase(aOverwrittenSetting);
817 		}
818 		else if (0 == pInfo->Name.compareToAscii("JDBCDRV"))
819 		{	// this is a compatibility setting, remove it from the sequence (it's replaced by JavaDriverClass)
820 			nObsoleteSetting = i;
821 		}
822 		else
823 			aPreservedSettings[i] = pInfo->Name;
824 	}
825 	if (-1 != nObsoleteSetting)
826 		::comphelper::removeElementAt(_rInfo, nObsoleteSetting);
827 
828 	if ( !aPreservedSettings.empty() )
829 	{	// check if there are settings which
830 		// * are known as indirect properties
831 		// * but not relevant for the current data source type
832 		// These settings have to be removed: If they're not relevant, we have no UI for changing them.
833 		// 25.06.2001 - 88004/87182 - frank.schoenheit@sun.com
834 
835 		// for this, we need a string-controlled quick access to m_aIndirectPropTranslator
836 		StringSet aIndirectProps;
837 		::std::transform(m_aIndirectPropTranslator.begin(),
838 						 m_aIndirectPropTranslator.end(),
839 						 ::std::insert_iterator<StringSet>(aIndirectProps,aIndirectProps.begin()),
840 						 ::std::select2nd<MapInt2String::value_type>());
841 
842 		// now check the to-be-preserved props
843 		::std::vector< sal_Int32 > aRemoveIndexes;
844 		sal_Int32 nPositionCorrector = 0;
845 		ConstMapInt2StringIterator aPreservedEnd = aPreservedSettings.end();
846 		for	(	ConstMapInt2StringIterator aPreserved = aPreservedSettings.begin();
847 				aPreserved != aPreservedEnd;
848 				++aPreserved
849 			)
850 		{
851 			if (aIndirectProps.end() != aIndirectProps.find(aPreserved->second))
852 			{
853 #ifdef DBG_UTIL
854 				const ::rtl::OUString sName = aPreserved->second;
855 #endif
856 				aRemoveIndexes.push_back(aPreserved->first - nPositionCorrector);
857 				++nPositionCorrector;
858 			}
859 		}
860 		// now finally remove all such props
861 		::std::vector< sal_Int32 >::const_iterator aRemoveEnd = aRemoveIndexes.end();
862 		for (	::std::vector< sal_Int32 >::const_iterator aRemoveIndex = aRemoveIndexes.begin();
863 				aRemoveIndex != aRemoveEnd;
864 				++aRemoveIndex
865 			)
866 			::comphelper::removeElementAt(_rInfo, *aRemoveIndex);
867 #ifdef DBG_UTIL
868 		const PropertyValue* pWhatsLeft = _rInfo.getConstArray();
869 		const PropertyValue* pWhatsLeftEnd = pWhatsLeft + _rInfo.getLength();
870 		for (; pWhatsLeft != pWhatsLeftEnd; ++pWhatsLeft)
871 		{
872 			::rtl::OUString sLookAtIt = pWhatsLeft->Name;
873 		}
874 #endif
875 	}
876 
877     ::connectivity::DriversConfig aDriverConfig(getORB());
878     const ::comphelper::NamedValueCollection& aProperties = aDriverConfig.getProperties(eType);
879     Sequence< Any> aTypeSettings;
880     aTypeSettings = aProperties.getOrDefault("TypeInfoSettings",aTypeSettings);
881     // here we have a special entry for types from oracle
882     if ( aTypeSettings.getLength() )
883     {
884         aRelevantSettings.insert(PropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("TypeInfoSettings")), 0, makeAny(aTypeSettings), PropertyState_DIRECT_VALUE));
885     }
886 
887 	// check which values are still left ('cause they were not present in the original sequence, but are to be set)
888 	if ( !aRelevantSettings.empty() )
889 	{
890 		sal_Int32 nOldLength = _rInfo.getLength();
891 		_rInfo.realloc(nOldLength + aRelevantSettings.size());
892 		PropertyValue* pAppendValues = _rInfo.getArray() + nOldLength;
893 		ConstPropertyValueSetIterator aRelevantEnd = aRelevantSettings.end();
894 		for	(	ConstPropertyValueSetIterator aLoop = aRelevantSettings.begin();
895 				aLoop != aRelevantEnd;
896 				++aLoop, ++pAppendValues
897 			)
898 		{
899 			if ( aLoop->Name == INFO_CHARSET )
900 			{
901 				::rtl::OUString sCharSet;
902 				aLoop->Value >>= sCharSet;
903 				if ( sCharSet.getLength() )
904 					*pAppendValues = *aLoop;
905 			}
906 			else
907 				*pAppendValues = *aLoop;
908 		}
909 	}
910 }
911 //-------------------------------------------------------------------------
912 Any ODbDataSourceAdministrationHelper::implTranslateProperty(const SfxPoolItem* _pItem)
913 {
914 	// translate the SfxPoolItem
915 	Any aValue;
916 
917     const SfxStringItem* pStringItem = PTR_CAST( SfxStringItem, _pItem );
918     const SfxBoolItem* pBoolItem = PTR_CAST( SfxBoolItem, _pItem );
919     const OptionalBoolItem* pOptBoolItem = PTR_CAST( OptionalBoolItem, _pItem );
920     const SfxInt32Item* pInt32Item = PTR_CAST( SfxInt32Item, _pItem );
921     const OStringListItem* pStringListItem = PTR_CAST( OStringListItem, _pItem );
922 
923 	if ( pStringItem )
924     {
925 		aValue <<= ::rtl::OUString( pStringItem->GetValue().GetBuffer() );
926     }
927 	else if ( pBoolItem )
928     {
929 		aValue <<= pBoolItem->GetValue();
930     }
931     else if ( pOptBoolItem )
932     {
933         if ( !pOptBoolItem->HasValue() )
934             aValue.clear();
935         else
936             aValue <<= (sal_Bool)pOptBoolItem->GetValue();
937     }
938 	else if ( pInt32Item )
939     {
940 		aValue <<= pInt32Item->GetValue();
941     }
942 	else if ( pStringListItem )
943     {
944 		aValue <<= pStringListItem->getList();
945     }
946 	else
947 	{
948 		DBG_ERROR("ODbDataSourceAdministrationHelper::implTranslateProperty: unsupported item type!");
949 		return aValue;
950 	}
951 
952 	return aValue;
953 }
954 //-------------------------------------------------------------------------
955 void ODbDataSourceAdministrationHelper::implTranslateProperty(const Reference< XPropertySet >& _rxSet, const ::rtl::OUString& _rName, const SfxPoolItem* _pItem)
956 {
957 	Any aValue = implTranslateProperty(_pItem);
958 	lcl_putProperty(_rxSet, _rName,aValue);
959 }
960 #ifdef DBG_UTIL
961 //-------------------------------------------------------------------------
962 ::rtl::OString ODbDataSourceAdministrationHelper::translatePropertyId( sal_Int32 _nId )
963 {
964 	::rtl::OUString aString;
965 
966 	MapInt2String::const_iterator aPos = m_aDirectPropTranslator.find( _nId );
967 	if ( m_aDirectPropTranslator.end() != aPos )
968 	{
969 		aString = aPos->second;
970 	}
971 	else
972 	{
973 		MapInt2String::const_iterator indirectPos = m_aIndirectPropTranslator.find( _nId );
974 		if ( m_aIndirectPropTranslator.end() != indirectPos )
975 			aString = indirectPos->second;
976 	}
977 
978 	::rtl::OString aReturn( aString.getStr(), aString.getLength(), RTL_TEXTENCODING_ASCII_US );
979 	return aReturn;
980 }
981 #endif
982 
983 //-------------------------------------------------------------------------
984 void ODbDataSourceAdministrationHelper::implTranslateProperty( SfxItemSet& _rSet, sal_Int32  _nId, const Any& _rValue )
985 {
986 	switch ( _rValue.getValueType().getTypeClass() )
987 	{
988 		case TypeClass_STRING:
989 			if ( implCheckItemType( _rSet, _nId, SfxStringItem::StaticType() ) )
990 			{
991 				::rtl::OUString sValue;
992 				_rValue >>= sValue;
993 				_rSet.Put(SfxStringItem(_nId, sValue.getStr()));
994 			}
995 			else {
996 				DBG_ERROR(
997 					(	::rtl::OString( "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value (" )
998 					+=	::rtl::OString( translatePropertyId( _nId ) )
999 					+=	::rtl::OString( " should be no string)!" )
1000 					).getStr()
1001 				);
1002             }
1003 			break;
1004 
1005 		case TypeClass_BOOLEAN:
1006 			if ( implCheckItemType( _rSet, _nId, SfxBoolItem::StaticType() ) )
1007 			{
1008 				sal_Bool bVal = sal_False;
1009 				_rValue >>= bVal;
1010 				_rSet.Put(SfxBoolItem(_nId, bVal));
1011 			}
1012             else if ( implCheckItemType( _rSet, _nId, OptionalBoolItem::StaticType() ) )
1013             {
1014                 OptionalBoolItem aItem( _nId );
1015                 if ( _rValue.hasValue() )
1016                 {
1017 				    sal_Bool bValue = sal_False;
1018 				    _rValue >>= bValue;
1019                     aItem.SetValue( bValue );
1020                 }
1021                 else
1022                     aItem.ClearValue();
1023 				_rSet.Put( aItem );
1024             }
1025 			else {
1026 				DBG_ERROR(
1027 					(	::rtl::OString( "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value (" )
1028 					+=	::rtl::OString( translatePropertyId( _nId ) )
1029 					+=	::rtl::OString( " should be no boolean)!" )
1030 					).getStr()
1031 				);
1032             }
1033 			break;
1034 
1035 		case TypeClass_LONG:
1036 			if ( implCheckItemType( _rSet, _nId, SfxInt32Item::StaticType() ) )
1037 			{
1038 				sal_Int32 nValue = 0;
1039 				_rValue >>= nValue;
1040 				_rSet.Put( SfxInt32Item( _nId, nValue ) );
1041 			}
1042 			else {
1043 				DBG_ERROR(
1044 					(	::rtl::OString( "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value (" )
1045 					+=	::rtl::OString( translatePropertyId( _nId ) )
1046 					+=	::rtl::OString( " should be no int)!" )
1047 					).getStr()
1048 				);
1049             }
1050 			break;
1051 
1052 		case TypeClass_SEQUENCE:
1053 			if ( implCheckItemType( _rSet, _nId, OStringListItem::StaticType() ) )
1054 			{
1055 				// determine the element type
1056 				TypeDescription aTD(_rValue.getValueType());
1057 				typelib_IndirectTypeDescription* pSequenceTD =
1058 					reinterpret_cast< typelib_IndirectTypeDescription* >(aTD.get());
1059 				DBG_ASSERT(pSequenceTD && pSequenceTD->pType, "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid sequence type!");
1060 
1061 				Type aElementType(pSequenceTD->pType);
1062 				switch (aElementType.getTypeClass())
1063 				{
1064 					case TypeClass_STRING:
1065 					{
1066 						Sequence< ::rtl::OUString > aStringList;
1067 						_rValue >>= aStringList;
1068 						_rSet.Put(OStringListItem(_nId, aStringList));
1069 					}
1070 					break;
1071 					default:
1072 						DBG_ERROR("ODbDataSourceAdministrationHelper::implTranslateProperty: unsupported property value type!");
1073 				}
1074 			}
1075 			else {
1076 				DBG_ERROR(
1077 					(	::rtl::OString( "ODbDataSourceAdministrationHelper::implTranslateProperty: invalid property value (" )
1078 					+=	::rtl::OString( translatePropertyId( _nId ) )
1079 					+=	::rtl::OString( " should be no string sequence)!" )
1080 					).getStr()
1081 				);
1082             }
1083 			break;
1084 
1085 		case TypeClass_VOID:
1086 			_rSet.ClearItem(_nId);
1087 			break;
1088 
1089 		default:
1090 			DBG_ERROR("ODbDataSourceAdministrationHelper::implTranslateProperty: unsupported property value type!");
1091 	}
1092 }
1093 
1094 
1095 String ODbDataSourceAdministrationHelper::getDocumentUrl(SfxItemSet& _rDest)
1096 {
1097     SFX_ITEMSET_GET(_rDest, pUrlItem, SfxStringItem, DSID_DOCUMENT_URL, sal_True);
1098 	OSL_ENSURE(pUrlItem,"Document URL is NULL. -> GPF!");
1099     return pUrlItem->GetValue();
1100 }
1101 
1102 
1103 // -----------------------------------------------------------------------------
1104 void ODbDataSourceAdministrationHelper::convertUrl(SfxItemSet& _rDest)
1105 {
1106 	::rtl::OUString eType = getDatasourceType(_rDest);
1107 
1108 	SFX_ITEMSET_GET(_rDest, pUrlItem, SfxStringItem, DSID_CONNECTURL, sal_True);
1109 	SFX_ITEMSET_GET(_rDest, pTypeCollection, DbuTypeCollectionItem, DSID_TYPECOLLECTION, sal_True);
1110 
1111 	OSL_ENSURE(pUrlItem,"Connection URL is NULL. -> GPF!");
1112 	DBG_ASSERT(pTypeCollection, "ODbAdminDialog::getDatasourceType: invalid items in the source set!");
1113 	::dbaccess::ODsnTypeCollection* pCollection = pTypeCollection->getCollection();
1114 	DBG_ASSERT(pCollection, "ODbAdminDialog::getDatasourceType: invalid type collection!");
1115 
1116 	sal_uInt16 nPortNumberId	= 0;
1117 	sal_Int32 nPortNumber	= -1;
1118 	String sNewHostName;
1119 	//String sUrl = pCollection->cutPrefix(pUrlItem->GetValue());
1120 	String sUrlPart;
1121 
1122 	pCollection->extractHostNamePort(pUrlItem->GetValue(),sUrlPart,sNewHostName,nPortNumber);
1123     const ::dbaccess::DATASOURCE_TYPE eTy = pCollection->determineType(eType);
1124 
1125 	switch( eTy )
1126 	{
1127         case  ::dbaccess::DST_MYSQL_NATIVE:
1128 		case  ::dbaccess::DST_MYSQL_JDBC:
1129 			nPortNumberId = DSID_MYSQL_PORTNUMBER;
1130 			break;
1131 		case  ::dbaccess::DST_ORACLE_JDBC:
1132 			nPortNumberId = DSID_ORACLE_PORTNUMBER;
1133 			break;
1134 		case  ::dbaccess::DST_LDAP:
1135 			nPortNumberId = DSID_CONN_LDAP_PORTNUMBER;
1136 			break;
1137         default:
1138             break;
1139 	}
1140 
1141 	if ( sUrlPart.Len() )
1142 	{
1143         if ( eTy == ::dbaccess::DST_MYSQL_NATIVE )
1144         {
1145 		    _rDest.Put( SfxStringItem( DSID_DATABASENAME, sUrlPart ) );
1146         }
1147         else
1148         {
1149 		    String sNewUrl = pCollection->getPrefix(eType);
1150 		    sNewUrl += sUrlPart;
1151 		    _rDest.Put( SfxStringItem( DSID_CONNECTURL, sNewUrl ) );
1152         }
1153 	}
1154 
1155 	if ( sNewHostName.Len() )
1156 		_rDest.Put(SfxStringItem(DSID_CONN_HOSTNAME, sNewHostName));
1157 
1158 	if ( nPortNumber != -1 && nPortNumberId != 0 )
1159 		_rDest.Put(SfxInt32Item(nPortNumberId, nPortNumber));
1160 
1161 }
1162 // -----------------------------------------------------------------------------
1163 sal_Bool ODbDataSourceAdministrationHelper::saveChanges(const SfxItemSet& _rSource)
1164 {
1165 	// put the remembered settings into the property set
1166 	Reference<XPropertySet> xDatasource = getCurrentDataSource();
1167 	if ( !xDatasource.is() )
1168 		return sal_False;
1169 
1170 	translateProperties(_rSource,xDatasource );
1171 
1172 	return sal_True;
1173 }
1174 // -----------------------------------------------------------------------------
1175 void ODbDataSourceAdministrationHelper::setDataSourceOrName( const Any& _rDataSourceOrName )
1176 {
1177     DBG_ASSERT( !m_aDataSourceOrName.hasValue(), "ODbDataSourceAdministrationHelper::setDataSourceOrName: already have one!" );
1178         // hmm. We could reset m_xDatasource/m_xModel, probably, and continue working
1179 	m_aDataSourceOrName = _rDataSourceOrName;
1180 }
1181 //=========================================================================
1182 //= DbuTypeCollectionItem
1183 //=========================================================================
1184 TYPEINIT1(DbuTypeCollectionItem, SfxPoolItem);
1185 //-------------------------------------------------------------------------
1186 DbuTypeCollectionItem::DbuTypeCollectionItem(sal_Int16 _nWhich, ::dbaccess::ODsnTypeCollection* _pCollection)
1187 	:SfxPoolItem(_nWhich)
1188 	,m_pCollection(_pCollection)
1189 {
1190 }
1191 
1192 //-------------------------------------------------------------------------
1193 DbuTypeCollectionItem::DbuTypeCollectionItem(const DbuTypeCollectionItem& _rSource)
1194 	:SfxPoolItem(_rSource)
1195 	,m_pCollection(_rSource.getCollection())
1196 {
1197 }
1198 
1199 //-------------------------------------------------------------------------
1200 int DbuTypeCollectionItem::operator==(const SfxPoolItem& _rItem) const
1201 {
1202 	DbuTypeCollectionItem* pCompare = PTR_CAST(DbuTypeCollectionItem, &_rItem);
1203 	return pCompare && (pCompare->getCollection() == getCollection());
1204 }
1205 
1206 //-------------------------------------------------------------------------
1207 SfxPoolItem* DbuTypeCollectionItem::Clone(SfxItemPool* /*_pPool*/) const
1208 {
1209 	return new DbuTypeCollectionItem(*this);
1210 }
1211 
1212 //.........................................................................
1213 }	// namespace dbaui
1214 //.........................................................................
1215 
1216 
1217 
1218