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