1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: JConnection.cxx,v $
10 * $Revision: 1.13.56.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
34 #include "java/sql/Connection.hxx"
35 #include "java/lang/Class.hxx"
36 #include "java/tools.hxx"
37 #include "java/ContextClassLoader.hxx"
38 #include "java/sql/DatabaseMetaData.hxx"
39 #include "java/sql/JStatement.hxx"
40 #include "java/sql/Driver.hxx"
41 #include "java/sql/PreparedStatement.hxx"
42 #include "java/sql/CallableStatement.hxx"
43 #include "java/sql/SQLWarning.hxx"
44 #include <com/sun/star/lang/DisposedException.hpp>
45 #include <com/sun/star/sdbc/SQLWarning.hpp>
46 #include <com/sun/star/sdbc/SQLWarning.hpp>
47 #include <com/sun/star/beans/NamedValue.hpp>
48 #include "connectivity/sqlparse.hxx"
49 #include "connectivity/dbexception.hxx"
50 #include "java/util/Property.hxx"
51 #include "java/LocalRef.hxx"
52 #include "resource/jdbc_log.hrc"
53 #include "com/sun/star/uno/XComponentContext.hpp"
54 #include "jvmaccess/classpath.hxx"
55 #include <comphelper/namedvaluecollection.hxx>
56 #include <rtl/ustrbuf.hxx>
58 #include "resource/common_res.hrc"
63 using namespace connectivity
;
64 using namespace connectivity::jdbc
;
65 using namespace ::com::sun::star::uno
;
66 using namespace ::com::sun::star::beans
;
67 using namespace ::com::sun::star::sdbc
;
68 using namespace ::com::sun::star::container
;
69 using namespace ::com::sun::star::lang
;
73 struct ClassMapEntry
{
75 rtl::OUString
const & theClassPath
, rtl::OUString
const & theClassName
):
76 classPath(theClassPath
), className(theClassName
), classLoader(NULL
),
79 rtl::OUString classPath
;
80 rtl::OUString className
;
85 typedef std::list
< ClassMapEntry
> ClassMap
;
93 struct ClassMapDataInit
{
94 ClassMapData
* operator()() {
95 static ClassMapData instance
;
100 template < typename T
>
101 bool getLocalFromWeakRef( jweak
& _weak
, LocalRef
< T
>& _inout_local
)
103 _inout_local
.set( static_cast< T
>( _inout_local
.env().NewLocalRef( _weak
) ) );
105 if ( !_inout_local
.is() )
107 if ( _inout_local
.env().ExceptionCheck())
111 else if ( _weak
!= NULL
)
113 _inout_local
.env().DeleteWeakGlobalRef( _weak
);
120 // Load a class. A map from pairs of (classPath, name) to pairs of weak Java
121 // references to (ClassLoader, Class) is maintained, so that a class is only
124 // It may happen that the weak reference to the ClassLoader becomes null while
125 // the reference to the Class remains non-null (in case the Class was actually
126 // loaded by some parent of the ClassLoader), in which case the ClassLoader is
127 // resurrected (which cannot cause any classes to be loaded multiple times, as
128 // the ClassLoader is no longer reachable, so no classes it has ever loaded are
131 // Similarly, it may happen that the weak reference to the Class becomes null
132 // while the reference to the ClassLoader remains non-null, in which case the
133 // Class is simply re-loaded.
135 // This code is close to the implementation of jvmaccess::ClassPath::loadClass
136 // in jvmaccess/classpath.hxx, but not close enough to avoid the duplication.
138 // If false is returned, a (still pending) JNI exception occurred.
140 Reference
< XComponentContext
> const & context
, JNIEnv
& environment
,
141 rtl::OUString
const & classPath
, rtl::OUString
const & name
,
142 LocalRef
< jobject
> * classLoaderPtr
, LocalRef
< jclass
> * classPtr
)
144 OSL_ASSERT(classLoaderPtr
!= NULL
);
145 // For any jweak entries still present in the map upon destruction,
146 // DeleteWeakGlobalRef is not called (which is a leak):
148 rtl_Instance
< ClassMapData
, ClassMapDataInit
, osl::MutexGuard
,
149 osl::GetGlobalMutex
>::create(
150 ClassMapDataInit(), osl::GetGlobalMutex());
151 osl::MutexGuard
g(d
->mutex
);
152 ClassMap::iterator
i(d
->map
.begin());
153 LocalRef
< jobject
> cloader(environment
);
154 LocalRef
< jclass
> cl(environment
);
155 // Prune dangling weak references from the list while searching for a match,
156 // so that the list cannot grow unbounded:
157 for (; i
!= d
->map
.end();)
159 LocalRef
< jobject
> classLoader( environment
);
160 if ( !getLocalFromWeakRef( i
->classLoader
, classLoader
) )
163 LocalRef
< jclass
> classObject( environment
);
164 if ( !getLocalFromWeakRef( i
->classObject
, classObject
) )
167 if ( !classLoader
.is() && !classObject
.is() )
171 else if ( i
->classPath
== classPath
&& i
->className
== name
)
173 cloader
.set( classLoader
.release() );
174 cl
.set( classObject
.release() );
182 if ( !cloader
.is() || !cl
.is() )
184 if ( i
== d
->map
.end() )
186 // Push a new ClassMapEntry (which can potentially fail) before
187 // loading the class, so that it never happens that a class is
188 // loaded but not added to the map (which could have effects on the
189 // JVM that are not easily undone). If the pushed ClassMapEntry is
190 // not used after all (return false, etc.) it will be pruned on next
191 // call because its classLoader/classObject are null:
192 d
->map
.push_front( ClassMapEntry( classPath
, name
) );
196 LocalRef
< jclass
> clClass( environment
);
197 clClass
.set( environment
.FindClass( "java/net/URLClassLoader" ) );
201 jweak wcloader
= NULL
;
204 jmethodID
ctorLoader( environment
.GetMethodID( clClass
.get(), "<init>", "([Ljava/net/URL;)V" ) );
205 if (ctorLoader
== NULL
)
208 LocalRef
< jobjectArray
> arr( environment
);
209 arr
.set( jvmaccess::ClassPath::translateToUrls( context
, &environment
, classPath
) );
215 cloader
.set( environment
.NewObjectA( clClass
.get(), ctorLoader
, &arg
) );
219 wcloader
= environment
.NewWeakGlobalRef( cloader
.get() );
220 if ( wcloader
== NULL
)
227 jmethodID
methLoadClass( environment
.GetMethodID( clClass
.get(), "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;" ) );
228 if ( methLoadClass
== NULL
)
231 LocalRef
< jstring
> str( environment
);
232 str
.set( convertwchar_tToJavaString( &environment
, name
) );
238 cl
.set( static_cast< jclass
>( environment
.CallObjectMethodA( cloader
.get(), methLoadClass
, &arg
) ) );
242 wcl
= environment
.NewWeakGlobalRef( cl
.get() );
247 if ( wcloader
!= NULL
)
249 i
->classLoader
= wcloader
;
253 i
->classObject
= wcl
;
257 classLoaderPtr
->set( cloader
.release() );
258 classPtr
->set( cl
.release() );
264 //------------------------------------------------------------------------------
265 IMPLEMENT_SERVICE_INFO(java_sql_Connection
,"com.sun.star.sdbcx.JConnection","com.sun.star.sdbc.Connection");
266 //------------------------------------------------------------------------------
267 //**************************************************************
268 //************ Class: java.sql.Connection
269 //**************************************************************
270 jclass
java_sql_Connection::theClass
= 0;
272 java_sql_Connection::java_sql_Connection( const java_sql_Driver
& _rDriver
)
273 :java_lang_Object( _rDriver
.getContext().getLegacyServiceFactory() )
274 ,OSubComponent
<java_sql_Connection
, java_sql_Connection_BASE
>((::cppu::OWeakObject
*)(&_rDriver
), this)
275 ,m_pDriver( &_rDriver
)
276 ,m_pDriverobject(NULL
)
277 ,m_pDriverClassLoader()
278 ,m_Driver_theClass(NULL
)
279 ,m_aLogger( _rDriver
.getLogger() )
280 ,m_bParameterSubstitution(sal_False
)
281 ,m_bIgnoreDriverPrivileges(sal_True
)
282 ,m_bIgnoreCurrency(sal_False
)
285 // -----------------------------------------------------------------------------
286 java_sql_Connection::~java_sql_Connection()
288 ::rtl::Reference
< jvmaccess::VirtualMachine
> xTest
= java_lang_Object::getVM();
292 clearObject(*t
.pEnv
);
295 if ( m_pDriverobject
)
296 t
.pEnv
->DeleteGlobalRef( m_pDriverobject
);
297 m_pDriverobject
= NULL
;
298 if ( m_Driver_theClass
)
299 t
.pEnv
->DeleteGlobalRef( m_Driver_theClass
);
300 m_Driver_theClass
= NULL
;
305 //-----------------------------------------------------------------------------
306 void SAL_CALL
java_sql_Connection::release() throw()
310 //------------------------------------------------------------------------------
311 void java_sql_Connection::disposing()
313 ::osl::MutexGuard
aGuard(m_aMutex
);
315 m_aLogger
.log( LogLevel::INFO
, STR_LOG_SHUTDOWN_CONNECTION
);
318 java_sql_Connection_BASE::disposing();
322 static jmethodID
mID(NULL
);
323 callVoidMethod("close",mID
);
326 // -------------------------------------------------------------------------
327 jclass
java_sql_Connection::getMyClass() const
329 // die Klasse muss nur einmal geholt werden, daher statisch
331 theClass
= findMyClass("java/sql/Connection");
335 // -------------------------------------------------------------------------
336 ::rtl::OUString SAL_CALL
java_sql_Connection::getCatalog( ) throw(SQLException
, RuntimeException
)
338 ::osl::MutexGuard
aGuard( m_aMutex
);
339 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
341 static jmethodID
mID(NULL
);
342 return callStringMethod("getCatalog",mID
);
344 // -------------------------------------------------------------------------
345 Reference
< XDatabaseMetaData
> SAL_CALL
java_sql_Connection::getMetaData( ) throw(SQLException
, RuntimeException
)
347 ::osl::MutexGuard
aGuard( m_aMutex
);
348 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
351 Reference
< XDatabaseMetaData
> xMetaData
= m_xMetaData
;
354 SDBThreadAttach t
; OSL_ENSURE(t
.pEnv
,"Java Enviroment geloescht worden!");
355 static jmethodID
mID(NULL
);
356 jobject out
= callObjectMethod(t
.pEnv
,"getMetaData","()Ljava/sql/DatabaseMetaData;", mID
);
359 xMetaData
= new java_sql_DatabaseMetaData( t
.pEnv
, out
, *this );
360 m_xMetaData
= xMetaData
;
366 // -------------------------------------------------------------------------
367 void SAL_CALL
java_sql_Connection::close( ) throw(SQLException
, RuntimeException
)
371 // -------------------------------------------------------------------------
372 void SAL_CALL
java_sql_Connection::commit( ) throw(SQLException
, RuntimeException
)
374 static jmethodID
mID(NULL
);
375 callVoidMethod("commit",mID
);
377 // -------------------------------------------------------------------------
378 sal_Bool SAL_CALL
java_sql_Connection::isClosed( ) throw(SQLException
, RuntimeException
)
380 ::osl::MutexGuard
aGuard( m_aMutex
);
382 static jmethodID
mID(NULL
);
383 return callBooleanMethod( "isClosed", mID
) && java_sql_Connection_BASE::rBHelper
.bDisposed
;
385 // -------------------------------------------------------------------------
386 sal_Bool SAL_CALL
java_sql_Connection::isReadOnly( ) throw(SQLException
, RuntimeException
)
388 ::osl::MutexGuard
aGuard( m_aMutex
);
389 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
390 static jmethodID
mID(NULL
);
391 return callBooleanMethod( "isReadOnly", mID
);
393 // -------------------------------------------------------------------------
394 void SAL_CALL
java_sql_Connection::setCatalog( const ::rtl::OUString
& catalog
) throw(SQLException
, RuntimeException
)
396 static jmethodID
mID(NULL
);
397 callVoidMethodWithStringArg("setCatalog",mID
,catalog
);
399 // -------------------------------------------------------------------------
400 void SAL_CALL
java_sql_Connection::rollback( ) throw(SQLException
, RuntimeException
)
402 static jmethodID
mID(NULL
);
403 callVoidMethod("rollback",mID
);
405 // -------------------------------------------------------------------------
406 sal_Bool SAL_CALL
java_sql_Connection::getAutoCommit( ) throw(SQLException
, RuntimeException
)
408 static jmethodID
mID(NULL
);
409 return callBooleanMethod( "getAutoCommit", mID
);
411 // -------------------------------------------------------------------------
412 void SAL_CALL
java_sql_Connection::setReadOnly( sal_Bool readOnly
) throw(SQLException
, RuntimeException
)
414 static jmethodID
mID(NULL
);
415 callVoidMethodWithBoolArg("setReadOnly",mID
,readOnly
);
417 // -------------------------------------------------------------------------
418 void SAL_CALL
java_sql_Connection::setAutoCommit( sal_Bool autoCommit
) throw(SQLException
, RuntimeException
)
420 static jmethodID
mID(NULL
);
421 callVoidMethodWithBoolArg("setAutoCommit",mID
,autoCommit
);
423 // -------------------------------------------------------------------------
424 Reference
< ::com::sun::star::container::XNameAccess
> SAL_CALL
java_sql_Connection::getTypeMap( ) throw(SQLException
, RuntimeException
)
426 ::osl::MutexGuard
aGuard( m_aMutex
);
427 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
429 SDBThreadAttach t
; OSL_ENSURE(t
.pEnv
,"Java Enviroment geloescht worden!");
430 static jmethodID
mID(NULL
);
431 /*jobject out = */callObjectMethod(t
.pEnv
,"getTypeMap","()Ljava/util/Map;", mID
);
432 // ACHTUNG: der Aufrufer wird Eigentuemer des zurueckgelieferten Zeigers !!!
433 return 0;// ? 0 : Map2XNameAccess( t.pEnv, out );
435 // -------------------------------------------------------------------------
436 void SAL_CALL
java_sql_Connection::setTypeMap( const Reference
< ::com::sun::star::container::XNameAccess
>& /*typeMap*/ ) throw(SQLException
, RuntimeException
)
438 ::osl::MutexGuard
aGuard( m_aMutex
);
439 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
441 ::dbtools::throwFeatureNotImplementedException( "XConnection::setTypeMap", *this );
444 // -------------------------------------------------------------------------
445 sal_Int32 SAL_CALL
java_sql_Connection::getTransactionIsolation( ) throw(SQLException
, RuntimeException
)
447 ::osl::MutexGuard
aGuard( m_aMutex
);
448 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
450 static jmethodID
mID(NULL
);
451 return callIntMethod("getTransactionIsolation",mID
);
453 // -------------------------------------------------------------------------
454 void SAL_CALL
java_sql_Connection::setTransactionIsolation( sal_Int32 level
) throw(SQLException
, RuntimeException
)
456 ::osl::MutexGuard
aGuard( m_aMutex
);
457 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
459 static jmethodID
mID(NULL
);
460 callVoidMethodWithIntArg("setTransactionIsolation",mID
,level
);
462 // -------------------------------------------------------------------------
463 Reference
< XStatement
> SAL_CALL
java_sql_Connection::createStatement( ) throw(SQLException
, RuntimeException
)
465 ::osl::MutexGuard
aGuard( m_aMutex
);
466 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
467 m_aLogger
.log( LogLevel::FINE
, STR_LOG_CREATE_STATEMENT
);
470 java_sql_Statement
* pStatement
= new java_sql_Statement( t
.pEnv
, *this );
471 Reference
< XStatement
> xStmt
= pStatement
;
472 m_aStatements
.push_back( WeakReferenceHelper( xStmt
) );
474 m_aLogger
.log( LogLevel::FINE
, STR_LOG_CREATED_STATEMENT_ID
, pStatement
->getStatementObjectID() );
477 // -----------------------------------------------------------------------------
478 ::rtl::OUString
java_sql_Connection::transFormPreparedStatement(const ::rtl::OUString
& _sSQL
)
480 ::rtl::OUString sSqlStatement
= _sSQL
;
481 if ( m_bParameterSubstitution
)
485 OSQLParser
aParser( m_pDriver
->getContext().getLegacyServiceFactory() );
486 ::rtl::OUString sErrorMessage
;
487 ::rtl::OUString sNewSql
;
488 OSQLParseNode
* pNode
= aParser
.parseTree(sErrorMessage
,_sSQL
);
490 { // special handling for parameters
491 OSQLParseNode::substituteParameterNames(pNode
);
492 pNode
->parseNodeToStr( sNewSql
, this );
494 sSqlStatement
= sNewSql
;
497 catch(const Exception
&)
501 return sSqlStatement
;
503 // -------------------------------------------------------------------------
504 Reference
< XPreparedStatement
> SAL_CALL
java_sql_Connection::prepareStatement( const ::rtl::OUString
& sql
) throw(SQLException
, RuntimeException
)
506 ::osl::MutexGuard
aGuard( m_aMutex
);
507 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
508 m_aLogger
.log( LogLevel::FINE
, STR_LOG_PREPARE_STATEMENT
, sql
);
511 ::rtl::OUString sSqlStatement
= sql
;
512 sSqlStatement
= transFormPreparedStatement( sSqlStatement
);
514 java_sql_PreparedStatement
* pStatement
= new java_sql_PreparedStatement( t
.pEnv
, *this, sSqlStatement
);
515 Reference
< XPreparedStatement
> xReturn( pStatement
);
516 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
518 m_aLogger
.log( LogLevel::FINE
, STR_LOG_PREPARED_STATEMENT_ID
, pStatement
->getStatementObjectID() );
521 // -------------------------------------------------------------------------
522 Reference
< XPreparedStatement
> SAL_CALL
java_sql_Connection::prepareCall( const ::rtl::OUString
& sql
) throw(SQLException
, RuntimeException
)
524 ::osl::MutexGuard
aGuard( m_aMutex
);
525 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
526 m_aLogger
.log( LogLevel::FINE
, STR_LOG_PREPARE_CALL
, sql
);
529 ::rtl::OUString sSqlStatement
= sql
;
530 sSqlStatement
= transFormPreparedStatement( sSqlStatement
);
532 java_sql_CallableStatement
* pStatement
= new java_sql_CallableStatement( t
.pEnv
, *this, sSqlStatement
);
533 Reference
< XPreparedStatement
> xStmt( pStatement
);
534 m_aStatements
.push_back(WeakReferenceHelper(xStmt
));
536 m_aLogger
.log( LogLevel::FINE
, STR_LOG_PREPARED_CALL_ID
, pStatement
->getStatementObjectID() );
539 // -------------------------------------------------------------------------
540 ::rtl::OUString SAL_CALL
java_sql_Connection::nativeSQL( const ::rtl::OUString
& sql
) throw(SQLException
, RuntimeException
)
542 ::osl::MutexGuard
aGuard( m_aMutex
);
543 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
545 ::rtl::OUString aStr
;
546 SDBThreadAttach t
; OSL_ENSURE(t
.pEnv
,"Java Enviroment geloescht worden!");
549 // temporaere Variable initialisieren
550 static const char * cSignature
= "(Ljava/lang/String;)Ljava/lang/String;";
551 static const char * cMethodName
= "nativeSQL";
552 // Java-Call absetzen
553 static jmethodID
mID(NULL
);
554 obtainMethodId(t
.pEnv
, cMethodName
,cSignature
, mID
);
555 // Parameter konvertieren
556 jstring str
= convertwchar_tToJavaString(t
.pEnv
,sql
);
558 jobject out
= t
.pEnv
->CallObjectMethod( object
, mID
, str
);
559 t
.pEnv
->DeleteLocalRef(str
);
560 aStr
= JavaString2String(t
.pEnv
, (jstring
)out
);
561 ThrowLoggedSQLException( m_aLogger
, t
.pEnv
, *this );
564 m_aLogger
.log( LogLevel::FINER
, STR_LOG_NATIVE_SQL
, sql
, aStr
);
568 // -------------------------------------------------------------------------
569 void SAL_CALL
java_sql_Connection::clearWarnings( ) throw(SQLException
, RuntimeException
)
571 static jmethodID
mID(NULL
);
572 callVoidMethod("clearWarnings",mID
);
574 // -------------------------------------------------------------------------
575 Any SAL_CALL
java_sql_Connection::getWarnings( ) throw(SQLException
, RuntimeException
)
577 ::osl::MutexGuard
aGuard( m_aMutex
);
578 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
581 static jmethodID
mID(NULL
);
582 jobject out
= callObjectMethod(t
.pEnv
,"getWarnings","()Ljava/sql/SQLWarning;", mID
);
583 // ACHTUNG: der Aufrufer wird Eigentuemer des zurueckgelieferten Zeigers !!!
586 java_sql_SQLWarning_BASE
warn_base(t
.pEnv
, out
);
587 SQLException
aAsException( static_cast< starsdbc::SQLException
>( java_sql_SQLWarning( warn_base
, *this ) ) );
589 // translate to warning
591 aWarning
.Context
= aAsException
.Context
;
592 aWarning
.Message
= aAsException
.Message
;
593 aWarning
.SQLState
= aAsException
.SQLState
;
594 aWarning
.ErrorCode
= aAsException
.ErrorCode
;
595 aWarning
.NextException
= aAsException
.NextException
;
597 return makeAny( aWarning
);
603 // -----------------------------------------------------------------------------
606 ::rtl::OUString
lcl_getDriverLoadErrorMessage( const ::connectivity::SharedResources
& _aResource
,const ::rtl::OUString
& _rDriverClass
, const ::rtl::OUString
& _rDriverClassPath
)
608 ::rtl::OUString
sError1( _aResource
.getResourceStringWithSubstitution(
610 "$classname$", _rDriverClass
612 if ( _rDriverClassPath
.getLength() )
614 const ::rtl::OUString
sError2( _aResource
.getResourceStringWithSubstitution(
615 STR_NO_CLASSNAME_PATH
,
616 "$classpath$", _rDriverClassPath
619 } // if ( _rDriverClassPath.getLength() )
624 // -----------------------------------------------------------------------------
627 bool lcl_setSystemProperties_nothrow( const java::sql::ConnectionLog
& _rLogger
,
628 JNIEnv
& _rEnv
, const Sequence
< NamedValue
>& _rSystemProperties
)
630 if ( _rSystemProperties
.getLength() == 0 )
634 LocalRef
< jclass
> systemClass( _rEnv
);
635 jmethodID nSetPropertyMethodID
= 0;
636 // retrieve the java.lang.System class
637 systemClass
.set( _rEnv
.FindClass( "java/lang/System" ) );
638 if ( systemClass
.is() )
640 nSetPropertyMethodID
= _rEnv
.GetStaticMethodID(
641 systemClass
.get(), "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;" );
644 if ( nSetPropertyMethodID
== 0 )
647 for ( const NamedValue
* pSystemProp
= _rSystemProperties
.getConstArray();
648 pSystemProp
!= _rSystemProperties
.getConstArray() + _rSystemProperties
.getLength();
652 ::rtl::OUString sValue
;
653 OSL_VERIFY( pSystemProp
->Value
>>= sValue
);
655 _rLogger
.log( LogLevel::FINER
, STR_LOG_SETTING_SYSTEM_PROPERTY
, pSystemProp
->Name
, sValue
);
657 LocalRef
< jstring
> jName( _rEnv
, convertwchar_tToJavaString( &_rEnv
, pSystemProp
->Name
) );
658 LocalRef
< jstring
> jValue( _rEnv
, convertwchar_tToJavaString( &_rEnv
, sValue
) );
660 _rEnv
.CallStaticObjectMethod( systemClass
.get(), nSetPropertyMethodID
, jName
.get(), jValue
.get() );
661 LocalRef
< jthrowable
> throwable( _rEnv
, _rEnv
.ExceptionOccurred() );
662 if ( throwable
.is() )
670 // -----------------------------------------------------------------------------
671 void java_sql_Connection::loadDriverFromProperties( const ::rtl::OUString
& _sDriverClass
, const ::rtl::OUString
& _sDriverClassPath
,
672 const Sequence
< NamedValue
>& _rSystemProperties
)
674 // contains the statement which should be used when query for automatically generated values
675 ::rtl::OUString sGeneratedValueStatement
;
676 // set to <TRUE/> when we should allow to query for generated values
677 sal_Bool bAutoRetrievingEnabled
= sal_False
;
679 // first try if the jdbc driver is alraedy registered at the driver manager
685 if ( !lcl_setSystemProperties_nothrow( getLogger(), *t
.pEnv
, _rSystemProperties
) )
686 ThrowLoggedSQLException( getLogger(), t
.pEnv
, *this );
688 m_pDriverClassLoader
.reset();
690 // here I try to find the class for jdbc driver
691 java_sql_SQLException_BASE::st_getMyClass();
692 java_lang_Throwable::st_getMyClass();
694 if ( !_sDriverClass
.getLength() )
696 m_aLogger
.log( LogLevel::SEVERE
, STR_LOG_NO_DRIVER_CLASS
);
697 ::dbtools::throwGenericSQLException(
698 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass
, _sDriverClassPath
),
704 m_aLogger
.log( LogLevel::INFO
, STR_LOG_LOADING_DRIVER
, _sDriverClass
);
705 // the driver manager holds the class of the driver for later use
706 ::std::auto_ptr
< java_lang_Class
> pDrvClass
;
707 if ( !_sDriverClassPath
.getLength() )
709 // if forName didn't find the class it will throw an exception
710 pDrvClass
= ::std::auto_ptr
< java_lang_Class
>(java_lang_Class::forName(_sDriverClass
));
714 LocalRef
< jclass
> driverClass(t
.env());
715 LocalRef
< jobject
> driverClassLoader(t
.env());
718 m_pDriver
->getContext().getUNOContext(),
719 t
.env(), _sDriverClassPath
, _sDriverClass
, &driverClassLoader
, &driverClass
);
721 m_pDriverClassLoader
.set( driverClassLoader
);
722 pDrvClass
.reset( new java_lang_Class( t
.pEnv
, driverClass
.release() ) );
724 ThrowLoggedSQLException( m_aLogger
, t
.pEnv
, *this );
726 if ( pDrvClass
.get() )
728 LocalRef
< jobject
> driverObject( t
.env() );
729 driverObject
.set( pDrvClass
->newInstanceObject() );
730 ThrowLoggedSQLException( m_aLogger
, t
.pEnv
, *this );
731 m_pDriverobject
= driverObject
.release();
733 if( t
.pEnv
&& m_pDriverobject
)
734 m_pDriverobject
= t
.pEnv
->NewGlobalRef( m_pDriverobject
);
737 jclass tempClass
= t
.pEnv
->GetObjectClass(m_pDriverobject
);
738 if ( m_pDriverobject
)
740 m_Driver_theClass
= (jclass
)t
.pEnv
->NewGlobalRef( tempClass
);
741 t
.pEnv
->DeleteLocalRef( tempClass
);
745 m_aLogger
.log( LogLevel::INFO
, STR_LOG_CONN_SUCCESS
);
749 catch( const SQLException
& e
)
752 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass
, _sDriverClassPath
),
761 ::dbtools::throwGenericSQLException(
762 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass
, _sDriverClassPath
),
767 enableAutoRetrievingEnabled( bAutoRetrievingEnabled
);
768 setAutoRetrievingStatement( sGeneratedValueStatement
);
771 // -----------------------------------------------------------------------------
772 sal_Bool
java_sql_Connection::construct(const ::rtl::OUString
& url
,
773 const Sequence
< PropertyValue
>& info
)
775 { // initialize the java vm
776 ::rtl::Reference
< jvmaccess::VirtualMachine
> xTest
= java_lang_Object::getVM(getORB());
778 throwGenericSQLException(STR_NO_JAVA
,*this);
781 t
.addRef(); // will be released in dtor
783 throwGenericSQLException(STR_NO_JAVA
,*this);
785 ::rtl::OUString sGeneratedValueStatement
; // contains the statement which should be used when query for automatically generated values
786 sal_Bool bAutoRetrievingEnabled
= sal_False
; // set to <TRUE/> when we should allow to query for generated values
787 ::rtl::OUString sDriverClassPath
,sDriverClass
;
788 Sequence
< NamedValue
> aSystemProperties
;
790 ::comphelper::NamedValueCollection
aSettings( info
);
791 sDriverClass
= aSettings
.getOrDefault( "JavaDriverClass", sDriverClass
);
792 sDriverClassPath
= aSettings
.getOrDefault( "JavaDriverClassPath", sDriverClassPath
);
793 bAutoRetrievingEnabled
= aSettings
.getOrDefault( "IsAutoRetrievingEnabled", bAutoRetrievingEnabled
);
794 sGeneratedValueStatement
= aSettings
.getOrDefault( "AutoRetrievingStatement", sGeneratedValueStatement
);
795 m_bParameterSubstitution
= aSettings
.getOrDefault( "ParameterNameSubstitution", m_bParameterSubstitution
);
796 m_bIgnoreDriverPrivileges
= aSettings
.getOrDefault( "IgnoreDriverPrivileges", m_bIgnoreDriverPrivileges
);
797 m_bIgnoreCurrency
= aSettings
.getOrDefault( "IgnoreCurrency", m_bIgnoreCurrency
);
798 aSystemProperties
= aSettings
.getOrDefault( "SystemProperties", aSystemProperties
);
799 m_aCatalogRestriction
= aSettings
.getOrDefault( "ImplicitCatalogRestriction", Any() );
800 m_aSchemaRestriction
= aSettings
.getOrDefault( "ImplicitSchemaRestriction", Any() );
802 loadDriverFromProperties( sDriverClass
, sDriverClassPath
, aSystemProperties
);
804 enableAutoRetrievingEnabled(bAutoRetrievingEnabled
);
805 setAutoRetrievingStatement(sGeneratedValueStatement
);
807 if ( t
.pEnv
&& m_Driver_theClass
&& m_pDriverobject
)
809 // temporaere Variable initialisieren
810 static const char * cSignature
= "(Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection;";
811 static const char * cMethodName
= "connect";
812 // Java-Call absetzen
813 jmethodID mID
= NULL
;
815 mID
= t
.pEnv
->GetMethodID( m_Driver_theClass
, cMethodName
, cSignature
);
819 // Parameter konvertieren
820 args
[0].l
= convertwchar_tToJavaString(t
.pEnv
,url
);
821 java_util_Properties
* pProps
= createStringPropertyArray(info
);
822 args
[1].l
= pProps
->getJavaObject();
824 LocalRef
< jobject
> ensureDelete( t
.env(), args
[0].l
);
827 // In some cases (e.g.,
828 // connectivity/source/drivers/hsqldb/HDriver.cxx:1.24
829 // l. 249) the JavaDriverClassPath contains multiple jars,
830 // as creating the JavaDriverClass instance requires
831 // (reflective) access to those other jars. Now, if the
832 // JavaDriverClass is actually loaded by some parent class
833 // loader (e.g., because its jar is also on the global
834 // class path), it would still not have access to the
835 // additional jars on the JavaDriverClassPath. Hence, the
836 // JavaDriverClassPath class loader is pushed as context
837 // class loader around the JavaDriverClass instance
839 // #i82222# / 2007-10-15
841 ContextClassLoaderScope
ccl( t
.env(), getDriverClassLoader(), getLogger(), *this );
842 out
= t
.pEnv
->CallObjectMethod( m_pDriverobject
, mID
, args
[0].l
,args
[1].l
);
843 delete pProps
, pProps
= NULL
;
844 ThrowLoggedSQLException( m_aLogger
, t
.pEnv
, *this );
848 m_aLogger
.log( LogLevel::SEVERE
, STR_LOG_NO_SYSTEM_CONNECTION
);
851 object
= t
.pEnv
->NewGlobalRef( out
);
854 m_aLogger
.log( LogLevel::INFO
, STR_LOG_GOT_JDBC_CONNECTION
, url
);
856 m_aConnectionInfo
= info
;
859 return object
!= NULL
;
861 // -----------------------------------------------------------------------------