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