22#include <osl/diagnose.h>
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>
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>
40#include <rtl/ustrbuf.hxx>
42#include <osl/process.h>
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;
72 using namespace css::reflection;
74 constexpr OUStringLiteral
IMPL_NAME =
u"com.sun.star.sdbcx.comp.hsqldb.Driver";
81 ,m_bInShutDownConnections(false)
86 ODriverDelegator::~ODriverDelegator()
90 ::comphelper::disposeComponent(m_xDriver);
98 void SAL_CALL ODriverDelegator::disposing()
104 for (
const auto& rConnection : m_aConnections)
106 Reference<XInterface > xTemp = rConnection.first.get();
107 ::comphelper::disposeComponent(xTemp);
114 m_aConnections.clear();
117 cppu::WeakComponentImplHelperBase::disposing();
120 Reference< XDriver >
const & ODriverDelegator::loadDriver( )
122 if ( !m_xDriver.is() )
124 Reference<XDriverManager2> xDriverAccess = DriverManager::create(
m_xContext );
125 m_xDriver = xDriverAccess->getDriverByURL(
"jdbc:hsqldb:db");
134 OUString lcl_getPermittedJavaMethods_nothrow(
const Reference< XComponentContext >& _rxContext )
136 OUString aConfigPath =
137 "/org.openoffice.Office.DataAccess/DriverSettings/" +
139 "/PermittedJavaMethods";
141 _rxContext, aConfigPath ) );
143 OUStringBuffer aPermittedMethods;
144 const Sequence< OUString > aNodeNames( aConfig.getNodeNames() );
145 for (
auto const & nodeName : aNodeNames )
147 OUString sPermittedMethod;
148 OSL_VERIFY( aConfig.getNodeValue( nodeName ) >>= sPermittedMethod );
150 if ( !aPermittedMethods.isEmpty() )
151 aPermittedMethods.append(
';' );
152 aPermittedMethods.append( sPermittedMethod );
155 return aPermittedMethods.makeStringAndClear();
160 Reference< XConnection > SAL_CALL ODriverDelegator::connect(
const OUString& url,
const Sequence< PropertyValue >& info )
162 Reference< XConnection > xConnection;
163 if ( acceptsURL(url) )
165 Reference< XDriver > xDriver = loadDriver();
169 Reference<XStorage> xStorage;
170 const PropertyValue* pIter = info.getConstArray();
171 const PropertyValue* pEnd = pIter + info.getLength();
173 for (;pIter != pEnd; ++pIter)
175 if ( pIter->Name ==
"Storage" )
177 xStorage.set(pIter->Value,UNO_QUERY);
179 else if ( pIter->Name ==
"URL" )
181 pIter->Value >>= sURL;
185 if ( !xStorage.is() || sURL.isEmpty() )
192 OUString sSystemPath;
193 osl_getSystemPathFromFileURL( sURL.pData, &sSystemPath.pData );
194 if ( sURL.isEmpty() || sSystemPath.isEmpty() )
201 bool bIsNewDatabase = !xStorage->hasElements();
206 OUString sKey = StorageContainer::registerStorage( xStorage, sSystemPath );
209 OUString(
"com.sun.star.sdbcx.comp.hsqldb.StorageAccess" ) );
211 OUString(
"com.sun.star.sdbcx.comp.hsqldb.StorageFileAccess" ) );
215 OUString(
"org.hsqldb.jdbcDriver" ) );
221 "vnd.sun.star.expand:$LO_JAVA_DIR/hsqldb.jar"
223 " vnd.sun.star.expand:$LO_JAVA_DIR/sdbc_hsqldb.jar"
227 aProperties.put(
"IsAutoRetrievingEnabled",
true );
229 OUString(
"CALL IDENTITY()" ) );
234 OUString(
"true" ) );
237 NamedValue aPermittedClasses(
238 "hsqldb.method_class_names",
239 Any( lcl_getPermittedJavaMethods_nothrow( m_xContext ) )
241 aProperties.put(
"SystemProperties", Sequence< NamedValue >( &aPermittedClasses, 1 ) );
246 static constexpr OUStringLiteral sProperties( u
"properties" );
247 if ( !bIsNewDatabase && xStorage->isStreamElement(sProperties) )
249 Reference<XStream >
xStream = xStorage->openStreamElement(sProperties,ElementModes::READ);
256 OString sVersionString;
257 while ( pStream->ReadLine(sLine) )
259 if ( sLine.isEmpty() )
262 const std::string_view sIniKey =
o3tl::getToken(sLine, 0,
'=', nIdx);
264 if( sIniKey ==
"hsqldb.compatible_version" )
266 sVersionString = sValue;
270 if (sIniKey ==
"version" && sVersionString.isEmpty())
272 sVersionString = sValue;
276 if (!sVersionString.isEmpty())
283 || ( nMajor == 1 && nMinor > 8 )
284 || ( nMajor == 1 && nMinor == 8 && nMicro > 0 ) )
292 ::comphelper::disposeComponent(xStream);
300 static constexpr OUStringLiteral
sScript(u
"script");
301 if (!bIsNewDatabase && xStorage->isStreamElement(sScript))
303 Reference<XStream >
xStream = xStorage->openStreamElement(sScript, ElementModes::READ);
310 while (pStream->ReadLine(sLine))
312 OString sText = sLine.makeStringAndClear().trim();
313 if (sText.startsWithIgnoreAsciiCase(
"SCRIPT"))
322 ::comphelper::disposeComponent(xStream);
335 Reference<XPropertySet> xProp(xStorage,UNO_QUERY);
339 xProp->getPropertyValue(
"OpenMode") >>= nMode;
340 if ( (nMode & ElementModes::WRITE) != ElementModes::WRITE )
346 Sequence< PropertyValue > aConnectionArgs;
348 OUString sConnectURL =
"jdbc:hsqldb:" + sSystemPath;
349 Reference<XConnection> xOrig;
352 xOrig = xDriver->connect( sConnectURL, aConnectionArgs );
354 catch(
const Exception&)
356 StorageContainer::revokeStorage(sKey,
nullptr);
362 if ( bIsNewDatabase && xOrig.is() )
363 onConnectedNewDatabase( xOrig );
368 auto pMetaConnection = comphelper::getFromUnoTunnel<OMetaConnection>(xOrig);
369 if ( pMetaConnection )
370 pMetaConnection->setURL(url);
372 Reference<XComponent> xComp(xOrig,UNO_QUERY);
374 xComp->addEventListener(
this);
377 static Reference< XTerminateListener> s_xTerminateListener = [&]()
379 Reference< XDesktop2 > xDesktop = Desktop::create( m_xContext );
382 xDesktop->addTerminateListener(tmp);
385 Reference< XComponent> xIfc =
new OHsqlConnection(
this, xOrig, m_xContext );
386 xConnection.set(xIfc,UNO_QUERY);
389 Reference<XTransactionBroadcaster> xBroad(xStorage,UNO_QUERY);
392 xBroad->addTransactionListener(Reference<XTransactionListener>(
this));
401 sal_Bool SAL_CALL ODriverDelegator::acceptsURL(
const OUString& url )
403 bool bEnabled =
false;
410 "connectivity.hsqldb",
411 "jfw_getEnabled: JFW_E_DIRECT_MODE, assuming true");
416 "connectivity.hsqldb",
"jfw_getEnabled: error code " << +e);
419 return bEnabled && url ==
"sdbc:embedded:hsqldb";
423 Sequence< DriverPropertyInfo > SAL_CALL ODriverDelegator::getPropertyInfo(
const OUString& url,
const Sequence< PropertyValue >& )
425 if ( !acceptsURL(url) )
426 return Sequence< DriverPropertyInfo >();
431 "Defines the storage where the database will be stored.",
438 "Defines the url of the data source.",
444 "AutoRetrievingStatement",
445 "Defines the statement which will be executed to retrieve auto increment values.",
454 sal_Int32 SAL_CALL ODriverDelegator::getMajorVersion( )
460 sal_Int32 SAL_CALL ODriverDelegator::getMinorVersion( )
466 Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByConnection(
const Reference< XConnection >& connection )
468 ::osl::MutexGuard aGuard( m_aMutex );
471 Reference< XTablesSupplier > xTab;
473 TWeakPairVector::iterator
i = std::find_if(m_aConnections.begin(), m_aConnections.end(),
474 [&connection](
const TWeakPairVector::value_type& rConnection) {
475 return rConnection.second.second.first.get() == connection.get(); });
476 if (i != m_aConnections.end())
478 xTab.set(
i->second.second.second,UNO_QUERY);
482 i->second.second.second = WeakReferenceHelper(xTab);
490 Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByURL(
const OUString& url,
const Sequence< PropertyValue >& info )
492 if ( ! acceptsURL(url) )
499 return getDataDefinitionByConnection(connect(url,info));
504 OUString SAL_CALL ODriverDelegator::getImplementationName( )
509 sal_Bool SAL_CALL ODriverDelegator::supportsService(
const OUString& _rServiceName )
514 Sequence< OUString > SAL_CALL ODriverDelegator::getSupportedServiceNames( )
516 return {
"com.sun.star.sdbc.Driver",
"com.sun.star.sdbcx.Driver" };
519 void SAL_CALL ODriverDelegator::createCatalog(
const Sequence< PropertyValue >& )
524 void ODriverDelegator::shutdownConnection(
const TWeakPairVector::iterator& _aIter )
526 OSL_ENSURE(m_aConnections.end() != _aIter,
"Iterator equals .end()");
527 bool bLastOne =
true;
530 Reference<XConnection> _xConnection(_aIter->first.get(),UNO_QUERY);
532 if ( _xConnection.is() )
534 Reference<XStatement> xStmt = _xConnection->createStatement();
537 Reference<XResultSet> xRes = xStmt->executeQuery(
"SELECT COUNT(*) FROM INFORMATION_SCHEMA.SYSTEM_SESSIONS WHERE USER_NAME ='SA'");
538 Reference<XRow> xRow(xRes,UNO_QUERY);
539 if ( xRow.is() && xRes->next() )
540 bLastOne = xRow->getInt(1) == 1;
542 xStmt->execute(
"SHUTDOWN");
553 StorageContainer::revokeStorage(_aIter->second.first,
nullptr);
555 if ( !m_bInShutDownConnections )
556 m_aConnections.erase(_aIter);
559 void SAL_CALL ODriverDelegator::disposing(
const css::lang::EventObject& Source )
562 Reference<XConnection> xCon(
Source.Source,UNO_QUERY);
565 TWeakPairVector::iterator
i = std::find_if(m_aConnections.begin(), m_aConnections.end(),
566 [&xCon](
const TWeakPairVector::value_type& rConnection) { return rConnection.first.get() == xCon.get(); });
568 if (
i != m_aConnections.end())
569 shutdownConnection(
i);
573 Reference< XStorage> xStorage(
Source.Source,UNO_QUERY);
576 OUString sKey = StorageContainer::getRegisteredKey(xStorage);
577 TWeakPairVector::iterator
i = std::find_if(m_aConnections.begin(),m_aConnections.end(),
578 [&sKey] (
const TWeakPairVector::value_type& conn) {
579 return conn.second.first == sKey;
582 if (
i != m_aConnections.end() )
583 shutdownConnection(
i);
588 void ODriverDelegator::shutdownConnections()
590 m_bInShutDownConnections =
true;
591 for (
const auto& rConnection : m_aConnections)
595 Reference<XConnection> xCon(rConnection.first,UNO_QUERY);
596 ::comphelper::disposeComponent(xCon);
602 m_aConnections.clear();
603 m_bInShutDownConnections =
true;
606 void ODriverDelegator::flushConnections()
608 for (
const auto& rConnection : m_aConnections)
612 Reference<XFlushable> xCon(rConnection.second.second.first.get(),UNO_QUERY);
623 void SAL_CALL ODriverDelegator::preCommit(
const css::lang::EventObject& aEvent )
627 Reference< XStorage> xStorage(
aEvent.Source,UNO_QUERY);
628 OUString sKey = StorageContainer::getRegisteredKey(xStorage);
629 if ( sKey.isEmpty() )
632 TWeakPairVector::const_iterator
i = std::find_if(m_aConnections.begin(), m_aConnections.end(),
633 [&sKey] (
const TWeakPairVector::value_type& conn) {
634 return conn.second.first == sKey;
637 OSL_ENSURE(
i != m_aConnections.end(),
"ODriverDelegator::preCommit: they're committing a storage which I do not know!" );
638 if (
i == m_aConnections.end() )
643 Reference<XConnection> xConnection(
i->first,UNO_QUERY);
644 if ( xConnection.is() )
646 Reference< XStatement> xStmt = xConnection->createStatement();
647 OSL_ENSURE( xStmt.is(),
"ODriverDelegator::preCommit: no statement!" );
649 xStmt->execute(
"SET WRITE_DELAY 0" );
651 bool bPreviousAutoCommit = xConnection->getAutoCommit();
652 xConnection->setAutoCommit(
false );
653 xConnection->commit();
654 xConnection->setAutoCommit( bPreviousAutoCommit );
657 xStmt->execute(
"SET WRITE_DELAY 60" );
666 void SAL_CALL ODriverDelegator::commited(
const css::lang::EventObject& )
670 void SAL_CALL ODriverDelegator::preRevert(
const css::lang::EventObject& )
674 void SAL_CALL ODriverDelegator::reverted(
const css::lang::EventObject& )
681 const char* lcl_getCollationForLocale(
const OUString& _rLocaleString,
bool _bAcceptCountryMismatch =
false )
683 static const char* pTranslations[] =
685 "af-ZA",
"Afrikaans",
689 "az-AZ",
"Azerbaijani_Latin",
690 "az-cyrillic",
"Azerbaijani_Cyrillic",
691 "be-BY",
"Belarusian",
692 "bg-BG",
"Bulgarian",
702 "en-US",
"Latin1_General",
714 "hu-HU",
"Hungarian",
716 "id-ID",
"Indonesian",
718 "is-IS",
"Icelandic",
720 "iu-CA",
"Inuktitut",
731 "lt-LT",
"Lithuanian",
734 "mk-MK",
"Macedonian",
735 "ml-IN",
"Malayalam",
736 "mn-MN",
"Mongolian",
737 "mni-IN",
"Manipuri",
742 "nb-NO",
"Danish_Norwegian",
745 "nn-NO",
"Norwegian",
750 "pt-PT",
"Portuguese",
756 "sl-SI",
"Slovenian",
759 "sr-YU",
"Serbian_Cyrillic",
770 "uk-UA",
"Ukrainian",
772 "uz-UZ",
"Uzbek_Latin",
774 "vi-VN",
"Vietnamese",
781 OUString sLocaleString( _rLocaleString );
782 char nCompareTermination = 0;
784 if ( _bAcceptCountryMismatch )
787 sal_Int32 nCountrySep = sLocaleString.indexOf(
'-' );
788 if ( nCountrySep > -1 )
789 sLocaleString = sLocaleString.copy( 0, nCountrySep );
793 nCompareTermination =
'-';
796 const char** pLookup = pTranslations;
797 for ( ; *pLookup; pLookup +=2 )
799 sal_Int32 nCompareUntil = 0;
800 while ( (*pLookup)[ nCompareUntil ] != nCompareTermination && (*pLookup)[ nCompareUntil ] != 0 )
803 if ( sLocaleString.equalsAsciiL( *pLookup, nCompareUntil ) )
804 return *( pLookup + 1 );
807 if ( !_bAcceptCountryMismatch )
809 return lcl_getCollationForLocale( _rLocaleString,
true );
811 OSL_FAIL(
"lcl_getCollationForLocale: unknown locale string, falling back to Latin1_General!" );
812 return "Latin1_General";
816 OUString lcl_getSystemLocale(
const Reference< XComponentContext >& _rxContext )
818 OUString sLocaleString =
"en-US";
822 Reference< XMultiServiceFactory > xConfigProvider(
823 css::configuration::theDefaultProvider::get( _rxContext ) );
829 {
"nodepath",
Any(OUString(
"/org.openoffice.Setup/L10N" ))},
830 {
"depth",
Any(sal_Int32(-1))},
833 Reference< XPropertySet > xNode(
834 xConfigProvider->createInstanceWithArguments(
835 "com.sun.star.configuration.ConfigurationAccess",
838 OSL_ENSURE( xNode.is(),
"lcl_getSystemLocale: invalid access returned (should throw an exception instead)!" );
843 xNode->getPropertyValue(
"ooSetupSystemLocale") >>= sLocaleString;
845 catch(
const Exception& )
849 if ( sLocaleString.isEmpty() )
851 rtl_Locale* pProcessLocale =
nullptr;
852 osl_getProcessLocale( &pProcessLocale );
855 return sLocaleString;
859 void ODriverDelegator::onConnectedNewDatabase(
const Reference< XConnection >& _rxConnection )
863 Reference< XStatement > xStatement = _rxConnection->createStatement();
864 OSL_ENSURE( xStatement.is(),
"ODriverDelegator::onConnectedNewDatabase: could not create a statement!" );
865 if ( xStatement.is() )
867 OUStringBuffer aStatement(
"SET DATABASE COLLATION \"" );
868 aStatement.appendAscii( lcl_getCollationForLocale( lcl_getSystemLocale(
m_xContext ) ) );
869 aStatement.append(
"\"" );
871 xStatement->execute( aStatement.makeStringAndClear() );
884extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
886 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any>
const&)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * connectivity_hsqldb_ODriverDelegator_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
Reference< XComponentContext > m_xContext
PropertiesInfo aProperties
const OUString & getBcp47(bool bResolveSystem=true) const
helper class for accessing resources shared by different libraries in the connectivity module
OUString getResourceString(TranslateId pResId) const
loads a string from the shared resource file
delegates all calls to the original driver and extend the existing one with the SDBCX layer.
ODriverDelegator(const css::uno::Reference< css::uno::XComponentContext > &_rxContext)
creates a new delegator for a HSQLDB driver
static OConfigurationTreeRoot createWithComponentContext(const css::uno::Reference< css::uno::XComponentContext > &_rxContext, const OUString &_rPath, sal_Int32 _nDepth=-1, CREATION_MODE _eMode=CM_UPDATABLE)
static std::unique_ptr< SvStream > CreateStream(const OUString &rFileName, StreamMode eOpenMode, css::uno::Reference< css::awt::XWindow > xParentWin=nullptr)
#define TOOLS_WARN_EXCEPTION(area, stream)
#define DBG_UNHANDLED_EXCEPTION(...)
javaFrameworkError jfw_getEnabled(bool *pbEnabled)
Sequence< PropertyValue > aArguments
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
css::uno::Sequence< css::uno::Any > InitAnyPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
std::pair< css::uno::WeakReferenceHelper, css::uno::WeakReferenceHelper > TWeakRefPair
std::pair< css::uno::WeakReferenceHelper, TWeakConnectionPair > TWeakPair
std::pair< OUString,TWeakRefPair > TWeakConnectionPair
::cppu::WeakComponentImplHelper< css::sdbc::XDriver, css::sdbcx::XDataDefinitionSupplier, css::lang::XServiceInfo, css::sdbcx::XCreateCatalog, css::embed::XTransactionListener > ODriverDelegator_BASE
std::vector< TWeakPair > TWeakPairVector
constexpr OUStringLiteral IMPL_NAME
void checkDisposed(bool _bThrow)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
constexpr OUStringLiteral sScript