merge the formfield patch from ooo-build
[ooovba.git] / connectivity / source / drivers / jdbc / JConnection.cxx
blobe2f1afcb7749d9ec428037d19e864057271a07b2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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>
57 #include <jni.h>
58 #include "resource/common_res.hrc"
60 #include <list>
61 #include <memory>
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;
71 namespace {
73 struct ClassMapEntry {
74 ClassMapEntry(
75 rtl::OUString const & theClassPath, rtl::OUString const & theClassName):
76 classPath(theClassPath), className(theClassName), classLoader(NULL),
77 classObject(NULL) {}
79 rtl::OUString classPath;
80 rtl::OUString className;
81 jweak classLoader;
82 jweak classObject;
85 typedef std::list< ClassMapEntry > ClassMap;
87 struct ClassMapData {
88 osl::Mutex mutex;
90 ClassMap map;
93 struct ClassMapDataInit {
94 ClassMapData * operator()() {
95 static ClassMapData instance;
96 return &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())
109 return false;
111 else if ( _weak != NULL )
113 _inout_local.env().DeleteWeakGlobalRef( _weak );
114 _weak = NULL;
117 return true;
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
122 // loaded once.
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
129 // still reachable).
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.
139 bool loadClass(
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):
147 ClassMapData * d =
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 ) )
161 return false;
163 LocalRef< jclass > classObject( environment );
164 if ( !getLocalFromWeakRef( i->classObject, classObject ) )
165 return false;
167 if ( !classLoader.is() && !classObject.is() )
169 i = d->map.erase(i);
171 else if ( i->classPath == classPath && i->className == name )
173 cloader.set( classLoader.release() );
174 cl.set( classObject.release() );
175 break;
177 else
179 ++i;
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 ) );
193 i = d->map.begin();
196 LocalRef< jclass > clClass( environment );
197 clClass.set( environment.FindClass( "java/net/URLClassLoader" ) );
198 if ( !clClass.is() )
199 return false;
201 jweak wcloader = NULL;
202 if (!cloader.is())
204 jmethodID ctorLoader( environment.GetMethodID( clClass.get(), "<init>", "([Ljava/net/URL;)V" ) );
205 if (ctorLoader == NULL)
206 return false;
208 LocalRef< jobjectArray > arr( environment );
209 arr.set( jvmaccess::ClassPath::translateToUrls( context, &environment, classPath ) );
210 if ( !arr.is() )
211 return false;
213 jvalue arg;
214 arg.l = arr.get();
215 cloader.set( environment.NewObjectA( clClass.get(), ctorLoader, &arg ) );
216 if ( !cloader.is() )
217 return false;
219 wcloader = environment.NewWeakGlobalRef( cloader.get() );
220 if ( wcloader == NULL )
221 return false;
224 jweak wcl = NULL;
225 if ( !cl.is() )
227 jmethodID methLoadClass( environment.GetMethodID( clClass.get(), "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;" ) );
228 if ( methLoadClass == NULL )
229 return false;
231 LocalRef< jstring > str( environment );
232 str.set( convertwchar_tToJavaString( &environment, name ) );
233 if ( !str.is() )
234 return false;
236 jvalue arg;
237 arg.l = str.get();
238 cl.set( static_cast< jclass >( environment.CallObjectMethodA( cloader.get(), methLoadClass, &arg ) ) );
239 if ( !cl.is() )
240 return false;
242 wcl = environment.NewWeakGlobalRef( cl.get() );
243 if ( wcl == NULL )
244 return false;
247 if ( wcloader != NULL)
249 i->classLoader = wcloader;
251 if ( wcl != NULL )
253 i->classObject = wcl;
257 classLoaderPtr->set( cloader.release() );
258 classPtr->set( cl.release() );
259 return true;
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();
289 if ( xTest.is() )
291 SDBThreadAttach t;
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;
302 t.releaseRef();
305 //-----------------------------------------------------------------------------
306 void SAL_CALL java_sql_Connection::release() throw()
308 relase_ChildImpl();
310 //------------------------------------------------------------------------------
311 void java_sql_Connection::disposing()
313 ::osl::MutexGuard aGuard(m_aMutex);
315 m_aLogger.log( LogLevel::INFO, STR_LOG_SHUTDOWN_CONNECTION );
317 dispose_ChildImpl();
318 java_sql_Connection_BASE::disposing();
320 if ( object )
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
330 if( !theClass )
331 theClass = findMyClass("java/sql/Connection");
332 return theClass;
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;
352 if(!xMetaData.is())
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);
357 if(out)
359 xMetaData = new java_sql_DatabaseMetaData( t.pEnv, out, *this );
360 m_xMetaData = xMetaData;
364 return xMetaData;
366 // -------------------------------------------------------------------------
367 void SAL_CALL java_sql_Connection::close( ) throw(SQLException, RuntimeException)
369 dispose();
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 );
469 SDBThreadAttach t;
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() );
475 return xStmt;
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);
489 if(pNode)
490 { // special handling for parameters
491 OSQLParseNode::substituteParameterNames(pNode);
492 pNode->parseNodeToStr( sNewSql, this );
493 delete pNode;
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 );
510 SDBThreadAttach t;
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() );
519 return xReturn;
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 );
528 SDBThreadAttach t;
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() );
537 return xStmt;
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 );
562 } //t.pEnv
564 m_aLogger.log( LogLevel::FINER, STR_LOG_NATIVE_SQL, sql, aStr );
566 return 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);
580 SDBThreadAttach t;
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 !!!
584 if( out )
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
590 SQLWarning aWarning;
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 );
600 return Any();
603 // -----------------------------------------------------------------------------
604 namespace
606 ::rtl::OUString lcl_getDriverLoadErrorMessage( const ::connectivity::SharedResources& _aResource,const ::rtl::OUString& _rDriverClass, const ::rtl::OUString& _rDriverClassPath )
608 ::rtl::OUString sError1( _aResource.getResourceStringWithSubstitution(
609 STR_NO_CLASSNAME,
610 "$classname$", _rDriverClass
611 ) );
612 if ( _rDriverClassPath.getLength() )
614 const ::rtl::OUString sError2( _aResource.getResourceStringWithSubstitution(
615 STR_NO_CLASSNAME_PATH,
616 "$classpath$", _rDriverClassPath
617 ) );
618 sError1 += sError2;
619 } // if ( _rDriverClassPath.getLength() )
620 return sError1;
624 // -----------------------------------------------------------------------------
625 namespace
627 bool lcl_setSystemProperties_nothrow( const java::sql::ConnectionLog& _rLogger,
628 JNIEnv& _rEnv, const Sequence< NamedValue >& _rSystemProperties )
630 if ( _rSystemProperties.getLength() == 0 )
631 // nothing to do
632 return true;
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 )
645 return false;
647 for ( const NamedValue* pSystemProp = _rSystemProperties.getConstArray();
648 pSystemProp != _rSystemProperties.getConstArray() + _rSystemProperties.getLength();
649 ++pSystemProp
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() )
663 return false;
666 return true;
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
680 SDBThreadAttach t;
683 if ( !object )
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 ),
699 *this
702 else
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));
712 else
714 LocalRef< jclass > driverClass(t.env());
715 LocalRef< jobject > driverClassLoader(t.env());
717 loadClass(
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 )
751 throw SQLException(
752 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass, _sDriverClassPath ),
753 *this,
754 ::rtl::OUString(),
755 1000,
756 makeAny(e)
759 catch( Exception& )
761 ::dbtools::throwGenericSQLException(
762 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass, _sDriverClassPath ),
763 *this
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());
777 if ( !xTest.is() )
778 throwGenericSQLException(STR_NO_JAVA,*this);
780 SDBThreadAttach t;
781 t.addRef(); // will be released in dtor
782 if ( !t.pEnv )
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;
814 if ( !mID )
815 mID = t.pEnv->GetMethodID( m_Driver_theClass, cMethodName, cSignature );
816 if ( mID )
818 jvalue args[2];
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 );
826 jobject out = NULL;
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
838 // creation:
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 );
847 if ( !out )
848 m_aLogger.log( LogLevel::SEVERE, STR_LOG_NO_SYSTEM_CONNECTION );
850 if ( out )
851 object = t.pEnv->NewGlobalRef( out );
853 if ( object )
854 m_aLogger.log( LogLevel::INFO, STR_LOG_GOT_JDBC_CONNECTION, url );
856 m_aConnectionInfo = info;
857 } //mID
858 } //t.pEnv
859 return object != NULL;
861 // -----------------------------------------------------------------------------