1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
42 #include <strings.hrc>
43 #include <unotools/confignode.hxx>
44 #include <strings.hxx>
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
;
60 struct ClassMapEntry
{
62 OUString theClassPath
, OUString theClassName
):
63 classPath(std::move(theClassPath
)), className(std::move(theClassName
)), classLoader(nullptr),
64 classObject(nullptr) {}
72 typedef std::vector
< ClassMapEntry
> ClassMap
;
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())
91 else if ( _weak
!= nullptr )
93 _inout_local
.env().DeleteWeakGlobalRef( _weak
);
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
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
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.
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
) )
140 LocalRef
< jclass
> classObject( environment
);
141 if ( !getLocalFromWeakRef( i
->classObject
, classObject
) )
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() );
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" ) );
178 jweak wcloader
= nullptr;
181 jmethodID
ctorLoader( environment
.GetMethodID( clClass
.get(), "<init>", "([Ljava/net/URL;)V" ) );
182 if (ctorLoader
== nullptr)
185 LocalRef
< jobjectArray
> arr( environment
);
186 arr
.set( jvmaccess::ClassPath::translateToUrls( context
, &environment
, classPath
) );
192 cloader
.set( environment
.NewObjectA( clClass
.get(), ctorLoader
, &arg
) );
196 wcloader
= environment
.NewWeakGlobalRef( cloader
.get() );
197 if ( wcloader
== nullptr )
204 jmethodID
methLoadClass( environment
.GetMethodID( clClass
.get(), "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;" ) );
205 if ( methLoadClass
== nullptr )
208 LocalRef
< jstring
> str( environment
);
209 str
.set( convertwchar_tToJavaString( &environment
, name
) );
215 cl
.set( static_cast< jclass
>( environment
.CallObjectMethodA( cloader
.get(), methLoadClass
, &arg
) ) );
219 wcl
= environment
.NewWeakGlobalRef( cl
.get() );
220 if ( wcl
== nullptr )
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() );
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();
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();
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
299 theClass
= findMyClass("java/sql/Connection");
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
;
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
);
327 xMetaData
= new java_sql_DatabaseMetaData( t
.pEnv
, out
, *this );
328 m_xMetaData
= xMetaData
;
335 void SAL_CALL
java_sql_Connection::close( )
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
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
);
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() );
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
);
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() );
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
);
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() );
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
);
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";
491 static jmethodID
mID(nullptr);
492 obtainMethodId_throwSQL(t
.pEnv
, cMethodName
,cSignature
, mID
);
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 );
501 m_aLogger
.log( LogLevel::FINER
, STR_LOG_NATIVE_SQL
, sql
, 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
);
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
523 java_sql_SQLWarning_BASE
warn_base(t
.pEnv
, out
);
524 SQLException
aAsException( java_sql_SQLWarning( warn_base
, *this ) );
526 // translate to warning
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
);
543 OUString
lcl_getDriverLoadErrorMessage( const ::connectivity::SharedResources
& _aResource
,const OUString
& _rDriverClass
, const OUString
& _rDriverClassPath
)
545 OUString
sError1( _aResource
.getResourceStringWithSubstitution(
547 "$classname$", _rDriverClass
549 if ( !_rDriverClassPath
.isEmpty() )
551 const OUString
sError2( _aResource
.getResourceStringWithSubstitution(
552 STR_NO_CLASSNAME_PATH
,
553 "$classpath$", _rDriverClassPath
556 } // if ( _rDriverClassPath.getLength() )
564 bool lcl_setSystemProperties_nothrow( const java::sql::ConnectionLog
& _rLogger
,
565 JNIEnv
& _rEnv
, const Sequence
< NamedValue
>& _rSystemProperties
)
567 if ( !_rSystemProperties
.hasElements() )
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 )
584 for ( auto const & systemProp
: _rSystemProperties
)
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() )
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
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
),
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
));
643 LocalRef
< jclass
> driverClass(t
.env());
644 LocalRef
< jobject
> driverClassLoader(t
.env());
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 );
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();
682 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass
, _sDriverClassPath
),
690 css::uno::Any anyEx
= cppu::getCaughtException();
691 ::dbtools::throwGenericSQLException(
692 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass
, _sDriverClassPath
),
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
);
706 if ( aNamesRoot
.isValid() && aNamesRoot
.hasByName( _sDriverClass
) )
708 ::utl::OConfigurationNode aRegisterObj
= aNamesRoot
.openNode( _sDriverClass
);
709 OSL_VERIFY( aRegisterObj
.getNodeValue( "Path" ) >>= 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
);
720 throwGenericSQLException(STR_NO_JAVA
,*this);
723 SDBThreadAttach::addRef(); // will be released in dtor
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
)
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
);
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
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
);
785 ThrowLoggedSQLException( m_aLogger
, t
.pEnv
, *this );
789 m_aLogger
.log( LogLevel::SEVERE
, STR_LOG_NO_SYSTEM_CONNECTION
);
792 object
= t
.pEnv
->NewGlobalRef( out
);
795 m_aLogger
.log( LogLevel::INFO
, STR_LOG_GOT_JDBC_CONNECTION
, url
);
797 m_aConnectionInfo
= info
;
800 return object
!= nullptr;
804 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */