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