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::beans
;
35 using namespace ::com::sun::star::sdbc
;
36 using namespace ::com::sun::star::container
;
37 using namespace ::com::sun::star::lang
;
40 static ::rtl::Reference
< jvmaccess::VirtualMachine
> const & getJavaVM2(const ::rtl::Reference
< jvmaccess::VirtualMachine
>& _rVM
= ::rtl::Reference
< jvmaccess::VirtualMachine
>(),
43 static ::rtl::Reference
< jvmaccess::VirtualMachine
> s_VM
;
44 if ( _rVM
.is() || _bSet
)
49 ::rtl::Reference
< jvmaccess::VirtualMachine
> java_lang_Object::getVM(const Reference
<XComponentContext
>& _rxContext
)
51 ::rtl::Reference
< jvmaccess::VirtualMachine
> xVM
= getJavaVM2();
52 if ( !xVM
.is() && _rxContext
.is() )
53 xVM
= getJavaVM2(::connectivity::getJavaVM(_rxContext
));
58 SDBThreadAttach::SDBThreadAttach()
59 : m_aGuard(java_lang_Object::getVM())
62 pEnv
= m_aGuard
.getEnvironment();
63 OSL_ENSURE(pEnv
,"Environment is nULL!");
66 SDBThreadAttach::~SDBThreadAttach()
70 static oslInterlockedCount
& getJavaVMRefCount()
72 static oslInterlockedCount s_nRefCount
= 0;
76 void SDBThreadAttach::addRef()
78 osl_atomic_increment(&getJavaVMRefCount());
81 void SDBThreadAttach::releaseRef()
83 osl_atomic_decrement(&getJavaVMRefCount());
84 if ( getJavaVMRefCount() == 0 )
86 getJavaVM2(::rtl::Reference
< jvmaccess::VirtualMachine
>(),true);
90 // static variables of the class
91 jclass
java_lang_Object::theClass
= nullptr;
93 jclass
java_lang_Object::getMyClass() const
96 theClass
= findMyClass("java/lang/Object");
99 // the actual constructor
100 java_lang_Object::java_lang_Object()
103 SDBThreadAttach::addRef();
106 // the protected-constructor for the derived classes
107 java_lang_Object::java_lang_Object( JNIEnv
* pXEnv
, jobject myObj
)
110 SDBThreadAttach::addRef();
112 object
= pXEnv
->NewGlobalRef( myObj
);
115 java_lang_Object::~java_lang_Object() COVERITY_NOEXCEPT_FALSE
120 clearObject(*t
.pEnv
);
122 SDBThreadAttach::releaseRef();
124 void java_lang_Object::clearObject(JNIEnv
& rEnv
)
128 rEnv
.DeleteGlobalRef( object
);
133 void java_lang_Object::clearObject()
138 clearObject(*t
.pEnv
);
141 // the protected-constructor for the derived classes
142 void java_lang_Object::saveRef( JNIEnv
* pXEnv
, jobject myObj
)
144 OSL_ENSURE( myObj
, "object in c++ -> Java Wrapper" );
146 object
= pXEnv
->NewGlobalRef( myObj
);
150 OUString
java_lang_Object::toString() const
152 static jmethodID
mID(nullptr);
153 return callStringMethod("toString",mID
);
159 bool lcl_translateJNIExceptionToUNOException(
160 JNIEnv
* _pEnvironment
, const Reference
< XInterface
>& _rxContext
, SQLException
& _out_rException
)
162 jthrowable jThrow
= _pEnvironment
? _pEnvironment
->ExceptionOccurred() : nullptr;
166 _pEnvironment
->ExceptionClear();
167 // we have to clear the exception here because we want to handle it itself
169 if ( _pEnvironment
->IsInstanceOf( jThrow
, java_sql_SQLException_BASE::st_getMyClass() ) )
171 java_sql_SQLException_BASE
aException( _pEnvironment
, jThrow
);
172 _out_rException
= SQLException( aException
.getMessage(), _rxContext
,
173 aException
.getSQLState(), aException
.getErrorCode(), Any() );
176 else if ( _pEnvironment
->IsInstanceOf( jThrow
, java_lang_Throwable::st_getMyClass() ) )
178 java_lang_Throwable
aThrow( _pEnvironment
, jThrow
);
179 #if OSL_DEBUG_LEVEL > 0
180 aThrow
.printStackTrace();
182 OUString sMessage
= aThrow
.getMessage();
183 if ( sMessage
.isEmpty() )
184 sMessage
= aThrow
.getLocalizedMessage();
185 if( sMessage
.isEmpty() )
186 sMessage
= aThrow
.toString();
187 _out_rException
= SQLException( sMessage
, _rxContext
, OUString(), -1, Any() );
191 _pEnvironment
->DeleteLocalRef( jThrow
);
197 void java_lang_Object::ThrowLoggedSQLException( const ::comphelper::EventLogger
& _rLogger
, JNIEnv
* _pEnvironment
,
198 const Reference
< XInterface
>& _rxContext
)
200 SQLException aException
;
201 if ( lcl_translateJNIExceptionToUNOException( _pEnvironment
, _rxContext
, aException
) )
203 _rLogger
.log( css::logging::LogLevel::SEVERE
, STR_LOG_THROWING_EXCEPTION
, aException
.Message
, aException
.SQLState
, aException
.ErrorCode
);
208 void java_lang_Object::ThrowSQLException( JNIEnv
* _pEnvironment
, const Reference
< XInterface
>& _rxContext
)
210 SQLException aException
;
211 if ( lcl_translateJNIExceptionToUNOException( _pEnvironment
, _rxContext
, aException
) )
215 void java_lang_Object::ThrowRuntimeException( JNIEnv
* _pEnvironment
, const Reference
< XInterface
>& _rxContext
)
219 ThrowSQLException(_pEnvironment
, _rxContext
);
221 catch (const SQLException
& e
)
223 css::uno::Any anyEx
= cppu::getCaughtException();
224 throw css::lang::WrappedTargetRuntimeException( e
.Message
,
229 void java_lang_Object::obtainMethodId_throwSQL(JNIEnv
* _pEnv
,const char* _pMethodName
, const char* _pSignature
,jmethodID
& _inout_MethodID
) const
231 if ( !_inout_MethodID
)
233 _inout_MethodID
= _pEnv
->GetMethodID( getMyClass(), _pMethodName
, _pSignature
);
234 OSL_ENSURE( _inout_MethodID
, _pSignature
);
235 if ( !_inout_MethodID
)
236 throw SQLException();
237 } // if ( !_inout_MethodID )
240 void java_lang_Object::obtainMethodId_throwRuntime(JNIEnv
* _pEnv
,const char* _pMethodName
, const char* _pSignature
,jmethodID
& _inout_MethodID
) const
242 if ( !_inout_MethodID
)
244 _inout_MethodID
= _pEnv
->GetMethodID( getMyClass(), _pMethodName
, _pSignature
);
245 OSL_ENSURE( _inout_MethodID
, _pSignature
);
246 if ( !_inout_MethodID
)
247 throw RuntimeException();
248 } // if ( !_inout_MethodID )
252 bool java_lang_Object::callBooleanMethod( const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
257 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callBooleanMethod: no Java environment anymore!" );
258 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"()Z", _inout_MethodID
);
260 out
= t
.pEnv
->CallBooleanMethod( object
, _inout_MethodID
);
261 ThrowSQLException( t
.pEnv
, nullptr );
266 bool java_lang_Object::callBooleanMethodWithIntArg( const char* _pMethodName
, jmethodID
& _inout_MethodID
, sal_Int32 _nArgument
) const
270 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callBooleanMethodWithIntArg: no Java environment anymore!" );
271 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(I)Z", _inout_MethodID
);
273 out
= t
.pEnv
->CallBooleanMethod( object
, _inout_MethodID
, _nArgument
);
274 ThrowSQLException( t
.pEnv
, nullptr );
279 jobject
java_lang_Object::callResultSetMethod( JNIEnv
& _rEnv
,const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
282 jobject out
= callObjectMethod(&_rEnv
,_pMethodName
,"()Ljava/sql/ResultSet;", _inout_MethodID
);
286 sal_Int32
java_lang_Object::callIntMethod_ThrowSQL(const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
289 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
290 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"()I", _inout_MethodID
);
292 jint
out( t
.pEnv
->CallIntMethod( object
, _inout_MethodID
) );
293 ThrowSQLException( t
.pEnv
, nullptr );
294 return static_cast<sal_Int32
>(out
);
297 sal_Int32
java_lang_Object::callIntMethod_ThrowRuntime(const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
300 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
301 obtainMethodId_throwRuntime(t
.pEnv
, _pMethodName
,"()I", _inout_MethodID
);
303 jint
out( t
.pEnv
->CallIntMethod( object
, _inout_MethodID
) );
304 ThrowRuntimeException(t
.pEnv
, nullptr);
305 return static_cast<sal_Int32
>(out
);
308 sal_Int32
java_lang_Object::callIntMethodWithIntArg_ThrowSQL( const char* _pMethodName
, jmethodID
& _inout_MethodID
,sal_Int32 _nArgument
) const
311 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
312 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(I)I", _inout_MethodID
);
314 jint
out( t
.pEnv
->CallIntMethod( object
, _inout_MethodID
, _nArgument
) );
315 ThrowSQLException( t
.pEnv
, nullptr );
316 return static_cast<sal_Int32
>(out
);
319 sal_Int32
java_lang_Object::callIntMethodWithIntArg_ThrowRuntime( const char* _pMethodName
, jmethodID
& _inout_MethodID
,sal_Int32 _nArgument
) const
322 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
323 obtainMethodId_throwRuntime(t
.pEnv
, _pMethodName
,"(I)I", _inout_MethodID
);
325 jint
out( t
.pEnv
->CallIntMethod( object
, _inout_MethodID
, _nArgument
) );
326 ThrowRuntimeException(t
.pEnv
, nullptr);
327 return static_cast<sal_Int32
>(out
);
330 void java_lang_Object::callVoidMethod_ThrowSQL( const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
333 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
334 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"()V", _inout_MethodID
);
337 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
);
338 ThrowSQLException( t
.pEnv
, nullptr );
341 void java_lang_Object::callVoidMethod_ThrowRuntime( const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
344 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
345 obtainMethodId_throwRuntime(t
.pEnv
, _pMethodName
,"()V", _inout_MethodID
);
348 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
);
349 ThrowRuntimeException(t
.pEnv
, nullptr);
352 void java_lang_Object::callVoidMethodWithIntArg_ThrowSQL( const char* _pMethodName
, jmethodID
& _inout_MethodID
, sal_Int32 _nArgument
) const
355 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
356 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(I)V", _inout_MethodID
);
359 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
,_nArgument
);
360 ThrowSQLException( t
.pEnv
, nullptr );
363 void java_lang_Object::callVoidMethodWithIntArg_ThrowRuntime( const char* _pMethodName
, jmethodID
& _inout_MethodID
, sal_Int32 _nArgument
) const
366 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
367 obtainMethodId_throwRuntime(t
.pEnv
, _pMethodName
,"(I)V", _inout_MethodID
);
370 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
,_nArgument
);
371 ThrowRuntimeException(t
.pEnv
, nullptr);
374 void java_lang_Object::callVoidMethodWithBoolArg_ThrowSQL( const char* _pMethodName
, jmethodID
& _inout_MethodID
, bool _nArgument
) const
377 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
378 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(Z)V", _inout_MethodID
);
380 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
,int(_nArgument
) );
381 ThrowSQLException( t
.pEnv
, nullptr );
384 void java_lang_Object::callVoidMethodWithBoolArg_ThrowRuntime( const char* _pMethodName
, jmethodID
& _inout_MethodID
, bool _nArgument
) const
387 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
388 obtainMethodId_throwRuntime(t
.pEnv
, _pMethodName
,"(Z)V", _inout_MethodID
);
390 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
,int(_nArgument
) );
391 ThrowRuntimeException(t
.pEnv
, nullptr);
394 OUString
java_lang_Object::callStringMethod( const char* _pMethodName
, jmethodID
& _inout_MethodID
) const
397 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callStringMethod: no Java environment anymore!" );
400 jstring out
= static_cast<jstring
>(callObjectMethod(t
.pEnv
,_pMethodName
,"()Ljava/lang/String;", _inout_MethodID
));
401 return JavaString2String( t
.pEnv
, out
);
404 jobject
java_lang_Object::callObjectMethod( JNIEnv
* _pEnv
,const char* _pMethodName
,const char* _pSignature
, jmethodID
& _inout_MethodID
) const
407 obtainMethodId_throwSQL(_pEnv
, _pMethodName
,_pSignature
, _inout_MethodID
);
409 jobject out
= _pEnv
->CallObjectMethod( object
, _inout_MethodID
);
410 ThrowSQLException( _pEnv
, nullptr );
415 jobject
java_lang_Object::callObjectMethodWithIntArg( JNIEnv
* _pEnv
,const char* _pMethodName
,const char* _pSignature
, jmethodID
& _inout_MethodID
, sal_Int32 _nArgument
) const
417 obtainMethodId_throwSQL(_pEnv
, _pMethodName
,_pSignature
, _inout_MethodID
);
419 jobject out
= _pEnv
->CallObjectMethod( object
, _inout_MethodID
,_nArgument
);
420 ThrowSQLException( _pEnv
, nullptr );
424 OUString
java_lang_Object::callStringMethodWithIntArg( const char* _pMethodName
, jmethodID
& _inout_MethodID
, sal_Int32 _nArgument
) const
427 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callStringMethod: no Java environment anymore!" );
428 jstring out
= static_cast<jstring
>(callObjectMethodWithIntArg(t
.pEnv
,_pMethodName
,"(I)Ljava/lang/String;",_inout_MethodID
,_nArgument
));
429 return JavaString2String( t
.pEnv
, out
);
432 void java_lang_Object::callVoidMethodWithStringArg( const char* _pMethodName
, jmethodID
& _inout_MethodID
,const OUString
& _nArgument
) const
435 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethod: no Java environment anymore!" );
436 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(Ljava/lang/String;)V", _inout_MethodID
);
438 jdbc::LocalRef
< jstring
> str( t
.env(),convertwchar_tToJavaString(t
.pEnv
,_nArgument
));
440 t
.pEnv
->CallVoidMethod( object
, _inout_MethodID
, str
.get());
441 ThrowSQLException( t
.pEnv
, nullptr );
444 sal_Int32
java_lang_Object::callIntMethodWithStringArg( const char* _pMethodName
, jmethodID
& _inout_MethodID
,const OUString
& _nArgument
) const
447 OSL_ENSURE( t
.pEnv
, "java_lang_Object::callIntMethodWithStringArg: no Java environment anymore!" );
448 obtainMethodId_throwSQL(t
.pEnv
, _pMethodName
,"(Ljava/lang/String;)I", _inout_MethodID
);
450 //TODO: Check if the code below is needed
451 //jdbc::LocalRef< jstring > str( t.env(), convertwchar_tToJavaString( t.pEnv, sql ) );
453 // jdbc::ContextClassLoaderScope ccl( t.env(),
454 // m_pConnection ? m_pConnection->getDriverClassLoader() : jdbc::GlobalRef< jobject >(),
459 jdbc::LocalRef
< jstring
> str( t
.env(),convertwchar_tToJavaString(t
.pEnv
,_nArgument
));
461 jint out
= t
.pEnv
->CallIntMethod( object
, _inout_MethodID
, str
.get());
462 ThrowSQLException( t
.pEnv
, nullptr );
463 return static_cast<sal_Int32
>(out
);
466 jclass
java_lang_Object::findMyClass(const char* _pClassName
)
468 // the class must be fetched only once, therefore static
470 jclass tempClass
= t
.pEnv
->FindClass(_pClassName
); OSL_ENSURE(tempClass
,"Java : FindClass not successful!");
473 t
.pEnv
->ExceptionDescribe();
474 t
.pEnv
->ExceptionClear();
476 jclass globClass
= static_cast<jclass
>(t
.pEnv
->NewGlobalRef( tempClass
));
477 t
.pEnv
->DeleteLocalRef( tempClass
);
481 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */