LCOV - code coverage report
Current view: top level - connectivity/source/drivers/hsqldb - HDriver.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 285 346 82.4 %
Date: 2015-06-13 12:38:46 Functions: 24 31 77.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include <config_folders.h>
      21             : 
      22             : #include "hsqldb/HDriver.hxx"
      23             : #include "hsqldb/HConnection.hxx"
      24             : #include <osl/diagnose.h>
      25             : #include <connectivity/dbexception.hxx>
      26             : #include <com/sun/star/configuration/theDefaultProvider.hpp>
      27             : #include <com/sun/star/sdbc/DriverManager.hpp>
      28             : #include <com/sun/star/sdbc/XDriverAccess.hpp>
      29             : #include <com/sun/star/sdbc/XResultSet.hpp>
      30             : #include <com/sun/star/sdbc/XRow.hpp>
      31             : #include <com/sun/star/embed/XTransactionBroadcaster.hpp>
      32             : #include <com/sun/star/embed/ElementModes.hpp>
      33             : #include "TConnection.hxx"
      34             : #include "hsqldb/HStorageMap.hxx"
      35             : #include <jvmfwk/framework.h>
      36             : #include <com/sun/star/reflection/XProxyFactory.hpp>
      37             : #include <com/sun/star/embed/XStorage.hpp>
      38             : #include <com/sun/star/frame/Desktop.hpp>
      39             : #include <com/sun/star/lang/Locale.hpp>
      40             : #include <com/sun/star/util/XFlushable.hpp>
      41             : #include "HTerminateListener.hxx"
      42             : #include "hsqldb/HCatalog.hxx"
      43             : #include "diagnose_ex.h"
      44             : #include <rtl/ustrbuf.hxx>
      45             : #include <osl/file.h>
      46             : #include <osl/process.h>
      47             : #include <comphelper/namedvaluecollection.hxx>
      48             : #include <comphelper/processfactory.hxx>
      49             : #include <comphelper/string.hxx>
      50             : #include <cppuhelper/supportsservice.hxx>
      51             : #include <unotools/confignode.hxx>
      52             : #include <unotools/ucbstreamhelper.hxx>
      53             : #include "resource/hsqldb_res.hrc"
      54             : #include "resource/sharedresources.hxx"
      55             : #include <i18nlangtag/languagetag.hxx>
      56             : #include <tools/diagnose_ex.h>
      57             : 
      58             : #include <o3tl/compat_functional.hxx>
      59             : 
      60             : #include <boost/scoped_ptr.hpp>
      61             : 
      62             : 
      63             : namespace connectivity
      64             : {
      65             : 
      66             :     using namespace hsqldb;
      67             :     using namespace ::com::sun::star::uno;
      68             :     using namespace ::com::sun::star::sdbc;
      69             :     using namespace ::com::sun::star::sdbcx;
      70             :     using namespace ::com::sun::star::beans;
      71             :     using namespace ::com::sun::star::frame;
      72             :     using namespace ::com::sun::star::lang;
      73             :     using namespace ::com::sun::star::embed;
      74             :     using namespace ::com::sun::star::io;
      75             :     using namespace ::com::sun::star::task;
      76             :     using namespace ::com::sun::star::util;
      77             :     using namespace ::com::sun::star::reflection;
      78             : 
      79             :     namespace hsqldb
      80             :     {
      81           5 :         Reference< XInterface >  SAL_CALL ODriverDelegator_CreateInstance(const Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxFac) throw( Exception )
      82             :         {
      83           5 :             return *(new ODriverDelegator(comphelper::getComponentContext(_rxFac)));
      84             :         }
      85             :     }
      86             : 
      87             : 
      88           5 :     ODriverDelegator::ODriverDelegator(const Reference< XComponentContext >& _rxContext)
      89             :         : ODriverDelegator_BASE(m_aMutex)
      90             :         ,m_xContext(_rxContext)
      91           5 :         ,m_bInShutDownConnections(false)
      92             :     {
      93           5 :     }
      94             : 
      95             : 
      96           6 :     ODriverDelegator::~ODriverDelegator()
      97             :     {
      98             :         try
      99             :         {
     100           2 :             ::comphelper::disposeComponent(m_xDriver);
     101             :         }
     102           0 :         catch(const Exception&)
     103             :         {
     104             :         }
     105           4 :     }
     106             : 
     107             : 
     108           2 :     void SAL_CALL ODriverDelegator::disposing()
     109             :     {
     110           2 :         ::osl::MutexGuard aGuard(m_aMutex);
     111             : 
     112             :         try
     113             :         {
     114           2 :             for (TWeakPairVector::iterator i = m_aConnections.begin(); m_aConnections.end() != i; ++i)
     115             :             {
     116           0 :                 Reference<XInterface > xTemp = i->first.get();
     117           0 :                 ::comphelper::disposeComponent(xTemp);
     118           0 :             }
     119             :         }
     120           0 :         catch(Exception&)
     121             :         {
     122             :             // not interested in
     123             :         }
     124           2 :         m_aConnections.clear();
     125           2 :         TWeakPairVector().swap(m_aConnections);
     126             : 
     127           2 :         cppu::WeakComponentImplHelperBase::disposing();
     128           2 :     }
     129             : 
     130           9 :     Reference< XDriver > ODriverDelegator::loadDriver( )
     131             :     {
     132           9 :         if ( !m_xDriver.is() )
     133             :         {
     134           4 :             OUString sURL("jdbc:hsqldb:db");
     135           8 :             Reference<XDriverManager2> xDriverAccess = DriverManager::create( m_xContext );
     136           8 :             m_xDriver = xDriverAccess->getDriverByURL(sURL);
     137             :         }
     138             : 
     139           9 :         return m_xDriver;
     140             :     }
     141             : 
     142             : 
     143             :     namespace
     144             :     {
     145           9 :         OUString lcl_getPermittedJavaMethods_nothrow( const Reference< XComponentContext >& _rxContext )
     146             :         {
     147           9 :             OUStringBuffer aConfigPath;
     148           9 :             aConfigPath.appendAscii( "/org.openoffice.Office.DataAccess/DriverSettings/" );
     149           9 :             aConfigPath.append     ( ODriverDelegator::getImplementationName_Static() );
     150           9 :             aConfigPath.appendAscii( "/PermittedJavaMethods" );
     151             :             ::utl::OConfigurationTreeRoot aConfig( ::utl::OConfigurationTreeRoot::createWithComponentContext(
     152          18 :                 _rxContext, aConfigPath.makeStringAndClear() ) );
     153             : 
     154          18 :             OUStringBuffer aPermittedMethods;
     155          18 :             Sequence< OUString > aNodeNames( aConfig.getNodeNames() );
     156          18 :             for (   const OUString* pNodeNames = aNodeNames.getConstArray();
     157           9 :                     pNodeNames != aNodeNames.getConstArray() + aNodeNames.getLength();
     158             :                     ++pNodeNames
     159             :                 )
     160             :             {
     161           0 :                 OUString sPermittedMethod;
     162           0 :                 OSL_VERIFY( aConfig.getNodeValue( *pNodeNames ) >>= sPermittedMethod );
     163             : 
     164           0 :                 if ( !aPermittedMethods.isEmpty() )
     165           0 :                     aPermittedMethods.append( ';' );
     166           0 :                 aPermittedMethods.append( sPermittedMethod );
     167           0 :             }
     168             : 
     169          18 :             return aPermittedMethods.makeStringAndClear();
     170             :         }
     171             :     }
     172             : 
     173             : 
     174           9 :     Reference< XConnection > SAL_CALL ODriverDelegator::connect( const OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException, std::exception)
     175             :     {
     176           9 :         Reference< XConnection > xConnection;
     177           9 :         if ( acceptsURL(url) )
     178             :         {
     179           9 :             Reference< XDriver > xDriver = loadDriver();
     180           9 :             if ( xDriver.is() )
     181             :             {
     182           9 :                 OUString sURL;
     183          18 :                 Reference<XStorage> xStorage;
     184           9 :                 const PropertyValue* pIter = info.getConstArray();
     185           9 :                 const PropertyValue* pEnd = pIter + info.getLength();
     186             : 
     187          45 :                 for (;pIter != pEnd; ++pIter)
     188             :                 {
     189          36 :                     if ( pIter->Name == "Storage" )
     190             :                     {
     191           9 :                         xStorage.set(pIter->Value,UNO_QUERY);
     192             :                     }
     193          27 :                     else if ( pIter->Name == "URL" )
     194             :                     {
     195           9 :                         pIter->Value >>= sURL;
     196             :                     }
     197             :                 }
     198             : 
     199           9 :                 if ( !xStorage.is() || sURL.isEmpty() )
     200             :                 {
     201           0 :                     ::connectivity::SharedResources aResources;
     202           0 :                     const OUString sMessage = aResources.getResourceString(STR_NO_STORAGE);
     203           0 :                     ::dbtools::throwGenericSQLException(sMessage ,*this);
     204             :                 }
     205             : 
     206          18 :                 OUString sSystemPath;
     207           9 :                 osl_getSystemPathFromFileURL( sURL.pData, &sSystemPath.pData );
     208           9 :                 if ( sURL.isEmpty() || sSystemPath.isEmpty() )
     209             :                 {
     210           0 :                     ::connectivity::SharedResources aResources;
     211           0 :                     const OUString sMessage = aResources.getResourceString(STR_INVALID_FILE_URL);
     212           0 :                     ::dbtools::throwGenericSQLException(sMessage ,*this);
     213             :                 }
     214             : 
     215           9 :                 bool bIsNewDatabase = !xStorage->hasElements();
     216             : 
     217          18 :                 ::comphelper::NamedValueCollection aProperties;
     218             : 
     219             :                 // properties for accessing the embedded storage
     220          18 :                 OUString sKey = StorageContainer::registerStorage( xStorage, sSystemPath );
     221           9 :                 aProperties.put( "storage_key", sKey );
     222             :                 aProperties.put( "storage_class_name",
     223           9 :                     OUString(  "com.sun.star.sdbcx.comp.hsqldb.StorageAccess"  ) );
     224             :                 aProperties.put( "fileaccess_class_name",
     225           9 :                     OUString(  "com.sun.star.sdbcx.comp.hsqldb.StorageFileAccess"  ) );
     226             : 
     227             :                 // JDBC driver and driver's classpath
     228             :                 aProperties.put( "JavaDriverClass",
     229           9 :                     OUString(  "org.hsqldb.jdbcDriver"  ) );
     230             :                 aProperties.put( "JavaDriverClassPath",
     231             :                     OUString(
     232             : #ifdef SYSTEM_HSQLDB
     233             :                         HSQLDB_JAR
     234             : #else
     235             :                         "vnd.sun.star.expand:$LO_JAVA_DIR/hsqldb.jar"
     236             : #endif
     237             :                         " vnd.sun.star.expand:$LO_JAVA_DIR/sdbc_hsqldb.jar"
     238           9 :                         ) );
     239             : 
     240             :                 // auto increment handling
     241           9 :                 aProperties.put( "IsAutoRetrievingEnabled", true );
     242             :                 aProperties.put( "AutoRetrievingStatement",
     243           9 :                     OUString(  "CALL IDENTITY()" ) );
     244           9 :                 aProperties.put( "IgnoreDriverPrivileges", true );
     245             : 
     246             :                 // don't want to expose HSQLDB's schema capabilities which exist since 1.8.0RC10
     247             :                 aProperties.put( "default_schema",
     248           9 :                     OUString(  "true"  ) );
     249             : 
     250             :                 // security: permitted Java classes
     251             :                 NamedValue aPermittedClasses(
     252             :                     OUString(  "hsqldb.method_class_names"  ),
     253             :                     makeAny( lcl_getPermittedJavaMethods_nothrow( m_xContext ) )
     254          18 :                 );
     255           9 :                 aProperties.put( "SystemProperties", Sequence< NamedValue >( &aPermittedClasses, 1 ) );
     256             : 
     257          18 :                 const OUString sProperties(  "properties"  );
     258          18 :                 OUString sMessage;
     259             :                 try
     260             :                 {
     261           9 :                     if ( !bIsNewDatabase && xStorage->isStreamElement(sProperties) )
     262             :                     {
     263           3 :                         Reference<XStream > xStream = xStorage->openStreamElement(sProperties,ElementModes::READ);
     264           3 :                         if ( xStream.is() )
     265             :                         {
     266           3 :                             boost::scoped_ptr<SvStream> pStream( ::utl::UcbStreamHelper::CreateStream(xStream) );
     267           3 :                             if ( pStream.get() )
     268             :                             {
     269           3 :                                 OString sLine;
     270           6 :                                 OString sVersionString;
     271          60 :                                 while ( pStream->ReadLine(sLine) )
     272             :                                 {
     273          54 :                                     if ( sLine.isEmpty() )
     274           0 :                                         continue;
     275          54 :                                     const OString sIniKey = sLine.getToken(0, '=');
     276         108 :                                     const OString sValue = sLine.getToken(1, '=');
     277          54 :                                     if( sIniKey == "hsqldb.compatible_version" )
     278             :                                     {
     279           3 :                                         sVersionString = sValue;
     280             :                                     }
     281             :                                     else
     282             :                                     {
     283          51 :                                         if (sIniKey == "version" && sVersionString.isEmpty())
     284             :                                         {
     285           3 :                                             sVersionString = sValue;
     286             :                                         }
     287             :                                     }
     288          54 :                                 }
     289           3 :                                 if (!sVersionString.isEmpty())
     290             :                                 {
     291           3 :                                     const sal_Int32 nMajor = sVersionString.getToken(0, '.').toInt32();
     292           3 :                                     const sal_Int32 nMinor = sVersionString.getToken(1, '.').toInt32();
     293           3 :                                     const sal_Int32 nMicro = sVersionString.getToken(2, '.').toInt32();
     294           3 :                                     if (     nMajor > 1
     295           3 :                                         || ( nMajor == 1 && nMinor > 8 )
     296           3 :                                         || ( nMajor == 1 && nMinor == 8 && nMicro > 0 ) )
     297             :                                     {
     298           0 :                                         ::connectivity::SharedResources aResources;
     299           0 :                                         sMessage = aResources.getResourceString(STR_ERROR_NEW_VERSION);
     300             :                                     }
     301           3 :                                 }
     302           3 :                             }
     303             :                         } // if ( xStream.is() )
     304           3 :                         ::comphelper::disposeComponent(xStream);
     305             :                     }
     306             :                 }
     307           0 :                 catch(Exception&)
     308             :                 {
     309             :                 }
     310           9 :                 if ( !sMessage.isEmpty() )
     311             :                 {
     312           0 :                     ::dbtools::throwGenericSQLException(sMessage ,*this);
     313             :                 }
     314             : 
     315             :                 // readonly?
     316          18 :                 Reference<XPropertySet> xProp(xStorage,UNO_QUERY);
     317           9 :                 if ( xProp.is() )
     318             :                 {
     319           9 :                     sal_Int32 nMode = 0;
     320           9 :                     xProp->getPropertyValue("OpenMode") >>= nMode;
     321           9 :                     if ( (nMode & ElementModes::WRITE) != ElementModes::WRITE )
     322             :                     {
     323           0 :                         aProperties.put( "readonly", OUString(  "true"  ) );
     324             :                     }
     325             :                 }
     326             : 
     327          18 :                 Sequence< PropertyValue > aConnectionArgs;
     328           9 :                 aProperties >>= aConnectionArgs;
     329             : 
     330          18 :                 OUString sConnectURL("jdbc:hsqldb:");
     331             : 
     332           9 :                 sConnectURL += sSystemPath;
     333          18 :                 Reference<XConnection> xOrig;
     334             :                 try
     335             :                 {
     336           9 :                     xOrig = xDriver->connect( sConnectURL, aConnectionArgs );
     337             :                 }
     338           0 :                 catch(const Exception& e)
     339             :                 {
     340           0 :                     StorageContainer::revokeStorage(sKey,NULL);
     341             :                     (void)e;
     342           0 :                     throw;
     343             :                 }
     344             : 
     345             :                 // if the storage is completely empty, then we just created a new HSQLDB
     346             :                 // In this case, do some initializations.
     347           9 :                 if ( bIsNewDatabase && xOrig.is() )
     348           6 :                     onConnectedNewDatabase( xOrig );
     349             : 
     350           9 :                 if ( xOrig.is() )
     351             :                 {
     352             :                     // now we have to set the URL to get the correct answer for metadata()->getURL()
     353           9 :                     Reference< XUnoTunnel> xTunnel(xOrig,UNO_QUERY);
     354           9 :                     if ( xTunnel.is() )
     355             :                     {
     356           9 :                         OMetaConnection* pMetaConnection = reinterpret_cast<OMetaConnection*>(xTunnel->getSomething( OMetaConnection::getUnoTunnelImplementationId() ));
     357           9 :                         if ( pMetaConnection )
     358           9 :                             pMetaConnection->setURL(url);
     359             :                     }
     360             : 
     361          18 :                     Reference<XComponent> xComp(xOrig,UNO_QUERY);
     362           9 :                     if ( xComp.is() )
     363           9 :                         xComp->addEventListener(this);
     364             : 
     365             :                     // we want to close all connections when the office shuts down
     366           9 :                     static Reference< XTerminateListener> s_xTerminateListener;
     367           9 :                     if( !s_xTerminateListener.is() )
     368             :                     {
     369           4 :                         Reference< XDesktop2 > xDesktop = Desktop::create( m_xContext );
     370             : 
     371           4 :                         s_xTerminateListener = new OConnectionController(this);
     372           4 :                         xDesktop->addTerminateListener(s_xTerminateListener);
     373             :                     }
     374          18 :                     Reference< XComponent> xIfc = new OHsqlConnection( this, xOrig, m_xContext );
     375           9 :                     xConnection.set(xIfc,UNO_QUERY);
     376           9 :                     m_aConnections.push_back(TWeakPair(WeakReferenceHelper(xOrig),TWeakConnectionPair(sKey,TWeakRefPair(WeakReferenceHelper(xConnection),WeakReferenceHelper()))));
     377             : 
     378          18 :                     Reference<XTransactionBroadcaster> xBroad(xStorage,UNO_QUERY);
     379           9 :                     if ( xBroad.is() )
     380             :                     {
     381           9 :                         Reference<XTransactionListener> xListener(*this,UNO_QUERY);
     382           9 :                         xBroad->addTransactionListener(xListener);
     383           9 :                     }
     384           9 :                 }
     385           9 :             }
     386             :         }
     387           9 :         return xConnection;
     388             :     }
     389             : 
     390             : 
     391          54 :     sal_Bool SAL_CALL ODriverDelegator::acceptsURL( const OUString& url ) throw (SQLException, RuntimeException, std::exception)
     392             :     {
     393          54 :         sal_Bool bEnabled = sal_False;
     394          54 :         javaFrameworkError e = jfw_getEnabled(&bEnabled);
     395          54 :         switch (e) {
     396             :         case JFW_E_NONE:
     397          18 :             break;
     398             :         case JFW_E_DIRECT_MODE:
     399             :             SAL_INFO(
     400             :                 "connectivity.hsqldb",
     401             :                 "jfw_getEnabled: JFW_E_DIRECT_MODE, assuming true");
     402          36 :             bEnabled = true;
     403          36 :             break;
     404             :         default:
     405             :             SAL_WARN(
     406             :                 "connectivity.hsqldb", "jfw_getEnabled: error code " << +e);
     407           0 :             break;
     408             :         }
     409          54 :         return bEnabled  && url == "sdbc:embedded:hsqldb";
     410             :     }
     411             : 
     412             : 
     413           9 :     Sequence< DriverPropertyInfo > SAL_CALL ODriverDelegator::getPropertyInfo( const OUString& url, const Sequence< PropertyValue >& /*info*/ ) throw (SQLException, RuntimeException, std::exception)
     414             :     {
     415           9 :         if ( !acceptsURL(url) )
     416           0 :             return Sequence< DriverPropertyInfo >();
     417           9 :         ::std::vector< DriverPropertyInfo > aDriverInfo;
     418             :         aDriverInfo.push_back(DriverPropertyInfo(
     419             :                 OUString("Storage")
     420             :                 ,OUString("Defines the storage where the database will be stored.")
     421             :                 ,sal_True
     422             :                 ,OUString()
     423             :                 ,Sequence< OUString >())
     424           9 :                 );
     425             :         aDriverInfo.push_back(DriverPropertyInfo(
     426             :                 OUString("URL")
     427             :                 ,OUString("Defines the url of the data source.")
     428             :                 ,sal_True
     429             :                 ,OUString()
     430             :                 ,Sequence< OUString >())
     431           9 :                 );
     432             :         aDriverInfo.push_back(DriverPropertyInfo(
     433             :                 OUString("AutoRetrievingStatement")
     434             :                 ,OUString("Defines the statement which will be executed to retrieve auto increment values.")
     435             :                 ,sal_False
     436             :                 ,OUString("CALL IDENTITY()")
     437             :                 ,Sequence< OUString >())
     438           9 :                 );
     439           9 :         return Sequence< DriverPropertyInfo >(&aDriverInfo[0],aDriverInfo.size());
     440             :     }
     441             : 
     442             : 
     443           0 :     sal_Int32 SAL_CALL ODriverDelegator::getMajorVersion(  ) throw (RuntimeException, std::exception)
     444             :     {
     445           0 :         return 1;
     446             :     }
     447             : 
     448             : 
     449           0 :     sal_Int32 SAL_CALL ODriverDelegator::getMinorVersion(  ) throw (RuntimeException, std::exception)
     450             :     {
     451           0 :         return 0;
     452             :     }
     453             : 
     454             : 
     455           9 :     Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByConnection( const Reference< XConnection >& connection ) throw (SQLException, RuntimeException, std::exception)
     456             :     {
     457           9 :         ::osl::MutexGuard aGuard( m_aMutex );
     458           9 :         checkDisposed(ODriverDelegator_BASE::rBHelper.bDisposed);
     459             : 
     460           9 :         Reference< XTablesSupplier > xTab;
     461             : 
     462           9 :         TWeakPairVector::iterator aEnd = m_aConnections.end();
     463          24 :         for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
     464             :         {
     465          24 :             if ( i->second.second.first.get() == connection.get() )
     466             :             {
     467           9 :                 xTab = Reference< XTablesSupplier >(i->second.second.second.get().get(),UNO_QUERY);
     468           9 :                 if ( !xTab.is() )
     469             :                 {
     470           9 :                     xTab = new OHCatalog(connection);
     471           9 :                     i->second.second.second = WeakReferenceHelper(xTab);
     472             :                 }
     473           9 :                 break;
     474             :             }
     475             :         }
     476             : 
     477           9 :         return xTab;
     478             :     }
     479             : 
     480             : 
     481           0 :     Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByURL( const OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException, std::exception)
     482             :     {
     483           0 :         if ( ! acceptsURL(url) )
     484             :         {
     485           0 :             ::connectivity::SharedResources aResources;
     486           0 :             const OUString sMessage = aResources.getResourceString(STR_URI_SYNTAX_ERROR);
     487           0 :             ::dbtools::throwGenericSQLException(sMessage ,*this);
     488             :         }
     489             : 
     490           0 :         return getDataDefinitionByConnection(connect(url,info));
     491             :     }
     492             : 
     493             :     // XServiceInfo
     494             : 
     495             : 
     496          15 :     OUString ODriverDelegator::getImplementationName_Static(  ) throw(RuntimeException)
     497             :     {
     498          15 :         return OUString("com.sun.star.sdbcx.comp.hsqldb.Driver");
     499             :     }
     500             : 
     501           6 :     Sequence< OUString > ODriverDelegator::getSupportedServiceNames_Static(  ) throw (RuntimeException)
     502             :     {
     503           6 :         Sequence< OUString > aSNS( 2 );
     504           6 :         aSNS[0] = "com.sun.star.sdbc.Driver";
     505           6 :         aSNS[1] = "com.sun.star.sdbcx.Driver";
     506           6 :         return aSNS;
     507             :     }
     508             : 
     509           1 :     OUString SAL_CALL ODriverDelegator::getImplementationName(  ) throw(RuntimeException, std::exception)
     510             :     {
     511           1 :         return getImplementationName_Static();
     512             :     }
     513             : 
     514           0 :     sal_Bool SAL_CALL ODriverDelegator::supportsService( const OUString& _rServiceName ) throw(RuntimeException, std::exception)
     515             :     {
     516           0 :         return cppu::supportsService(this, _rServiceName);
     517             :     }
     518             : 
     519           1 :     Sequence< OUString > SAL_CALL ODriverDelegator::getSupportedServiceNames(  ) throw(RuntimeException, std::exception)
     520             :     {
     521           1 :         return getSupportedServiceNames_Static();
     522             :     }
     523             : 
     524           0 :     void SAL_CALL ODriverDelegator::createCatalog( const Sequence< PropertyValue >& /*info*/ ) throw (SQLException, ::com::sun::star::container::ElementExistException, RuntimeException, std::exception)
     525             :     {
     526           0 :         ::dbtools::throwFeatureNotImplementedSQLException( "XCreateCatalog::createCatalog", *this );
     527           0 :     }
     528             : 
     529           9 :     void ODriverDelegator::shutdownConnection(const TWeakPairVector::iterator& _aIter )
     530             :     {
     531             :         OSL_ENSURE(m_aConnections.end() != _aIter,"Iterator equals .end()");
     532           9 :         bool bLastOne = true;
     533             :         try
     534             :         {
     535           9 :             Reference<XConnection> _xConnection(_aIter->first.get(),UNO_QUERY);
     536             : 
     537           9 :             if ( _xConnection.is() )
     538             :             {
     539           9 :                 Reference<XStatement> xStmt = _xConnection->createStatement();
     540           9 :                 if ( xStmt.is() )
     541             :                 {
     542           9 :                     Reference<XResultSet> xRes(xStmt->executeQuery(OUString("SELECT COUNT(*) FROM INFORMATION_SCHEMA.SYSTEM_SESSIONS WHERE USER_NAME ='SA'")),UNO_QUERY);
     543          18 :                     Reference<XRow> xRow(xRes,UNO_QUERY);
     544           9 :                     if ( xRow.is() && xRes->next() )
     545           9 :                         bLastOne = xRow->getInt(1) == 1;
     546           9 :                     if ( bLastOne )
     547          18 :                         xStmt->execute(OUString("SHUTDOWN"));
     548           9 :                 }
     549           9 :             }
     550             :         }
     551           0 :         catch(Exception&)
     552             :         {
     553             :         }
     554           9 :         if ( bLastOne )
     555             :         {
     556             :             // Reference<XTransactionListener> xListener(*this,UNO_QUERY);
     557             :             // a shutdown should commit all changes to the db files
     558           9 :             StorageContainer::revokeStorage(_aIter->second.first,NULL);
     559             :         }
     560           9 :         if ( !m_bInShutDownConnections )
     561           3 :             m_aConnections.erase(_aIter);
     562           9 :     }
     563             : 
     564          18 :     void SAL_CALL ODriverDelegator::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException, std::exception)
     565             :     {
     566          18 :         ::osl::MutexGuard aGuard(m_aMutex);
     567          36 :         Reference<XConnection> xCon(Source.Source,UNO_QUERY);
     568          18 :         if ( xCon.is() )
     569             :         {
     570           9 :             TWeakPairVector::iterator i = m_aConnections.begin();
     571          24 :             for (; m_aConnections.end() != i; ++i)
     572             :             {
     573          24 :                 if ( i->first.get() == xCon.get() )
     574             :                 {
     575           9 :                     shutdownConnection(i);
     576           9 :                     break;
     577             :                 }
     578             :             }
     579             :         }
     580             :         else
     581             :         {
     582           9 :             Reference< XStorage> xStorage(Source.Source,UNO_QUERY);
     583           9 :             if ( xStorage.is() )
     584             :             {
     585           9 :                 OUString sKey = StorageContainer::getRegisteredKey(xStorage);
     586             :                 TWeakPairVector::iterator i = ::std::find_if(m_aConnections.begin(),m_aConnections.end(),::o3tl::compose1(
     587             :                                 ::std::bind2nd(::std::equal_to< OUString >(),sKey)
     588           9 :                                 ,::o3tl::compose1(::o3tl::select1st<TWeakConnectionPair>(),::o3tl::select2nd< TWeakPair >())));
     589           9 :                 if ( i != m_aConnections.end() )
     590           0 :                     shutdownConnection(i);
     591           9 :             }
     592          18 :         }
     593          18 :     }
     594             : 
     595           1 :     void ODriverDelegator::shutdownConnections()
     596             :     {
     597           1 :         m_bInShutDownConnections = true;
     598           1 :         TWeakPairVector::iterator aEnd = m_aConnections.end();
     599           7 :         for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
     600             :         {
     601             :             try
     602             :             {
     603           6 :                 Reference<XConnection> xCon(i->first,UNO_QUERY);
     604           6 :                 ::comphelper::disposeComponent(xCon);
     605             :             }
     606           0 :             catch(Exception&)
     607             :             {
     608             :             }
     609             :         }
     610           1 :         m_aConnections.clear();
     611           1 :         m_bInShutDownConnections = true;
     612           1 :     }
     613             : 
     614           1 :     void ODriverDelegator::flushConnections()
     615             :     {
     616           1 :         TWeakPairVector::iterator aEnd = m_aConnections.end();
     617           7 :         for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
     618             :         {
     619             :             try
     620             :             {
     621           6 :                 Reference<XFlushable> xCon(i->second.second.first.get(),UNO_QUERY);
     622           6 :                 if (xCon.is())
     623           6 :                     xCon->flush();
     624             :             }
     625           0 :             catch(Exception&)
     626             :             {
     627             :                 DBG_UNHANDLED_EXCEPTION();
     628             :             }
     629             :         }
     630           1 :     }
     631             : 
     632          15 :     void SAL_CALL ODriverDelegator::preCommit( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException, std::exception)
     633             :     {
     634          15 :         ::osl::MutexGuard aGuard(m_aMutex);
     635             : 
     636          30 :         Reference< XStorage> xStorage(aEvent.Source,UNO_QUERY);
     637          30 :         OUString sKey = StorageContainer::getRegisteredKey(xStorage);
     638          15 :         if ( !sKey.isEmpty() )
     639             :         {
     640             :             TWeakPairVector::iterator i = ::std::find_if(m_aConnections.begin(),m_aConnections.end(),::o3tl::compose1(
     641             :                             ::std::bind2nd(::std::equal_to< OUString >(),sKey)
     642           6 :                             ,::o3tl::compose1(::o3tl::select1st<TWeakConnectionPair>(),::o3tl::select2nd< TWeakPair >())));
     643             :             OSL_ENSURE( i != m_aConnections.end(), "ODriverDelegator::preCommit: they're committing a storage which I do not know!" );
     644           6 :             if ( i != m_aConnections.end() )
     645             :             {
     646             :                 try
     647             :                 {
     648           6 :                     Reference<XConnection> xConnection(i->first,UNO_QUERY);
     649           6 :                     if ( xConnection.is() )
     650             :                     {
     651           6 :                         Reference< XStatement> xStmt = xConnection->createStatement();
     652             :                         OSL_ENSURE( xStmt.is(), "ODriverDelegator::preCommit: no statement!" );
     653           6 :                         if ( xStmt.is() )
     654           6 :                             xStmt->execute( OUString(  "SET WRITE_DELAY 0"  ) );
     655             : 
     656           6 :                         bool bPreviousAutoCommit = xConnection->getAutoCommit();
     657           6 :                         xConnection->setAutoCommit( sal_False );
     658           6 :                         xConnection->commit();
     659           6 :                         xConnection->setAutoCommit( bPreviousAutoCommit );
     660             : 
     661           6 :                         if ( xStmt.is() )
     662           6 :                             xStmt->execute( OUString(  "SET WRITE_DELAY 60"  ) );
     663           6 :                     }
     664             :                 }
     665           0 :                 catch(Exception&)
     666             :                 {
     667             :                     OSL_FAIL( "ODriverDelegator::preCommit: caught an exception!" );
     668             :                 }
     669             :             }
     670          15 :         }
     671          15 :     }
     672             : 
     673          15 :     void SAL_CALL ODriverDelegator::commited( const ::com::sun::star::lang::EventObject& /*aEvent*/ ) throw (::com::sun::star::uno::RuntimeException, std::exception)
     674             :     {
     675          15 :     }
     676             : 
     677           0 :     void SAL_CALL ODriverDelegator::preRevert( const ::com::sun::star::lang::EventObject& /*aEvent*/ ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException, std::exception)
     678             :     {
     679           0 :     }
     680             : 
     681           0 :     void SAL_CALL ODriverDelegator::reverted( const ::com::sun::star::lang::EventObject& /*aEvent*/ ) throw (::com::sun::star::uno::RuntimeException, std::exception)
     682             :     {
     683           0 :     }
     684             : 
     685             :     namespace
     686             :     {
     687             : 
     688           6 :         const sal_Char* lcl_getCollationForLocale( const OUString& _rLocaleString, bool _bAcceptCountryMismatch = false )
     689             :         {
     690             :             static const sal_Char* pTranslations[] =
     691             :             {
     692             :                 "af-ZA", "Afrikaans",
     693             :                 "am-ET", "Amharic",
     694             :                 "ar", "Arabic",
     695             :                 "as-IN", "Assamese",
     696             :                 "az-AZ", "Azerbaijani_Latin",
     697             :                 "az-cyrillic", "Azerbaijani_Cyrillic",
     698             :                 "be-BY", "Belarusian",
     699             :                 "bg-BG", "Bulgarian",
     700             :                 "bn-IN", "Bengali",
     701             :                 "bo-CN", "Tibetan",
     702             :                 "bs-BA", "Bosnian",
     703             :                 "ca-ES", "Catalan",
     704             :                 "cs-CZ", "Czech",
     705             :                 "cy-GB", "Welsh",
     706             :                 "da-DK", "Danish",
     707             :                 "de-DE", "German",
     708             :                 "el-GR", "Greek",
     709             :                 "en-US", "Latin1_General",
     710             :                 "es-ES", "Spanish",
     711             :                 "et-EE", "Estonian",
     712             :                 "eu", "Basque",
     713             :                 "fi-FI", "Finnish",
     714             :                 "fr-FR", "French",
     715             :                 "gn-PY", "Guarani",
     716             :                 "gu-IN", "Gujarati",
     717             :                 "ha-NG", "Hausa",
     718             :                 "he-IL", "Hebrew",
     719             :                 "hi-IN", "Hindi",
     720             :                 "hr-HR", "Croatian",
     721             :                 "hu-HU", "Hungarian",
     722             :                 "hy-AM", "Armenian",
     723             :                 "id-ID", "Indonesian",
     724             :                 "ig-NG", "Igbo",
     725             :                 "is-IS", "Icelandic",
     726             :                 "it-IT", "Italian",
     727             :                 "iu-CA", "Inuktitut",
     728             :                 "ja-JP", "Japanese",
     729             :                 "ka-GE", "Georgian",
     730             :                 "kk-KZ", "Kazakh",
     731             :                 "km-KH", "Khmer",
     732             :                 "kn-IN", "Kannada",
     733             :                 "ko-KR", "Korean",
     734             :                 "kok-IN", "Konkani",
     735             :                 "ks", "Kashmiri",
     736             :                 "ky-KG", "Kirghiz",
     737             :                 "lo-LA", "Lao",
     738             :                 "lt-LT", "Lithuanian",
     739             :                 "lv-LV", "Latvian",
     740             :                 "mi-NZ", "Maori",
     741             :                 "mk-MK", "Macedonian",
     742             :                 "ml-IN", "Malayalam",
     743             :                 "mn-MN", "Mongolian",
     744             :                 "mni-IN", "Manipuri",
     745             :                 "mr-IN", "Marathi",
     746             :                 "ms-MY", "Malay",
     747             :                 "mt-MT", "Maltese",
     748             :                 "my-MM", "Burmese",
     749             :                 "nb-NO", "Danish_Norwegian",
     750             :                 "ne-NP", "Nepali",
     751             :                 "nl-NL", "Dutch",
     752             :                 "nn-NO", "Norwegian",
     753             :                 "or-IN", "Odia",
     754             :                 "pa-IN", "Punjabi",
     755             :                 "pl-PL", "Polish",
     756             :                 "ps-AF", "Pashto",
     757             :                 "pt-PT", "Portuguese",
     758             :                 "ro-RO", "Romanian",
     759             :                 "ru-RU", "Russian",
     760             :                 "sa-IN", "Sanskrit",
     761             :                 "sd-IN", "Sindhi",
     762             :                 "sk-SK", "Slovak",
     763             :                 "sl-SI", "Slovenian",
     764             :                 "so-SO", "Somali",
     765             :                 "sq-AL", "Albanian",
     766             :                 "sr-YU", "Serbian_Cyrillic",
     767             :                 "sv-SE", "Swedish",
     768             :                 "sw-KE", "Swahili",
     769             :                 "ta-IN", "Tamil",
     770             :                 "te-IN", "Telugu",
     771             :                 "tg-TJ", "Tajik",
     772             :                 "th-TH", "Thai",
     773             :                 "tk-TM", "Turkmen",
     774             :                 "tn-BW", "Tswana",
     775             :                 "tr-TR", "Turkish",
     776             :                 "tt-RU", "Tatar",
     777             :                 "uk-UA", "Ukrainian",
     778             :                 "ur-PK", "Urdu",
     779             :                 "uz-UZ", "Uzbek_Latin",
     780             :                 "ven-ZA", "Venda",
     781             :                 "vi-VN", "Vietnamese",
     782             :                 "yo-NG", "Yoruba",
     783             :                 "zh-CN", "Chinese",
     784             :                 "zu-ZA", "Zulu",
     785             :                 NULL, NULL
     786             :             };
     787             : 
     788           6 :             OUString sLocaleString( _rLocaleString );
     789           6 :             sal_Char nCompareTermination = 0;
     790             : 
     791           6 :             if ( _bAcceptCountryMismatch )
     792             :             {
     793             :                 // strip the country part from the compare string
     794           0 :                 sal_Int32 nCountrySep = sLocaleString.indexOf( '-' );
     795           0 :                 if ( nCountrySep > -1 )
     796           0 :                     sLocaleString = sLocaleString.copy( 0, nCountrySep );
     797             : 
     798             :                 // the entries in the translation table are compared until the
     799             :                 // - character only, not until the terminating 0
     800           0 :                 nCompareTermination = '-';
     801             :             }
     802             : 
     803           6 :             const sal_Char** pLookup = pTranslations;
     804         108 :             for ( ; *pLookup; pLookup +=2 )
     805             :             {
     806         108 :                 sal_Int32 nCompareUntil = 0;
     807         774 :                 while ( (*pLookup)[ nCompareUntil ] != nCompareTermination && (*pLookup)[ nCompareUntil ] != 0 )
     808         558 :                     ++nCompareUntil;
     809             : 
     810         108 :                 if ( sLocaleString.equalsAsciiL( *pLookup, nCompareUntil ) )
     811           6 :                     return *( pLookup + 1 );
     812             :             }
     813             : 
     814           0 :             if ( !_bAcceptCountryMismatch )
     815             :                 // second round, this time without matching the country
     816           0 :                 return lcl_getCollationForLocale( _rLocaleString, true );
     817             : 
     818             :             OSL_FAIL( "lcl_getCollationForLocale: unknown locale string, falling back to Latin1_General!" );
     819           0 :             return "Latin1_General";
     820             :         }
     821             : 
     822             : 
     823           6 :         OUString lcl_getSystemLocale( const Reference< XComponentContext >& _rxContext )
     824             :         {
     825           6 :             OUString sLocaleString = "en-US";
     826             :             try
     827             :             {
     828             : 
     829             :                 Reference< XMultiServiceFactory > xConfigProvider(
     830           6 :                     com::sun::star::configuration::theDefaultProvider::get( _rxContext ) );
     831             : 
     832             : 
     833             :                 // arguments for creating the config access
     834          12 :                 Sequence< Any > aArguments(2);
     835             :                 // the path to the node to open
     836          12 :                 OUString sNodePath("/org.openoffice.Setup/L10N" );
     837          12 :                 aArguments[0] <<= PropertyValue( OUString("nodepath"), 0,
     838             :                     makeAny( sNodePath ), PropertyState_DIRECT_VALUE
     839           6 :                 );
     840             :                 // the depth: -1 means unlimited
     841          12 :                 aArguments[1] <<= PropertyValue(
     842             :                     OUString("depth"), 0,
     843             :                     makeAny( (sal_Int32)-1 ), PropertyState_DIRECT_VALUE
     844           6 :                 );
     845             : 
     846             : 
     847             :                 // create the access
     848             :                 Reference< XPropertySet > xNode(
     849           6 :                     xConfigProvider->createInstanceWithArguments(
     850             :                         OUString("com.sun.star.configuration.ConfigurationAccess"),
     851           6 :                         aArguments ),
     852          12 :                     UNO_QUERY );
     853             :                 OSL_ENSURE( xNode.is(), "lcl_getSystemLocale: invalid access returned (should throw an exception instead)!" );
     854             : 
     855             : 
     856             :                 // ask for the system locale setting
     857           6 :                 if ( xNode.is() )
     858          12 :                     xNode->getPropertyValue("ooSetupSystemLocale") >>= sLocaleString;
     859             :             }
     860           0 :             catch( const Exception& )
     861             :             {
     862             :                 OSL_FAIL( "lcl_getSystemLocale: caught an exception!" );
     863             :             }
     864           6 :             if ( sLocaleString.isEmpty() )
     865             :             {
     866           6 :                 rtl_Locale* pProcessLocale = NULL;
     867           6 :                 osl_getProcessLocale( &pProcessLocale );
     868           6 :                 sLocaleString = LanguageTag( *pProcessLocale).getBcp47();
     869             :             }
     870           6 :             return sLocaleString;
     871             :         }
     872             :     }
     873             : 
     874           6 :     void ODriverDelegator::onConnectedNewDatabase( const Reference< XConnection >& _rxConnection )
     875             :     {
     876             :         try
     877             :         {
     878           6 :             Reference< XStatement > xStatement = _rxConnection->createStatement();
     879             :             OSL_ENSURE( xStatement.is(), "ODriverDelegator::onConnectedNewDatabase: could not create a statement!" );
     880           6 :             if ( xStatement.is() )
     881             :             {
     882           6 :                 OUStringBuffer aStatement;
     883           6 :                 aStatement.appendAscii( "SET DATABASE COLLATION \"" );
     884           6 :                 aStatement.appendAscii( lcl_getCollationForLocale( lcl_getSystemLocale( m_xContext ) ) );
     885           6 :                 aStatement.appendAscii( "\"" );
     886             : 
     887           6 :                 xStatement->execute( aStatement.makeStringAndClear() );
     888           6 :             }
     889             :         }
     890           0 :         catch( const Exception& )
     891             :         {
     892             :             OSL_FAIL( "ODriverDelegator::onConnectedNewDatabase: caught an exception!" );
     893             :         }
     894           6 :     }
     895             : 
     896             : 
     897             : 
     898             : 
     899             : }   // namespace connectivity
     900             : 
     901             : 
     902             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11