LibreOffice Module connectivity (master) 1
JConnection.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21
23#include <java/lang/Class.hxx>
24#include <java/tools.hxx>
28#include <java/sql/Driver.hxx>
32#include <com/sun/star/sdbc/SQLWarning.hpp>
33#include <com/sun/star/beans/NamedValue.hpp>
36#include <java/LocalRef.hxx>
37#include <com/sun/star/uno/XComponentContext.hpp>
41#include <jni.h>
42#include <strings.hrc>
44#include <strings.hxx>
45
46#include <utility>
47#include <vector>
48#include <memory>
49
50using namespace connectivity;
51using namespace connectivity::jdbc;
52using namespace ::com::sun::star::uno;
53using namespace ::com::sun::star::beans;
54using namespace ::com::sun::star::sdbc;
55using namespace ::com::sun::star::container;
56using namespace ::com::sun::star::lang;
57
58namespace {
59
60struct ClassMapEntry {
61 ClassMapEntry(
62 OUString theClassPath, OUString theClassName):
63 classPath(std::move(theClassPath)), className(std::move(theClassName)), classLoader(nullptr),
64 classObject(nullptr) {}
65
66 OUString classPath;
67 OUString className;
68 jweak classLoader;
69 jweak classObject;
70};
71
72typedef std::vector< ClassMapEntry > ClassMap;
73
74struct ClassMapData {
75 osl::Mutex mutex;
76
77 ClassMap map;
78};
79
80template < typename T >
81bool getLocalFromWeakRef( jweak& _weak, LocalRef< T >& _inout_local )
82{
83 _inout_local.set( static_cast< T >( _inout_local.env().NewLocalRef( _weak ) ) );
84
85 if ( !_inout_local.is() )
86 {
87 if ( _inout_local.env().ExceptionCheck())
88 {
89 return false;
90 }
91 else if ( _weak != nullptr )
92 {
93 _inout_local.env().DeleteWeakGlobalRef( _weak );
94 _weak = nullptr;
95 }
96 }
97 return true;
98}
99
100// Load a class. A map from pairs of (classPath, name) to pairs of weak Java
101// references to (ClassLoader, Class) is maintained, so that a class is only
102// loaded once.
103//
104// It may happen that the weak reference to the ClassLoader becomes null while
105// the reference to the Class remains non-null (in case the Class was actually
106// loaded by some parent of the ClassLoader), in which case the ClassLoader is
107// resurrected (which cannot cause any classes to be loaded multiple times, as
108// the ClassLoader is no longer reachable, so no classes it has ever loaded are
109// still reachable).
110//
111// Similarly, it may happen that the weak reference to the Class becomes null
112// while the reference to the ClassLoader remains non-null, in which case the
113// Class is simply re-loaded.
114//
115// This code is close to the implementation of jvmaccess::ClassPath::loadClass
116// in jvmaccess/classpath.hxx, but not close enough to avoid the duplication.
117//
118// If false is returned, a (still pending) JNI exception occurred.
119bool loadClass(
120 Reference< XComponentContext > const & context, JNIEnv& environment,
121 OUString const & classPath, OUString const & name,
122 LocalRef< jobject > * classLoaderPtr, LocalRef< jclass > * classPtr)
123{
124 OSL_ASSERT(classLoaderPtr != nullptr);
125 // For any jweak entries still present in the map upon destruction,
126 // DeleteWeakGlobalRef is not called (which is a leak):
127 static ClassMapData classMapData;
128 osl::MutexGuard g(classMapData.mutex);
129 ClassMap::iterator i(classMapData.map.begin());
130 LocalRef< jobject > cloader(environment);
131 LocalRef< jclass > cl(environment);
132 // Prune dangling weak references from the list while searching for a match,
133 // so that the list cannot grow unbounded:
134 for (; i != classMapData.map.end();)
135 {
136 LocalRef< jobject > classLoader( environment );
137 if ( !getLocalFromWeakRef( i->classLoader, classLoader ) )
138 return false;
139
140 LocalRef< jclass > classObject( environment );
141 if ( !getLocalFromWeakRef( i->classObject, classObject ) )
142 return false;
143
144 if ( !classLoader.is() && !classObject.is() )
145 {
146 i = classMapData.map.erase(i);
147 }
148 else if ( i->classPath == classPath && i->className == name )
149 {
150 cloader.set( classLoader.release() );
151 cl.set( classObject.release() );
152 break;
153 }
154 else
155 {
156 ++i;
157 }
158 }
159 if ( !cloader.is() || !cl.is() )
160 {
161 if ( i == classMapData.map.end() )
162 {
163 // Push a new ClassMapEntry (which can potentially fail) before
164 // loading the class, so that it never happens that a class is
165 // loaded but not added to the map (which could have effects on the
166 // JVM that are not easily undone). If the pushed ClassMapEntry is
167 // not used after all (return false, etc.) it will be pruned on next
168 // call because its classLoader/classObject are null:
169 classMapData.map.push_back( ClassMapEntry( classPath, name ) );
170 i = std::prev(classMapData.map.end());
171 }
172
173 LocalRef< jclass > clClass( environment );
174 clClass.set( environment.FindClass( "java/net/URLClassLoader" ) );
175 if ( !clClass.is() )
176 return false;
177
178 jweak wcloader = nullptr;
179 if (!cloader.is())
180 {
181 jmethodID ctorLoader( environment.GetMethodID( clClass.get(), "<init>", "([Ljava/net/URL;)V" ) );
182 if (ctorLoader == nullptr)
183 return false;
184
185 LocalRef< jobjectArray > arr( environment );
186 arr.set( jvmaccess::ClassPath::translateToUrls( context, &environment, classPath ) );
187 if ( !arr.is() )
188 return false;
189
190 jvalue arg;
191 arg.l = arr.get();
192 cloader.set( environment.NewObjectA( clClass.get(), ctorLoader, &arg ) );
193 if ( !cloader.is() )
194 return false;
195
196 wcloader = environment.NewWeakGlobalRef( cloader.get() );
197 if ( wcloader == nullptr )
198 return false;
199 }
200
201 jweak wcl = nullptr;
202 if ( !cl.is() )
203 {
204 jmethodID methLoadClass( environment.GetMethodID( clClass.get(), "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;" ) );
205 if ( methLoadClass == nullptr )
206 return false;
207
208 LocalRef< jstring > str( environment );
209 str.set( convertwchar_tToJavaString( &environment, name ) );
210 if ( !str.is() )
211 return false;
212
213 jvalue arg;
214 arg.l = str.get();
215 cl.set( static_cast< jclass >( environment.CallObjectMethodA( cloader.get(), methLoadClass, &arg ) ) );
216 if ( !cl.is() )
217 return false;
218
219 wcl = environment.NewWeakGlobalRef( cl.get() );
220 if ( wcl == nullptr )
221 return false;
222 }
223
224 if ( wcloader != nullptr)
225 {
226 i->classLoader = wcloader;
227 }
228 if ( wcl != nullptr )
229 {
230 i->classObject = wcl;
231 }
232 }
233
234 classLoaderPtr->set( cloader.release() );
235 classPtr->set( cl.release() );
236 return true;
237}
238
239}
240
241
242IMPLEMENT_SERVICE_INFO(java_sql_Connection,"com.sun.star.sdbcx.JConnection","com.sun.star.sdbc.Connection");
243
244
245//************ Class: java.sql.Connection
246
247jclass java_sql_Connection::theClass = nullptr;
248
249java_sql_Connection::java_sql_Connection( const java_sql_Driver& _rDriver )
250 :m_xContext( _rDriver.getContext() )
251 ,m_pDriver( &_rDriver )
252 ,m_pDriverobject(nullptr)
253 ,m_Driver_theClass(nullptr)
254 ,m_aLogger( _rDriver.getLogger() )
255 ,m_bIgnoreDriverPrivileges(true)
256 ,m_bIgnoreCurrency(false)
257{
258}
259
261{
263 if ( !xTest.is() )
264 return;
265
267 clearObject(*t.pEnv);
268
269 {
270 if ( m_pDriverobject )
271 t.pEnv->DeleteGlobalRef( m_pDriverobject );
272 m_pDriverobject = nullptr;
273 if ( m_Driver_theClass )
274 t.pEnv->DeleteGlobalRef( m_Driver_theClass );
275 m_Driver_theClass = nullptr;
276 }
278}
279
281{
282 ::osl::MutexGuard aGuard(m_aMutex);
283
284 m_aLogger.log( LogLevel::INFO, STR_LOG_SHUTDOWN_CONNECTION );
285
287
288 if ( object )
289 {
290 static jmethodID mID(nullptr);
291 callVoidMethod_ThrowSQL("close", mID);
292 }
293}
294
296{
297 // the class must be fetched only once, therefore static
298 if( !theClass )
299 theClass = findMyClass("java/sql/Connection");
300 return theClass;
301}
302
303
305{
306 ::osl::MutexGuard aGuard( m_aMutex );
307 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
308
309 static jmethodID mID(nullptr);
310 return callStringMethod("getCatalog",mID);
311}
312
313Reference< XDatabaseMetaData > SAL_CALL java_sql_Connection::getMetaData( )
314{
315 ::osl::MutexGuard aGuard( m_aMutex );
316 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
317
318
319 Reference< XDatabaseMetaData > xMetaData = m_xMetaData;
320 if(!xMetaData.is())
321 {
322 SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!");
323 static jmethodID mID(nullptr);
324 jobject out = callObjectMethod(t.pEnv,"getMetaData","()Ljava/sql/DatabaseMetaData;", mID);
325 if(out)
326 {
327 xMetaData = new java_sql_DatabaseMetaData( t.pEnv, out, *this );
328 m_xMetaData = xMetaData;
329 }
330 }
331
332 return xMetaData;
333}
334
336{
337 dispose();
338}
339
341{
342 static jmethodID mID(nullptr);
343 callVoidMethod_ThrowSQL("commit", mID);
344}
345
347{
348 ::osl::MutexGuard aGuard( m_aMutex );
349
350 static jmethodID mID(nullptr);
351 return callBooleanMethod( "isClosed", mID ) && java_sql_Connection_BASE::rBHelper.bDisposed;
352}
353
355{
356 ::osl::MutexGuard aGuard( m_aMutex );
357 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
358 static jmethodID mID(nullptr);
359 return callBooleanMethod( "isReadOnly", mID );
360}
361
362void SAL_CALL java_sql_Connection::setCatalog( const OUString& catalog )
363{
364 static jmethodID mID(nullptr);
365 callVoidMethodWithStringArg("setCatalog",mID,catalog);
366}
367
369{
370 static jmethodID mID(nullptr);
371 callVoidMethod_ThrowSQL("rollback", mID);
372}
373
375{
376 static jmethodID mID(nullptr);
377 return callBooleanMethod( "getAutoCommit", mID );
378}
379
381{
382 static jmethodID mID(nullptr);
383 callVoidMethodWithBoolArg_ThrowSQL("setReadOnly", mID, readOnly);
384}
385
387{
388 static jmethodID mID(nullptr);
389 callVoidMethodWithBoolArg_ThrowSQL("setAutoCommit", mID, autoCommit);
390}
391
392Reference< css::container::XNameAccess > SAL_CALL java_sql_Connection::getTypeMap( )
393{
394 ::osl::MutexGuard aGuard( m_aMutex );
395 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
396
397 SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!");
398 static jmethodID mID(nullptr);
399 callObjectMethod(t.pEnv,"getTypeMap","()Ljava/util/Map;", mID);
400 // WARNING: the caller becomes the owner of the returned pointer
401 return nullptr;
402}
403
404void SAL_CALL java_sql_Connection::setTypeMap( const Reference< css::container::XNameAccess >& /*typeMap*/ )
405{
406 ::osl::MutexGuard aGuard( m_aMutex );
407 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
408
409 ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setTypeMap", *this );
410}
411
412
414{
415 ::osl::MutexGuard aGuard( m_aMutex );
416 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
417
418 static jmethodID mID(nullptr);
419 return callIntMethod_ThrowSQL("getTransactionIsolation", mID);
420}
421
422void SAL_CALL java_sql_Connection::setTransactionIsolation( sal_Int32 level )
423{
424 ::osl::MutexGuard aGuard( m_aMutex );
425 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
426
427 static jmethodID mID(nullptr);
428 callVoidMethodWithIntArg_ThrowSQL("setTransactionIsolation", mID, level);
429}
430
431Reference< XStatement > SAL_CALL java_sql_Connection::createStatement( )
432{
433 ::osl::MutexGuard aGuard( m_aMutex );
434 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
435 m_aLogger.log( LogLevel::FINE, STR_LOG_CREATE_STATEMENT );
436
438 rtl::Reference<java_sql_Statement> pStatement = new java_sql_Statement( t.pEnv, *this );
439 Reference< XStatement > xStmt = pStatement;
440 m_aStatements.push_back( WeakReferenceHelper( xStmt ) );
441
442 m_aLogger.log( LogLevel::FINE, STR_LOG_CREATED_STATEMENT_ID, pStatement->getStatementObjectID() );
443 return xStmt;
444}
445
446Reference< XPreparedStatement > SAL_CALL java_sql_Connection::prepareStatement( const OUString& sql )
447{
448 ::osl::MutexGuard aGuard( m_aMutex );
449 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
450 m_aLogger.log( LogLevel::FINE, STR_LOG_PREPARE_STATEMENT, sql );
451
453
455 Reference< XPreparedStatement > xReturn( pStatement );
456 m_aStatements.push_back(WeakReferenceHelper(xReturn));
457
458 m_aLogger.log( LogLevel::FINE, STR_LOG_PREPARED_STATEMENT_ID, pStatement->getStatementObjectID() );
459 return xReturn;
460}
461
462Reference< XPreparedStatement > SAL_CALL java_sql_Connection::prepareCall( const OUString& sql )
463{
464 ::osl::MutexGuard aGuard( m_aMutex );
465 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
466 m_aLogger.log( LogLevel::FINE, STR_LOG_PREPARE_CALL, sql );
467
469
471 Reference< XPreparedStatement > xStmt( pStatement );
472 m_aStatements.push_back(WeakReferenceHelper(xStmt));
473
474 m_aLogger.log( LogLevel::FINE, STR_LOG_PREPARED_CALL_ID, pStatement->getStatementObjectID() );
475 return xStmt;
476}
477
478OUString SAL_CALL java_sql_Connection::nativeSQL( const OUString& sql )
479{
480 ::osl::MutexGuard aGuard( m_aMutex );
481 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
482
483 OUString aStr;
484 SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!");
485 {
486
487 // initialize temporary Variable
488 static const char * const cSignature = "(Ljava/lang/String;)Ljava/lang/String;";
489 static const char * const cMethodName = "nativeSQL";
490 // Java-Call
491 static jmethodID mID(nullptr);
492 obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID);
493 // Convert Parameter
495
496 jobject out = t.pEnv->CallObjectMethod( object, mID, str.get() );
497 aStr = JavaString2String(t.pEnv, static_cast<jstring>(out) );
498 ThrowLoggedSQLException( m_aLogger, t.pEnv, *this );
499 } //t.pEnv
500
501 m_aLogger.log( LogLevel::FINER, STR_LOG_NATIVE_SQL, sql, aStr );
502
503 return aStr;
504}
505
507{
508 static jmethodID mID(nullptr);
509 callVoidMethod_ThrowSQL("clearWarnings", mID);
510}
511
513{
514 ::osl::MutexGuard aGuard( m_aMutex );
515 checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed);
516
518 static jmethodID mID(nullptr);
519 jobject out = callObjectMethod(t.pEnv,"getWarnings","()Ljava/sql/SQLWarning;", mID);
520 // WARNING: the caller becomes the owner of the returned pointer
521 if( out )
522 {
523 java_sql_SQLWarning_BASE warn_base(t.pEnv, out);
524 SQLException aAsException( java_sql_SQLWarning( warn_base, *this ) );
525
526 // translate to warning
527 SQLWarning aWarning;
528 aWarning.Context = aAsException.Context;
529 aWarning.Message = aAsException.Message;
530 aWarning.SQLState = aAsException.SQLState;
531 aWarning.ErrorCode = aAsException.ErrorCode;
532 aWarning.NextException = aAsException.NextException;
533
534 return Any( aWarning );
535 }
536
537 return Any();
538}
539
540
541namespace
542{
543 OUString lcl_getDriverLoadErrorMessage( const ::connectivity::SharedResources& _aResource,const OUString& _rDriverClass, const OUString& _rDriverClassPath )
544 {
545 OUString sError1( _aResource.getResourceStringWithSubstitution(
546 STR_NO_CLASSNAME,
547 "$classname$", _rDriverClass
548 ) );
549 if ( !_rDriverClassPath.isEmpty() )
550 {
551 const OUString sError2( _aResource.getResourceStringWithSubstitution(
552 STR_NO_CLASSNAME_PATH,
553 "$classpath$", _rDriverClassPath
554 ) );
555 sError1 += sError2;
556 } // if ( _rDriverClassPath.getLength() )
557 return sError1;
558 }
559}
560
561
562namespace
563{
564 bool lcl_setSystemProperties_nothrow( const java::sql::ConnectionLog& _rLogger,
565 JNIEnv& _rEnv, const Sequence< NamedValue >& _rSystemProperties )
566 {
567 if ( !_rSystemProperties.hasElements() )
568 // nothing to do
569 return true;
570
571 LocalRef< jclass > systemClass( _rEnv );
572 jmethodID nSetPropertyMethodID = nullptr;
573 // retrieve the java.lang.System class
574 systemClass.set( _rEnv.FindClass( "java/lang/System" ) );
575 if ( systemClass.is() )
576 {
577 nSetPropertyMethodID = _rEnv.GetStaticMethodID(
578 systemClass.get(), "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;" );
579 }
580
581 if ( nSetPropertyMethodID == nullptr )
582 return false;
583
584 for ( auto const & systemProp : _rSystemProperties )
585 {
586 OUString sValue;
587 OSL_VERIFY( systemProp.Value >>= sValue );
588
589 _rLogger.log( LogLevel::FINER, STR_LOG_SETTING_SYSTEM_PROPERTY, systemProp.Name, sValue );
590
591 LocalRef< jstring > jName( _rEnv, convertwchar_tToJavaString( &_rEnv, systemProp.Name ) );
592 LocalRef< jstring > jValue( _rEnv, convertwchar_tToJavaString( &_rEnv, sValue ) );
593
594 _rEnv.CallStaticObjectMethod( systemClass.get(), nSetPropertyMethodID, jName.get(), jValue.get() );
595 LocalRef< jthrowable > throwable( _rEnv, _rEnv.ExceptionOccurred() );
596 if ( throwable.is() )
597 return false;
598 }
599
600 return true;
601 }
602}
603
604
605void java_sql_Connection::loadDriverFromProperties( const OUString& _sDriverClass, const OUString& _sDriverClassPath,
606 const Sequence< NamedValue >& _rSystemProperties )
607{
608 // first try if the jdbc driver is already registered at the driver manager
610 try
611 {
612 if ( !object )
613 {
614 if ( !lcl_setSystemProperties_nothrow( getLogger(), *t.pEnv, _rSystemProperties ) )
615 ThrowLoggedSQLException( getLogger(), t.pEnv, *this );
616
618
619 // here I try to find the class for jdbc driver
622
623 if ( _sDriverClass.isEmpty() )
624 {
625 m_aLogger.log( LogLevel::SEVERE, STR_LOG_NO_DRIVER_CLASS );
627 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass, _sDriverClassPath ),
628 *this
629 );
630 }
631 else
632 {
633 m_aLogger.log( LogLevel::INFO, STR_LOG_LOADING_DRIVER, _sDriverClass );
634 // the driver manager holds the class of the driver for later use
635 std::unique_ptr< java_lang_Class > pDrvClass;
636 if ( _sDriverClassPath.isEmpty() )
637 {
638 // if forName didn't find the class it will throw an exception
639 pDrvClass.reset(java_lang_Class::forName(_sDriverClass));
640 }
641 else
642 {
643 LocalRef< jclass > driverClass(t.env());
644 LocalRef< jobject > driverClassLoader(t.env());
645
646 loadClass(
648 t.env(), _sDriverClassPath, _sDriverClass, &driverClassLoader, &driverClass );
649
650 m_pDriverClassLoader.set( driverClassLoader );
651 pDrvClass.reset( new java_lang_Class( t.pEnv, driverClass.release() ) );
652
653 ThrowLoggedSQLException( m_aLogger, t.pEnv, *this );
654 }
655 if (pDrvClass)
656 {
657 LocalRef< jobject > driverObject( t.env() );
658 driverObject.set( pDrvClass->newInstanceObject() );
659 ThrowLoggedSQLException( m_aLogger, t.pEnv, *this );
660 m_pDriverobject = driverObject.release();
661
662 if( m_pDriverobject )
663 m_pDriverobject = t.pEnv->NewGlobalRef( m_pDriverobject );
664
665 {
666 jclass tempClass = t.pEnv->GetObjectClass(m_pDriverobject);
667 if ( m_pDriverobject )
668 {
669 m_Driver_theClass = static_cast<jclass>(t.pEnv->NewGlobalRef( tempClass ));
670 t.pEnv->DeleteLocalRef( tempClass );
671 }
672 }
673 }
674 m_aLogger.log( LogLevel::INFO, STR_LOG_CONN_SUCCESS );
675 }
676 }
677 }
678 catch( const SQLException& )
679 {
680 css::uno::Any anyEx = cppu::getCaughtException();
681 throw SQLException(
682 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass, _sDriverClassPath ),
683 *this,
684 OUString(),
685 1000,
686 anyEx);
687 }
688 catch( Exception& )
689 {
690 css::uno::Any anyEx = cppu::getCaughtException();
692 lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass, _sDriverClassPath ),
693 *this,
694 anyEx
695 );
696 }
697}
698
699OUString java_sql_Connection::impl_getJavaDriverClassPath_nothrow(const OUString& _sDriverClass)
700{
701 static constexpr OUStringLiteral s_sNodeName
702 = u"org.openoffice.Office.DataAccess/JDBC/DriverClassPaths";
705 OUString sURL;
706 if ( aNamesRoot.isValid() && aNamesRoot.hasByName( _sDriverClass ) )
707 {
708 ::utl::OConfigurationNode aRegisterObj = aNamesRoot.openNode( _sDriverClass );
709 OSL_VERIFY( aRegisterObj.getNodeValue( "Path" ) >>= sURL );
710 }
711 return sURL;
712}
713
714bool java_sql_Connection::construct(const OUString& url,
715 const Sequence< PropertyValue >& info)
716{
717 { // initialize the java vm
719 if ( !xTest.is() )
720 throwGenericSQLException(STR_NO_JAVA,*this);
721 }
723 SDBThreadAttach::addRef(); // will be released in dtor
724 if ( !t.pEnv )
725 throwGenericSQLException(STR_NO_JAVA,*this);
726
727 OUString sGeneratedValueStatement; // contains the statement which should be used when query for automatically generated values
728 bool bAutoRetrievingEnabled = false; // set to <TRUE/> when we should allow to query for generated values
729 OUString sDriverClassPath,sDriverClass;
730 Sequence< NamedValue > aSystemProperties;
731
732 ::comphelper::NamedValueCollection aSettings( info );
733 sDriverClass = aSettings.getOrDefault( "JavaDriverClass", sDriverClass );
734 sDriverClassPath = aSettings.getOrDefault( "JavaDriverClassPath", sDriverClassPath);
735 if ( sDriverClassPath.isEmpty() )
736 sDriverClassPath = impl_getJavaDriverClassPath_nothrow(sDriverClass);
737 bAutoRetrievingEnabled = aSettings.getOrDefault( "IsAutoRetrievingEnabled", bAutoRetrievingEnabled );
738 sGeneratedValueStatement = aSettings.getOrDefault( "AutoRetrievingStatement", sGeneratedValueStatement );
739 m_bIgnoreDriverPrivileges = aSettings.getOrDefault( "IgnoreDriverPrivileges", m_bIgnoreDriverPrivileges );
740 m_bIgnoreCurrency = aSettings.getOrDefault( "IgnoreCurrency", m_bIgnoreCurrency );
741 aSystemProperties = aSettings.getOrDefault( "SystemProperties", aSystemProperties );
742 m_aCatalogRestriction = aSettings.getOrDefault( "ImplicitCatalogRestriction", Any() );
743 m_aSchemaRestriction = aSettings.getOrDefault( "ImplicitSchemaRestriction", Any() );
744
745 loadDriverFromProperties( sDriverClass, sDriverClassPath, aSystemProperties );
746
747 enableAutoRetrievingEnabled(bAutoRetrievingEnabled);
748 setAutoRetrievingStatement(sGeneratedValueStatement);
749
750 if ( t.pEnv && m_Driver_theClass && m_pDriverobject )
751 {
752 // Java-Call
753 static const char * const cSignature = "(Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection;";
754 static const char * const cMethodName = "connect";
755 jmethodID mID = t.pEnv->GetMethodID( m_Driver_theClass, cMethodName, cSignature );
756
757 if ( mID )
758 {
759 jvalue args[2];
760 // convert Parameter
761 args[0].l = convertwchar_tToJavaString(t.pEnv,url);
762 std::unique_ptr<java_util_Properties> pProps = createStringPropertyArray(info);
763 args[1].l = pProps->getJavaObject();
764
765 LocalRef< jobject > ensureDelete( t.env(), args[0].l );
766
767 jobject out = nullptr;
768 // In some cases (e.g.,
769 // connectivity/source/drivers/hsqldb/HDriver.cxx:1.24
770 // l. 249) the JavaDriverClassPath contains multiple jars,
771 // as creating the JavaDriverClass instance requires
772 // (reflective) access to those other jars. Now, if the
773 // JavaDriverClass is actually loaded by some parent class
774 // loader (e.g., because its jar is also on the global
775 // class path), it would still not have access to the
776 // additional jars on the JavaDriverClassPath. Hence, the
777 // JavaDriverClassPath class loader is pushed as context
778 // class loader around the JavaDriverClass instance
779 // creation:
780 // #i82222# / 2007-10-15
781 {
783 out = t.pEnv->CallObjectMethod( m_pDriverobject, mID, args[0].l,args[1].l );
784 pProps.reset();
785 ThrowLoggedSQLException( m_aLogger, t.pEnv, *this );
786 }
787
788 if ( !out )
789 m_aLogger.log( LogLevel::SEVERE, STR_LOG_NO_SYSTEM_CONNECTION );
790
791 if ( out )
792 object = t.pEnv->NewGlobalRef( out );
793
794 if ( object )
795 m_aLogger.log( LogLevel::INFO, STR_LOG_GOT_JDBC_CONNECTION, url );
796
797 m_aConnectionInfo = info;
798 } //mID
799 } //t.pEnv
800 return object != nullptr;
801}
802
803
804/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
IMPLEMENT_SERVICE_INFO(java_sql_Connection,"com.sun.star.sdbcx.JConnection","com.sun.star.sdbc.Connection")
Reference< XComponentContext > m_xContext
XPropertyListType t
VALUE_TYPE getOrDefault(const OUString &_rValueName, const VALUE_TYPE &_rDefault) const
void setAutoRetrievingStatement(const OUString &_sStmt)
void enableAutoRetrievingEnabled(bool _bAutoEnable)
css::uno::Sequence< css::beans::PropertyValue > m_aConnectionInfo
Definition: TConnection.hxx:46
connectivity::OWeakRefArray m_aStatements
Definition: TConnection.hxx:47
css::uno::WeakReference< css::sdbc::XDatabaseMetaData > m_xMetaData
Definition: TConnection.hxx:53
const SharedResources & getResources() const
Definition: TConnection.hxx:65
void throwGenericSQLException(TranslateId pErrorResourceId, const css::uno::Reference< css::uno::XInterface > &_xContext)
Definition: TConnection.cxx:74
virtual void SAL_CALL disposing() override
Definition: TConnection.cxx:39
static void releaseRef()
Definition: Object.cxx:81
void log(const sal_Int32 _nLogLevel, const OUString &rMessage)
logs a given message, without any arguments, or source class/method names
static java_lang_Class * forName(std::u16string_view _par0)
Definition: Class.cxx:39
jobject callObjectMethod(JNIEnv *pEnv, const char *_pMethodName, const char *_pSignature, jmethodID &_inout_MethodID) const
Definition: Object.cxx:404
sal_Int32 callIntMethod_ThrowSQL(const char *_pMethodName, jmethodID &_inout_MethodID) const
Definition: Object.cxx:286
bool callBooleanMethod(const char *_pMethodName, jmethodID &_inout_MethodID) const
Definition: Object.cxx:252
static ::rtl::Reference< jvmaccess::VirtualMachine > getVM(const css::uno::Reference< css::uno::XComponentContext > &_rxContext=nullptr)
Definition: Object.cxx:49
void callVoidMethodWithStringArg(const char *_pMethodName, jmethodID &_inout_MethodID, const OUString &_nArgument) const
Definition: Object.cxx:432
void callVoidMethod_ThrowSQL(const char *_pMethodName, jmethodID &_inout_MethodID) const
Definition: Object.cxx:330
void callVoidMethodWithIntArg_ThrowSQL(const char *_pMethodName, jmethodID &_inout_MethodID, sal_Int32 _nArgument) const
Definition: Object.cxx:352
OUString callStringMethod(const char *_pMethodName, jmethodID &_inout_MethodID) const
Definition: Object.cxx:394
static void ThrowLoggedSQLException(const ::comphelper::EventLogger &_rLogger, JNIEnv *pEnvironment, const css::uno::Reference< css::uno::XInterface > &_rxContext)
Definition: Object.cxx:197
static jclass findMyClass(const char *_pClassName)
Definition: Object.cxx:466
void callVoidMethodWithBoolArg_ThrowSQL(const char *_pMethodName, jmethodID &_inout_MethodID, bool _nArgument) const
Definition: Object.cxx:374
void obtainMethodId_throwSQL(JNIEnv *_pEnv, const char *_pMethodName, const char *_pSignature, jmethodID &_inout_MethodID) const
Definition: Object.cxx:229
virtual void SAL_CALL rollback() override
virtual void SAL_CALL setTypeMap(const css::uno::Reference< css::container::XNameAccess > &typeMap) override
virtual void SAL_CALL setAutoCommit(sal_Bool autoCommit) override
virtual sal_Bool SAL_CALL isClosed() override
virtual void SAL_CALL commit() override
virtual css::uno::Reference< css::sdbc::XStatement > SAL_CALL createStatement() override
virtual void SAL_CALL setTransactionIsolation(sal_Int32 level) override
virtual void SAL_CALL setCatalog(const OUString &catalog) override
virtual css::uno::Any SAL_CALL getWarnings() override
virtual css::uno::Reference< css::sdbc::XPreparedStatement > SAL_CALL prepareStatement(const OUString &sql) override
virtual void SAL_CALL disposing() override
virtual void SAL_CALL close() override
virtual ~java_sql_Connection() override
jdbc::GlobalRef< jobject > m_pDriverClassLoader
virtual css::uno::Reference< css::sdbc::XPreparedStatement > SAL_CALL prepareCall(const OUString &sql) override
virtual sal_Int32 SAL_CALL getTransactionIsolation() override
bool construct(const OUString &url, const css::uno::Sequence< css::beans::PropertyValue > &info)
virtual css::uno::Reference< css::sdbc::XDatabaseMetaData > SAL_CALL getMetaData() override
const jdbc::GlobalRef< jobject > & getDriverClassLoader() const
returns the class loader which was used to load the driver class
virtual sal_Bool SAL_CALL getAutoCommit() override
virtual void SAL_CALL clearWarnings() override
const java::sql::ConnectionLog & getLogger() const
returns the instance used for logging events related to this connection
virtual void SAL_CALL setReadOnly(sal_Bool readOnly) override
void loadDriverFromProperties(const OUString &_sDriverClass, const OUString &_sDriverClassPath, const css::uno::Sequence< css::beans::NamedValue > &_rSystemProperties)
virtual OUString SAL_CALL nativeSQL(const OUString &sql) override
virtual css::uno::Reference< css::container::XNameAccess > SAL_CALL getTypeMap() override
virtual sal_Bool SAL_CALL isReadOnly() override
virtual OUString SAL_CALL getCatalog() override
OUString impl_getJavaDriverClassPath_nothrow(const OUString &_sDriverClass)
load driver class path from system configuration.
css::uno::Reference< css::uno::XComponentContext > m_xContext
virtual jclass getMyClass() const override
const css::uno::Reference< css::uno::XComponentContext > & getContext() const
void set(JNIEnv &_environment, T _object)
Definition: GlobalRef.hxx:70
helper class to hold a local ref to a JNI object
Definition: LocalRef.hxx:42
JNIEnv & env() const
Definition: LocalRef.hxx:79
css::uno::Any getNodeValue(const OUString &_rPath) const noexcept
bool hasByName(const OUString &_rName) const noexcept
OConfigurationNode openNode(const OUString &_rPath) const noexcept
static OConfigurationTreeRoot createWithComponentContext(const css::uno::Reference< css::uno::XComponentContext > &_rxContext, const OUString &_rPath, sal_Int32 _nDepth=-1, CREATION_MODE _eMode=CM_UPDATABLE)
float u
aStr
@ Exception
OUString JavaString2String(JNIEnv *pEnv, jstring Str)
Definition: tools.cxx:162
jstring convertwchar_tToJavaString(JNIEnv *pEnv, const OUString &Temp)
Definition: tools.cxx:93
std::unique_ptr< java_util_Properties > createStringPropertyArray(const css::uno::Sequence< css::beans::PropertyValue > &info)
void checkDisposed(bool _bThrow)
Definition: dbtools.cxx:1951
Any SAL_CALL getCaughtException()
void throwFeatureNotImplementedSQLException(const OUString &_rFeatureName, const Reference< XInterface > &_rxContext, const Any &_rNextException)
void throwGenericSQLException(const OUString &_rMsg, const css::uno::Reference< css::uno::XInterface > &_rxSource)
throw a generic SQLException, i.e.
int i
arr
JVMACCESS_DLLPUBLIC jobjectArray translateToUrls(css::uno::Reference< css::uno::XComponentContext > const &context, JNIEnv *environment, std::u16string_view classPath)
args
void dispose()
OUString name
Definition: pq_statics.cxx:74
std::map< OUString, rtl::Reference< Entity > > map
constexpr OUStringLiteral STR_LOG_GOT_JDBC_CONNECTION
Definition: strings.hxx:29
constexpr OUStringLiteral STR_LOG_PREPARED_CALL_ID
Definition: strings.hxx:23
constexpr OUStringLiteral STR_LOG_SETTING_SYSTEM_PROPERTY
Definition: strings.hxx:71
constexpr OUStringLiteral STR_LOG_PREPARE_CALL
Definition: strings.hxx:22
constexpr OUStringLiteral STR_LOG_PREPARE_STATEMENT
Definition: strings.hxx:20
constexpr OUStringLiteral STR_LOG_NO_SYSTEM_CONNECTION
Definition: strings.hxx:28
constexpr OUStringLiteral STR_LOG_CONN_SUCCESS
Definition: strings.hxx:27
constexpr OUStringLiteral STR_LOG_CREATED_STATEMENT_ID
Definition: strings.hxx:19
constexpr OUStringLiteral STR_LOG_NO_DRIVER_CLASS
Definition: strings.hxx:26
constexpr OUStringLiteral STR_LOG_SHUTDOWN_CONNECTION
Definition: strings.hxx:30
constexpr OUStringLiteral STR_LOG_NATIVE_SQL
Definition: strings.hxx:24
constexpr OUStringLiteral STR_LOG_PREPARED_STATEMENT_ID
Definition: strings.hxx:21
constexpr OUStringLiteral STR_LOG_CREATE_STATEMENT
Definition: strings.hxx:18
constexpr OUStringLiteral STR_LOG_LOADING_DRIVER
Definition: strings.hxx:25
std::mutex mutex
unsigned char sal_Bool