1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "java/sql/Connection.hxx"
31 #include "java/lang/Class.hxx"
32 #include "java/tools.hxx"
33 #include "java/ContextClassLoader.hxx"
34 #include "java/sql/DatabaseMetaData.hxx"
35 #include "java/sql/JStatement.hxx"
36 #include "java/sql/Driver.hxx"
37 #include "java/sql/PreparedStatement.hxx"
38 #include "java/sql/CallableStatement.hxx"
39 #include "java/sql/SQLWarning.hxx"
40 #include <com/sun/star/lang/DisposedException.hpp>
41 #include <com/sun/star/sdbc/SQLWarning.hpp>
42 #include <com/sun/star/beans/NamedValue.hpp>
43 #include "connectivity/sqlparse.hxx"
44 #include "connectivity/dbexception.hxx"
45 #include "java/util/Property.hxx"
46 #include "java/LocalRef.hxx"
47 #include "resource/jdbc_log.hrc"
48 #include "com/sun/star/uno/XComponentContext.hpp"
49 #include "jvmaccess/classpath.hxx"
50 #include <comphelper/namedvaluecollection.hxx>
51 #include <rtl/ustrbuf.hxx>
53 #include "resource/common_res.hrc"
54 #include <unotools/confignode.hxx>
59 using namespace connectivity
;
60 using namespace connectivity::jdbc
;
61 using namespace ::com::sun::star::uno
;
62 using namespace ::com::sun::star::beans
;
63 using namespace ::com::sun::star::sdbc
;
64 using namespace ::com::sun::star::container
;
65 using namespace ::com::sun::star::lang
;
69 struct ClassMapEntry
{
71 rtl::OUString
const & theClassPath
, rtl::OUString
const & theClassName
):
72 classPath(theClassPath
), className(theClassName
), classLoader(NULL
),
75 rtl::OUString classPath
;
76 rtl::OUString className
;
81 typedef std::list
< ClassMapEntry
> ClassMap
;
89 struct ClassMapDataInit
{
90 ClassMapData
* operator()() {
91 static ClassMapData instance
;
96 template < typename T
>
97 bool getLocalFromWeakRef( jweak
& _weak
, LocalRef
< T
>& _inout_local
)
99 _inout_local
.set( static_cast< T
>( _inout_local
.env().NewLocalRef( _weak
) ) );
101 if ( !_inout_local
.is() )
103 if ( _inout_local
.env().ExceptionCheck())
107 else if ( _weak
!= NULL
)
109 _inout_local
.env().DeleteWeakGlobalRef( _weak
);
116 // Load a class. A map from pairs of (classPath, name) to pairs of weak Java
117 // references to (ClassLoader, Class) is maintained, so that a class is only
120 // It may happen that the weak reference to the ClassLoader becomes null while
121 // the reference to the Class remains non-null (in case the Class was actually
122 // loaded by some parent of the ClassLoader), in which case the ClassLoader is
123 // resurrected (which cannot cause any classes to be loaded multiple times, as
124 // the ClassLoader is no longer reachable, so no classes it has ever loaded are
127 // Similarly, it may happen that the weak reference to the Class becomes null
128 // while the reference to the ClassLoader remains non-null, in which case the
129 // Class is simply re-loaded.
131 // This code is close to the implementation of jvmaccess::ClassPath::loadClass
132 // in jvmaccess/classpath.hxx, but not close enough to avoid the duplication.
134 // If false is returned, a (still pending) JNI exception occurred.
136 Reference
< XComponentContext
> const & context
, JNIEnv
& environment
,
137 rtl::OUString
const & classPath
, rtl::OUString
const & name
,
138 LocalRef
< jobject
> * classLoaderPtr
, LocalRef
< jclass
> * classPtr
)
140 OSL_ASSERT(classLoaderPtr
!= NULL
);
141 // For any jweak entries still present in the map upon destruction,
142 // DeleteWeakGlobalRef is not called (which is a leak):
144 rtl_Instance
< ClassMapData
, ClassMapDataInit
, osl::MutexGuard
,
145 osl::GetGlobalMutex
>::create(
146 ClassMapDataInit(), osl::GetGlobalMutex());
147 osl::MutexGuard
g(d
->mutex
);
148 ClassMap::iterator
i(d
->map
.begin());
149 LocalRef
< jobject
> cloader(environment
);
150 LocalRef
< jclass
> cl(environment
);
151 // Prune dangling weak references from the list while searching for a match,
152 // so that the list cannot grow unbounded:
153 for (; i
!= d
->map
.end();)
155 LocalRef
< jobject
> classLoader( environment
);
156 if ( !getLocalFromWeakRef( i
->classLoader
, classLoader
) )
159 LocalRef
< jclass
> classObject( environment
);
160 if ( !getLocalFromWeakRef( i
->classObject
, classObject
) )
163 if ( !classLoader
.is() && !classObject
.is() )
167 else if ( i
->classPath
== classPath
&& i
->className
== name
)
169 cloader
.set( classLoader
.release() );
170 cl
.set( classObject
.release() );
178 if ( !cloader
.is() || !cl
.is() )
180 if ( i
== d
->map
.end() )
182 // Push a new ClassMapEntry (which can potentially fail) before
183 // loading the class, so that it never happens that a class is
184 // loaded but not added to the map (which could have effects on the
185 // JVM that are not easily undone). If the pushed ClassMapEntry is
186 // not used after all (return false, etc.) it will be pruned on next
187 // call because its classLoader/classObject are null:
188 d
->map
.push_front( ClassMapEntry( classPath
, name
) );
192 LocalRef
< jclass
> clClass( environment
);
193 clClass
.set( environment
.FindClass( "java/net/URLClassLoader" ) );
197 jweak wcloader
= NULL
;
200 jmethodID
ctorLoader( environment
.GetMethodID( clClass
.get(), "<init>", "([Ljava/net/URL;)V" ) );
201 if (ctorLoader
== NULL
)
204 LocalRef
< jobjectArray
> arr( environment
);
205 arr
.set( jvmaccess::ClassPath::translateToUrls( context
, &environment
, classPath
) );
211 cloader
.set( environment
.NewObjectA( clClass
.get(), ctorLoader
, &arg
) );
215 wcloader
= environment
.NewWeakGlobalRef( cloader
.get() );
216 if ( wcloader
== NULL
)
223 jmethodID
methLoadClass( environment
.GetMethodID( clClass
.get(), "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;" ) );
224 if ( methLoadClass
== NULL
)
227 LocalRef
< jstring
> str( environment
);
228 str
.set( convertwchar_tToJavaString( &environment
, name
) );
234 cl
.set( static_cast< jclass
>( environment
.CallObjectMethodA( cloader
.get(), methLoadClass
, &arg
) ) );
238 wcl
= environment
.NewWeakGlobalRef( cl
.get() );
243 if ( wcloader
!= NULL
)
245 i
->classLoader
= wcloader
;
249 i
->classObject
= wcl
;
253 classLoaderPtr
->set( cloader
.release() );
254 classPtr
->set( cl
.release() );
260 //------------------------------------------------------------------------------
261 IMPLEMENT_SERVICE_INFO(java_sql_Connection
,"com.sun.star.sdbcx.JConnection","com.sun.star.sdbc.Connection");
262 //------------------------------------------------------------------------------
263 //**************************************************************
264 //************ Class: java.sql.Connection
265 //**************************************************************
266 jclass
java_sql_Connection::theClass
= 0;
268 java_sql_Connection::java_sql_Connection( const java_sql_Driver
& _rDriver
)
269 :java_lang_Object( _rDriver
.getContext().getLegacyServiceFactory() )
270 ,OSubComponent
<java_sql_Connection
, java_sql_Connection_BASE
>((::cppu::OWeakObject
*)(&_rDriver
), this)
271 ,m_pDriver( &_rDriver
)
272 ,m_pDriverobject(NULL
)
273 ,m_pDriverClassLoader()
274 ,m_Driver_theClass(NULL
)
275 ,m_aLogger( _rDriver
.getLogger() )
276 ,m_bParameterSubstitution(sal_False
)
277 ,m_bIgnoreDriverPrivileges(sal_True
)
278 ,m_bIgnoreCurrency(sal_False
)
281 // -----------------------------------------------------------------------------
282 java_sql_Connection::~java_sql_Connection()
284 ::rtl::Reference
< jvmaccess::VirtualMachine
> xTest
= java_lang_Object::getVM();
288 clearObject(*t
.pEnv
);
291 if ( m_pDriverobject
)
292 t
.pEnv
->DeleteGlobalRef( m_pDriverobject
);
293 m_pDriverobject
= NULL
;
294 if ( m_Driver_theClass
)
295 t
.pEnv
->DeleteGlobalRef( m_Driver_theClass
);
296 m_Driver_theClass
= NULL
;
301 //-----------------------------------------------------------------------------
302 void SAL_CALL
java_sql_Connection::release() throw()
306 //------------------------------------------------------------------------------
307 void java_sql_Connection::disposing()
309 ::osl::MutexGuard
aGuard(m_aMutex
);
311 m_aLogger
.log( LogLevel::INFO
, STR_LOG_SHUTDOWN_CONNECTION
);
314 java_sql_Connection_BASE::disposing();
318 static jmethodID
mID(NULL
);
319 callVoidMethod("close",mID
);
322 // -------------------------------------------------------------------------
323 jclass
java_sql_Connection::getMyClass() const
325 // the class must be fetched only once, therefore static
327 theClass
= findMyClass("java/sql/Connection");
331 // -------------------------------------------------------------------------
332 ::rtl::OUString SAL_CALL
java_sql_Connection::getCatalog( ) throw(SQLException
, RuntimeException
)
334 ::osl::MutexGuard
aGuard( m_aMutex
);
335 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
337 static jmethodID
mID(NULL
);
338 return callStringMethod("getCatalog",mID
);
340 // -------------------------------------------------------------------------
341 Reference
< XDatabaseMetaData
> SAL_CALL
java_sql_Connection::getMetaData( ) throw(SQLException
, RuntimeException
)
343 ::osl::MutexGuard
aGuard( m_aMutex
);
344 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
347 Reference
< XDatabaseMetaData
> xMetaData
= m_xMetaData
;
350 SDBThreadAttach t
; OSL_ENSURE(t
.pEnv
,"Java Enviroment geloescht worden!");
351 static jmethodID
mID(NULL
);
352 jobject out
= callObjectMethod(t
.pEnv
,"getMetaData","()Ljava/sql/DatabaseMetaData;", mID
);
355 xMetaData
= new java_sql_DatabaseMetaData( t
.pEnv
, out
, *this );
356 m_xMetaData
= xMetaData
;
362 // -------------------------------------------------------------------------
363 void SAL_CALL
java_sql_Connection::close( ) throw(SQLException
, RuntimeException
)
367 // -------------------------------------------------------------------------
368 void SAL_CALL
java_sql_Connection::commit( ) throw(SQLException
, RuntimeException
)
370 static jmethodID
mID(NULL
);
371 callVoidMethod("commit",mID
);
373 // -------------------------------------------------------------------------
374 sal_Bool SAL_CALL
java_sql_Connection::isClosed( ) throw(SQLException
, RuntimeException
)
376 ::osl::MutexGuard
aGuard( m_aMutex
);
378 static jmethodID
mID(NULL
);
379 return callBooleanMethod( "isClosed", mID
) && java_sql_Connection_BASE::rBHelper
.bDisposed
;
381 // -------------------------------------------------------------------------
382 sal_Bool SAL_CALL
java_sql_Connection::isReadOnly( ) throw(SQLException
, RuntimeException
)
384 ::osl::MutexGuard
aGuard( m_aMutex
);
385 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
386 static jmethodID
mID(NULL
);
387 return callBooleanMethod( "isReadOnly", mID
);
389 // -------------------------------------------------------------------------
390 void SAL_CALL
java_sql_Connection::setCatalog( const ::rtl::OUString
& catalog
) throw(SQLException
, RuntimeException
)
392 static jmethodID
mID(NULL
);
393 callVoidMethodWithStringArg("setCatalog",mID
,catalog
);
395 // -------------------------------------------------------------------------
396 void SAL_CALL
java_sql_Connection::rollback( ) throw(SQLException
, RuntimeException
)
398 static jmethodID
mID(NULL
);
399 callVoidMethod("rollback",mID
);
401 // -------------------------------------------------------------------------
402 sal_Bool SAL_CALL
java_sql_Connection::getAutoCommit( ) throw(SQLException
, RuntimeException
)
404 static jmethodID
mID(NULL
);
405 return callBooleanMethod( "getAutoCommit", mID
);
407 // -------------------------------------------------------------------------
408 void SAL_CALL
java_sql_Connection::setReadOnly( sal_Bool readOnly
) throw(SQLException
, RuntimeException
)
410 static jmethodID
mID(NULL
);
411 callVoidMethodWithBoolArg("setReadOnly",mID
,readOnly
);
413 // -------------------------------------------------------------------------
414 void SAL_CALL
java_sql_Connection::setAutoCommit( sal_Bool autoCommit
) throw(SQLException
, RuntimeException
)
416 static jmethodID
mID(NULL
);
417 callVoidMethodWithBoolArg("setAutoCommit",mID
,autoCommit
);
419 // -------------------------------------------------------------------------
420 Reference
< ::com::sun::star::container::XNameAccess
> SAL_CALL
java_sql_Connection::getTypeMap( ) throw(SQLException
, RuntimeException
)
422 ::osl::MutexGuard
aGuard( m_aMutex
);
423 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
425 SDBThreadAttach t
; OSL_ENSURE(t
.pEnv
,"Java Enviroment geloescht worden!");
426 static jmethodID
mID(NULL
);
427 callObjectMethod(t
.pEnv
,"getTypeMap","()Ljava/util/Map;", mID
);
428 // WARNING: the caller becomes the owner of the returned pointer
431 // -------------------------------------------------------------------------
432 void SAL_CALL
java_sql_Connection::setTypeMap( const Reference
< ::com::sun::star::container::XNameAccess
>& /*typeMap*/ ) throw(SQLException
, RuntimeException
)
434 ::osl::MutexGuard
aGuard( m_aMutex
);
435 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
437 ::dbtools::throwFeatureNotImplementedException( "XConnection::setTypeMap", *this );
440 // -------------------------------------------------------------------------
441 sal_Int32 SAL_CALL
java_sql_Connection::getTransactionIsolation( ) throw(SQLException
, RuntimeException
)
443 ::osl::MutexGuard
aGuard( m_aMutex
);
444 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
446 static jmethodID
mID(NULL
);
447 return callIntMethod("getTransactionIsolation",mID
);
449 // -------------------------------------------------------------------------
450 void SAL_CALL
java_sql_Connection::setTransactionIsolation( sal_Int32 level
) throw(SQLException
, RuntimeException
)
452 ::osl::MutexGuard
aGuard( m_aMutex
);
453 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
455 static jmethodID
mID(NULL
);
456 callVoidMethodWithIntArg("setTransactionIsolation",mID
,level
);
458 // -------------------------------------------------------------------------
459 Reference
< XStatement
> SAL_CALL
java_sql_Connection::createStatement( ) throw(SQLException
, RuntimeException
)
461 ::osl::MutexGuard
aGuard( m_aMutex
);
462 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
463 m_aLogger
.log( LogLevel::FINE
, STR_LOG_CREATE_STATEMENT
);
466 java_sql_Statement
* pStatement
= new java_sql_Statement( t
.pEnv
, *this );
467 Reference
< XStatement
> xStmt
= pStatement
;
468 m_aStatements
.push_back( WeakReferenceHelper( xStmt
) );
470 m_aLogger
.log( LogLevel::FINE
, STR_LOG_CREATED_STATEMENT_ID
, pStatement
->getStatementObjectID() );
473 // -----------------------------------------------------------------------------
474 ::rtl::OUString
java_sql_Connection::transFormPreparedStatement(const ::rtl::OUString
& _sSQL
)
476 ::rtl::OUString sSqlStatement
= _sSQL
;
477 if ( m_bParameterSubstitution
)
481 OSQLParser
aParser( m_pDriver
->getContext().getLegacyServiceFactory() );
482 ::rtl::OUString sErrorMessage
;
483 ::rtl::OUString sNewSql
;
484 OSQLParseNode
* pNode
= aParser
.parseTree(sErrorMessage
,_sSQL
);
486 { // special handling for parameters
487 OSQLParseNode::substituteParameterNames(pNode
);
488 pNode
->parseNodeToStr( sNewSql
, this );
490 sSqlStatement
= sNewSql
;
493 catch(const Exception
&)
497 return sSqlStatement
;
499 // -------------------------------------------------------------------------
500 Reference
< XPreparedStatement
> SAL_CALL
java_sql_Connection::prepareStatement( const ::rtl::OUString
& sql
) throw(SQLException
, RuntimeException
)
502 ::osl::MutexGuard
aGuard( m_aMutex
);
503 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
504 m_aLogger
.log( LogLevel::FINE
, STR_LOG_PREPARE_STATEMENT
, sql
);
507 ::rtl::OUString sSqlStatement
= sql
;
508 sSqlStatement
= transFormPreparedStatement( sSqlStatement
);
510 java_sql_PreparedStatement
* pStatement
= new java_sql_PreparedStatement( t
.pEnv
, *this, sSqlStatement
);
511 Reference
< XPreparedStatement
> xReturn( pStatement
);
512 m_aStatements
.push_back(WeakReferenceHelper(xReturn
));
514 m_aLogger
.log( LogLevel::FINE
, STR_LOG_PREPARED_STATEMENT_ID
, pStatement
->getStatementObjectID() );
517 // -------------------------------------------------------------------------
518 Reference
< XPreparedStatement
> SAL_CALL
java_sql_Connection::prepareCall( const ::rtl::OUString
& sql
) throw(SQLException
, RuntimeException
)
520 ::osl::MutexGuard
aGuard( m_aMutex
);
521 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
522 m_aLogger
.log( LogLevel::FINE
, STR_LOG_PREPARE_CALL
, sql
);
525 ::rtl::OUString sSqlStatement
= sql
;
526 sSqlStatement
= transFormPreparedStatement( sSqlStatement
);
528 java_sql_CallableStatement
* pStatement
= new java_sql_CallableStatement( t
.pEnv
, *this, sSqlStatement
);
529 Reference
< XPreparedStatement
> xStmt( pStatement
);
530 m_aStatements
.push_back(WeakReferenceHelper(xStmt
));
532 m_aLogger
.log( LogLevel::FINE
, STR_LOG_PREPARED_CALL_ID
, pStatement
->getStatementObjectID() );
535 // -------------------------------------------------------------------------
536 ::rtl::OUString SAL_CALL
java_sql_Connection::nativeSQL( const ::rtl::OUString
& sql
) throw(SQLException
, RuntimeException
)
538 ::osl::MutexGuard
aGuard( m_aMutex
);
539 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
541 ::rtl::OUString aStr
;
542 SDBThreadAttach t
; OSL_ENSURE(t
.pEnv
,"Java Enviroment geloescht worden!");
545 // initialize temporary Variable
546 static const char * cSignature
= "(Ljava/lang/String;)Ljava/lang/String;";
547 static const char * cMethodName
= "nativeSQL";
549 static jmethodID
mID(NULL
);
550 obtainMethodId(t
.pEnv
, cMethodName
,cSignature
, mID
);
552 jdbc::LocalRef
< jstring
> str( t
.env(),convertwchar_tToJavaString(t
.pEnv
,sql
));
554 jobject out
= t
.pEnv
->CallObjectMethod( object
, mID
, str
.get() );
555 aStr
= JavaString2String(t
.pEnv
, (jstring
)out
);
556 ThrowLoggedSQLException( m_aLogger
, t
.pEnv
, *this );
559 m_aLogger
.log( LogLevel::FINER
, STR_LOG_NATIVE_SQL
, sql
, aStr
);
563 // -------------------------------------------------------------------------
564 void SAL_CALL
java_sql_Connection::clearWarnings( ) throw(SQLException
, RuntimeException
)
566 static jmethodID
mID(NULL
);
567 callVoidMethod("clearWarnings",mID
);
569 // -------------------------------------------------------------------------
570 Any SAL_CALL
java_sql_Connection::getWarnings( ) throw(SQLException
, RuntimeException
)
572 ::osl::MutexGuard
aGuard( m_aMutex
);
573 checkDisposed(java_sql_Connection_BASE::rBHelper
.bDisposed
);
576 static jmethodID
mID(NULL
);
577 jobject out
= callObjectMethod(t
.pEnv
,"getWarnings","()Ljava/sql/SQLWarning;", mID
);
578 // WARNING: the caller becomes the owner of the returned pointer
581 java_sql_SQLWarning_BASE
warn_base(t
.pEnv
, out
);
582 SQLException
aAsException( static_cast< starsdbc::SQLException
>( java_sql_SQLWarning( warn_base
, *this ) ) );
584 // translate to warning
586 aWarning
.Context
= aAsException
.Context
;
587 aWarning
.Message
= aAsException
.Message
;
588 aWarning
.SQLState
= aAsException
.SQLState
;
589 aWarning
.ErrorCode
= aAsException
.ErrorCode
;
590 aWarning
.NextException
= aAsException
.NextException
;
592 return makeAny( aWarning
);
598 // -----------------------------------------------------------------------------
601 ::rtl::OUString
lcl_getDriverLoadErrorMessage( const ::connectivity::SharedResources
& _aResource
,const ::rtl::OUString
& _rDriverClass
, const ::rtl::OUString
& _rDriverClassPath
)
603 ::rtl::OUString
sError1( _aResource
.getResourceStringWithSubstitution(
605 "$classname$", _rDriverClass
607 if ( !_rDriverClassPath
.isEmpty() )
609 const ::rtl::OUString
sError2( _aResource
.getResourceStringWithSubstitution(
610 STR_NO_CLASSNAME_PATH
,
611 "$classpath$", _rDriverClassPath
614 } // if ( _rDriverClassPath.getLength() )
619 // -----------------------------------------------------------------------------
622 bool lcl_setSystemProperties_nothrow( const java::sql::ConnectionLog
& _rLogger
,
623 JNIEnv
& _rEnv
, const Sequence
< NamedValue
>& _rSystemProperties
)
625 if ( _rSystemProperties
.getLength() == 0 )
629 LocalRef
< jclass
> systemClass( _rEnv
);
630 jmethodID nSetPropertyMethodID
= 0;
631 // retrieve the java.lang.System class
632 systemClass
.set( _rEnv
.FindClass( "java/lang/System" ) );
633 if ( systemClass
.is() )
635 nSetPropertyMethodID
= _rEnv
.GetStaticMethodID(
636 systemClass
.get(), "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;" );
639 if ( nSetPropertyMethodID
== 0 )
642 for ( const NamedValue
* pSystemProp
= _rSystemProperties
.getConstArray();
643 pSystemProp
!= _rSystemProperties
.getConstArray() + _rSystemProperties
.getLength();
647 ::rtl::OUString sValue
;
648 OSL_VERIFY( pSystemProp
->Value
>>= sValue
);
650 _rLogger
.log( LogLevel::FINER
, STR_LOG_SETTING_SYSTEM_PROPERTY
, pSystemProp
->Name
, sValue
);
652 LocalRef
< jstring
> jName( _rEnv
, convertwchar_tToJavaString( &_rEnv
, pSystemProp
->Name
) );
653 LocalRef
< jstring
> jValue( _rEnv
, convertwchar_tToJavaString( &_rEnv
, sValue
) );
655 _rEnv
.CallStaticObjectMethod( systemClass
.get(), nSetPropertyMethodID
, jName
.get(), jValue
.get() );
656 LocalRef
< jthrowable
> throwable( _rEnv
, _rEnv
.ExceptionOccurred() );
657 if ( throwable
.is() )
665 // -----------------------------------------------------------------------------
666 void java_sql_Connection::loadDriverFromProperties( const ::rtl::OUString
& _sDriverClass
, const ::rtl::OUString
& _sDriverClassPath
,
667 const Sequence
< NamedValue
>& _rSystemProperties
)
669 // contains the statement which should be used when query for automatically generated values
670 ::rtl::OUString sGeneratedValueStatement
;
671 // set to <TRUE/> when we should allow to query for generated values
672 sal_Bool bAutoRetrievingEnabled
= sal_False
;
674 // first try if the jdbc driver is alraedy registered at the driver manager
680 if ( !lcl_setSystemProperties_nothrow( getLogger(), *t
.pEnv
, _rSystemProperties
) )
681 ThrowLoggedSQLException( getLogger(), t
.pEnv
, *this );
683 m_pDriverClassLoader
.reset();
685 // here I try to find the class for jdbc driver
686 java_sql_SQLException_BASE::st_getMyClass();
687 java_lang_Throwable::st_getMyClass();
689 if ( _sDriverClass
.isEmpty() )
691 m_aLogger
.log( LogLevel::SEVERE
, STR_LOG_NO_DRIVER_CLASS
);
692 ::dbtools::throwGenericSQLException(
693 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass
, _sDriverClassPath
),
699 m_aLogger
.log( LogLevel::INFO
, STR_LOG_LOADING_DRIVER
, _sDriverClass
);
700 // the driver manager holds the class of the driver for later use
701 ::std::auto_ptr
< java_lang_Class
> pDrvClass
;
702 if ( _sDriverClassPath
.isEmpty() )
704 // if forName didn't find the class it will throw an exception
705 pDrvClass
= ::std::auto_ptr
< java_lang_Class
>(java_lang_Class::forName(_sDriverClass
));
709 LocalRef
< jclass
> driverClass(t
.env());
710 LocalRef
< jobject
> driverClassLoader(t
.env());
713 m_pDriver
->getContext().getUNOContext(),
714 t
.env(), _sDriverClassPath
, _sDriverClass
, &driverClassLoader
, &driverClass
);
716 m_pDriverClassLoader
.set( driverClassLoader
);
717 pDrvClass
.reset( new java_lang_Class( t
.pEnv
, driverClass
.release() ) );
719 ThrowLoggedSQLException( m_aLogger
, t
.pEnv
, *this );
721 if ( pDrvClass
.get() )
723 LocalRef
< jobject
> driverObject( t
.env() );
724 driverObject
.set( pDrvClass
->newInstanceObject() );
725 ThrowLoggedSQLException( m_aLogger
, t
.pEnv
, *this );
726 m_pDriverobject
= driverObject
.release();
728 if( t
.pEnv
&& m_pDriverobject
)
729 m_pDriverobject
= t
.pEnv
->NewGlobalRef( m_pDriverobject
);
732 jclass tempClass
= t
.pEnv
->GetObjectClass(m_pDriverobject
);
733 if ( m_pDriverobject
)
735 m_Driver_theClass
= (jclass
)t
.pEnv
->NewGlobalRef( tempClass
);
736 t
.pEnv
->DeleteLocalRef( tempClass
);
740 m_aLogger
.log( LogLevel::INFO
, STR_LOG_CONN_SUCCESS
);
744 catch( const SQLException
& e
)
747 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass
, _sDriverClassPath
),
756 ::dbtools::throwGenericSQLException(
757 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass
, _sDriverClassPath
),
762 enableAutoRetrievingEnabled( bAutoRetrievingEnabled
);
763 setAutoRetrievingStatement( sGeneratedValueStatement
);
765 // -----------------------------------------------------------------------------
766 ::rtl::OUString
java_sql_Connection::impl_getJavaDriverClassPath_nothrow(const ::rtl::OUString
& _sDriverClass
)
768 static const ::rtl::OUString
s_sNodeName(RTL_CONSTASCII_USTRINGPARAM("org.openoffice.Office.DataAccess/JDBC/DriverClassPaths"));
769 ::utl::OConfigurationTreeRoot aNamesRoot
= ::utl::OConfigurationTreeRoot::createWithServiceFactory(
770 m_pDriver
->getContext().getLegacyServiceFactory(), s_sNodeName
, -1, ::utl::OConfigurationTreeRoot::CM_READONLY
);
771 ::rtl::OUString sURL
;
772 if ( aNamesRoot
.isValid() && aNamesRoot
.hasByName( _sDriverClass
) )
774 ::utl::OConfigurationNode aRegisterObj
= aNamesRoot
.openNode( _sDriverClass
);
775 OSL_VERIFY( aRegisterObj
.getNodeValue( "Path" ) >>= sURL
);
779 // -----------------------------------------------------------------------------
780 sal_Bool
java_sql_Connection::construct(const ::rtl::OUString
& url
,
781 const Sequence
< PropertyValue
>& info
)
783 { // initialize the java vm
784 ::rtl::Reference
< jvmaccess::VirtualMachine
> xTest
= java_lang_Object::getVM(getORB());
786 throwGenericSQLException(STR_NO_JAVA
,*this);
789 t
.addRef(); // will be released in dtor
791 throwGenericSQLException(STR_NO_JAVA
,*this);
793 ::rtl::OUString sGeneratedValueStatement
; // contains the statement which should be used when query for automatically generated values
794 sal_Bool bAutoRetrievingEnabled
= sal_False
; // set to <TRUE/> when we should allow to query for generated values
795 ::rtl::OUString sDriverClassPath
,sDriverClass
;
796 Sequence
< NamedValue
> aSystemProperties
;
798 ::comphelper::NamedValueCollection
aSettings( info
);
799 sDriverClass
= aSettings
.getOrDefault( "JavaDriverClass", sDriverClass
);
800 sDriverClassPath
= aSettings
.getOrDefault( "JavaDriverClassPath", sDriverClassPath
);
801 if ( sDriverClassPath
.isEmpty() )
802 sDriverClassPath
= impl_getJavaDriverClassPath_nothrow(sDriverClass
);
803 bAutoRetrievingEnabled
= aSettings
.getOrDefault( "IsAutoRetrievingEnabled", bAutoRetrievingEnabled
);
804 sGeneratedValueStatement
= aSettings
.getOrDefault( "AutoRetrievingStatement", sGeneratedValueStatement
);
805 m_bParameterSubstitution
= aSettings
.getOrDefault( "ParameterNameSubstitution", m_bParameterSubstitution
);
806 m_bIgnoreDriverPrivileges
= aSettings
.getOrDefault( "IgnoreDriverPrivileges", m_bIgnoreDriverPrivileges
);
807 m_bIgnoreCurrency
= aSettings
.getOrDefault( "IgnoreCurrency", m_bIgnoreCurrency
);
808 aSystemProperties
= aSettings
.getOrDefault( "SystemProperties", aSystemProperties
);
809 m_aCatalogRestriction
= aSettings
.getOrDefault( "ImplicitCatalogRestriction", Any() );
810 m_aSchemaRestriction
= aSettings
.getOrDefault( "ImplicitSchemaRestriction", Any() );
812 loadDriverFromProperties( sDriverClass
, sDriverClassPath
, aSystemProperties
);
814 enableAutoRetrievingEnabled(bAutoRetrievingEnabled
);
815 setAutoRetrievingStatement(sGeneratedValueStatement
);
817 if ( t
.pEnv
&& m_Driver_theClass
&& m_pDriverobject
)
819 // initialize temporary Variable
820 static const char * cSignature
= "(Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection;";
821 static const char * cMethodName
= "connect";
823 jmethodID mID
= NULL
;
825 mID
= t
.pEnv
->GetMethodID( m_Driver_theClass
, cMethodName
, cSignature
);
830 args
[0].l
= convertwchar_tToJavaString(t
.pEnv
,url
);
831 java_util_Properties
* pProps
= createStringPropertyArray(info
);
832 args
[1].l
= pProps
->getJavaObject();
834 LocalRef
< jobject
> ensureDelete( t
.env(), args
[0].l
);
837 // In some cases (e.g.,
838 // connectivity/source/drivers/hsqldb/HDriver.cxx:1.24
839 // l. 249) the JavaDriverClassPath contains multiple jars,
840 // as creating the JavaDriverClass instance requires
841 // (reflective) access to those other jars. Now, if the
842 // JavaDriverClass is actually loaded by some parent class
843 // loader (e.g., because its jar is also on the global
844 // class path), it would still not have access to the
845 // additional jars on the JavaDriverClassPath. Hence, the
846 // JavaDriverClassPath class loader is pushed as context
847 // class loader around the JavaDriverClass instance
849 // #i82222# / 2007-10-15
851 ContextClassLoaderScope
ccl( t
.env(), getDriverClassLoader(), getLogger(), *this );
852 out
= t
.pEnv
->CallObjectMethod( m_pDriverobject
, mID
, args
[0].l
,args
[1].l
);
853 delete pProps
, pProps
= NULL
;
854 ThrowLoggedSQLException( m_aLogger
, t
.pEnv
, *this );
858 m_aLogger
.log( LogLevel::SEVERE
, STR_LOG_NO_SYSTEM_CONNECTION
);
861 object
= t
.pEnv
->NewGlobalRef( out
);
864 m_aLogger
.log( LogLevel::INFO
, STR_LOG_GOT_JDBC_CONNECTION
, url
);
866 m_aConnectionInfo
= info
;
869 return object
!= NULL
;
871 // -----------------------------------------------------------------------------
873 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */