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/XDesktop.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< XDesktop > xDesktop( m_xFactory->createInstance( ::rtl::OUString("com.sun.star.frame.Desktop") ), UNO_QUERY );
376 :
377 0 : if( xDesktop.is() )
378 : {
379 0 : s_xTerminateListener = new OConnectionController(this);
380 0 : xDesktop->addTerminateListener(s_xTerminateListener);
381 0 : }
382 : }
383 0 : Reference< XComponent> xIfc = new OHsqlConnection( this, xOrig, comphelper::getComponentContext(m_xFactory) );
384 0 : xConnection.set(xIfc,UNO_QUERY);
385 0 : m_aConnections.push_back(TWeakPair(WeakReferenceHelper(xOrig),TWeakConnectionPair(sKey,TWeakRefPair(WeakReferenceHelper(xConnection),WeakReferenceHelper()))));
386 :
387 0 : Reference<XTransactionBroadcaster> xBroad(xStorage,UNO_QUERY);
388 0 : if ( xBroad.is() )
389 : {
390 0 : Reference<XTransactionListener> xListener(*this,UNO_QUERY);
391 0 : xBroad->addTransactionListener(xListener);
392 0 : }
393 0 : }
394 0 : }
395 : }
396 0 : return xConnection;
397 : }
398 :
399 : //--------------------------------------------------------------------
400 0 : sal_Bool SAL_CALL ODriverDelegator::acceptsURL( const ::rtl::OUString& url ) throw (SQLException, RuntimeException)
401 : {
402 0 : sal_Bool bEnabled = sal_False;
403 0 : OSL_VERIFY_EQUALS( jfw_getEnabled( &bEnabled ), JFW_E_NONE, "error in jfw_getEnabled" );
404 0 : return bEnabled && url.compareToAscii("sdbc:embedded:hsqldb",sizeof("sdbc:embedded:hsqldb")) == 0;
405 : }
406 :
407 : //--------------------------------------------------------------------
408 0 : Sequence< DriverPropertyInfo > SAL_CALL ODriverDelegator::getPropertyInfo( const ::rtl::OUString& url, const Sequence< PropertyValue >& /*info*/ ) throw (SQLException, RuntimeException)
409 : {
410 0 : if ( !acceptsURL(url) )
411 0 : return Sequence< DriverPropertyInfo >();
412 0 : ::std::vector< DriverPropertyInfo > aDriverInfo;
413 : aDriverInfo.push_back(DriverPropertyInfo(
414 : ::rtl::OUString("Storage")
415 : ,::rtl::OUString("Defines the storage where the database will be stored.")
416 : ,sal_True
417 : ,::rtl::OUString()
418 : ,Sequence< ::rtl::OUString >())
419 0 : );
420 : aDriverInfo.push_back(DriverPropertyInfo(
421 : ::rtl::OUString("URL")
422 : ,::rtl::OUString("Defines the url of the data source.")
423 : ,sal_True
424 : ,::rtl::OUString()
425 : ,Sequence< ::rtl::OUString >())
426 0 : );
427 : aDriverInfo.push_back(DriverPropertyInfo(
428 : ::rtl::OUString("AutoRetrievingStatement")
429 : ,::rtl::OUString("Defines the statement which will be executed to retrieve auto increment values.")
430 : ,sal_False
431 : ,::rtl::OUString("CALL IDENTITY()")
432 : ,Sequence< ::rtl::OUString >())
433 0 : );
434 0 : return Sequence< DriverPropertyInfo >(&aDriverInfo[0],aDriverInfo.size());
435 : }
436 :
437 : //--------------------------------------------------------------------
438 0 : sal_Int32 SAL_CALL ODriverDelegator::getMajorVersion( ) throw (RuntimeException)
439 : {
440 0 : return 1;
441 : }
442 :
443 : //--------------------------------------------------------------------
444 0 : sal_Int32 SAL_CALL ODriverDelegator::getMinorVersion( ) throw (RuntimeException)
445 : {
446 0 : return 0;
447 : }
448 :
449 : //--------------------------------------------------------------------
450 0 : Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByConnection( const Reference< XConnection >& connection ) throw (SQLException, RuntimeException)
451 : {
452 0 : ::osl::MutexGuard aGuard( m_aMutex );
453 0 : checkDisposed(ODriverDelegator_BASE::rBHelper.bDisposed);
454 :
455 0 : Reference< XTablesSupplier > xTab;
456 :
457 0 : TWeakPairVector::iterator aEnd = m_aConnections.end();
458 0 : for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
459 : {
460 0 : if ( i->second.second.first.get() == connection.get() )
461 : {
462 0 : xTab = Reference< XTablesSupplier >(i->second.second.second.get().get(),UNO_QUERY);
463 0 : if ( !xTab.is() )
464 : {
465 0 : xTab = new OHCatalog(connection);
466 0 : i->second.second.second = WeakReferenceHelper(xTab);
467 : }
468 0 : break;
469 : }
470 : }
471 :
472 0 : return xTab;
473 : }
474 :
475 : //--------------------------------------------------------------------
476 0 : Reference< XTablesSupplier > SAL_CALL ODriverDelegator::getDataDefinitionByURL( const ::rtl::OUString& url, const Sequence< PropertyValue >& info ) throw (SQLException, RuntimeException)
477 : {
478 0 : if ( ! acceptsURL(url) )
479 : {
480 0 : ::connectivity::SharedResources aResources;
481 0 : const ::rtl::OUString sMessage = aResources.getResourceString(STR_URI_SYNTAX_ERROR);
482 0 : ::dbtools::throwGenericSQLException(sMessage ,*this);
483 : }
484 :
485 0 : return getDataDefinitionByConnection(connect(url,info));
486 : }
487 :
488 : // XServiceInfo
489 : // --------------------------------------------------------------------------------
490 : //------------------------------------------------------------------------------
491 0 : rtl::OUString ODriverDelegator::getImplementationName_Static( ) throw(RuntimeException)
492 : {
493 0 : return rtl::OUString("com.sun.star.sdbcx.comp.hsqldb.Driver");
494 : }
495 : //------------------------------------------------------------------------------
496 0 : Sequence< ::rtl::OUString > ODriverDelegator::getSupportedServiceNames_Static( ) throw (RuntimeException)
497 : {
498 0 : Sequence< ::rtl::OUString > aSNS( 2 );
499 0 : aSNS[0] = ::rtl::OUString("com.sun.star.sdbc.Driver");
500 0 : aSNS[1] = ::rtl::OUString("com.sun.star.sdbcx.Driver");
501 0 : return aSNS;
502 : }
503 : //------------------------------------------------------------------
504 0 : ::rtl::OUString SAL_CALL ODriverDelegator::getImplementationName( ) throw(RuntimeException)
505 : {
506 0 : return getImplementationName_Static();
507 : }
508 :
509 : //------------------------------------------------------------------
510 0 : sal_Bool SAL_CALL ODriverDelegator::supportsService( const ::rtl::OUString& _rServiceName ) throw(RuntimeException)
511 : {
512 0 : Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames());
513 0 : const ::rtl::OUString* pSupported = aSupported.getConstArray();
514 0 : const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();
515 0 : for (;pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported)
516 : ;
517 :
518 0 : return pSupported != pEnd;
519 : }
520 : //------------------------------------------------------------------
521 0 : Sequence< ::rtl::OUString > SAL_CALL ODriverDelegator::getSupportedServiceNames( ) throw(RuntimeException)
522 : {
523 0 : return getSupportedServiceNames_Static();
524 : }
525 : //------------------------------------------------------------------
526 0 : void SAL_CALL ODriverDelegator::createCatalog( const Sequence< PropertyValue >& /*info*/ ) throw (SQLException, ::com::sun::star::container::ElementExistException, RuntimeException)
527 : {
528 0 : ::dbtools::throwFeatureNotImplementedException( "XCreateCatalog::createCatalog", *this );
529 0 : }
530 : //------------------------------------------------------------------
531 0 : void ODriverDelegator::shutdownConnection(const TWeakPairVector::iterator& _aIter )
532 : {
533 : OSL_ENSURE(m_aConnections.end() != _aIter,"Iterator equals .end()");
534 0 : sal_Bool bLastOne = sal_True;
535 : try
536 : {
537 0 : Reference<XConnection> _xConnection(_aIter->first.get(),UNO_QUERY);
538 :
539 0 : if ( _xConnection.is() )
540 : {
541 0 : Reference<XStatement> xStmt = _xConnection->createStatement();
542 0 : if ( xStmt.is() )
543 : {
544 0 : Reference<XResultSet> xRes(xStmt->executeQuery(::rtl::OUString("SELECT COUNT(*) FROM INFORMATION_SCHEMA.SYSTEM_SESSIONS WHERE USER_NAME ='SA'")),UNO_QUERY);
545 0 : Reference<XRow> xRow(xRes,UNO_QUERY);
546 0 : if ( xRow.is() && xRes->next() )
547 0 : bLastOne = xRow->getInt(1) == 1;
548 0 : if ( bLastOne )
549 0 : xStmt->execute(::rtl::OUString("SHUTDOWN"));
550 0 : }
551 0 : }
552 : }
553 0 : catch(Exception&)
554 : {
555 : }
556 0 : if ( bLastOne )
557 : {
558 : // Reference<XTransactionListener> xListener(*this,UNO_QUERY);
559 : // a shutdown should commit all changes to the db files
560 0 : StorageContainer::revokeStorage(_aIter->second.first,NULL);
561 : }
562 0 : if ( !m_bInShutDownConnections )
563 0 : m_aConnections.erase(_aIter);
564 0 : }
565 : //------------------------------------------------------------------
566 0 : void SAL_CALL ODriverDelegator::disposing( const ::com::sun::star::lang::EventObject& Source ) throw(::com::sun::star::uno::RuntimeException)
567 : {
568 0 : ::osl::MutexGuard aGuard(m_aMutex);
569 0 : Reference<XConnection> xCon(Source.Source,UNO_QUERY);
570 0 : if ( xCon.is() )
571 : {
572 0 : TWeakPairVector::iterator i = m_aConnections.begin();
573 0 : for (; m_aConnections.end() != i; ++i)
574 : {
575 0 : if ( i->first.get() == xCon.get() )
576 : {
577 0 : shutdownConnection(i);
578 0 : break;
579 : }
580 : }
581 : }
582 : else
583 : {
584 0 : Reference< XStorage> xStorage(Source.Source,UNO_QUERY);
585 0 : if ( xStorage.is() )
586 : {
587 0 : ::rtl::OUString sKey = StorageContainer::getRegisteredKey(xStorage);
588 : TWeakPairVector::iterator i = ::std::find_if(m_aConnections.begin(),m_aConnections.end(),::o3tl::compose1(
589 : ::std::bind2nd(::std::equal_to< ::rtl::OUString >(),sKey)
590 0 : ,::o3tl::compose1(::o3tl::select1st<TWeakConnectionPair>(),::o3tl::select2nd< TWeakPair >())));
591 0 : if ( i != m_aConnections.end() )
592 0 : shutdownConnection(i);
593 0 : }
594 0 : }
595 0 : }
596 : //------------------------------------------------------------------
597 0 : void ODriverDelegator::shutdownConnections()
598 : {
599 0 : m_bInShutDownConnections = sal_True;
600 0 : TWeakPairVector::iterator aEnd = m_aConnections.end();
601 0 : for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
602 : {
603 : try
604 : {
605 0 : Reference<XConnection> xCon(i->first,UNO_QUERY);
606 0 : ::comphelper::disposeComponent(xCon);
607 : }
608 0 : catch(Exception&)
609 : {
610 : }
611 : }
612 0 : m_aConnections.clear();
613 0 : m_bInShutDownConnections = sal_True;
614 0 : }
615 : //------------------------------------------------------------------
616 0 : void ODriverDelegator::flushConnections()
617 : {
618 0 : TWeakPairVector::iterator aEnd = m_aConnections.end();
619 0 : for (TWeakPairVector::iterator i = m_aConnections.begin(); aEnd != i; ++i)
620 : {
621 : try
622 : {
623 0 : Reference<XFlushable> xCon(i->second.second.first.get(),UNO_QUERY);
624 0 : xCon->flush();
625 : }
626 0 : catch(Exception&)
627 : {
628 : }
629 : }
630 0 : }
631 : //------------------------------------------------------------------
632 0 : void SAL_CALL ODriverDelegator::preCommit( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
633 : {
634 0 : ::osl::MutexGuard aGuard(m_aMutex);
635 :
636 0 : Reference< XStorage> xStorage(aEvent.Source,UNO_QUERY);
637 0 : ::rtl::OUString sKey = StorageContainer::getRegisteredKey(xStorage);
638 0 : if ( !sKey.isEmpty() )
639 : {
640 : TWeakPairVector::iterator i = ::std::find_if(m_aConnections.begin(),m_aConnections.end(),::o3tl::compose1(
641 : ::std::bind2nd(::std::equal_to< ::rtl::OUString >(),sKey)
642 0 : ,::o3tl::compose1(::o3tl::select1st<TWeakConnectionPair>(),::o3tl::select2nd< TWeakPair >())));
643 : OSL_ENSURE( i != m_aConnections.end(), "ODriverDelegator::preCommit: they're committing a storage which I do not know!" );
644 0 : if ( i != m_aConnections.end() )
645 : {
646 : try
647 : {
648 0 : Reference<XConnection> xConnection(i->first,UNO_QUERY);
649 0 : if ( xConnection.is() )
650 : {
651 0 : Reference< XStatement> xStmt = xConnection->createStatement();
652 : OSL_ENSURE( xStmt.is(), "ODriverDelegator::preCommit: no statement!" );
653 0 : if ( xStmt.is() )
654 0 : xStmt->execute( ::rtl::OUString( "SET WRITE_DELAY 0" ) );
655 :
656 0 : sal_Bool bPreviousAutoCommit = xConnection->getAutoCommit();
657 0 : xConnection->setAutoCommit( sal_False );
658 0 : xConnection->commit();
659 0 : xConnection->setAutoCommit( bPreviousAutoCommit );
660 :
661 0 : if ( xStmt.is() )
662 0 : xStmt->execute( ::rtl::OUString( "SET WRITE_DELAY 60" ) );
663 0 : }
664 : }
665 0 : catch(Exception&)
666 : {
667 : OSL_FAIL( "ODriverDelegator::preCommit: caught an exception!" );
668 : }
669 : }
670 0 : }
671 0 : }
672 : //------------------------------------------------------------------
673 0 : void SAL_CALL ODriverDelegator::commited( const ::com::sun::star::lang::EventObject& /*aEvent*/ ) throw (::com::sun::star::uno::RuntimeException)
674 : {
675 0 : }
676 : //------------------------------------------------------------------
677 0 : void SAL_CALL ODriverDelegator::preRevert( const ::com::sun::star::lang::EventObject& /*aEvent*/ ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException)
678 : {
679 0 : }
680 : //------------------------------------------------------------------
681 0 : void SAL_CALL ODriverDelegator::reverted( const ::com::sun::star::lang::EventObject& /*aEvent*/ ) throw (::com::sun::star::uno::RuntimeException)
682 : {
683 0 : }
684 : //------------------------------------------------------------------
685 : namespace
686 : {
687 : //..............................................................
688 0 : const sal_Char* lcl_getCollationForLocale( const ::rtl::OUString& _rLocaleString, bool _bAcceptCountryMismatch = false )
689 : {
690 : static const sal_Char* pTranslations[] =
691 : {
692 : "af-ZA", "Afrikaans",
693 : "am-ET", "Amharic",
694 : "ar", "Arabic",
695 : "as-IN", "Assamese",
696 : "az-AZ", "Azerbaijani_Latin",
697 : "az-cyrillic", "Azerbaijani_Cyrillic",
698 : "be-BY", "Belarusian",
699 : "bg-BG", "Bulgarian",
700 : "bn-IN", "Bengali",
701 : "bo-CN", "Tibetan",
702 : "bs-BA", "Bosnian",
703 : "ca-ES", "Catalan",
704 : "cs-CZ", "Czech",
705 : "cy-GB", "Welsh",
706 : "da-DK", "Danish",
707 : "de-DE", "German",
708 : "el-GR", "Greek",
709 : "en-US", "Latin1_General",
710 : "es-ES", "Spanish",
711 : "et-EE", "Estonian",
712 : "eu", "Basque",
713 : "fi-FI", "Finnish",
714 : "fr-FR", "French",
715 : "gn-PY", "Guarani",
716 : "gu-IN", "Gujarati",
717 : "ha-NG", "Hausa",
718 : "he-IL", "Hebrew",
719 : "hi-IN", "Hindi",
720 : "hr-HR", "Croatian",
721 : "hu-HU", "Hungarian",
722 : "hy-AM", "Armenian",
723 : "id-ID", "Indonesian",
724 : "ig-NG", "Igbo",
725 : "is-IS", "Icelandic",
726 : "it-IT", "Italian",
727 : "iu-CA", "Inuktitut",
728 : "ja-JP", "Japanese",
729 : "ka-GE", "Georgian",
730 : "kk-KZ", "Kazakh",
731 : "km-KH", "Khmer",
732 : "kn-IN", "Kannada",
733 : "ko-KR", "Korean",
734 : "kok-IN", "Konkani",
735 : "ks", "Kashmiri",
736 : "ky-KG", "Kirghiz",
737 : "lo-LA", "Lao",
738 : "lt-LT", "Lithuanian",
739 : "lv-LV", "Latvian",
740 : "mi-NZ", "Maori",
741 : "mk-MK", "Macedonian",
742 : "ml-IN", "Malayalam",
743 : "mn-MN", "Mongolian",
744 : "mni-IN", "Manipuri",
745 : "mr-IN", "Marathi",
746 : "ms-MY", "Malay",
747 : "mt-MT", "Maltese",
748 : "my-MM", "Burmese",
749 : "nb-NO", "Danish_Norwegian",
750 : "ne-NP", "Nepali",
751 : "nl-NL", "Dutch",
752 : "nn-NO", "Norwegian",
753 : "or-IN", "Oriya",
754 : "pa-IN", "Punjabi",
755 : "pl-PL", "Polish",
756 : "ps-AF", "Pashto",
757 : "pt-PT", "Portuguese",
758 : "ro-RO", "Romanian",
759 : "ru-RU", "Russian",
760 : "sa-IN", "Sanskrit",
761 : "sd-IN", "Sindhi",
762 : "sk-SK", "Slovak",
763 : "sl-SI", "Slovenian",
764 : "so-SO", "Somali",
765 : "sq-AL", "Albanian",
766 : "sr-YU", "Serbian_Cyrillic",
767 : "sv-SE", "Swedish",
768 : "sw-KE", "Swahili",
769 : "ta-IN", "Tamil",
770 : "te-IN", "Telugu",
771 : "tg-TJ", "Tajik",
772 : "th-TH", "Thai",
773 : "tk-TM", "Turkmen",
774 : "tn-BW", "Tswana",
775 : "tr-TR", "Turkish",
776 : "tt-RU", "Tatar",
777 : "uk-UA", "Ukrainian",
778 : "ur-PK", "Urdu",
779 : "uz-UZ", "Uzbek_Latin",
780 : "ven-ZA", "Venda",
781 : "vi-VN", "Vietnamese",
782 : "yo-NG", "Yoruba",
783 : "zh-CN", "Chinese",
784 : "zu-ZA", "Zulu",
785 : NULL, NULL
786 : };
787 :
788 0 : ::rtl::OUString sLocaleString( _rLocaleString );
789 0 : sal_Char nCompareTermination = 0;
790 :
791 0 : if ( _bAcceptCountryMismatch )
792 : {
793 : // strip the country part from the compare string
794 0 : sal_Int32 nCountrySep = sLocaleString.indexOf( '-' );
795 0 : if ( nCountrySep > -1 )
796 0 : sLocaleString = sLocaleString.copy( 0, nCountrySep );
797 :
798 : // the entries in the translation table are compared until the
799 : // - character only, not until the terminating 0
800 0 : nCompareTermination = '-';
801 : }
802 :
803 0 : const sal_Char** pLookup = pTranslations;
804 0 : for ( ; *pLookup; pLookup +=2 )
805 : {
806 0 : sal_Int32 nCompareUntil = 0;
807 0 : while ( (*pLookup)[ nCompareUntil ] != nCompareTermination && (*pLookup)[ nCompareUntil ] != 0 )
808 0 : ++nCompareUntil;
809 :
810 0 : if ( sLocaleString.equalsAsciiL( *pLookup, nCompareUntil ) )
811 0 : return *( pLookup + 1 );
812 : }
813 :
814 0 : if ( !_bAcceptCountryMismatch )
815 : // second round, this time without matching the country
816 0 : return lcl_getCollationForLocale( _rLocaleString, true );
817 :
818 : OSL_FAIL( "lcl_getCollationForLocale: unknown locale string, falling back to Latin1_General!" );
819 0 : return "Latin1_General";
820 : }
821 :
822 : //..............................................................
823 0 : ::rtl::OUString lcl_getSystemLocale( const Reference< XMultiServiceFactory >& _rxORB )
824 : {
825 0 : ::rtl::OUString sLocaleString = ::rtl::OUString( "en-US" );
826 : try
827 : {
828 : //.........................................................
829 : Reference< XMultiServiceFactory > xConfigProvider(
830 : com::sun::star::configuration::theDefaultProvider::get(
831 0 : comphelper::getComponentContext( _rxORB ) ) );
832 :
833 : //.........................................................
834 : // arguments for creating the config access
835 0 : Sequence< Any > aArguments(2);
836 : // the path to the node to open
837 0 : ::rtl::OUString sNodePath("/org.openoffice.Setup/L10N" );
838 0 : aArguments[0] <<= PropertyValue( ::rtl::OUString("nodepath"), 0,
839 : makeAny( sNodePath ), PropertyState_DIRECT_VALUE
840 0 : );
841 : // the depth: -1 means unlimited
842 0 : aArguments[1] <<= PropertyValue(
843 : ::rtl::OUString("depth"), 0,
844 : makeAny( (sal_Int32)-1 ), PropertyState_DIRECT_VALUE
845 0 : );
846 :
847 : //.........................................................
848 : // create the access
849 : Reference< XPropertySet > xNode(
850 0 : xConfigProvider->createInstanceWithArguments(
851 : ::rtl::OUString("com.sun.star.configuration.ConfigurationAccess"),
852 0 : aArguments ),
853 0 : UNO_QUERY );
854 : OSL_ENSURE( xNode.is(), "lcl_getSystemLocale: invalid access returned (should throw an exception instead)!" );
855 :
856 : //.........................................................
857 : // ask for the system locale setting
858 0 : if ( xNode.is() )
859 0 : xNode->getPropertyValue( ::rtl::OUString( "ooSetupSystemLocale" ) ) >>= sLocaleString;
860 : }
861 0 : catch( const Exception& )
862 : {
863 : OSL_FAIL( "lcl_getSystemLocale: caught an exception!" );
864 : }
865 0 : if ( sLocaleString.isEmpty() )
866 : {
867 0 : rtl_Locale* pProcessLocale = NULL;
868 0 : osl_getProcessLocale( &pProcessLocale );
869 :
870 0 : ::rtl::OUStringBuffer aProcLocale;
871 0 : aProcLocale.append( pProcessLocale->Language->buffer, pProcessLocale->Language->length );
872 0 : if ( pProcessLocale->Country->length )
873 : {
874 0 : aProcLocale.appendAscii( "-" );
875 0 : aProcLocale.append( pProcessLocale->Country->buffer, pProcessLocale->Country->length );
876 : }
877 0 : sLocaleString = aProcLocale.makeStringAndClear();
878 : }
879 0 : return sLocaleString;
880 : }
881 : }
882 : //------------------------------------------------------------------
883 0 : void ODriverDelegator::onConnectedNewDatabase( const Reference< XConnection >& _rxConnection )
884 : {
885 : try
886 : {
887 0 : Reference< XStatement > xStatement = _rxConnection->createStatement();
888 : OSL_ENSURE( xStatement.is(), "ODriverDelegator::onConnectedNewDatabase: could not create a statement!" );
889 0 : if ( xStatement.is() )
890 : {
891 0 : ::rtl::OUStringBuffer aStatement;
892 0 : aStatement.appendAscii( "SET DATABASE COLLATION \"" );
893 0 : aStatement.appendAscii( lcl_getCollationForLocale( lcl_getSystemLocale( m_xFactory ) ) );
894 0 : aStatement.appendAscii( "\"" );
895 :
896 0 : xStatement->execute( aStatement.makeStringAndClear() );
897 0 : }
898 : }
899 0 : catch( const Exception& )
900 : {
901 : OSL_FAIL( "ODriverDelegator::onConnectedNewDatabase: caught an exception!" );
902 : }
903 0 : }
904 :
905 : //------------------------------------------------------------------
906 : //------------------------------------------------------------------
907 : //........................................................................
908 : } // namespace connectivity
909 : //........................................................................
910 :
911 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|