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>
34 using namespace connectivity
;
35 using namespace ::com::sun::star::uno
;
36 using namespace ::com::sun::star::beans
;
37 using namespace ::com::sun::star::sdbc
;
38 using namespace ::com::sun::star::container
;
39 using namespace ::com::sun::star::lang
;
42 static ::rtl::Reference
< jvmaccess::VirtualMachine
> const & getJavaVM2(const ::rtl::Reference
< jvmaccess::VirtualMachine
>& _rVM
= ::rtl::Reference
< jvmaccess::VirtualMachine
>(),
45 static ::rtl::Reference
< jvmaccess::VirtualMachine
> s_VM
;
46 if ( _rVM
.is() || _bSet
)
51 ::rtl::Reference
< jvmaccess::VirtualMachine
> java_lang_Object::getVM(const Reference
<XComponentContext
>& _rxContext
)
53 ::rtl::Reference
< jvmaccess::VirtualMachine
> xVM
= getJavaVM2();
54 if ( !xVM
.is() && _rxContext
.is() )
55 xVM
= getJavaVM2(::connectivity::getJavaVM(_rxContext
));
60 SDBThreadAttach::SDBThreadAttach()
61 : m_aGuard(java_lang_Object::getVM())
64 pEnv
= m_aGuard
.getEnvironment();
65 OSL_ENSURE(pEnv
,"Environment is nULL!");
68 SDBThreadAttach::~SDBThreadAttach()
72 static oslInterlockedCount
& getJavaVMRefCount()
74 static oslInterlockedCount s_nRefCount
= 0;
78 void SDBThreadAttach::addRef()
80 osl_atomic_increment(&getJavaVMRefCount());
83 void SDBThreadAttach::releaseRef()
85 osl_atomic_decrement(&getJavaVMRefCount());
86 if ( getJavaVMRefCount() == 0 )
88 getJavaVM2(::rtl::Reference
< jvmaccess::VirtualMachine
>(),true);
92 // static variables of the class
93 jclass
java_lang_Object::theClass
= nullptr;
95 jclass
java_lang_Object::getMyClass() const
98 theClass
= findMyClass("java/lang/Object");
101 // the actual constructor
102 java_lang_Object::java_lang_Object()
105 SDBThreadAttach::addRef();
108 // the protected-constructor for the derived classes
109 java_lang_Object::java_lang_Object( JNIEnv
* pXEnv
, jobject myObj
)
112 SDBThreadAttach::addRef();
114 object
= pXEnv
->NewGlobalRef( myObj
);
117 java_lang_Object::~java_lang_Object() COVERITY_NOEXCEPT_FALSE
122 clearObject(*t
.pEnv
);
124 SDBThreadAttach::releaseRef();
126 void java_lang_Object::clearObject(JNIEnv
& rEnv
)
130 rEnv
.DeleteGlobalRef( object
);
135 void java_lang_Object::clearObject()
140 clearObject(*t
.pEnv
);
143 // the protected-constructor for the derived classes
144 void java_lang_Object::saveRef( JNIEnv
* pXEnv
, jobject myObj
)
146 OSL_ENSURE( myObj
, "object in c++ -> Java Wrapper" );
148 object
= pXEnv
->NewGlobalRef( myObj
);
152 OUString
java_lang_Object::toString() const
154 static jmethodID
mID(nullptr);
155 return callStringMethod("toString",mID
);
161 bool lcl_translateJNIExceptionToUNOException(
162 JNIEnv
* _pEnvironment
, const Reference
< XInterface
>& _rxContext
, SQLException
& _out_rException
)
164 jthrowable jThrow
= _pEnvironment
? _pEnvironment
->ExceptionOccurred() : nullptr;
168 _pEnvironment
->ExceptionClear();
169 // we have to clear the exception here because we want to handle it itself
171 if ( _pEnvironment
->IsInstanceOf( jThrow
, java_sql_SQLException_BASE::st_getMyClass() ) )
173 java_sql_SQLException_BASE
aException( _pEnvironment
, jThrow
);
174 _out_rException
= SQLException( aException
.getMessage(), _rxContext
,
175 aException
.getSQLState(), aException
.getErrorCode(), Any() );
178 else if ( _pEnvironment
->IsInstanceOf( jThrow
, java_lang_Throwable::st_getMyClass() ) )
180 java_lang_Throwable
aThrow( _pEnvironment
, jThrow
);
181 #if OSL_DEBUG_LEVEL > 0
182 aThrow
.printStackTrace();
184 OUString sMessage
= aThrow
.getMessage();
185 if ( sMessage
.isEmpty() )
186 sMessage
= aThrow
.getLocalizedMessage();
187 if( sMessage
.isEmpty() )
188 sMessage
= aThrow
.toString();
189 _out_rException
= SQLException( sMessage
, _rxContext
, OUString(), -1, Any() );
193 _pEnvironment
->DeleteLocalRef( jThrow
);
199 void java_lang_Object::ThrowLoggedSQLException( const ::comphelper::EventLogger
& _rLogger
, JNIEnv
* _pEnvironment
,
200 const Reference
< XInterface
>& _rxContext
)
202 SQLException aException
;
203 if ( lcl_translateJNIExceptionToUNOException( _pEnvironment
, _rxContext
, aException
) )
205 _rLogger
.log( css::logging::LogLevel::SEVERE
, STR_LOG_THROWING_EXCEPTION
, aException
.Message
, aException
.SQLState
, aException
.ErrorCode
);
210 void java_lang_Object::ThrowSQLException( JNIEnv
* _pEnvironment
, const Reference
< XInterface
>& _rxContext
)
212 SQLException aException
;
213 if ( lcl_translateJNIExceptionToUNOException( _pEnvironment
, _rxContext
, aException
) )
217 void java_lang_Object::ThrowRuntimeException( JNIEnv
* _pEnvironment
, const Reference
< XInterface
>& _rxContext
)
221 ThrowSQLException(_pEnvironment
, _rxContext
);
223 catch (const SQLException
& e
)
225 css::uno::Any anyEx
= cppu::getCaughtException();
226 throw css::lang::WrappedTargetRuntimeException( e
.Message
,
231 void java_lang_Object::obtainMethodId_throwSQL(JNIEnv
* _pEnv
,const char* _pMethodName
, const char* _pSignature
,jmethodID
& _inout_MethodID
) const
233 if ( !_inout_MethodID
)
235 _inout_MethodID
= _pEnv
->GetMethodID( getMyClass(), _pMethodName
, _pSignature
);
236 OSL_ENSURE( _inout_MethodID
, _pSignature
);
237 if ( !_inout_MethodID
)
238 throw SQLException();
239 } // if ( !_inout_MethodID )
242 void java_lang_Object::obtainMethodId_throwRuntime(JNIEnv
* _pEnv
,const char* _pMethodName
, const char* _pSignature
,jmethodID
& _inout_MethodID
) const
244 if ( !_inout_MethodID
)
246 _inout_MethodID
= _pEnv
->GetMethodID( getMyClass(), _pMethodName
, _pSignature
);
247 OSL_ENSURE( _inout_MethodID
, _pSignature
);
248 if ( !_inout_MethodID
)
249 throw RuntimeException();
250 } // if ( !_inout_MethodID )
254 bool java_lang_Object::callBooleanMethod( const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
259 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callBooleanMethod: no Java environment anymore!" );
260 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"()Z", _inout_MethodID
);
262 out
= t
.pEnv
->CallBooleanMethod( object
, _inout_MethodID
);
263 ThrowSQLException( t
.pEnv
, nullptr );
268 bool java_lang_Object::callBooleanMethodWithIntArg( const char* _pMethodName
, jmethodID
& _inout_MethodID
, sal_Int32 _nArgument
) const
272 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callBooleanMethodWithIntArg: no Java environment anymore!" );
273 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(I)Z", _inout_MethodID
);
275 out
= t
.pEnv
->CallBooleanMethod( object
, _inout_MethodID
, _nArgument
);
276 ThrowSQLException( t
.pEnv
, nullptr );
281 jobject
java_lang_Object::callResultSetMethod( JNIEnv
& _rEnv
,const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
284 jobject out
= callObjectMethod(&_rEnv
,_pMethodName
,"()Ljava/sql/ResultSet;", _inout_MethodID
);
288 sal_Int32
java_lang_Object::callIntMethod_ThrowSQL(const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
291 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
292 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"()I", _inout_MethodID
);
294 jint
out( t
.pEnv
->CallIntMethod( object
, _inout_MethodID
) );
295 ThrowSQLException( t
.pEnv
, nullptr );
296 return static_cast<sal_Int32
>(out
);
299 sal_Int32
java_lang_Object::callIntMethod_ThrowRuntime(const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
302 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
303 obtainMethodId_throwRuntime(t
.pEnv
, _pMethodName
,"()I", _inout_MethodID
);
305 jint
out( t
.pEnv
->CallIntMethod( object
, _inout_MethodID
) );
306 ThrowRuntimeException(t
.pEnv
, nullptr);
307 return static_cast<sal_Int32
>(out
);
310 sal_Int32
java_lang_Object::callIntMethodWithIntArg_ThrowSQL( const char* _pMethodName
, jmethodID
& _inout_MethodID
,sal_Int32 _nArgument
) const
313 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
314 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(I)I", _inout_MethodID
);
316 jint
out( t
.pEnv
->CallIntMethod( object
, _inout_MethodID
, _nArgument
) );
317 ThrowSQLException( t
.pEnv
, nullptr );
318 return static_cast<sal_Int32
>(out
);
321 sal_Int32
java_lang_Object::callIntMethodWithIntArg_ThrowRuntime( const char* _pMethodName
, jmethodID
& _inout_MethodID
,sal_Int32 _nArgument
) const
324 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
325 obtainMethodId_throwRuntime(t
.pEnv
, _pMethodName
,"(I)I", _inout_MethodID
);
327 jint
out( t
.pEnv
->CallIntMethod( object
, _inout_MethodID
, _nArgument
) );
328 ThrowRuntimeException(t
.pEnv
, nullptr);
329 return static_cast<sal_Int32
>(out
);
332 void java_lang_Object::callVoidMethod_ThrowSQL( const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
335 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
336 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"()V", _inout_MethodID
);
339 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
);
340 ThrowSQLException( t
.pEnv
, nullptr );
343 void java_lang_Object::callVoidMethod_ThrowRuntime( const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
346 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
347 obtainMethodId_throwRuntime(t
.pEnv
, _pMethodName
,"()V", _inout_MethodID
);
350 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
);
351 ThrowRuntimeException(t
.pEnv
, nullptr);
354 void java_lang_Object::callVoidMethodWithIntArg_ThrowSQL( const char* _pMethodName
, jmethodID
& _inout_MethodID
, sal_Int32 _nArgument
) const
357 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
358 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(I)V", _inout_MethodID
);
361 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
,_nArgument
);
362 ThrowSQLException( t
.pEnv
, nullptr );
365 void java_lang_Object::callVoidMethodWithIntArg_ThrowRuntime( const char* _pMethodName
, jmethodID
& _inout_MethodID
, sal_Int32 _nArgument
) const
368 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
369 obtainMethodId_throwRuntime(t
.pEnv
, _pMethodName
,"(I)V", _inout_MethodID
);
372 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
,_nArgument
);
373 ThrowRuntimeException(t
.pEnv
, nullptr);
376 void java_lang_Object::callVoidMethodWithBoolArg_ThrowSQL( const char* _pMethodName
, jmethodID
& _inout_MethodID
, bool _nArgument
) const
379 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
380 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(Z)V", _inout_MethodID
);
382 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
,int(_nArgument
) );
383 ThrowSQLException( t
.pEnv
, nullptr );
386 void java_lang_Object::callVoidMethodWithBoolArg_ThrowRuntime( const char* _pMethodName
, jmethodID
& _inout_MethodID
, bool _nArgument
) const
389 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
390 obtainMethodId_throwRuntime(t
.pEnv
, _pMethodName
,"(Z)V", _inout_MethodID
);
392 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
,int(_nArgument
) );
393 ThrowRuntimeException(t
.pEnv
, nullptr);
396 OUString
java_lang_Object::callStringMethod( const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
399 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callStringMethod: no Java environment anymore!" );
402 jstring out
= static_cast<jstring
>(callObjectMethod(t
.pEnv
,_pMethodName
,"()Ljava/lang/String;", _inout_MethodID
));
403 return JavaString2String( t
.pEnv
, out
);
406 jobject
java_lang_Object::callObjectMethod( JNIEnv
* _pEnv
,const char* _pMethodName
,const char* _pSignature
, jmethodID
& _inout_MethodID
) const
409 obtainMethodId_throwSQL(_pEnv
, _pMethodName
,_pSignature
, _inout_MethodID
);
411 jobject out
= _pEnv
->CallObjectMethod( object
, _inout_MethodID
);
412 ThrowSQLException( _pEnv
, nullptr );
417 jobject
java_lang_Object::callObjectMethodWithIntArg( JNIEnv
* _pEnv
,const char* _pMethodName
,const char* _pSignature
, jmethodID
& _inout_MethodID
, sal_Int32 _nArgument
) const
419 obtainMethodId_throwSQL(_pEnv
, _pMethodName
,_pSignature
, _inout_MethodID
);
421 jobject out
= _pEnv
->CallObjectMethod( object
, _inout_MethodID
,_nArgument
);
422 ThrowSQLException( _pEnv
, nullptr );
426 OUString
java_lang_Object::callStringMethodWithIntArg( const char* _pMethodName
, jmethodID
& _inout_MethodID
, sal_Int32 _nArgument
) const
429 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callStringMethod: no Java environment anymore!" );
430 jstring out
= static_cast<jstring
>(callObjectMethodWithIntArg(t
.pEnv
,_pMethodName
,"(I)Ljava/lang/String;",_inout_MethodID
,_nArgument
));
431 return JavaString2String( t
.pEnv
, out
);
434 void java_lang_Object::callVoidMethodWithStringArg( const char* _pMethodName
, jmethodID
& _inout_MethodID
,const OUString
& _nArgument
) const
437 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
438 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(Ljava/lang/String;)V", _inout_MethodID
);
440 jdbc::LocalRef
< jstring
> str( t
.env(),convertwchar_tToJavaString(t
.pEnv
,_nArgument
));
442 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
, str
.get());
443 ThrowSQLException( t
.pEnv
, nullptr );
446 sal_Int32
java_lang_Object::callIntMethodWithStringArg( const char* _pMethodName
, jmethodID
& _inout_MethodID
,const OUString
& _nArgument
) const
449 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethodWithStringArg: no Java environment anymore!" );
450 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(Ljava/lang/String;)I", _inout_MethodID
);
452 //TODO: Check if the code below is needed
453 //jdbc::LocalRef< jstring > str( t.env(), convertwchar_tToJavaString( t.pEnv, sql ) );
455 // jdbc::ContextClassLoaderScope ccl( t.env(),
456 // m_pConnection ? m_pConnection->getDriverClassLoader() : jdbc::GlobalRef< jobject >(),
461 jdbc::LocalRef
< jstring
> str( t
.env(),convertwchar_tToJavaString(t
.pEnv
,_nArgument
));
463 jint out
= t
.pEnv
->CallIntMethod( object
, _inout_MethodID
, str
.get());
464 ThrowSQLException( t
.pEnv
, nullptr );
465 return static_cast<sal_Int32
>(out
);
468 jclass
java_lang_Object::findMyClass(const char* _pClassName
)
470 // the class must be fetched only once, therefore static
472 jclass tempClass
= t
.pEnv
->FindClass(_pClassName
); OSL_ENSURE(tempClass
,"Java : FindClass not successful!");
475 t
.pEnv
->ExceptionDescribe();
476 t
.pEnv
->ExceptionClear();
478 jclass globClass
= static_cast<jclass
>(t
.pEnv
->NewGlobalRef( tempClass
));
479 t
.pEnv
->DeleteLocalRef( tempClass
);
483 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */