1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <connectivity/CommonTools.hxx>
21 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
22 #include <com/sun/star/logging/LogLevel.hpp>
23 #include <java/tools.hxx>
24 #include <java/sql/SQLException.hxx>
25 #include <osl/diagnose.h>
26 #include <java/LocalRef.hxx>
27 #include <strings.hxx>
29 #include <comphelper/logging.hxx>
30 #include <cppuhelper/exc_hlp.hxx>
32 using namespace connectivity
;
33 using namespace ::com::sun::star::uno
;
34 using namespace ::com::sun::star::sdbc
;
35 using namespace ::com::sun::star::lang
;
38 static ::rtl::Reference
< jvmaccess::VirtualMachine
> const & getJavaVM2(const ::rtl::Reference
< jvmaccess::VirtualMachine
>& _rVM
= ::rtl::Reference
< jvmaccess::VirtualMachine
>(),
41 static ::rtl::Reference
< jvmaccess::VirtualMachine
> s_VM
;
42 if ( _rVM
.is() || _bSet
)
47 ::rtl::Reference
< jvmaccess::VirtualMachine
> java_lang_Object::getVM(const Reference
<XComponentContext
>& _rxContext
)
49 ::rtl::Reference
< jvmaccess::VirtualMachine
> xVM
= getJavaVM2();
50 if ( !xVM
.is() && _rxContext
.is() )
51 xVM
= getJavaVM2(::connectivity::getJavaVM(_rxContext
));
56 SDBThreadAttach::SDBThreadAttach()
57 : m_aGuard(java_lang_Object::getVM())
60 pEnv
= m_aGuard
.getEnvironment();
61 OSL_ENSURE(pEnv
,"Environment is nULL!");
64 SDBThreadAttach::~SDBThreadAttach()
68 static oslInterlockedCount
& getJavaVMRefCount()
70 static oslInterlockedCount s_nRefCount
= 0;
74 void SDBThreadAttach::addRef()
76 osl_atomic_increment(&getJavaVMRefCount());
79 void SDBThreadAttach::releaseRef()
81 osl_atomic_decrement(&getJavaVMRefCount());
82 if ( getJavaVMRefCount() == 0 )
84 getJavaVM2(::rtl::Reference
< jvmaccess::VirtualMachine
>(),true);
88 // static variables of the class
89 jclass
java_lang_Object::theClass
= nullptr;
91 jclass
java_lang_Object::getMyClass() const
94 theClass
= findMyClass("java/lang/Object");
97 // the actual constructor
98 java_lang_Object::java_lang_Object()
101 SDBThreadAttach::addRef();
104 // the protected-constructor for the derived classes
105 java_lang_Object::java_lang_Object( JNIEnv
* pXEnv
, jobject myObj
)
108 SDBThreadAttach::addRef();
110 object
= pXEnv
->NewGlobalRef( myObj
);
113 java_lang_Object::~java_lang_Object() COVERITY_NOEXCEPT_FALSE
118 clearObject(*t
.pEnv
);
120 SDBThreadAttach::releaseRef();
122 void java_lang_Object::clearObject(JNIEnv
& rEnv
)
126 rEnv
.DeleteGlobalRef( object
);
131 void java_lang_Object::clearObject()
136 clearObject(*t
.pEnv
);
139 // the protected-constructor for the derived classes
140 void java_lang_Object::saveRef( JNIEnv
* pXEnv
, jobject myObj
)
142 OSL_ENSURE( myObj
, "object in c++ -> Java Wrapper" );
144 object
= pXEnv
->NewGlobalRef( myObj
);
148 OUString
java_lang_Object::toString() const
150 static jmethodID
mID(nullptr);
151 return callStringMethod("toString",mID
);
157 bool lcl_translateJNIExceptionToUNOException(
158 JNIEnv
* _pEnvironment
, const Reference
< XInterface
>& _rxContext
, SQLException
& _out_rException
)
160 jthrowable jThrow
= _pEnvironment
? _pEnvironment
->ExceptionOccurred() : nullptr;
164 _pEnvironment
->ExceptionClear();
165 // we have to clear the exception here because we want to handle it itself
167 if ( _pEnvironment
->IsInstanceOf( jThrow
, java_sql_SQLException_BASE::st_getMyClass() ) )
169 java_sql_SQLException_BASE
aException( _pEnvironment
, jThrow
);
170 _out_rException
= SQLException( aException
.getMessage(), _rxContext
,
171 aException
.getSQLState(), aException
.getErrorCode(), Any() );
174 else if ( _pEnvironment
->IsInstanceOf( jThrow
, java_lang_Throwable::st_getMyClass() ) )
176 java_lang_Throwable
aThrow( _pEnvironment
, jThrow
);
177 #if OSL_DEBUG_LEVEL > 0
178 aThrow
.printStackTrace();
180 OUString sMessage
= aThrow
.getMessage();
181 if ( sMessage
.isEmpty() )
182 sMessage
= aThrow
.getLocalizedMessage();
183 if( sMessage
.isEmpty() )
184 sMessage
= aThrow
.toString();
185 _out_rException
= SQLException( sMessage
, _rxContext
, OUString(), -1, Any() );
189 _pEnvironment
->DeleteLocalRef( jThrow
);
195 void java_lang_Object::ThrowLoggedSQLException( const ::comphelper::EventLogger
& _rLogger
, JNIEnv
* _pEnvironment
,
196 const Reference
< XInterface
>& _rxContext
)
198 SQLException aException
;
199 if ( lcl_translateJNIExceptionToUNOException( _pEnvironment
, _rxContext
, aException
) )
201 _rLogger
.log( css::logging::LogLevel::SEVERE
, STR_LOG_THROWING_EXCEPTION
, aException
.Message
, aException
.SQLState
, aException
.ErrorCode
);
206 void java_lang_Object::ThrowSQLException( JNIEnv
* _pEnvironment
, const Reference
< XInterface
>& _rxContext
)
208 SQLException aException
;
209 if ( lcl_translateJNIExceptionToUNOException( _pEnvironment
, _rxContext
, aException
) )
213 void java_lang_Object::ThrowRuntimeException( JNIEnv
* _pEnvironment
, const Reference
< XInterface
>& _rxContext
)
217 ThrowSQLException(_pEnvironment
, _rxContext
);
219 catch (const SQLException
& e
)
221 css::uno::Any anyEx
= cppu::getCaughtException();
222 throw css::lang::WrappedTargetRuntimeException( e
.Message
,
227 void java_lang_Object::obtainMethodId_throwSQL(JNIEnv
* _pEnv
,const char* _pMethodName
, const char* _pSignature
,jmethodID
& _inout_MethodID
) const
229 if ( !_inout_MethodID
)
231 _inout_MethodID
= _pEnv
->GetMethodID( getMyClass(), _pMethodName
, _pSignature
);
232 OSL_ENSURE( _inout_MethodID
, _pSignature
);
233 if ( !_inout_MethodID
)
234 throw SQLException();
235 } // if ( !_inout_MethodID )
238 void java_lang_Object::obtainMethodId_throwRuntime(JNIEnv
* _pEnv
,const char* _pMethodName
, const char* _pSignature
,jmethodID
& _inout_MethodID
) const
240 if ( !_inout_MethodID
)
242 _inout_MethodID
= _pEnv
->GetMethodID( getMyClass(), _pMethodName
, _pSignature
);
243 OSL_ENSURE( _inout_MethodID
, _pSignature
);
244 if ( !_inout_MethodID
)
245 throw RuntimeException();
246 } // if ( !_inout_MethodID )
250 bool java_lang_Object::callBooleanMethod( const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
255 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callBooleanMethod: no Java environment anymore!" );
256 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"()Z", _inout_MethodID
);
258 out
= t
.pEnv
->CallBooleanMethod( object
, _inout_MethodID
);
259 ThrowSQLException( t
.pEnv
, nullptr );
264 bool java_lang_Object::callBooleanMethodWithIntArg( const char* _pMethodName
, jmethodID
& _inout_MethodID
, sal_Int32 _nArgument
) const
268 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callBooleanMethodWithIntArg: no Java environment anymore!" );
269 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(I)Z", _inout_MethodID
);
271 out
= t
.pEnv
->CallBooleanMethod( object
, _inout_MethodID
, _nArgument
);
272 ThrowSQLException( t
.pEnv
, nullptr );
277 jobject
java_lang_Object::callResultSetMethod( JNIEnv
& _rEnv
,const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
280 jobject out
= callObjectMethod(&_rEnv
,_pMethodName
,"()Ljava/sql/ResultSet;", _inout_MethodID
);
284 sal_Int32
java_lang_Object::callIntMethod_ThrowSQL(const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
287 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
288 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"()I", _inout_MethodID
);
290 jint
out( t
.pEnv
->CallIntMethod( object
, _inout_MethodID
) );
291 ThrowSQLException( t
.pEnv
, nullptr );
292 return static_cast<sal_Int32
>(out
);
295 sal_Int32
java_lang_Object::callIntMethod_ThrowRuntime(const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
298 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
299 obtainMethodId_throwRuntime(t
.pEnv
, _pMethodName
,"()I", _inout_MethodID
);
301 jint
out( t
.pEnv
->CallIntMethod( object
, _inout_MethodID
) );
302 ThrowRuntimeException(t
.pEnv
, nullptr);
303 return static_cast<sal_Int32
>(out
);
306 sal_Int32
java_lang_Object::callIntMethodWithIntArg_ThrowSQL( const char* _pMethodName
, jmethodID
& _inout_MethodID
,sal_Int32 _nArgument
) const
309 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
310 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(I)I", _inout_MethodID
);
312 jint
out( t
.pEnv
->CallIntMethod( object
, _inout_MethodID
, _nArgument
) );
313 ThrowSQLException( t
.pEnv
, nullptr );
314 return static_cast<sal_Int32
>(out
);
317 sal_Int32
java_lang_Object::callIntMethodWithIntArg_ThrowRuntime( const char* _pMethodName
, jmethodID
& _inout_MethodID
,sal_Int32 _nArgument
) const
320 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
321 obtainMethodId_throwRuntime(t
.pEnv
, _pMethodName
,"(I)I", _inout_MethodID
);
323 jint
out( t
.pEnv
->CallIntMethod( object
, _inout_MethodID
, _nArgument
) );
324 ThrowRuntimeException(t
.pEnv
, nullptr);
325 return static_cast<sal_Int32
>(out
);
328 void java_lang_Object::callVoidMethod_ThrowSQL( const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
331 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
332 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"()V", _inout_MethodID
);
335 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
);
336 ThrowSQLException( t
.pEnv
, nullptr );
339 void java_lang_Object::callVoidMethod_ThrowRuntime( const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
342 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
343 obtainMethodId_throwRuntime(t
.pEnv
, _pMethodName
,"()V", _inout_MethodID
);
346 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
);
347 ThrowRuntimeException(t
.pEnv
, nullptr);
350 void java_lang_Object::callVoidMethodWithIntArg_ThrowSQL( const char* _pMethodName
, jmethodID
& _inout_MethodID
, sal_Int32 _nArgument
) const
353 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
354 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(I)V", _inout_MethodID
);
357 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
,_nArgument
);
358 ThrowSQLException( t
.pEnv
, nullptr );
361 void java_lang_Object::callVoidMethodWithIntArg_ThrowRuntime( const char* _pMethodName
, jmethodID
& _inout_MethodID
, sal_Int32 _nArgument
) const
364 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
365 obtainMethodId_throwRuntime(t
.pEnv
, _pMethodName
,"(I)V", _inout_MethodID
);
368 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
,_nArgument
);
369 ThrowRuntimeException(t
.pEnv
, nullptr);
372 void java_lang_Object::callVoidMethodWithBoolArg_ThrowSQL( const char* _pMethodName
, jmethodID
& _inout_MethodID
, bool _nArgument
) const
375 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
376 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(Z)V", _inout_MethodID
);
378 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
,int(_nArgument
) );
379 ThrowSQLException( t
.pEnv
, nullptr );
382 void java_lang_Object::callVoidMethodWithBoolArg_ThrowRuntime( const char* _pMethodName
, jmethodID
& _inout_MethodID
, bool _nArgument
) const
385 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
386 obtainMethodId_throwRuntime(t
.pEnv
, _pMethodName
,"(Z)V", _inout_MethodID
);
388 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
,int(_nArgument
) );
389 ThrowRuntimeException(t
.pEnv
, nullptr);
392 OUString
java_lang_Object::callStringMethod( const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
395 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callStringMethod: no Java environment anymore!" );
398 jstring out
= static_cast<jstring
>(callObjectMethod(t
.pEnv
,_pMethodName
,"()Ljava/lang/String;", _inout_MethodID
));
399 return JavaString2String( t
.pEnv
, out
);
402 jobject
java_lang_Object::callObjectMethod( JNIEnv
* _pEnv
,const char* _pMethodName
,const char* _pSignature
, jmethodID
& _inout_MethodID
) const
405 obtainMethodId_throwSQL(_pEnv
, _pMethodName
,_pSignature
, _inout_MethodID
);
407 jobject out
= _pEnv
->CallObjectMethod( object
, _inout_MethodID
);
408 ThrowSQLException( _pEnv
, nullptr );
413 jobject
java_lang_Object::callObjectMethodWithIntArg( JNIEnv
* _pEnv
,const char* _pMethodName
,const char* _pSignature
, jmethodID
& _inout_MethodID
, sal_Int32 _nArgument
) const
415 obtainMethodId_throwSQL(_pEnv
, _pMethodName
,_pSignature
, _inout_MethodID
);
417 jobject out
= _pEnv
->CallObjectMethod( object
, _inout_MethodID
,_nArgument
);
418 ThrowSQLException( _pEnv
, nullptr );
422 OUString
java_lang_Object::callStringMethodWithIntArg( const char* _pMethodName
, jmethodID
& _inout_MethodID
, sal_Int32 _nArgument
) const
425 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callStringMethod: no Java environment anymore!" );
426 jstring out
= static_cast<jstring
>(callObjectMethodWithIntArg(t
.pEnv
,_pMethodName
,"(I)Ljava/lang/String;",_inout_MethodID
,_nArgument
));
427 return JavaString2String( t
.pEnv
, out
);
430 void java_lang_Object::callVoidMethodWithStringArg( const char* _pMethodName
, jmethodID
& _inout_MethodID
,const OUString
& _nArgument
) const
433 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
434 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(Ljava/lang/String;)V", _inout_MethodID
);
436 jdbc::LocalRef
< jstring
> str( t
.env(),convertwchar_tToJavaString(t
.pEnv
,_nArgument
));
438 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
, str
.get());
439 ThrowSQLException( t
.pEnv
, nullptr );
442 sal_Int32
java_lang_Object::callIntMethodWithStringArg( const char* _pMethodName
, jmethodID
& _inout_MethodID
,const OUString
& _nArgument
) const
445 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethodWithStringArg: no Java environment anymore!" );
446 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(Ljava/lang/String;)I", _inout_MethodID
);
448 //TODO: Check if the code below is needed
449 //jdbc::LocalRef< jstring > str( t.env(), convertwchar_tToJavaString( t.pEnv, sql ) );
451 // jdbc::ContextClassLoaderScope ccl( t.env(),
452 // m_pConnection ? m_pConnection->getDriverClassLoader() : jdbc::GlobalRef< jobject >(),
457 jdbc::LocalRef
< jstring
> str( t
.env(),convertwchar_tToJavaString(t
.pEnv
,_nArgument
));
459 jint out
= t
.pEnv
->CallIntMethod( object
, _inout_MethodID
, str
.get());
460 ThrowSQLException( t
.pEnv
, nullptr );
461 return static_cast<sal_Int32
>(out
);
464 jclass
java_lang_Object::findMyClass(const char* _pClassName
)
466 // the class must be fetched only once, therefore static
468 jclass tempClass
= t
.pEnv
->FindClass(_pClassName
); OSL_ENSURE(tempClass
,"Java : FindClass not successful!");
471 t
.pEnv
->ExceptionDescribe();
472 t
.pEnv
->ExceptionClear();
474 jclass globClass
= static_cast<jclass
>(t
.pEnv
->NewGlobalRef( tempClass
));
475 t
.pEnv
->DeleteLocalRef( tempClass
);
479 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */