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