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