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>
49 using namespace connectivity
;
50 using namespace connectivity::jdbc
;
51 using namespace ::com::sun::star::uno
;
52 using namespace ::com::sun::star::beans
;
53 using namespace ::com::sun::star::sdbc
;
54 using namespace ::com::sun::star::container
;
55 using namespace ::com::sun::star::lang
;
59 struct ClassMapEntry
{
61 OUString
const & theClassPath
, OUString
const & theClassName
):
62 classPath(theClassPath
), className(theClassName
), classLoader(nullptr),
63 classObject(nullptr) {}
71 typedef std::vector
< ClassMapEntry
> ClassMap
;
79 template < typename T
>
80 bool getLocalFromWeakRef( jweak
& _weak
, LocalRef
< T
>& _inout_local
)
82 _inout_local
.set( static_cast< T
>( _inout_local
.env().NewLocalRef( _weak
) ) );
84 if ( !_inout_local
.is() )
86 if ( _inout_local
.env().ExceptionCheck())
90 else if ( _weak
!= nullptr )
92 _inout_local
.env().DeleteWeakGlobalRef( _weak
);
99 // Load a class. A map from pairs of (classPath, name) to pairs of weak Java
100 // references to (ClassLoader, Class) is maintained, so that a class is only
103 // It may happen that the weak reference to the ClassLoader becomes null while
104 // the reference to the Class remains non-null (in case the Class was actually
105 // loaded by some parent of the ClassLoader), in which case the ClassLoader is
106 // resurrected (which cannot cause any classes to be loaded multiple times, as
107 // the ClassLoader is no longer reachable, so no classes it has ever loaded are
110 // Similarly, it may happen that the weak reference to the Class becomes null
111 // while the reference to the ClassLoader remains non-null, in which case the
112 // Class is simply re-loaded.
114 // This code is close to the implementation of jvmaccess::ClassPath::loadClass
115 // in jvmaccess/classpath.hxx, but not close enough to avoid the duplication.
117 // If false is returned, a (still pending) JNI exception occurred.
119 Reference
< XComponentContext
> const & context
, JNIEnv
& environment
,
120 OUString
const & classPath
, OUString
const & name
,
121 LocalRef
< jobject
> * classLoaderPtr
, LocalRef
< jclass
> * classPtr
)
123 OSL_ASSERT(classLoaderPtr
!= nullptr);
124 // For any jweak entries still present in the map upon destruction,
125 // DeleteWeakGlobalRef is not called (which is a leak):
126 static ClassMapData classMapData
;
127 osl::MutexGuard
g(classMapData
.mutex
);
128 ClassMap::iterator
i(classMapData
.map
.begin());
129 LocalRef
< jobject
> cloader(environment
);
130 LocalRef
< jclass
> cl(environment
);
131 // Prune dangling weak references from the list while searching for a match,
132 // so that the list cannot grow unbounded:
133 for (; i
!= classMapData
.map
.end();)
135 LocalRef
< jobject
> classLoader( environment
);
136 if ( !getLocalFromWeakRef( i
->classLoader
, classLoader
) )
139 LocalRef
< jclass
> classObject( environment
);
140 if ( !getLocalFromWeakRef( i
->classObject
, classObject
) )
143 if ( !classLoader
.is() && !classObject
.is() )
145 i
= classMapData
.map
.erase(i
);
147 else if ( i
->classPath
== classPath
&& i
->className
== name
)
149 cloader
.set( classLoader
.release() );
150 cl
.set( classObject
.release() );
158 if ( !cloader
.is() || !cl
.is() )
160 if ( i
== classMapData
.map
.end() )
162 // Push a new ClassMapEntry (which can potentially fail) before
163 // loading the class, so that it never happens that a class is
164 // loaded but not added to the map (which could have effects on the
165 // JVM that are not easily undone). If the pushed ClassMapEntry is
166 // not used after all (return false, etc.) it will be pruned on next
167 // call because its classLoader/classObject are null:
168 classMapData
.map
.push_back( ClassMapEntry( classPath
, name
) );
169 i
= std::prev(classMapData
.map
.end());
172 LocalRef
< jclass
> clClass( environment
);
173 clClass
.set( environment
.FindClass( "java/net/URLClassLoader" ) );
177 jweak wcloader
= nullptr;
180 jmethodID
ctorLoader( environment
.GetMethodID( clClass
.get(), "<init>", "([Ljava/net/URL;)V" ) );
181 if (ctorLoader
== nullptr)
184 LocalRef
< jobjectArray
> arr( environment
);
185 arr
.set( jvmaccess::ClassPath::translateToUrls( context
, &environment
, classPath
) );
191 cloader
.set( environment
.NewObjectA( clClass
.get(), ctorLoader
, &arg
) );
195 wcloader
= environment
.NewWeakGlobalRef( cloader
.get() );
196 if ( wcloader
== nullptr )
203 jmethodID
methLoadClass( environment
.GetMethodID( clClass
.get(), "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;" ) );
204 if ( methLoadClass
== nullptr )
207 LocalRef
< jstring
> str( environment
);
208 str
.set( convertwchar_tToJavaString( &environment
, name
) );
214 cl
.set( static_cast< jclass
>( environment
.CallObjectMethodA( cloader
.get(), methLoadClass
, &arg
) ) );
218 wcl
= environment
.NewWeakGlobalRef( cl
.get() );
219 if ( wcl
== nullptr )
223 if ( wcloader
!= nullptr)
225 i
->classLoader
= wcloader
;
227 if ( wcl
!= nullptr )
229 i
->classObject
= wcl
;
233 classLoaderPtr
->set( cloader
.release() );
234 classPtr
->set( cl
.release() );
241 IMPLEMENT_SERVICE_INFO(java_sql_Connection
,"com.sun.star.sdbcx.JConnection","com.sun.star.sdbc.Connection");
244 //************ Class: java.sql.Connection
246 jclass
java_sql_Connection::theClass
= nullptr;
248 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_pDriverClassLoader()
254 ,m_Driver_theClass(nullptr)
255 ,m_aLogger( _rDriver
.getLogger() )
256 ,m_bIgnoreDriverPrivileges(true)
257 ,m_bIgnoreCurrency(false)
261 java_sql_Connection::~java_sql_Connection()
263 ::rtl::Reference
< jvmaccess::VirtualMachine
> xTest
= java_lang_Object::getVM();
268 clearObject(*t
.pEnv
);
271 if ( m_pDriverobject
)
272 t
.pEnv
->DeleteGlobalRef( m_pDriverobject
);
273 m_pDriverobject
= nullptr;
274 if ( m_Driver_theClass
)
275 t
.pEnv
->DeleteGlobalRef( m_Driver_theClass
);
276 m_Driver_theClass
= nullptr;
278 SDBThreadAttach::releaseRef();
281 void java_sql_Connection::disposing()
283 ::osl::MutexGuard
aGuard(m_aMutex
);
285 m_aLogger
.log( LogLevel::INFO
, STR_LOG_SHUTDOWN_CONNECTION
);
287 java_sql_Connection_BASE::disposing();
291 static jmethodID
mID(nullptr);
292 callVoidMethod_ThrowSQL("close", mID
);
296 jclass
java_sql_Connection::getMyClass() const
298 // the class must be fetched only once, therefore static
300 theClass
= findMyClass("java/sql/Connection");
305 OUString SAL_CALL
java_sql_Connection::getCatalog( )
307 ::osl::MutexGuard
aGuard( m_aMutex
);
308 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
310 static jmethodID
mID(nullptr);
311 return callStringMethod("getCatalog",mID
);
314 Reference
< XDatabaseMetaData
> SAL_CALL
java_sql_Connection::getMetaData( )
316 ::osl::MutexGuard
aGuard( m_aMutex
);
317 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
320 Reference
< XDatabaseMetaData
> xMetaData
= m_xMetaData
;
323 SDBThreadAttach t
; OSL_ENSURE(t
.pEnv
,"Java environment has been deleted!");
324 static jmethodID
mID(nullptr);
325 jobject out
= callObjectMethod(t
.pEnv
,"getMetaData","()Ljava/sql/DatabaseMetaData;", mID
);
328 xMetaData
= new java_sql_DatabaseMetaData( t
.pEnv
, out
, *this );
329 m_xMetaData
= xMetaData
;
336 void SAL_CALL
java_sql_Connection::close( )
341 void SAL_CALL
java_sql_Connection::commit( )
343 static jmethodID
mID(nullptr);
344 callVoidMethod_ThrowSQL("commit", mID
);
347 sal_Bool SAL_CALL
java_sql_Connection::isClosed( )
349 ::osl::MutexGuard
aGuard( m_aMutex
);
351 static jmethodID
mID(nullptr);
352 return callBooleanMethod( "isClosed", mID
) && java_sql_Connection_BASE::rBHelper
.bDisposed
;
355 sal_Bool SAL_CALL
java_sql_Connection::isReadOnly( )
357 ::osl::MutexGuard
aGuard( m_aMutex
);
358 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
359 static jmethodID
mID(nullptr);
360 return callBooleanMethod( "isReadOnly", mID
);
363 void SAL_CALL
java_sql_Connection::setCatalog( const OUString
& catalog
)
365 static jmethodID
mID(nullptr);
366 callVoidMethodWithStringArg("setCatalog",mID
,catalog
);
369 void SAL_CALL
java_sql_Connection::rollback( )
371 static jmethodID
mID(nullptr);
372 callVoidMethod_ThrowSQL("rollback", mID
);
375 sal_Bool SAL_CALL
java_sql_Connection::getAutoCommit( )
377 static jmethodID
mID(nullptr);
378 return callBooleanMethod( "getAutoCommit", mID
);
381 void SAL_CALL
java_sql_Connection::setReadOnly( sal_Bool readOnly
)
383 static jmethodID
mID(nullptr);
384 callVoidMethodWithBoolArg_ThrowSQL("setReadOnly", mID
, readOnly
);
387 void SAL_CALL
java_sql_Connection::setAutoCommit( sal_Bool autoCommit
)
389 static jmethodID
mID(nullptr);
390 callVoidMethodWithBoolArg_ThrowSQL("setAutoCommit", mID
, autoCommit
);
393 Reference
< css::container::XNameAccess
> SAL_CALL
java_sql_Connection::getTypeMap( )
395 ::osl::MutexGuard
aGuard( m_aMutex
);
396 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
398 SDBThreadAttach t
; OSL_ENSURE(t
.pEnv
,"Java environment has been deleted!");
399 static jmethodID
mID(nullptr);
400 callObjectMethod(t
.pEnv
,"getTypeMap","()Ljava/util/Map;", mID
);
401 // WARNING: the caller becomes the owner of the returned pointer
405 void SAL_CALL
java_sql_Connection::setTypeMap( const Reference
< css::container::XNameAccess
>& /*typeMap*/ )
407 ::osl::MutexGuard
aGuard( m_aMutex
);
408 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
410 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setTypeMap", *this );
414 sal_Int32 SAL_CALL
java_sql_Connection::getTransactionIsolation( )
416 ::osl::MutexGuard
aGuard( m_aMutex
);
417 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
419 static jmethodID
mID(nullptr);
420 return callIntMethod_ThrowSQL("getTransactionIsolation", mID
);
423 void SAL_CALL
java_sql_Connection::setTransactionIsolation( sal_Int32 level
)
425 ::osl::MutexGuard
aGuard( m_aMutex
);
426 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
428 static jmethodID
mID(nullptr);
429 callVoidMethodWithIntArg_ThrowSQL("setTransactionIsolation", mID
, level
);
432 Reference
< XStatement
> SAL_CALL
java_sql_Connection::createStatement( )
434 ::osl::MutexGuard
aGuard( m_aMutex
);
435 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
436 m_aLogger
.log( LogLevel::FINE
, STR_LOG_CREATE_STATEMENT
);
439 rtl::Reference
<java_sql_Statement
> pStatement
= new java_sql_Statement( t
.pEnv
, *this );
440 Reference
< XStatement
> xStmt
= pStatement
;
441 m_aStatements
.push_back( WeakReferenceHelper( xStmt
) );
443 m_aLogger
.log( LogLevel::FINE
, STR_LOG_CREATED_STATEMENT_ID
, pStatement
->getStatementObjectID() );
447 Reference
< XPreparedStatement
> SAL_CALL
java_sql_Connection::prepareStatement( const OUString
& sql
)
449 ::osl::MutexGuard
aGuard( m_aMutex
);
450 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
451 m_aLogger
.log( LogLevel::FINE
, STR_LOG_PREPARE_STATEMENT
, sql
);
455 rtl::Reference
<java_sql_PreparedStatement
> pStatement
= new java_sql_PreparedStatement( t
.pEnv
, *this, sql
);
456 Reference
< XPreparedStatement
> xReturn( pStatement
);
457 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
459 m_aLogger
.log( LogLevel::FINE
, STR_LOG_PREPARED_STATEMENT_ID
, pStatement
->getStatementObjectID() );
463 Reference
< XPreparedStatement
> SAL_CALL
java_sql_Connection::prepareCall( const OUString
& sql
)
465 ::osl::MutexGuard
aGuard( m_aMutex
);
466 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
467 m_aLogger
.log( LogLevel::FINE
, STR_LOG_PREPARE_CALL
, sql
);
471 rtl::Reference
<java_sql_CallableStatement
> pStatement
= new java_sql_CallableStatement( t
.pEnv
, *this, sql
);
472 Reference
< XPreparedStatement
> xStmt( pStatement
);
473 m_aStatements
.push_back(WeakReferenceHelper(xStmt
));
475 m_aLogger
.log( LogLevel::FINE
, STR_LOG_PREPARED_CALL_ID
, pStatement
->getStatementObjectID() );
479 OUString SAL_CALL
java_sql_Connection::nativeSQL( const OUString
& sql
)
481 ::osl::MutexGuard
aGuard( m_aMutex
);
482 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
485 SDBThreadAttach t
; OSL_ENSURE(t
.pEnv
,"Java environment has been deleted!");
488 // initialize temporary Variable
489 static const char * const cSignature
= "(Ljava/lang/String;)Ljava/lang/String;";
490 static const char * const cMethodName
= "nativeSQL";
492 static jmethodID
mID(nullptr);
493 obtainMethodId_throwSQL(t
.pEnv
, cMethodName
,cSignature
, mID
);
495 jdbc::LocalRef
< jstring
> str( t
.env(),convertwchar_tToJavaString(t
.pEnv
,sql
));
497 jobject out
= t
.pEnv
->CallObjectMethod( object
, mID
, str
.get() );
498 aStr
= JavaString2String(t
.pEnv
, static_cast<jstring
>(out
) );
499 ThrowLoggedSQLException( m_aLogger
, t
.pEnv
, *this );
502 m_aLogger
.log( LogLevel::FINER
, STR_LOG_NATIVE_SQL
, sql
, aStr
);
507 void SAL_CALL
java_sql_Connection::clearWarnings( )
509 static jmethodID
mID(nullptr);
510 callVoidMethod_ThrowSQL("clearWarnings", mID
);
513 Any SAL_CALL
java_sql_Connection::getWarnings( )
515 ::osl::MutexGuard
aGuard( m_aMutex
);
516 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
519 static jmethodID
mID(nullptr);
520 jobject out
= callObjectMethod(t
.pEnv
,"getWarnings","()Ljava/sql/SQLWarning;", mID
);
521 // WARNING: the caller becomes the owner of the returned pointer
524 java_sql_SQLWarning_BASE
warn_base(t
.pEnv
, out
);
525 SQLException
aAsException( java_sql_SQLWarning( warn_base
, *this ) );
527 // translate to warning
529 aWarning
.Context
= aAsException
.Context
;
530 aWarning
.Message
= aAsException
.Message
;
531 aWarning
.SQLState
= aAsException
.SQLState
;
532 aWarning
.ErrorCode
= aAsException
.ErrorCode
;
533 aWarning
.NextException
= aAsException
.NextException
;
535 return makeAny( aWarning
);
544 OUString
lcl_getDriverLoadErrorMessage( const ::connectivity::SharedResources
& _aResource
,const OUString
& _rDriverClass
, const OUString
& _rDriverClassPath
)
546 OUString
sError1( _aResource
.getResourceStringWithSubstitution(
548 "$classname$", _rDriverClass
550 if ( !_rDriverClassPath
.isEmpty() )
552 const OUString
sError2( _aResource
.getResourceStringWithSubstitution(
553 STR_NO_CLASSNAME_PATH
,
554 "$classpath$", _rDriverClassPath
557 } // if ( _rDriverClassPath.getLength() )
565 bool lcl_setSystemProperties_nothrow( const java::sql::ConnectionLog
& _rLogger
,
566 JNIEnv
& _rEnv
, const Sequence
< NamedValue
>& _rSystemProperties
)
568 if ( !_rSystemProperties
.hasElements() )
572 LocalRef
< jclass
> systemClass( _rEnv
);
573 jmethodID nSetPropertyMethodID
= nullptr;
574 // retrieve the java.lang.System class
575 systemClass
.set( _rEnv
.FindClass( "java/lang/System" ) );
576 if ( systemClass
.is() )
578 nSetPropertyMethodID
= _rEnv
.GetStaticMethodID(
579 systemClass
.get(), "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;" );
582 if ( nSetPropertyMethodID
== nullptr )
585 for ( auto const & systemProp
: _rSystemProperties
)
588 OSL_VERIFY( systemProp
.Value
>>= sValue
);
590 _rLogger
.log( LogLevel::FINER
, STR_LOG_SETTING_SYSTEM_PROPERTY
, systemProp
.Name
, sValue
);
592 LocalRef
< jstring
> jName( _rEnv
, convertwchar_tToJavaString( &_rEnv
, systemProp
.Name
) );
593 LocalRef
< jstring
> jValue( _rEnv
, convertwchar_tToJavaString( &_rEnv
, sValue
) );
595 _rEnv
.CallStaticObjectMethod( systemClass
.get(), nSetPropertyMethodID
, jName
.get(), jValue
.get() );
596 LocalRef
< jthrowable
> throwable( _rEnv
, _rEnv
.ExceptionOccurred() );
597 if ( throwable
.is() )
606 void java_sql_Connection::loadDriverFromProperties( const OUString
& _sDriverClass
, const OUString
& _sDriverClassPath
,
607 const Sequence
< NamedValue
>& _rSystemProperties
)
609 // first try if the jdbc driver is already registered at the driver manager
615 if ( !lcl_setSystemProperties_nothrow( getLogger(), *t
.pEnv
, _rSystemProperties
) )
616 ThrowLoggedSQLException( getLogger(), t
.pEnv
, *this );
618 m_pDriverClassLoader
.reset();
620 // here I try to find the class for jdbc driver
621 java_sql_SQLException_BASE::st_getMyClass();
622 java_lang_Throwable::st_getMyClass();
624 if ( _sDriverClass
.isEmpty() )
626 m_aLogger
.log( LogLevel::SEVERE
, STR_LOG_NO_DRIVER_CLASS
);
627 ::dbtools::throwGenericSQLException(
628 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass
, _sDriverClassPath
),
634 m_aLogger
.log( LogLevel::INFO
, STR_LOG_LOADING_DRIVER
, _sDriverClass
);
635 // the driver manager holds the class of the driver for later use
636 std::unique_ptr
< java_lang_Class
> pDrvClass
;
637 if ( _sDriverClassPath
.isEmpty() )
639 // if forName didn't find the class it will throw an exception
640 pDrvClass
.reset(java_lang_Class::forName(_sDriverClass
));
644 LocalRef
< jclass
> driverClass(t
.env());
645 LocalRef
< jobject
> driverClassLoader(t
.env());
648 m_pDriver
->getContext(),
649 t
.env(), _sDriverClassPath
, _sDriverClass
, &driverClassLoader
, &driverClass
);
651 m_pDriverClassLoader
.set( driverClassLoader
);
652 pDrvClass
.reset( new java_lang_Class( t
.pEnv
, driverClass
.release() ) );
654 ThrowLoggedSQLException( m_aLogger
, t
.pEnv
, *this );
658 LocalRef
< jobject
> driverObject( t
.env() );
659 driverObject
.set( pDrvClass
->newInstanceObject() );
660 ThrowLoggedSQLException( m_aLogger
, t
.pEnv
, *this );
661 m_pDriverobject
= driverObject
.release();
663 if( m_pDriverobject
)
664 m_pDriverobject
= t
.pEnv
->NewGlobalRef( m_pDriverobject
);
667 jclass tempClass
= t
.pEnv
->GetObjectClass(m_pDriverobject
);
668 if ( m_pDriverobject
)
670 m_Driver_theClass
= static_cast<jclass
>(t
.pEnv
->NewGlobalRef( tempClass
));
671 t
.pEnv
->DeleteLocalRef( tempClass
);
675 m_aLogger
.log( LogLevel::INFO
, STR_LOG_CONN_SUCCESS
);
679 catch( const SQLException
& )
681 css::uno::Any anyEx
= cppu::getCaughtException();
683 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass
, _sDriverClassPath
),
691 css::uno::Any anyEx
= cppu::getCaughtException();
692 ::dbtools::throwGenericSQLException(
693 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass
, _sDriverClassPath
),
700 OUString
java_sql_Connection::impl_getJavaDriverClassPath_nothrow(const OUString
& _sDriverClass
)
702 static constexpr OUStringLiteral s_sNodeName
703 = u
"org.openoffice.Office.DataAccess/JDBC/DriverClassPaths";
704 ::utl::OConfigurationTreeRoot aNamesRoot
= ::utl::OConfigurationTreeRoot::createWithComponentContext(
705 m_pDriver
->getContext(), s_sNodeName
, -1, ::utl::OConfigurationTreeRoot::CM_READONLY
);
707 if ( aNamesRoot
.isValid() && aNamesRoot
.hasByName( _sDriverClass
) )
709 ::utl::OConfigurationNode aRegisterObj
= aNamesRoot
.openNode( _sDriverClass
);
710 OSL_VERIFY( aRegisterObj
.getNodeValue( "Path" ) >>= sURL
);
715 bool java_sql_Connection::construct(const OUString
& url
,
716 const Sequence
< PropertyValue
>& info
)
718 { // initialize the java vm
719 ::rtl::Reference
< jvmaccess::VirtualMachine
> xTest
= java_lang_Object::getVM(m_xContext
);
721 throwGenericSQLException(STR_NO_JAVA
,*this);
724 SDBThreadAttach::addRef(); // will be released in dtor
726 throwGenericSQLException(STR_NO_JAVA
,*this);
728 OUString sGeneratedValueStatement
; // contains the statement which should be used when query for automatically generated values
729 bool bAutoRetrievingEnabled
= false; // set to <TRUE/> when we should allow to query for generated values
730 OUString sDriverClassPath
,sDriverClass
;
731 Sequence
< NamedValue
> aSystemProperties
;
733 ::comphelper::NamedValueCollection
aSettings( info
);
734 sDriverClass
= aSettings
.getOrDefault( "JavaDriverClass", sDriverClass
);
735 sDriverClassPath
= aSettings
.getOrDefault( "JavaDriverClassPath", sDriverClassPath
);
736 if ( sDriverClassPath
.isEmpty() )
737 sDriverClassPath
= impl_getJavaDriverClassPath_nothrow(sDriverClass
);
738 bAutoRetrievingEnabled
= aSettings
.getOrDefault( "IsAutoRetrievingEnabled", bAutoRetrievingEnabled
);
739 sGeneratedValueStatement
= aSettings
.getOrDefault( "AutoRetrievingStatement", sGeneratedValueStatement
);
740 m_bIgnoreDriverPrivileges
= aSettings
.getOrDefault( "IgnoreDriverPrivileges", m_bIgnoreDriverPrivileges
);
741 m_bIgnoreCurrency
= aSettings
.getOrDefault( "IgnoreCurrency", m_bIgnoreCurrency
);
742 aSystemProperties
= aSettings
.getOrDefault( "SystemProperties", aSystemProperties
);
743 m_aCatalogRestriction
= aSettings
.getOrDefault( "ImplicitCatalogRestriction", Any() );
744 m_aSchemaRestriction
= aSettings
.getOrDefault( "ImplicitSchemaRestriction", Any() );
746 loadDriverFromProperties( sDriverClass
, sDriverClassPath
, aSystemProperties
);
748 enableAutoRetrievingEnabled(bAutoRetrievingEnabled
);
749 setAutoRetrievingStatement(sGeneratedValueStatement
);
751 if ( t
.pEnv
&& m_Driver_theClass
&& m_pDriverobject
)
754 static const char * const cSignature
= "(Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection;";
755 static const char * const cMethodName
= "connect";
756 jmethodID mID
= t
.pEnv
->GetMethodID( m_Driver_theClass
, cMethodName
, cSignature
);
762 args
[0].l
= convertwchar_tToJavaString(t
.pEnv
,url
);
763 std::unique_ptr
<java_util_Properties
> pProps
= createStringPropertyArray(info
);
764 args
[1].l
= pProps
->getJavaObject();
766 LocalRef
< jobject
> ensureDelete( t
.env(), args
[0].l
);
768 jobject out
= nullptr;
769 // In some cases (e.g.,
770 // connectivity/source/drivers/hsqldb/HDriver.cxx:1.24
771 // l. 249) the JavaDriverClassPath contains multiple jars,
772 // as creating the JavaDriverClass instance requires
773 // (reflective) access to those other jars. Now, if the
774 // JavaDriverClass is actually loaded by some parent class
775 // loader (e.g., because its jar is also on the global
776 // class path), it would still not have access to the
777 // additional jars on the JavaDriverClassPath. Hence, the
778 // JavaDriverClassPath class loader is pushed as context
779 // class loader around the JavaDriverClass instance
781 // #i82222# / 2007-10-15
783 ContextClassLoaderScope
ccl( t
.env(), getDriverClassLoader(), getLogger(), *this );
784 out
= t
.pEnv
->CallObjectMethod( m_pDriverobject
, mID
, args
[0].l
,args
[1].l
);
786 ThrowLoggedSQLException( m_aLogger
, t
.pEnv
, *this );
790 m_aLogger
.log( LogLevel::SEVERE
, STR_LOG_NO_SYSTEM_CONNECTION
);
793 object
= t
.pEnv
->NewGlobalRef( out
);
796 m_aLogger
.log( LogLevel::INFO
, STR_LOG_GOT_JDBC_CONNECTION
, url
);
798 m_aConnectionInfo
= info
;
801 return object
!= nullptr;
805 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */