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 <hsqldb/HDriver.hxx>
21 #include <hsqldb/HConnection.hxx>
22 #include <osl/diagnose.h>
23 #include <sal/log.hxx>
24 #include <connectivity/dbexception.hxx>
25 #include <com/sun/star/configuration/theDefaultProvider.hpp>
26 #include <com/sun/star/sdbc/DriverManager.hpp>
27 #include <com/sun/star/sdbc/XResultSet.hpp>
28 #include <com/sun/star/sdbc/XRow.hpp>
29 #include <com/sun/star/embed/XTransactionBroadcaster.hpp>
30 #include <com/sun/star/embed/ElementModes.hpp>
31 #include <TConnection.hxx>
32 #include <hsqldb/HStorageMap.hxx>
33 #include <jvmfwk/framework.hxx>
34 #include <com/sun/star/reflection/XProxyFactory.hpp>
35 #include <com/sun/star/embed/XStorage.hpp>
36 #include <com/sun/star/frame/Desktop.hpp>
37 #include <com/sun/star/util/XFlushable.hpp>
38 #include "HTerminateListener.hxx"
39 #include <hsqldb/HCatalog.hxx>
40 #include <rtl/ustrbuf.hxx>
42 #include <osl/process.h>
43 #include <comphelper/namedvaluecollection.hxx>
44 #include <comphelper/propertysequence.hxx>
45 #include <comphelper/servicehelper.hxx>
46 #include <cppuhelper/supportsservice.hxx>
47 #include <comphelper/types.hxx>
48 #include <unotools/confignode.hxx>
49 #include <unotools/ucbstreamhelper.hxx>
50 #include <strings.hrc>
51 #include <resource/sharedresources.hxx>
52 #include <i18nlangtag/languagetag.hxx>
53 #include <comphelper/diagnose_ex.hxx>
54 #include <o3tl/string_view.hxx>
59 namespace connectivity
62 using namespace hsqldb
;
63 using namespace css::uno
;
64 using namespace css::sdbc
;
65 using namespace css::sdbcx
;
66 using namespace css::beans
;
67 using namespace css::frame
;
68 using namespace css::lang
;
69 using namespace css::embed
;
70 using namespace css::io
;
71 using namespace css::util
;
73 constexpr OUString IMPL_NAME
= u
"com.sun.star.sdbcx.comp.hsqldb.Driver"_ustr
;
77 ODriverDelegator::ODriverDelegator(const Reference
< XComponentContext
>& _rxContext
)
78 : ODriverDelegator_BASE(m_aMutex
)
79 ,m_xContext(_rxContext
)
80 ,m_bInShutDownConnections(false)
85 ODriverDelegator::~ODriverDelegator()
89 ::comphelper::disposeComponent(m_xDriver
);
91 catch(const Exception
&)
97 void SAL_CALL
ODriverDelegator::disposing()
99 ::osl::MutexGuard
aGuard(m_aMutex
);
103 for (const auto& rConnection
: m_aConnections
)
105 Reference
<XInterface
> xTemp
= rConnection
.first
.get();
106 ::comphelper::disposeComponent(xTemp
);
113 m_aConnections
.clear();
114 TWeakPairVector().swap(m_aConnections
);
116 cppu::WeakComponentImplHelperBase::disposing();
119 Reference
< XDriver
> const & ODriverDelegator::loadDriver( )
121 if ( !m_xDriver
.is() )
123 Reference
<XDriverManager2
> xDriverAccess
= DriverManager::create( m_xContext
);
124 m_xDriver
= xDriverAccess
->getDriverByURL(u
"jdbc:hsqldb:db"_ustr
);
133 OUString
lcl_getPermittedJavaMethods_nothrow( const Reference
< XComponentContext
>& _rxContext
)
135 OUString aConfigPath
=
136 "/org.openoffice.Office.DataAccess/DriverSettings/" +
138 "/PermittedJavaMethods";
139 ::utl::OConfigurationTreeRoot
aConfig( ::utl::OConfigurationTreeRoot::createWithComponentContext(
140 _rxContext
, aConfigPath
) );
142 OUStringBuffer aPermittedMethods
;
143 const Sequence
< OUString
> aNodeNames( aConfig
.getNodeNames() );
144 for ( auto const & nodeName
: aNodeNames
)
146 OUString sPermittedMethod
;
147 OSL_VERIFY( aConfig
.getNodeValue( nodeName
) >>= sPermittedMethod
);
149 if ( !aPermittedMethods
.isEmpty() )
150 aPermittedMethods
.append( ';' );
151 aPermittedMethods
.append( sPermittedMethod
);
154 return aPermittedMethods
.makeStringAndClear();
159 Reference
< XConnection
> SAL_CALL
ODriverDelegator::connect( const OUString
& url
, const Sequence
< PropertyValue
>& info
)
161 Reference
< XConnection
> xConnection
;
162 if ( acceptsURL(url
) )
164 Reference
< XDriver
> xDriver
= loadDriver();
168 Reference
<XStorage
> xStorage
;
169 const PropertyValue
* pIter
= info
.getConstArray();
170 const PropertyValue
* pEnd
= pIter
+ info
.getLength();
172 for (;pIter
!= pEnd
; ++pIter
)
174 if ( pIter
->Name
== "Storage" )
176 xStorage
.set(pIter
->Value
,UNO_QUERY
);
178 else if ( pIter
->Name
== "URL" )
180 pIter
->Value
>>= sURL
;
184 if ( !xStorage
.is() || sURL
.isEmpty() )
186 ::connectivity::SharedResources aResources
;
187 const OUString sMessage
= aResources
.getResourceString(STR_NO_STORAGE
);
188 ::dbtools::throwGenericSQLException(sMessage
,*this);
191 OUString sSystemPath
;
192 osl_getSystemPathFromFileURL( sURL
.pData
, &sSystemPath
.pData
);
193 if ( sURL
.isEmpty() || sSystemPath
.isEmpty() )
195 ::connectivity::SharedResources aResources
;
196 const OUString sMessage
= aResources
.getResourceString(STR_INVALID_FILE_URL
);
197 ::dbtools::throwGenericSQLException(sMessage
,*this);
200 bool bIsNewDatabase
= !xStorage
->hasElements();
202 ::comphelper::NamedValueCollection aProperties
;
204 // properties for accessing the embedded storage
205 OUString sKey
= StorageContainer::registerStorage( xStorage
, sSystemPath
);
206 aProperties
.put( u
"storage_key"_ustr
, sKey
);
207 aProperties
.put( u
"storage_class_name"_ustr
,
208 u
"com.sun.star.sdbcx.comp.hsqldb.StorageAccess"_ustr
);
209 aProperties
.put( u
"fileaccess_class_name"_ustr
,
210 u
"com.sun.star.sdbcx.comp.hsqldb.StorageFileAccess"_ustr
);
212 // JDBC driver and driver's classpath
213 aProperties
.put( u
"JavaDriverClass"_ustr
, u
"org.hsqldb.jdbcDriver"_ustr
);
214 aProperties
.put( u
"JavaDriverClassPath"_ustr
,
218 u
"vnd.sun.star.expand:$LO_JAVA_DIR/hsqldb.jar"
220 " vnd.sun.star.expand:$LO_JAVA_DIR/sdbc_hsqldb.jar"_ustr
);
222 // auto increment handling
223 aProperties
.put( u
"IsAutoRetrievingEnabled"_ustr
, true );
224 aProperties
.put( u
"AutoRetrievingStatement"_ustr
,
225 u
"CALL IDENTITY()"_ustr
);
226 aProperties
.put( u
"IgnoreDriverPrivileges"_ustr
, true );
228 // don't want to expose HSQLDB's schema capabilities which exist since 1.8.0RC10
229 aProperties
.put( u
"default_schema"_ustr
,
232 // security: permitted Java classes
233 NamedValue
aPermittedClasses(
234 u
"hsqldb.method_class_names"_ustr
,
235 Any( lcl_getPermittedJavaMethods_nothrow( m_xContext
) )
237 aProperties
.put( u
"SystemProperties"_ustr
, Sequence
< NamedValue
>( &aPermittedClasses
, 1 ) );
242 static constexpr OUString
sProperties( u
"properties"_ustr
);
243 if ( !bIsNewDatabase
&& xStorage
->isStreamElement(sProperties
) )
245 Reference
<XStream
> xStream
= xStorage
->openStreamElement(sProperties
,ElementModes::READ
);
248 std::unique_ptr
<SvStream
> pStream( ::utl::UcbStreamHelper::CreateStream(xStream
) );
252 OString sVersionString
;
253 while ( pStream
->ReadLine(sLine
) )
255 if ( sLine
.isEmpty() )
258 const std::string_view sIniKey
= o3tl::getToken(sLine
, 0, '=', nIdx
);
259 const OString
sValue(o3tl::getToken(sLine
, 0, '=', nIdx
));
260 if( sIniKey
== "hsqldb.compatible_version" )
262 sVersionString
= sValue
;
266 if (sIniKey
== "version" && sVersionString
.isEmpty())
268 sVersionString
= sValue
;
272 if (!sVersionString
.isEmpty())
275 const sal_Int32 nMajor
= o3tl::toInt32(o3tl::getToken(sVersionString
, 0, '.', nIdx
));
276 const sal_Int32 nMinor
= o3tl::toInt32(o3tl::getToken(sVersionString
, 0, '.', nIdx
));
277 const sal_Int32 nMicro
= o3tl::toInt32(o3tl::getToken(sVersionString
, 0, '.', nIdx
));
279 || ( nMajor
== 1 && nMinor
> 8 )
280 || ( nMajor
== 1 && nMinor
== 8 && nMicro
> 0 ) )
282 ::connectivity::SharedResources aResources
;
283 sMessage
= aResources
.getResourceString(STR_ERROR_NEW_VERSION
);
287 } // if ( xStream.is() )
288 ::comphelper::disposeComponent(xStream
);
291 // disallow any database/script files that contain a "SCRIPT[.*]" entry (this is belt and braces
292 // in that bundled hsqldb 1.8.0 is patched to also reject them)
294 // hsqldb 2.6.0 release notes have: added system role SCRIPT_OPS for export / import of database structure and data
295 // which seems to provide a builtin way to do this with contemporary hsqldb
296 static constexpr OUString
sScript(u
"script"_ustr
);
297 if (!bIsNewDatabase
&& xStorage
->isStreamElement(sScript
))
299 Reference
<XStream
> xStream
= xStorage
->openStreamElement(sScript
, ElementModes::READ
);
302 std::unique_ptr
<SvStream
> pStream(::utl::UcbStreamHelper::CreateStream(xStream
));
306 while (pStream
->ReadLine(sLine
))
308 OString sText
= sLine
.makeStringAndClear().trim();
309 if (sText
.startsWithIgnoreAsciiCase("SCRIPT"))
311 ::connectivity::SharedResources aResources
;
312 sMessage
= aResources
.getResourceString(STR_COULD_NOT_LOAD_FILE
).replaceFirst("$filename$", sSystemPath
);
317 } // if ( xStream.is() )
318 ::comphelper::disposeComponent(xStream
);
325 if ( !sMessage
.isEmpty() )
327 ::dbtools::throwGenericSQLException(sMessage
,*this);
331 Reference
<XPropertySet
> xProp(xStorage
,UNO_QUERY
);
335 xProp
->getPropertyValue(u
"OpenMode"_ustr
) >>= nMode
;
336 if ( (nMode
& ElementModes::WRITE
) != ElementModes::WRITE
)
338 aProperties
.put( u
"readonly"_ustr
, u
"true"_ustr
);
342 Sequence
< PropertyValue
> aConnectionArgs
;
343 aProperties
>>= aConnectionArgs
;
344 OUString sConnectURL
= "jdbc:hsqldb:" + sSystemPath
;
345 Reference
<XConnection
> xOrig
;
348 xOrig
= xDriver
->connect( sConnectURL
, aConnectionArgs
);
350 catch(const Exception
&)
352 StorageContainer::revokeStorage(sKey
,nullptr);
356 // if the storage is completely empty, then we just created a new HSQLDB
357 // In this case, do some initializations.
358 if ( bIsNewDatabase
&& xOrig
.is() )
359 onConnectedNewDatabase( xOrig
);
363 // now we have to set the URL to get the correct answer for metadata()->getURL()
364 auto pMetaConnection
= comphelper::getFromUnoTunnel
<OMetaConnection
>(xOrig
);
365 if ( pMetaConnection
)
366 pMetaConnection
->setURL(url
);
368 Reference
<XComponent
> xComp(xOrig
,UNO_QUERY
);
370 xComp
->addEventListener(this);
372 // we want to close all connections when the office shuts down
373 static Reference
< XTerminateListener
> s_xTerminateListener
= [&]()
375 Reference
< XDesktop2
> xDesktop
= Desktop::create( m_xContext
);
377 rtl::Reference
<OConnectionController
> tmp
= new OConnectionController(this);
378 xDesktop
->addTerminateListener(tmp
);
381 Reference
< XComponent
> xIfc
= new OHsqlConnection( this, xOrig
, m_xContext
);
382 xConnection
.set(xIfc
,UNO_QUERY
);
383 m_aConnections
.push_back(TWeakPair(WeakReferenceHelper(xOrig
),TWeakConnectionPair(sKey
,TWeakRefPair(WeakReferenceHelper(xConnection
),WeakReferenceHelper()))));
385 Reference
<XTransactionBroadcaster
> xBroad(xStorage
,UNO_QUERY
);
388 xBroad
->addTransactionListener(Reference
<XTransactionListener
>(this));
397 sal_Bool SAL_CALL
ODriverDelegator::acceptsURL( const OUString
& url
)
399 bool bEnabled
= false;
400 javaFrameworkError e
= jfw_getEnabled(&bEnabled
);
404 case JFW_E_DIRECT_MODE
:
406 "connectivity.hsqldb",
407 "jfw_getEnabled: JFW_E_DIRECT_MODE, assuming true");
412 "connectivity.hsqldb", "jfw_getEnabled: error code " << +e
);
415 return bEnabled
&& url
== "sdbc:embedded:hsqldb";
419 Sequence
< DriverPropertyInfo
> SAL_CALL
ODriverDelegator::getPropertyInfo( const OUString
& url
, const Sequence
< PropertyValue
>& /*info*/ )
421 if ( !acceptsURL(url
) )
422 return Sequence
< DriverPropertyInfo
>();
427 u
"Defines the storage where the database will be stored."_ustr
,
434 u
"Defines the url of the data source."_ustr
,
440 u
"AutoRetrievingStatement"_ustr
,
441 u
"Defines the statement which will be executed to retrieve auto increment values."_ustr
,
443 u
"CALL IDENTITY()"_ustr
,
450 sal_Int32 SAL_CALL
ODriverDelegator::getMajorVersion( )
456 sal_Int32 SAL_CALL
ODriverDelegator::getMinorVersion( )
462 Reference
< XTablesSupplier
> SAL_CALL
ODriverDelegator::getDataDefinitionByConnection( const Reference
< XConnection
>& connection
)
464 ::osl::MutexGuard
aGuard( m_aMutex
);
465 checkDisposed(ODriverDelegator_BASE::rBHelper
.bDisposed
);
467 Reference
< XTablesSupplier
> xTab
;
469 TWeakPairVector::iterator i
= std::find_if(m_aConnections
.begin(), m_aConnections
.end(),
470 [&connection
](const TWeakPairVector::value_type
& rConnection
) {
471 return rConnection
.second
.second
.first
.get() == connection
.get(); });
472 if (i
!= m_aConnections
.end())
474 xTab
.set(i
->second
.second
.second
,UNO_QUERY
);
477 xTab
= new OHCatalog(connection
);
478 i
->second
.second
.second
= WeakReferenceHelper(xTab
);
486 Reference
< XTablesSupplier
> SAL_CALL
ODriverDelegator::getDataDefinitionByURL( const OUString
& url
, const Sequence
< PropertyValue
>& info
)
488 if ( ! acceptsURL(url
) )
490 ::connectivity::SharedResources aResources
;
491 const OUString sMessage
= aResources
.getResourceString(STR_URI_SYNTAX_ERROR
);
492 ::dbtools::throwGenericSQLException(sMessage
,*this);
495 return getDataDefinitionByConnection(connect(url
,info
));
500 OUString SAL_CALL
ODriverDelegator::getImplementationName( )
505 sal_Bool SAL_CALL
ODriverDelegator::supportsService( const OUString
& _rServiceName
)
507 return cppu::supportsService(this, _rServiceName
);
510 Sequence
< OUString
> SAL_CALL
ODriverDelegator::getSupportedServiceNames( )
512 return { u
"com.sun.star.sdbc.Driver"_ustr
, u
"com.sun.star.sdbcx.Driver"_ustr
};
515 void SAL_CALL
ODriverDelegator::createCatalog( const Sequence
< PropertyValue
>& /*info*/ )
517 ::dbtools::throwFeatureNotImplementedSQLException( u
"XCreateCatalog::createCatalog"_ustr
, *this );
520 void ODriverDelegator::shutdownConnection(const TWeakPairVector::iterator
& _aIter
)
522 OSL_ENSURE(m_aConnections
.end() != _aIter
,"Iterator equals .end()");
523 bool bLastOne
= true;
526 Reference
<XConnection
> _xConnection(_aIter
->first
.get(),UNO_QUERY
);
528 if ( _xConnection
.is() )
530 Reference
<XStatement
> xStmt
= _xConnection
->createStatement();
533 Reference
<XResultSet
> xRes
= xStmt
->executeQuery(u
"SELECT COUNT(*) FROM INFORMATION_SCHEMA.SYSTEM_SESSIONS WHERE USER_NAME ='SA'"_ustr
);
534 Reference
<XRow
> xRow(xRes
,UNO_QUERY
);
535 if ( xRow
.is() && xRes
->next() )
536 bLastOne
= xRow
->getInt(1) == 1;
538 xStmt
->execute(u
"SHUTDOWN"_ustr
);
547 // Reference<XTransactionListener> xListener(*this,UNO_QUERY);
548 // a shutdown should commit all changes to the db files
549 StorageContainer::revokeStorage(_aIter
->second
.first
,nullptr);
551 if ( !m_bInShutDownConnections
)
552 m_aConnections
.erase(_aIter
);
555 void SAL_CALL
ODriverDelegator::disposing( const css::lang::EventObject
& Source
)
557 ::osl::MutexGuard
aGuard(m_aMutex
);
558 Reference
<XConnection
> xCon(Source
.Source
,UNO_QUERY
);
561 TWeakPairVector::iterator i
= std::find_if(m_aConnections
.begin(), m_aConnections
.end(),
562 [&xCon
](const TWeakPairVector::value_type
& rConnection
) { return rConnection
.first
.get() == xCon
.get(); });
564 if (i
!= m_aConnections
.end())
565 shutdownConnection(i
);
569 Reference
< XStorage
> xStorage(Source
.Source
,UNO_QUERY
);
572 OUString sKey
= StorageContainer::getRegisteredKey(xStorage
);
573 TWeakPairVector::iterator i
= std::find_if(m_aConnections
.begin(),m_aConnections
.end(),
574 [&sKey
] (const TWeakPairVector::value_type
& conn
) {
575 return conn
.second
.first
== sKey
;
578 if ( i
!= m_aConnections
.end() )
579 shutdownConnection(i
);
584 void ODriverDelegator::shutdownConnections()
586 m_bInShutDownConnections
= true;
587 for (const auto& rConnection
: m_aConnections
)
591 Reference
<XConnection
> xCon(rConnection
.first
,UNO_QUERY
);
592 ::comphelper::disposeComponent(xCon
);
598 m_aConnections
.clear();
599 m_bInShutDownConnections
= true;
602 void ODriverDelegator::flushConnections()
604 for (const auto& rConnection
: m_aConnections
)
608 Reference
<XFlushable
> xCon(rConnection
.second
.second
.first
.get(),UNO_QUERY
);
614 DBG_UNHANDLED_EXCEPTION("connectivity.hsqldb");
619 void SAL_CALL
ODriverDelegator::preCommit( const css::lang::EventObject
& aEvent
)
621 ::osl::MutexGuard
aGuard(m_aMutex
);
623 Reference
< XStorage
> xStorage(aEvent
.Source
,UNO_QUERY
);
624 OUString sKey
= StorageContainer::getRegisteredKey(xStorage
);
625 if ( sKey
.isEmpty() )
628 TWeakPairVector::const_iterator i
= std::find_if(m_aConnections
.begin(), m_aConnections
.end(),
629 [&sKey
] (const TWeakPairVector::value_type
& conn
) {
630 return conn
.second
.first
== sKey
;
633 OSL_ENSURE( i
!= m_aConnections
.end(), "ODriverDelegator::preCommit: they're committing a storage which I do not know!" );
634 if ( i
== m_aConnections
.end() )
639 Reference
<XConnection
> xConnection(i
->first
,UNO_QUERY
);
640 if ( xConnection
.is() )
642 Reference
< XStatement
> xStmt
= xConnection
->createStatement();
643 OSL_ENSURE( xStmt
.is(), "ODriverDelegator::preCommit: no statement!" );
645 xStmt
->execute( u
"SET WRITE_DELAY 0"_ustr
);
647 bool bPreviousAutoCommit
= xConnection
->getAutoCommit();
648 xConnection
->setAutoCommit( false );
649 xConnection
->commit();
650 xConnection
->setAutoCommit( bPreviousAutoCommit
);
653 xStmt
->execute( u
"SET WRITE_DELAY 60"_ustr
);
658 TOOLS_WARN_EXCEPTION( "connectivity.hsqldb", "ODriverDelegator::preCommit" );
662 void SAL_CALL
ODriverDelegator::commited( const css::lang::EventObject
& /*aEvent*/ )
666 void SAL_CALL
ODriverDelegator::preRevert( const css::lang::EventObject
& /*aEvent*/ )
670 void SAL_CALL
ODriverDelegator::reverted( const css::lang::EventObject
& /*aEvent*/ )
677 const char* lcl_getCollationForLocale( const OUString
& _rLocaleString
, bool _bAcceptCountryMismatch
= false )
679 static const char* pTranslations
[] =
681 "af-ZA", "Afrikaans",
685 "az-AZ", "Azerbaijani_Latin",
686 "az-cyrillic", "Azerbaijani_Cyrillic",
687 "be-BY", "Belarusian",
688 "bg-BG", "Bulgarian",
698 "en-US", "Latin1_General",
710 "hu-HU", "Hungarian",
712 "id-ID", "Indonesian",
714 "is-IS", "Icelandic",
716 "iu-CA", "Inuktitut",
727 "lt-LT", "Lithuanian",
730 "mk-MK", "Macedonian",
731 "ml-IN", "Malayalam",
732 "mn-MN", "Mongolian",
733 "mni-IN", "Manipuri",
738 "nb-NO", "Danish_Norwegian",
741 "nn-NO", "Norwegian",
746 "pt-PT", "Portuguese",
752 "sl-SI", "Slovenian",
755 "sr-YU", "Serbian_Cyrillic",
766 "uk-UA", "Ukrainian",
768 "uz-UZ", "Uzbek_Latin",
770 "vi-VN", "Vietnamese",
777 OUString
sLocaleString( _rLocaleString
);
778 char nCompareTermination
= 0;
780 if ( _bAcceptCountryMismatch
)
782 // strip the country part from the compare string
783 sal_Int32 nCountrySep
= sLocaleString
.indexOf( '-' );
784 if ( nCountrySep
> -1 )
785 sLocaleString
= sLocaleString
.copy( 0, nCountrySep
);
787 // the entries in the translation table are compared until the
788 // - character only, not until the terminating 0
789 nCompareTermination
= '-';
792 const char** pLookup
= pTranslations
;
793 for ( ; *pLookup
; pLookup
+=2 )
795 sal_Int32 nCompareUntil
= 0;
796 while ( (*pLookup
)[ nCompareUntil
] != nCompareTermination
&& (*pLookup
)[ nCompareUntil
] != 0 )
799 if ( sLocaleString
.equalsAsciiL( *pLookup
, nCompareUntil
) )
800 return *( pLookup
+ 1 );
803 if ( !_bAcceptCountryMismatch
)
804 // second round, this time without matching the country
805 return lcl_getCollationForLocale( _rLocaleString
, true );
807 OSL_FAIL( "lcl_getCollationForLocale: unknown locale string, falling back to Latin1_General!" );
808 return "Latin1_General";
812 OUString
lcl_getSystemLocale( const Reference
< XComponentContext
>& _rxContext
)
814 OUString sLocaleString
= u
"en-US"_ustr
;
818 Reference
< XMultiServiceFactory
> xConfigProvider(
819 css::configuration::theDefaultProvider::get( _rxContext
) );
822 // arguments for creating the config access
823 Sequence
<Any
> aArguments(comphelper::InitAnyPropertySequence(
825 {"nodepath", Any(u
"/org.openoffice.Setup/L10N"_ustr
)}, // the path to the node to open
826 {"depth", Any(sal_Int32(-1))}, // the depth: -1 means unlimited
829 Reference
< XPropertySet
> xNode(
830 xConfigProvider
->createInstanceWithArguments(
831 u
"com.sun.star.configuration.ConfigurationAccess"_ustr
,
834 OSL_ENSURE( xNode
.is(), "lcl_getSystemLocale: invalid access returned (should throw an exception instead)!" );
837 // ask for the system locale setting
839 xNode
->getPropertyValue(u
"ooSetupSystemLocale"_ustr
) >>= sLocaleString
;
841 catch( const Exception
& )
843 TOOLS_WARN_EXCEPTION( "connectivity.hsqldb", "lcl_getSystemLocale" );
845 if ( sLocaleString
.isEmpty() )
847 rtl_Locale
* pProcessLocale
= nullptr;
848 osl_getProcessLocale( &pProcessLocale
);
849 sLocaleString
= LanguageTag( *pProcessLocale
).getBcp47();
851 return sLocaleString
;
855 void ODriverDelegator::onConnectedNewDatabase( const Reference
< XConnection
>& _rxConnection
)
859 Reference
< XStatement
> xStatement
= _rxConnection
->createStatement();
860 OSL_ENSURE( xStatement
.is(), "ODriverDelegator::onConnectedNewDatabase: could not create a statement!" );
861 if ( xStatement
.is() )
863 OUStringBuffer
aStatement( "SET DATABASE COLLATION \"" );
864 aStatement
.appendAscii( lcl_getCollationForLocale( lcl_getSystemLocale( m_xContext
) ) );
865 aStatement
.append( "\"" );
867 xStatement
->execute( aStatement
.makeStringAndClear() );
870 catch( const Exception
& )
872 TOOLS_WARN_EXCEPTION( "connectivity.hsqldb", "ODriverDelegator::onConnectedNewDatabase" );
877 } // namespace connectivity
880 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
881 connectivity_hsqldb_ODriverDelegator_implementation(
882 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const&)
884 return cppu::acquire(new connectivity::ODriverDelegator(context
));
888 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */