1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_connectivity.hxx" 30 31 32 #ifndef _CONNECTIVITY_JAVA_LANG_OBJJECT_HXX_ 33 #include "java/lang/Class.hxx" 34 #endif 35 #include "connectivity/CommonTools.hxx" 36 #include <com/sun/star/uno/Exception.hpp> 37 #include "java/tools.hxx" 38 #include "java/sql/SQLException.hxx" 39 #include <vos/process.hxx> 40 #include <vos/mutex.hxx> 41 #include <osl/thread.h> 42 #include <com/sun/star/uno/Sequence.hxx> 43 #include "java/LocalRef.hxx" 44 #include "resource/jdbc_log.hrc" 45 #include <rtl/logfile.hxx> 46 #include <comphelper/logging.hxx> 47 48 #include <memory> 49 50 using namespace connectivity; 51 using namespace ::com::sun::star::uno; 52 using namespace ::com::sun::star::beans; 53 using namespace ::com::sun::star::sdbc; 54 using namespace ::com::sun::star::container; 55 using namespace ::com::sun::star::lang; 56 57 58 // ----------------------------------------------------------------------------- 59 ::rtl::Reference< jvmaccess::VirtualMachine > getJavaVM2(const ::rtl::Reference< jvmaccess::VirtualMachine >& _rVM = ::rtl::Reference< jvmaccess::VirtualMachine >(), 60 sal_Bool _bSet = sal_False) 61 { 62 static ::rtl::Reference< jvmaccess::VirtualMachine > s_VM; 63 if ( _rVM.is() || _bSet ) 64 s_VM = _rVM; 65 return s_VM; 66 } 67 // ----------------------------------------------------------------------------- 68 ::rtl::Reference< jvmaccess::VirtualMachine > java_lang_Object::getVM(const Reference<XMultiServiceFactory >& _rxFactory) 69 { 70 ::rtl::Reference< jvmaccess::VirtualMachine > xVM = getJavaVM2(); 71 if ( !xVM.is() && _rxFactory.is() ) 72 xVM = getJavaVM2(::connectivity::getJavaVM(_rxFactory)); 73 74 return xVM; 75 } 76 // ----------------------------------------------------------------------------- 77 SDBThreadAttach::SDBThreadAttach() 78 : m_aGuard(java_lang_Object::getVM()) 79 , pEnv(NULL) 80 { 81 pEnv = m_aGuard.getEnvironment(); 82 OSL_ENSURE(pEnv,"Environment is nULL!"); 83 } 84 // ----------------------------------------------------------------------------- 85 SDBThreadAttach::~SDBThreadAttach() 86 { 87 } 88 // ----------------------------------------------------------------------------- 89 oslInterlockedCount& getJavaVMRefCount() 90 { 91 static oslInterlockedCount s_nRefCount = 0; 92 return s_nRefCount; 93 } 94 // ----------------------------------------------------------------------------- 95 void SDBThreadAttach::addRef() 96 { 97 osl_incrementInterlockedCount(&getJavaVMRefCount()); 98 } 99 // ----------------------------------------------------------------------------- 100 void SDBThreadAttach::releaseRef() 101 { 102 osl_decrementInterlockedCount(&getJavaVMRefCount()); 103 if ( getJavaVMRefCount() == 0 ) 104 { 105 getJavaVM2(::rtl::Reference< jvmaccess::VirtualMachine >(),sal_True); 106 } 107 } 108 // ----------------------------------------------------------------------------- 109 // statische Variablen der Klasse: 110 jclass java_lang_Object::theClass = 0; 111 112 jclass java_lang_Object::getMyClass() const 113 { 114 if( !theClass ) 115 theClass = findMyClass("java/lang/Object"); 116 return theClass; 117 } 118 // der eigentliche Konstruktor 119 java_lang_Object::java_lang_Object(const Reference<XMultiServiceFactory >& _rxFactory) 120 : m_xFactory(_rxFactory),object( 0 ) 121 { 122 SDBThreadAttach::addRef(); 123 } 124 125 // der protected-Konstruktor fuer abgeleitete Klassen 126 java_lang_Object::java_lang_Object( JNIEnv * pXEnv, jobject myObj ) 127 : object( NULL ) 128 { 129 SDBThreadAttach::addRef(); 130 if( pXEnv && myObj ) 131 object = pXEnv->NewGlobalRef( myObj ); 132 } 133 134 java_lang_Object::~java_lang_Object() 135 { 136 if( object ) 137 { 138 SDBThreadAttach t; 139 clearObject(*t.pEnv); 140 } 141 SDBThreadAttach::releaseRef(); 142 } 143 void java_lang_Object::clearObject(JNIEnv& rEnv) 144 { 145 if( object ) 146 { 147 rEnv.DeleteGlobalRef( object ); 148 object = NULL; 149 } 150 } 151 152 void java_lang_Object::clearObject() 153 { 154 if( object ) 155 { 156 SDBThreadAttach t; 157 clearObject(*t.pEnv); 158 } 159 } 160 // der protected-Konstruktor fuer abgeleitete Klassen 161 void java_lang_Object::saveRef( JNIEnv * pXEnv, jobject myObj ) 162 { 163 OSL_ENSURE( myObj, "object in c++ -> Java Wrapper" ); 164 if( myObj ) 165 object = pXEnv->NewGlobalRef( myObj ); 166 } 167 168 169 ::rtl::OUString java_lang_Object::toString() const 170 { 171 static jmethodID mID(NULL); 172 return callStringMethod("toString",mID); 173 } 174 175 // -------------------------------------------------------------------------------- 176 namespace 177 { 178 bool lcl_translateJNIExceptionToUNOException( 179 JNIEnv* _pEnvironment, const Reference< XInterface >& _rxContext, SQLException& _out_rException ) 180 { 181 jthrowable jThrow = _pEnvironment ? _pEnvironment->ExceptionOccurred() : NULL; 182 if ( !jThrow ) 183 return false; 184 185 _pEnvironment->ExceptionClear(); 186 // we have to clear the exception here because we want to handle it itself 187 188 if ( _pEnvironment->IsInstanceOf( jThrow, java_sql_SQLException_BASE::st_getMyClass() ) ) 189 { 190 ::std::auto_ptr< java_sql_SQLException_BASE > pException( new java_sql_SQLException_BASE( _pEnvironment, jThrow ) ); 191 _out_rException = SQLException( pException->getMessage(), _rxContext, 192 pException->getSQLState(), pException->getErrorCode(), Any() ); 193 return true; 194 } 195 else if ( _pEnvironment->IsInstanceOf( jThrow, java_lang_Throwable::st_getMyClass() ) ) 196 { 197 ::std::auto_ptr< java_lang_Throwable > pThrow( new java_lang_Throwable( _pEnvironment, jThrow ) ); 198 ::rtl::OUString sMessage = pThrow->getMessage(); 199 if ( !sMessage.getLength() ) 200 sMessage = pThrow->getLocalizedMessage(); 201 if( !sMessage.getLength() ) 202 sMessage = pThrow->toString(); 203 _out_rException = SQLException( sMessage, _rxContext, ::rtl::OUString(), -1, Any() ); 204 return true; 205 } 206 else 207 _pEnvironment->DeleteLocalRef( jThrow ); 208 return false; 209 } 210 } 211 212 // -------------------------------------------------------------------------------- 213 void java_lang_Object::ThrowLoggedSQLException( const ::comphelper::ResourceBasedEventLogger& _rLogger, JNIEnv* _pEnvironment, 214 const Reference< XInterface >& _rxContext ) 215 { 216 SQLException aException; 217 if ( lcl_translateJNIExceptionToUNOException( _pEnvironment, _rxContext, aException ) ) 218 { 219 _rLogger.log( ::com::sun::star::logging::LogLevel::SEVERE, STR_LOG_THROWING_EXCEPTION, aException.Message, aException.SQLState, aException.ErrorCode ); 220 throw aException; 221 } 222 } 223 224 // -------------------------------------------------------------------------------- 225 void java_lang_Object::ThrowSQLException( JNIEnv* _pEnvironment, const Reference< XInterface>& _rxContext ) 226 { 227 SQLException aException; 228 if ( lcl_translateJNIExceptionToUNOException( _pEnvironment, _rxContext, aException ) ) 229 throw aException; 230 } 231 // ----------------------------------------------------------------------------- 232 void java_lang_Object::obtainMethodId(JNIEnv* _pEnv,const char* _pMethodName, const char* _pSignature,jmethodID& _inout_MethodID) const 233 { 234 if ( !_inout_MethodID ) 235 { 236 _inout_MethodID = _pEnv->GetMethodID( getMyClass(), _pMethodName, _pSignature ); 237 OSL_ENSURE( _inout_MethodID, _pSignature ); 238 if ( !_inout_MethodID ) 239 throw SQLException(); 240 } // if ( !_inout_MethodID ) 241 } 242 // ----------------------------------------------------------------------------- 243 sal_Bool java_lang_Object::callBooleanMethod( const char* _pMethodName, jmethodID& _inout_MethodID ) const 244 { 245 jboolean out( sal_False ); 246 247 SDBThreadAttach t; 248 OSL_ENSURE( t.pEnv, "java_lang_Object::callBooleanMethod: no Java enviroment anymore!" ); 249 obtainMethodId(t.pEnv, _pMethodName,"()Z", _inout_MethodID); 250 // call method 251 out = t.pEnv->CallBooleanMethod( object, _inout_MethodID ); 252 ThrowSQLException( t.pEnv, NULL ); 253 254 return out; 255 } 256 // ----------------------------------------------------------------------------- 257 sal_Bool java_lang_Object::callBooleanMethodWithIntArg( const char* _pMethodName, jmethodID& _inout_MethodID, sal_Int32 _nArgument ) const 258 { 259 jboolean out( sal_False ); 260 SDBThreadAttach t; 261 OSL_ENSURE( t.pEnv, "java_lang_Object::callBooleanMethodWithIntArg: no Java enviroment anymore!" ); 262 obtainMethodId(t.pEnv, _pMethodName,"(I)Z", _inout_MethodID); 263 // call method 264 out = t.pEnv->CallBooleanMethod( object, _inout_MethodID, _nArgument ); 265 ThrowSQLException( t.pEnv, NULL ); 266 267 return out; 268 } 269 // ------------------------------------------------------------------------- 270 jobject java_lang_Object::callResultSetMethod( JNIEnv& _rEnv,const char* _pMethodName, jmethodID& _inout_MethodID ) const 271 { 272 // call method 273 jobject out = callObjectMethod(&_rEnv,_pMethodName,"()Ljava/sql/ResultSet;", _inout_MethodID); 274 return out; 275 } 276 // ------------------------------------------------------------------------- 277 sal_Int32 java_lang_Object::callIntMethod( const char* _pMethodName, jmethodID& _inout_MethodID,bool _bIgnoreException ) const 278 { 279 SDBThreadAttach t; 280 OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java enviroment anymore!" ); 281 obtainMethodId(t.pEnv, _pMethodName,"()I", _inout_MethodID); 282 283 // call method 284 jint out( t.pEnv->CallIntMethod( object, _inout_MethodID ) ); 285 if ( _bIgnoreException ) 286 isExceptionOccured(t.pEnv,sal_True); 287 else 288 ThrowSQLException( t.pEnv, NULL ); 289 290 return (sal_Int32)out; 291 } 292 // ------------------------------------------------------------------------- 293 sal_Int32 java_lang_Object::callIntMethodWithIntArg( const char* _pMethodName, jmethodID& _inout_MethodID,sal_Int32 _nArgument ) const 294 { 295 SDBThreadAttach t; 296 OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java enviroment anymore!" ); 297 obtainMethodId(t.pEnv, _pMethodName,"(I)I", _inout_MethodID); 298 // call method 299 jint out( t.pEnv->CallIntMethod( object, _inout_MethodID , _nArgument) ); 300 ThrowSQLException( t.pEnv, NULL ); 301 302 return (sal_Int32)out; 303 } 304 // ------------------------------------------------------------------------- 305 void java_lang_Object::callVoidMethod( const char* _pMethodName, jmethodID& _inout_MethodID) const 306 { 307 SDBThreadAttach t; 308 OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java enviroment anymore!" ); 309 obtainMethodId(t.pEnv, _pMethodName,"()V", _inout_MethodID); 310 311 // call method 312 t.pEnv->CallVoidMethod( object, _inout_MethodID ); 313 ThrowSQLException( t.pEnv, NULL ); 314 } 315 // ------------------------------------------------------------------------- 316 void java_lang_Object::callVoidMethodWithIntArg( const char* _pMethodName, jmethodID& _inout_MethodID, sal_Int32 _nArgument,bool _bIgnoreException ) const 317 { 318 SDBThreadAttach t; 319 OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java enviroment anymore!" ); 320 obtainMethodId(t.pEnv, _pMethodName,"(I)V", _inout_MethodID); 321 322 // call method 323 t.pEnv->CallVoidMethod( object, _inout_MethodID,_nArgument ); 324 if ( _bIgnoreException ) 325 isExceptionOccured(t.pEnv,sal_True); 326 else 327 ThrowSQLException( t.pEnv, NULL ); 328 } 329 // ------------------------------------------------------------------------- 330 void java_lang_Object::callVoidMethodWithBoolArg( const char* _pMethodName, jmethodID& _inout_MethodID, sal_Int32 _nArgument,bool _bIgnoreException ) const 331 { 332 SDBThreadAttach t; 333 OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java enviroment anymore!" ); 334 obtainMethodId(t.pEnv, _pMethodName,"(Z)V", _inout_MethodID); 335 // call method 336 t.pEnv->CallVoidMethod( object, _inout_MethodID,_nArgument ); 337 if ( _bIgnoreException ) 338 isExceptionOccured(t.pEnv,sal_True); 339 else 340 ThrowSQLException( t.pEnv, NULL ); 341 } 342 // ----------------------------------------------------------------------------- 343 ::rtl::OUString java_lang_Object::callStringMethod( const char* _pMethodName, jmethodID& _inout_MethodID ) const 344 { 345 SDBThreadAttach t; 346 OSL_ENSURE( t.pEnv, "java_lang_Object::callStringMethod: no Java enviroment anymore!" ); 347 348 // call method 349 jstring out = (jstring)callObjectMethod(t.pEnv,_pMethodName,"()Ljava/lang/String;", _inout_MethodID); 350 return JavaString2String( t.pEnv, out ); 351 } 352 // ----------------------------------------------------------------------------- 353 jobject java_lang_Object::callObjectMethod( JNIEnv * _pEnv,const char* _pMethodName,const char* _pSignature, jmethodID& _inout_MethodID ) const 354 { 355 // obtain method ID 356 obtainMethodId(_pEnv, _pMethodName,_pSignature, _inout_MethodID); 357 // call method 358 jobject out = _pEnv->CallObjectMethod( object, _inout_MethodID); 359 ThrowSQLException( _pEnv, NULL ); 360 return out; 361 } 362 363 // ----------------------------------------------------------------------------- 364 jobject java_lang_Object::callObjectMethodWithIntArg( JNIEnv * _pEnv,const char* _pMethodName,const char* _pSignature, jmethodID& _inout_MethodID , sal_Int32 _nArgument) const 365 { 366 obtainMethodId(_pEnv, _pMethodName,_pSignature, _inout_MethodID); 367 // call method 368 jobject out = _pEnv->CallObjectMethod( object, _inout_MethodID,_nArgument ); 369 ThrowSQLException( _pEnv, NULL ); 370 return out; 371 } 372 // ----------------------------------------------------------------------------- 373 ::rtl::OUString java_lang_Object::callStringMethodWithIntArg( const char* _pMethodName, jmethodID& _inout_MethodID , sal_Int32 _nArgument) const 374 { 375 SDBThreadAttach t; 376 OSL_ENSURE( t.pEnv, "java_lang_Object::callStringMethod: no Java enviroment anymore!" ); 377 jstring out = (jstring)callObjectMethodWithIntArg(t.pEnv,_pMethodName,"(I)Ljava/lang/String;",_inout_MethodID,_nArgument); 378 return JavaString2String( t.pEnv, out ); 379 } 380 // ------------------------------------------------------------------------- 381 void java_lang_Object::callVoidMethodWithStringArg( const char* _pMethodName, jmethodID& _inout_MethodID,const ::rtl::OUString& _nArgument ) const 382 { 383 SDBThreadAttach t; 384 OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java enviroment anymore!" ); 385 obtainMethodId(t.pEnv, _pMethodName,"(Ljava/lang/String;)V", _inout_MethodID); 386 387 jdbc::LocalRef< jstring > str( t.env(),convertwchar_tToJavaString(t.pEnv,_nArgument)); 388 // call method 389 t.pEnv->CallVoidMethod( object, _inout_MethodID , str.get()); 390 ThrowSQLException( t.pEnv, NULL ); 391 } 392 // ------------------------------------------------------------------------- 393 sal_Int32 java_lang_Object::callIntMethodWithStringArg( const char* _pMethodName, jmethodID& _inout_MethodID,const ::rtl::OUString& _nArgument ) const 394 { 395 SDBThreadAttach t; 396 OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethodWithStringArg: no Java enviroment anymore!" ); 397 obtainMethodId(t.pEnv, _pMethodName,"(Ljava/lang/String;)I", _inout_MethodID); 398 399 //TODO: Check if the code below is needed 400 //jdbc::LocalRef< jstring > str( t.env(), convertwchar_tToJavaString( t.pEnv, sql ) ); 401 //{ 402 // jdbc::ContextClassLoaderScope ccl( t.env(), 403 // m_pConnection ? m_pConnection->getDriverClassLoader() : jdbc::GlobalRef< jobject >(), 404 // m_aLogger, 405 // *this 406 // ); 407 408 jdbc::LocalRef< jstring > str( t.env(),convertwchar_tToJavaString(t.pEnv,_nArgument)); 409 // call method 410 jint out = t.pEnv->CallIntMethod( object, _inout_MethodID , str.get()); 411 ThrowSQLException( t.pEnv, NULL ); 412 return (sal_Int32)out; 413 } 414 // ----------------------------------------------------------------------------- 415 jclass java_lang_Object::findMyClass(const char* _pClassName) 416 { 417 // die Klasse muss nur einmal geholt werden, daher statisch 418 SDBThreadAttach t; 419 jclass tempClass = t.pEnv->FindClass(_pClassName); OSL_ENSURE(tempClass,"Java : FindClass nicht erfolgreich!"); 420 if(!tempClass) 421 { 422 t.pEnv->ExceptionDescribe(); 423 t.pEnv->ExceptionClear(); 424 } 425 jclass globClass = (jclass)t.pEnv->NewGlobalRef( tempClass ); 426 t.pEnv->DeleteLocalRef( tempClass ); 427 return globClass; 428 } 429 430