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