Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / connectivity / source / drivers / jdbc / JConnection.cxx
blobcff6f8f4e45bbf4288f502ac4e67142af1d36390
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <java/sql/Connection.hxx>
23 #include <java/lang/Class.hxx>
24 #include <java/tools.hxx>
25 #include <java/ContextClassLoader.hxx>
26 #include <java/sql/DatabaseMetaData.hxx>
27 #include <java/sql/JStatement.hxx>
28 #include <java/sql/Driver.hxx>
29 #include <java/sql/PreparedStatement.hxx>
30 #include <java/sql/CallableStatement.hxx>
31 #include <java/sql/SQLWarning.hxx>
32 #include <com/sun/star/sdbc/SQLWarning.hpp>
33 #include <com/sun/star/beans/NamedValue.hpp>
34 #include <connectivity/dbexception.hxx>
35 #include <java/util/Property.hxx>
36 #include <java/LocalRef.hxx>
37 #include <com/sun/star/uno/XComponentContext.hpp>
38 #include <jvmaccess/classpath.hxx>
39 #include <comphelper/namedvaluecollection.hxx>
40 #include <cppuhelper/exc_hlp.hxx>
41 #include <jni.h>
42 #include <strings.hrc>
43 #include <unotools/confignode.hxx>
44 #include <strings.hxx>
46 #include <utility>
47 #include <vector>
48 #include <memory>
50 using namespace connectivity;
51 using namespace connectivity::jdbc;
52 using namespace ::com::sun::star::uno;
53 using namespace ::com::sun::star::beans;
54 using namespace ::com::sun::star::sdbc;
55 using namespace ::com::sun::star::container;
56 using namespace ::com::sun::star::lang;
58 namespace {
60 struct ClassMapEntry {
61 ClassMapEntry(
62 OUString theClassPath, OUString theClassName):
63 classPath(std::move(theClassPath)), className(std::move(theClassName)), classLoader(nullptr),
64 classObject(nullptr) {}
66 OUString classPath;
67 OUString className;
68 jweak classLoader;
69 jweak classObject;
72 typedef std::vector< ClassMapEntry > ClassMap;
74 struct ClassMapData {
75 osl::Mutex mutex;
77 ClassMap map;
80 template < typename T >
81 bool getLocalFromWeakRef( jweak& _weak, LocalRef< T >& _inout_local )
83 _inout_local.set( static_cast< T >( _inout_local.env().NewLocalRef( _weak ) ) );
85 if ( !_inout_local.is() )
87 if ( _inout_local.env().ExceptionCheck())
89 return false;
91 else if ( _weak != nullptr )
93 _inout_local.env().DeleteWeakGlobalRef( _weak );
94 _weak = nullptr;
97 return true;
100 // Load a class. A map from pairs of (classPath, name) to pairs of weak Java
101 // references to (ClassLoader, Class) is maintained, so that a class is only
102 // loaded once.
104 // It may happen that the weak reference to the ClassLoader becomes null while
105 // the reference to the Class remains non-null (in case the Class was actually
106 // loaded by some parent of the ClassLoader), in which case the ClassLoader is
107 // resurrected (which cannot cause any classes to be loaded multiple times, as
108 // the ClassLoader is no longer reachable, so no classes it has ever loaded are
109 // still reachable).
111 // Similarly, it may happen that the weak reference to the Class becomes null
112 // while the reference to the ClassLoader remains non-null, in which case the
113 // Class is simply re-loaded.
115 // This code is close to the implementation of jvmaccess::ClassPath::loadClass
116 // in jvmaccess/classpath.hxx, but not close enough to avoid the duplication.
118 // If false is returned, a (still pending) JNI exception occurred.
119 bool loadClass(
120 Reference< XComponentContext > const & context, JNIEnv& environment,
121 OUString const & classPath, OUString const & name,
122 LocalRef< jobject > * classLoaderPtr, LocalRef< jclass > * classPtr)
124 OSL_ASSERT(classLoaderPtr != nullptr);
125 // For any jweak entries still present in the map upon destruction,
126 // DeleteWeakGlobalRef is not called (which is a leak):
127 static ClassMapData classMapData;
128 osl::MutexGuard g(classMapData.mutex);
129 ClassMap::iterator i(classMapData.map.begin());
130 LocalRef< jobject > cloader(environment);
131 LocalRef< jclass > cl(environment);
132 // Prune dangling weak references from the list while searching for a match,
133 // so that the list cannot grow unbounded:
134 for (; i != classMapData.map.end();)
136 LocalRef< jobject > classLoader( environment );
137 if ( !getLocalFromWeakRef( i->classLoader, classLoader ) )
138 return false;
140 LocalRef< jclass > classObject( environment );
141 if ( !getLocalFromWeakRef( i->classObject, classObject ) )
142 return false;
144 if ( !classLoader.is() && !classObject.is() )
146 i = classMapData.map.erase(i);
148 else if ( i->classPath == classPath && i->className == name )
150 cloader.set( classLoader.release() );
151 cl.set( classObject.release() );
152 break;
154 else
156 ++i;
159 if ( !cloader.is() || !cl.is() )
161 if ( i == classMapData.map.end() )
163 // Push a new ClassMapEntry (which can potentially fail) before
164 // loading the class, so that it never happens that a class is
165 // loaded but not added to the map (which could have effects on the
166 // JVM that are not easily undone). If the pushed ClassMapEntry is
167 // not used after all (return false, etc.) it will be pruned on next
168 // call because its classLoader/classObject are null:
169 classMapData.map.push_back( ClassMapEntry( classPath, name ) );
170 i = std::prev(classMapData.map.end());
173 LocalRef< jclass > clClass( environment );
174 clClass.set( environment.FindClass( "java/net/URLClassLoader" ) );
175 if ( !clClass.is() )
176 return false;
178 jweak wcloader = nullptr;
179 if (!cloader.is())
181 jmethodID ctorLoader( environment.GetMethodID( clClass.get(), "<init>", "([Ljava/net/URL;)V" ) );
182 if (ctorLoader == nullptr)
183 return false;
185 LocalRef< jobjectArray > arr( environment );
186 arr.set( jvmaccess::ClassPath::translateToUrls( context, &environment, classPath ) );
187 if ( !arr.is() )
188 return false;
190 jvalue arg;
191 arg.l = arr.get();
192 cloader.set( environment.NewObjectA( clClass.get(), ctorLoader, &arg ) );
193 if ( !cloader.is() )
194 return false;
196 wcloader = environment.NewWeakGlobalRef( cloader.get() );
197 if ( wcloader == nullptr )
198 return false;
201 jweak wcl = nullptr;
202 if ( !cl.is() )
204 jmethodID methLoadClass( environment.GetMethodID( clClass.get(), "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;" ) );
205 if ( methLoadClass == nullptr )
206 return false;
208 LocalRef< jstring > str( environment );
209 str.set( convertwchar_tToJavaString( &environment, name ) );
210 if ( !str.is() )
211 return false;
213 jvalue arg;
214 arg.l = str.get();
215 cl.set( static_cast< jclass >( environment.CallObjectMethodA( cloader.get(), methLoadClass, &arg ) ) );
216 if ( !cl.is() )
217 return false;
219 wcl = environment.NewWeakGlobalRef( cl.get() );
220 if ( wcl == nullptr )
221 return false;
224 if ( wcloader != nullptr)
226 i->classLoader = wcloader;
228 if ( wcl != nullptr )
230 i->classObject = wcl;
234 classLoaderPtr->set( cloader.release() );
235 classPtr->set( cl.release() );
236 return true;
242 IMPLEMENT_SERVICE_INFO(java_sql_Connection,"com.sun.star.sdbcx.JConnection","com.sun.star.sdbc.Connection");
245 //************ Class: java.sql.Connection
247 jclass java_sql_Connection::theClass = nullptr;
249 java_sql_Connection::java_sql_Connection( const java_sql_Driver& _rDriver )
250 :m_xContext( _rDriver.getContext() )
251 ,m_pDriver( &_rDriver )
252 ,m_pDriverobject(nullptr)
253 ,m_Driver_theClass(nullptr)
254 ,m_aLogger( _rDriver.getLogger() )
255 ,m_bIgnoreDriverPrivileges(true)
256 ,m_bIgnoreCurrency(false)
260 java_sql_Connection::~java_sql_Connection()
262 ::rtl::Reference< jvmaccess::VirtualMachine > xTest = java_lang_Object::getVM();
263 if ( !xTest.is() )
264 return;
266 SDBThreadAttach t;
267 clearObject(*t.pEnv);
270 if ( m_pDriverobject )
271 t.pEnv->DeleteGlobalRef( m_pDriverobject );
272 m_pDriverobject = nullptr;
273 if ( m_Driver_theClass )
274 t.pEnv->DeleteGlobalRef( m_Driver_theClass );
275 m_Driver_theClass = nullptr;
277 SDBThreadAttach::releaseRef();
280 void java_sql_Connection::disposing()
282 ::osl::MutexGuard aGuard(m_aMutex);
284 m_aLogger.log( LogLevel::INFO, STR_LOG_SHUTDOWN_CONNECTION );
286 java_sql_Connection_BASE::disposing();
288 if ( object )
290 static jmethodID mID(nullptr);
291 callVoidMethod_ThrowSQL("close", mID);
295 jclass java_sql_Connection::getMyClass() const
297 // the class must be fetched only once, therefore static
298 if( !theClass )
299 theClass = findMyClass("java/sql/Connection");
300 return theClass;
304 OUString SAL_CALL java_sql_Connection::getCatalog( )
306 ::osl::MutexGuard aGuard( m_aMutex );
307 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
309 static jmethodID mID(nullptr);
310 return callStringMethod("getCatalog",mID);
313 Reference< XDatabaseMetaData > SAL_CALL java_sql_Connection::getMetaData( )
315 ::osl::MutexGuard aGuard( m_aMutex );
316 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
319 Reference< XDatabaseMetaData > xMetaData = m_xMetaData;
320 if(!xMetaData.is())
322 SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!");
323 static jmethodID mID(nullptr);
324 jobject out = callObjectMethod(t.pEnv,"getMetaData","()Ljava/sql/DatabaseMetaData;", mID);
325 if(out)
327 xMetaData = new java_sql_DatabaseMetaData( t.pEnv, out, *this );
328 m_xMetaData = xMetaData;
332 return xMetaData;
335 void SAL_CALL java_sql_Connection::close( )
337 dispose();
340 void SAL_CALL java_sql_Connection::commit( )
342 static jmethodID mID(nullptr);
343 callVoidMethod_ThrowSQL("commit", mID);
346 sal_Bool SAL_CALL java_sql_Connection::isClosed( )
348 ::osl::MutexGuard aGuard( m_aMutex );
350 static jmethodID mID(nullptr);
351 return callBooleanMethod( "isClosed", mID ) && java_sql_Connection_BASE::rBHelper.bDisposed;
354 sal_Bool SAL_CALL java_sql_Connection::isReadOnly( )
356 ::osl::MutexGuard aGuard( m_aMutex );
357 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
358 static jmethodID mID(nullptr);
359 return callBooleanMethod( "isReadOnly", mID );
362 void SAL_CALL java_sql_Connection::setCatalog( const OUString& catalog )
364 static jmethodID mID(nullptr);
365 callVoidMethodWithStringArg("setCatalog",mID,catalog);
368 void SAL_CALL java_sql_Connection::rollback( )
370 static jmethodID mID(nullptr);
371 callVoidMethod_ThrowSQL("rollback", mID);
374 sal_Bool SAL_CALL java_sql_Connection::getAutoCommit( )
376 static jmethodID mID(nullptr);
377 return callBooleanMethod( "getAutoCommit", mID );
380 void SAL_CALL java_sql_Connection::setReadOnly( sal_Bool readOnly )
382 static jmethodID mID(nullptr);
383 callVoidMethodWithBoolArg_ThrowSQL("setReadOnly", mID, readOnly);
386 void SAL_CALL java_sql_Connection::setAutoCommit( sal_Bool autoCommit )
388 static jmethodID mID(nullptr);
389 callVoidMethodWithBoolArg_ThrowSQL("setAutoCommit", mID, autoCommit);
392 Reference< css::container::XNameAccess > SAL_CALL java_sql_Connection::getTypeMap( )
394 ::osl::MutexGuard aGuard( m_aMutex );
395 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
397 SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!");
398 static jmethodID mID(nullptr);
399 callObjectMethod(t.pEnv,"getTypeMap","()Ljava/util/Map;", mID);
400 // WARNING: the caller becomes the owner of the returned pointer
401 return nullptr;
404 void SAL_CALL java_sql_Connection::setTypeMap( const Reference< css::container::XNameAccess >& /*typeMap*/ )
406 ::osl::MutexGuard aGuard( m_aMutex );
407 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
409 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setTypeMap", *this );
413 sal_Int32 SAL_CALL java_sql_Connection::getTransactionIsolation( )
415 ::osl::MutexGuard aGuard( m_aMutex );
416 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
418 static jmethodID mID(nullptr);
419 return callIntMethod_ThrowSQL("getTransactionIsolation", mID);
422 void SAL_CALL java_sql_Connection::setTransactionIsolation( sal_Int32 level )
424 ::osl::MutexGuard aGuard( m_aMutex );
425 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
427 static jmethodID mID(nullptr);
428 callVoidMethodWithIntArg_ThrowSQL("setTransactionIsolation", mID, level);
431 Reference< XStatement > SAL_CALL java_sql_Connection::createStatement( )
433 ::osl::MutexGuard aGuard( m_aMutex );
434 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
435 m_aLogger.log( LogLevel::FINE, STR_LOG_CREATE_STATEMENT );
437 SDBThreadAttach t;
438 rtl::Reference<java_sql_Statement> pStatement = new java_sql_Statement( t.pEnv, *this );
439 Reference< XStatement > xStmt = pStatement;
440 m_aStatements.push_back( WeakReferenceHelper( xStmt ) );
442 m_aLogger.log( LogLevel::FINE, STR_LOG_CREATED_STATEMENT_ID, pStatement->getStatementObjectID() );
443 return xStmt;
446 Reference< XPreparedStatement > SAL_CALL java_sql_Connection::prepareStatement( const OUString& sql )
448 ::osl::MutexGuard aGuard( m_aMutex );
449 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
450 m_aLogger.log( LogLevel::FINE, STR_LOG_PREPARE_STATEMENT, sql );
452 SDBThreadAttach t;
454 rtl::Reference<java_sql_PreparedStatement> pStatement = new java_sql_PreparedStatement( t.pEnv, *this, sql );
455 Reference< XPreparedStatement > xReturn( pStatement );
456 m_aStatements.push_back(WeakReferenceHelper(xReturn));
458 m_aLogger.log( LogLevel::FINE, STR_LOG_PREPARED_STATEMENT_ID, pStatement->getStatementObjectID() );
459 return xReturn;
462 Reference< XPreparedStatement > SAL_CALL java_sql_Connection::prepareCall( const OUString& sql )
464 ::osl::MutexGuard aGuard( m_aMutex );
465 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
466 m_aLogger.log( LogLevel::FINE, STR_LOG_PREPARE_CALL, sql );
468 SDBThreadAttach t;
470 rtl::Reference<java_sql_CallableStatement> pStatement = new java_sql_CallableStatement( t.pEnv, *this, sql );
471 Reference< XPreparedStatement > xStmt( pStatement );
472 m_aStatements.push_back(WeakReferenceHelper(xStmt));
474 m_aLogger.log( LogLevel::FINE, STR_LOG_PREPARED_CALL_ID, pStatement->getStatementObjectID() );
475 return xStmt;
478 OUString SAL_CALL java_sql_Connection::nativeSQL( const OUString& sql )
480 ::osl::MutexGuard aGuard( m_aMutex );
481 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
483 OUString aStr;
484 SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!");
487 // initialize temporary Variable
488 static const char * const cSignature = "(Ljava/lang/String;)Ljava/lang/String;";
489 static const char * const cMethodName = "nativeSQL";
490 // Java-Call
491 static jmethodID mID(nullptr);
492 obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID);
493 // Convert Parameter
494 jdbc::LocalRef< jstring > str( t.env(),convertwchar_tToJavaString(t.pEnv,sql));
496 jobject out = t.pEnv->CallObjectMethod( object, mID, str.get() );
497 aStr = JavaString2String(t.pEnv, static_cast<jstring>(out) );
498 ThrowLoggedSQLException( m_aLogger, t.pEnv, *this );
499 } //t.pEnv
501 m_aLogger.log( LogLevel::FINER, STR_LOG_NATIVE_SQL, sql, aStr );
503 return aStr;
506 void SAL_CALL java_sql_Connection::clearWarnings( )
508 static jmethodID mID(nullptr);
509 callVoidMethod_ThrowSQL("clearWarnings", mID);
512 Any SAL_CALL java_sql_Connection::getWarnings( )
514 ::osl::MutexGuard aGuard( m_aMutex );
515 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
517 SDBThreadAttach t;
518 static jmethodID mID(nullptr);
519 jobject out = callObjectMethod(t.pEnv,"getWarnings","()Ljava/sql/SQLWarning;", mID);
520 // WARNING: the caller becomes the owner of the returned pointer
521 if( out )
523 java_sql_SQLWarning_BASE warn_base(t.pEnv, out);
524 SQLException aAsException( java_sql_SQLWarning( warn_base, *this ) );
526 // translate to warning
527 SQLWarning aWarning;
528 aWarning.Context = aAsException.Context;
529 aWarning.Message = aAsException.Message;
530 aWarning.SQLState = aAsException.SQLState;
531 aWarning.ErrorCode = aAsException.ErrorCode;
532 aWarning.NextException = aAsException.NextException;
534 return Any( aWarning );
537 return Any();
541 namespace
543 OUString lcl_getDriverLoadErrorMessage( const ::connectivity::SharedResources& _aResource,const OUString& _rDriverClass, const OUString& _rDriverClassPath )
545 OUString sError1( _aResource.getResourceStringWithSubstitution(
546 STR_NO_CLASSNAME,
547 "$classname$", _rDriverClass
548 ) );
549 if ( !_rDriverClassPath.isEmpty() )
551 const OUString sError2( _aResource.getResourceStringWithSubstitution(
552 STR_NO_CLASSNAME_PATH,
553 "$classpath$", _rDriverClassPath
554 ) );
555 sError1 += sError2;
556 } // if ( _rDriverClassPath.getLength() )
557 return sError1;
562 namespace
564 bool lcl_setSystemProperties_nothrow( const java::sql::ConnectionLog& _rLogger,
565 JNIEnv& _rEnv, const Sequence< NamedValue >& _rSystemProperties )
567 if ( !_rSystemProperties.hasElements() )
568 // nothing to do
569 return true;
571 LocalRef< jclass > systemClass( _rEnv );
572 jmethodID nSetPropertyMethodID = nullptr;
573 // retrieve the java.lang.System class
574 systemClass.set( _rEnv.FindClass( "java/lang/System" ) );
575 if ( systemClass.is() )
577 nSetPropertyMethodID = _rEnv.GetStaticMethodID(
578 systemClass.get(), "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;" );
581 if ( nSetPropertyMethodID == nullptr )
582 return false;
584 for ( auto const & systemProp : _rSystemProperties )
586 OUString sValue;
587 OSL_VERIFY( systemProp.Value >>= sValue );
589 _rLogger.log( LogLevel::FINER, STR_LOG_SETTING_SYSTEM_PROPERTY, systemProp.Name, sValue );
591 LocalRef< jstring > jName( _rEnv, convertwchar_tToJavaString( &_rEnv, systemProp.Name ) );
592 LocalRef< jstring > jValue( _rEnv, convertwchar_tToJavaString( &_rEnv, sValue ) );
594 _rEnv.CallStaticObjectMethod( systemClass.get(), nSetPropertyMethodID, jName.get(), jValue.get() );
595 LocalRef< jthrowable > throwable( _rEnv, _rEnv.ExceptionOccurred() );
596 if ( throwable.is() )
597 return false;
600 return true;
605 void java_sql_Connection::loadDriverFromProperties( const OUString& _sDriverClass, const OUString& _sDriverClassPath,
606 const Sequence< NamedValue >& _rSystemProperties )
608 // first try if the jdbc driver is already registered at the driver manager
609 SDBThreadAttach t;
612 if ( !object )
614 if ( !lcl_setSystemProperties_nothrow( getLogger(), *t.pEnv, _rSystemProperties ) )
615 ThrowLoggedSQLException( getLogger(), t.pEnv, *this );
617 m_pDriverClassLoader.reset();
619 // here I try to find the class for jdbc driver
620 java_sql_SQLException_BASE::st_getMyClass();
621 java_lang_Throwable::st_getMyClass();
623 if ( _sDriverClass.isEmpty() )
625 m_aLogger.log( LogLevel::SEVERE, STR_LOG_NO_DRIVER_CLASS );
626 ::dbtools::throwGenericSQLException(
627 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass, _sDriverClassPath ),
628 *this
631 else
633 m_aLogger.log( LogLevel::INFO, STR_LOG_LOADING_DRIVER, _sDriverClass );
634 // the driver manager holds the class of the driver for later use
635 std::unique_ptr< java_lang_Class > pDrvClass;
636 if ( _sDriverClassPath.isEmpty() )
638 // if forName didn't find the class it will throw an exception
639 pDrvClass.reset(java_lang_Class::forName(_sDriverClass));
641 else
643 LocalRef< jclass > driverClass(t.env());
644 LocalRef< jobject > driverClassLoader(t.env());
646 loadClass(
647 m_pDriver->getContext(),
648 t.env(), _sDriverClassPath, _sDriverClass, &driverClassLoader, &driverClass );
650 m_pDriverClassLoader.set( driverClassLoader );
651 pDrvClass.reset( new java_lang_Class( t.pEnv, driverClass.release() ) );
653 ThrowLoggedSQLException( m_aLogger, t.pEnv, *this );
655 if (pDrvClass)
657 LocalRef< jobject > driverObject( t.env() );
658 driverObject.set( pDrvClass->newInstanceObject() );
659 ThrowLoggedSQLException( m_aLogger, t.pEnv, *this );
660 m_pDriverobject = driverObject.release();
662 if( m_pDriverobject )
663 m_pDriverobject = t.pEnv->NewGlobalRef( m_pDriverobject );
666 jclass tempClass = t.pEnv->GetObjectClass(m_pDriverobject);
667 if ( m_pDriverobject )
669 m_Driver_theClass = static_cast<jclass>(t.pEnv->NewGlobalRef( tempClass ));
670 t.pEnv->DeleteLocalRef( tempClass );
674 m_aLogger.log( LogLevel::INFO, STR_LOG_CONN_SUCCESS );
678 catch( const SQLException& )
680 css::uno::Any anyEx = cppu::getCaughtException();
681 throw SQLException(
682 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass, _sDriverClassPath ),
683 *this,
684 OUString(),
685 1000,
686 anyEx);
688 catch( Exception& )
690 css::uno::Any anyEx = cppu::getCaughtException();
691 ::dbtools::throwGenericSQLException(
692 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass, _sDriverClassPath ),
693 *this,
694 anyEx
699 OUString java_sql_Connection::impl_getJavaDriverClassPath_nothrow(const OUString& _sDriverClass)
701 static constexpr OUStringLiteral s_sNodeName
702 = u"org.openoffice.Office.DataAccess/JDBC/DriverClassPaths";
703 ::utl::OConfigurationTreeRoot aNamesRoot = ::utl::OConfigurationTreeRoot::createWithComponentContext(
704 m_pDriver->getContext(), s_sNodeName, -1, ::utl::OConfigurationTreeRoot::CM_READONLY);
705 OUString sURL;
706 if ( aNamesRoot.isValid() && aNamesRoot.hasByName( _sDriverClass ) )
708 ::utl::OConfigurationNode aRegisterObj = aNamesRoot.openNode( _sDriverClass );
709 OSL_VERIFY( aRegisterObj.getNodeValue( "Path" ) >>= sURL );
711 return sURL;
714 bool java_sql_Connection::construct(const OUString& url,
715 const Sequence< PropertyValue >& info)
717 { // initialize the java vm
718 ::rtl::Reference< jvmaccess::VirtualMachine > xTest = java_lang_Object::getVM(m_xContext);
719 if ( !xTest.is() )
720 throwGenericSQLException(STR_NO_JAVA,*this);
722 SDBThreadAttach t;
723 SDBThreadAttach::addRef(); // will be released in dtor
724 if ( !t.pEnv )
725 throwGenericSQLException(STR_NO_JAVA,*this);
727 OUString sGeneratedValueStatement; // contains the statement which should be used when query for automatically generated values
728 bool bAutoRetrievingEnabled = false; // set to <TRUE/> when we should allow to query for generated values
729 OUString sDriverClassPath,sDriverClass;
730 Sequence< NamedValue > aSystemProperties;
732 ::comphelper::NamedValueCollection aSettings( info );
733 sDriverClass = aSettings.getOrDefault( "JavaDriverClass", sDriverClass );
734 sDriverClassPath = aSettings.getOrDefault( "JavaDriverClassPath", sDriverClassPath);
735 if ( sDriverClassPath.isEmpty() )
736 sDriverClassPath = impl_getJavaDriverClassPath_nothrow(sDriverClass);
737 bAutoRetrievingEnabled = aSettings.getOrDefault( "IsAutoRetrievingEnabled", bAutoRetrievingEnabled );
738 sGeneratedValueStatement = aSettings.getOrDefault( "AutoRetrievingStatement", sGeneratedValueStatement );
739 m_bIgnoreDriverPrivileges = aSettings.getOrDefault( "IgnoreDriverPrivileges", m_bIgnoreDriverPrivileges );
740 m_bIgnoreCurrency = aSettings.getOrDefault( "IgnoreCurrency", m_bIgnoreCurrency );
741 aSystemProperties = aSettings.getOrDefault( "SystemProperties", aSystemProperties );
742 m_aCatalogRestriction = aSettings.getOrDefault( "ImplicitCatalogRestriction", Any() );
743 m_aSchemaRestriction = aSettings.getOrDefault( "ImplicitSchemaRestriction", Any() );
745 loadDriverFromProperties( sDriverClass, sDriverClassPath, aSystemProperties );
747 enableAutoRetrievingEnabled(bAutoRetrievingEnabled);
748 setAutoRetrievingStatement(sGeneratedValueStatement);
750 if ( t.pEnv && m_Driver_theClass && m_pDriverobject )
752 // Java-Call
753 static const char * const cSignature = "(Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection;";
754 static const char * const cMethodName = "connect";
755 jmethodID mID = t.pEnv->GetMethodID( m_Driver_theClass, cMethodName, cSignature );
757 if ( mID )
759 jvalue args[2];
760 // convert Parameter
761 args[0].l = convertwchar_tToJavaString(t.pEnv,url);
762 std::unique_ptr<java_util_Properties> pProps = createStringPropertyArray(info);
763 args[1].l = pProps->getJavaObject();
765 LocalRef< jobject > ensureDelete( t.env(), args[0].l );
767 jobject out = nullptr;
768 // In some cases (e.g.,
769 // connectivity/source/drivers/hsqldb/HDriver.cxx:1.24
770 // l. 249) the JavaDriverClassPath contains multiple jars,
771 // as creating the JavaDriverClass instance requires
772 // (reflective) access to those other jars. Now, if the
773 // JavaDriverClass is actually loaded by some parent class
774 // loader (e.g., because its jar is also on the global
775 // class path), it would still not have access to the
776 // additional jars on the JavaDriverClassPath. Hence, the
777 // JavaDriverClassPath class loader is pushed as context
778 // class loader around the JavaDriverClass instance
779 // creation:
780 // #i82222# / 2007-10-15
782 ContextClassLoaderScope ccl( t.env(), getDriverClassLoader(), getLogger(), *this );
783 out = t.pEnv->CallObjectMethod( m_pDriverobject, mID, args[0].l,args[1].l );
784 pProps.reset();
785 ThrowLoggedSQLException( m_aLogger, t.pEnv, *this );
788 if ( !out )
789 m_aLogger.log( LogLevel::SEVERE, STR_LOG_NO_SYSTEM_CONNECTION );
791 if ( out )
792 object = t.pEnv->NewGlobalRef( out );
794 if ( object )
795 m_aLogger.log( LogLevel::INFO, STR_LOG_GOT_JDBC_CONNECTION, url );
797 m_aConnectionInfo = info;
798 } //mID
799 } //t.pEnv
800 return object != nullptr;
804 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */