merge the formfield patch from ooo-build
[ooovba.git] / bridges / source / jni_uno / jni_uno2java.cxx
blob2ea0632fd7a2b29180bfba7b7f1a63454216962a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: jni_uno2java.cxx,v $
10 * $Revision: 1.24 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_bridges.hxx"
34 #include <sal/alloca.h>
36 #include "com/sun/star/uno/RuntimeException.hpp"
38 #include "rtl/ustrbuf.hxx"
40 #include "jni_bridge.h"
43 using namespace ::std;
44 using namespace ::rtl;
46 namespace
48 extern "C"
51 //------------------------------------------------------------------------------
52 void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy )
53 SAL_THROW_EXTERN_C();
55 //------------------------------------------------------------------------------
56 void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI )
57 SAL_THROW_EXTERN_C();
59 //------------------------------------------------------------------------------
60 void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI )
61 SAL_THROW_EXTERN_C();
63 //------------------------------------------------------------------------------
64 void SAL_CALL UNO_proxy_dispatch(
65 uno_Interface * pUnoI, typelib_TypeDescription const * member_td,
66 void * uno_ret, void * uno_args[], uno_Any ** uno_exc )
67 SAL_THROW_EXTERN_C();
71 namespace jni_uno
74 //______________________________________________________________________________
75 void Bridge::handle_java_exc(
76 JNI_context const & jni,
77 JLocalAutoRef const & jo_exc, uno_Any * uno_exc ) const
79 OSL_ASSERT( jo_exc.is() );
80 if (! jo_exc.is())
82 throw BridgeRuntimeError(
83 OUSTR("java exception occured, but no java exception available!?") +
84 jni.get_stack_trace() );
87 JLocalAutoRef jo_class( jni, jni->GetObjectClass( jo_exc.get() ) );
88 JLocalAutoRef jo_class_name(
89 jni, jni->CallObjectMethodA(
90 jo_class.get(), m_jni_info->m_method_Class_getName, 0 ) );
91 jni.ensure_no_exception();
92 OUString exc_name(
93 jstring_to_oustring( jni, (jstring) jo_class_name.get() ) );
95 ::com::sun::star::uno::TypeDescription td( exc_name.pData );
96 if (!td.is() || (typelib_TypeClass_EXCEPTION != td.get()->eTypeClass))
98 // call toString()
99 JLocalAutoRef jo_descr(
100 jni, jni->CallObjectMethodA(
101 jo_exc.get(), m_jni_info->m_method_Object_toString, 0 ) );
102 jni.ensure_no_exception();
103 OUStringBuffer buf( 128 );
104 buf.appendAscii(
105 RTL_CONSTASCII_STRINGPARAM("non-UNO exception occurred: ") );
106 buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
107 buf.append( jni.get_stack_trace( jo_exc.get() ) );
108 throw BridgeRuntimeError( buf.makeStringAndClear() );
111 auto_ptr< rtl_mem > uno_data( rtl_mem::allocate( td.get()->nSize ) );
112 jvalue val;
113 val.l = jo_exc.get();
114 map_to_uno(
115 jni, uno_data.get(), val, td.get()->pWeakRef, 0,
116 false /* no assign */, false /* no out param */ );
118 #if OSL_DEBUG_LEVEL > 0
119 // patch Message, append stack trace
120 reinterpret_cast< ::com::sun::star::uno::Exception * >(
121 uno_data.get() )->Message += jni.get_stack_trace( jo_exc.get() );
122 #endif
124 typelib_typedescriptionreference_acquire( td.get()->pWeakRef );
125 uno_exc->pType = td.get()->pWeakRef;
126 uno_exc->pData = uno_data.release();
128 #if OSL_DEBUG_LEVEL > 1
129 OUStringBuffer trace_buf( 128 );
130 trace_buf.appendAscii(
131 RTL_CONSTASCII_STRINGPARAM("exception occured uno->java: [") );
132 trace_buf.append( exc_name );
133 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") );
134 trace_buf.append(
135 reinterpret_cast< ::com::sun::star::uno::Exception const * >(
136 uno_exc->pData )->Message );
137 OString cstr_trace(
138 OUStringToOString(
139 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
140 OSL_TRACE( cstr_trace.getStr() );
141 #endif
144 //______________________________________________________________________________
145 void Bridge::call_java(
146 jobject javaI, typelib_InterfaceTypeDescription * iface_td,
147 sal_Int32 local_member_index, sal_Int32 function_pos_offset,
148 typelib_TypeDescriptionReference * return_type,
149 typelib_MethodParameter * params, sal_Int32 nParams,
150 void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const
152 OSL_ASSERT( function_pos_offset == 0 || function_pos_offset == 1 );
154 JNI_guarded_context jni(
155 m_jni_info, reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
156 m_java_env->pContext ) );
158 // assure fully initialized iface_td:
159 ::com::sun::star::uno::TypeDescription iface_holder;
160 if (! iface_td->aBase.bComplete) {
161 iface_holder = ::com::sun::star::uno::TypeDescription(
162 reinterpret_cast<typelib_TypeDescription *>(iface_td) );
163 iface_holder.makeComplete();
164 if (! iface_holder.get()->bComplete) {
165 OUStringBuffer buf;
166 buf.appendAscii(
167 RTL_CONSTASCII_STRINGPARAM("cannot make type complete: ") );
168 buf.append( OUString::unacquired(&iface_holder.get()->pTypeName) );
169 buf.append( jni.get_stack_trace() );
170 throw BridgeRuntimeError( buf.makeStringAndClear() );
172 iface_td = reinterpret_cast<typelib_InterfaceTypeDescription *>(
173 iface_holder.get() );
174 OSL_ASSERT( iface_td->aBase.eTypeClass == typelib_TypeClass_INTERFACE );
177 // prepare java args, save param td
178 #ifdef BROKEN_ALLOCA
179 jvalue * java_args = (jvalue *) malloc( sizeof (jvalue) * nParams );
180 #else
181 jvalue * java_args = (jvalue *) alloca( sizeof (jvalue) * nParams );
182 #endif
184 sal_Int32 nPos;
185 for ( nPos = 0; nPos < nParams; ++nPos )
189 typelib_MethodParameter const & param = params[ nPos ];
190 java_args[ nPos ].l = 0; // if out: build up array[ 1 ]
191 map_to_java(
192 jni, &java_args[ nPos ],
193 uno_args[ nPos ],
194 param.pTypeRef, 0,
195 sal_False != param.bIn /* convert uno value */,
196 sal_False != param.bOut /* build up array[ 1 ] */ );
198 catch (...)
200 // cleanup
201 for ( sal_Int32 n = 0; n < nPos; ++n )
203 typelib_MethodParameter const & param = params[ n ];
204 if (param.bOut ||
205 typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass)
207 jni->DeleteLocalRef( java_args[ n ].l );
210 #ifdef BROKEN_ALLOCA
211 free( java_args );
212 #endif
213 throw;
217 sal_Int32 base_members = iface_td->nAllMembers - iface_td->nMembers;
218 OSL_ASSERT( base_members < iface_td->nAllMembers );
219 sal_Int32 base_members_function_pos =
220 iface_td->pMapMemberIndexToFunctionIndex[ base_members ];
221 sal_Int32 member_pos = base_members + local_member_index;
222 OSL_ENSURE(
223 member_pos < iface_td->nAllMembers, "### member pos out of range!" );
224 sal_Int32 function_pos =
225 iface_td->pMapMemberIndexToFunctionIndex[ member_pos ]
226 + function_pos_offset;
227 OSL_ENSURE(
228 function_pos >= base_members_function_pos
229 && function_pos < iface_td->nMapFunctionIndexToMemberIndex,
230 "### illegal function index!" );
231 function_pos -= base_members_function_pos;
233 JNI_interface_type_info const * info =
234 static_cast< JNI_interface_type_info const * >(
235 m_jni_info->get_type_info( jni, &iface_td->aBase ) );
236 jmethodID method_id = info->m_methods[ function_pos ];
238 #if OSL_DEBUG_LEVEL > 1
239 OUStringBuffer trace_buf( 128 );
240 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("calling ") );
241 JLocalAutoRef jo_method(
242 jni, jni->ToReflectedMethod( info->m_class, method_id, JNI_FALSE ) );
243 jni.ensure_no_exception();
244 JLocalAutoRef jo_descr(
245 jni, jni->CallObjectMethodA(
246 jo_method.get(), m_jni_info->m_method_Object_toString, 0 ) );
247 jni.ensure_no_exception();
248 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
249 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on ") );
250 jo_descr.reset(
251 jni->CallObjectMethodA(
252 javaI, m_jni_info->m_method_Object_toString, 0 ) );
253 jni.ensure_no_exception();
254 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
255 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (") );
256 JLocalAutoRef jo_class( jni, jni->GetObjectClass( javaI ) );
257 jo_descr.reset(
258 jni->CallObjectMethodA(
259 jo_class.get(), m_jni_info->m_method_Object_toString, 0 ) );
260 jni.ensure_no_exception();
261 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
262 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(")") );
263 OString cstr_trace(
264 OUStringToOString(
265 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
266 OSL_TRACE( cstr_trace.getStr() );
267 #endif
269 // complex return value
270 JLocalAutoRef java_ret( jni );
272 switch (return_type->eTypeClass)
274 case typelib_TypeClass_VOID:
275 jni->CallVoidMethodA( javaI, method_id, java_args );
276 break;
277 case typelib_TypeClass_CHAR:
278 *(sal_Unicode *)uno_ret =
279 jni->CallCharMethodA( javaI, method_id, java_args );
280 break;
281 case typelib_TypeClass_BOOLEAN:
282 *(sal_Bool *)uno_ret =
283 jni->CallBooleanMethodA( javaI, method_id, java_args );
284 break;
285 case typelib_TypeClass_BYTE:
286 *(sal_Int8 *)uno_ret =
287 jni->CallByteMethodA( javaI, method_id, java_args );
288 break;
289 case typelib_TypeClass_SHORT:
290 case typelib_TypeClass_UNSIGNED_SHORT:
291 *(sal_Int16 *)uno_ret =
292 jni->CallShortMethodA( javaI, method_id, java_args );
293 break;
294 case typelib_TypeClass_LONG:
295 case typelib_TypeClass_UNSIGNED_LONG:
296 *(sal_Int32 *)uno_ret =
297 jni->CallIntMethodA( javaI, method_id, java_args );
298 break;
299 case typelib_TypeClass_HYPER:
300 case typelib_TypeClass_UNSIGNED_HYPER:
301 *(sal_Int64 *)uno_ret =
302 jni->CallLongMethodA( javaI, method_id, java_args );
303 break;
304 case typelib_TypeClass_FLOAT:
305 *(float *)uno_ret =
306 jni->CallFloatMethodA( javaI, method_id, java_args );
307 break;
308 case typelib_TypeClass_DOUBLE:
309 *(double *)uno_ret =
310 jni->CallDoubleMethodA( javaI, method_id, java_args );
311 break;
312 default:
313 java_ret.reset(
314 jni->CallObjectMethodA( javaI, method_id, java_args ) );
315 break;
318 if (jni->ExceptionCheck())
320 JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() );
321 jni->ExceptionClear();
323 // release temp java local refs
324 for ( nPos = 0; nPos < nParams; ++nPos )
326 typelib_MethodParameter const & param = params[ nPos ];
327 if (param.bOut ||
328 typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass)
330 jni->DeleteLocalRef( java_args[ nPos ].l );
334 handle_java_exc( jni, jo_exc, *uno_exc );
336 else // no exception
338 for ( nPos = 0; nPos < nParams; ++nPos )
340 typelib_MethodParameter const & param = params[ nPos ];
341 if (param.bOut)
345 map_to_uno(
346 jni, uno_args[ nPos ],
347 java_args[ nPos ], param.pTypeRef, 0,
348 sal_False != param.bIn /* assign if inout */,
349 true /* out param */ );
351 catch (...)
353 // cleanup uno pure out
354 for ( sal_Int32 n = 0; n < nPos; ++n )
356 typelib_MethodParameter const & p = params[ n ];
357 if (! p.bIn)
359 uno_type_destructData(
360 uno_args[ n ], p.pTypeRef, 0 );
363 // cleanup java temp local refs
364 for ( ; nPos < nParams; ++nPos )
366 typelib_MethodParameter const & p = params[ nPos ];
367 if (p.bOut ||
368 typelib_TypeClass_DOUBLE <
369 p.pTypeRef->eTypeClass)
371 jni->DeleteLocalRef( java_args[ nPos ].l );
374 #ifdef BROKEN_ALLOCA
375 free( java_args );
376 #endif
377 throw;
379 jni->DeleteLocalRef( java_args[ nPos ].l );
381 else // pure temp in param
383 if (typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass)
384 jni->DeleteLocalRef( java_args[ nPos ].l );
388 // return value
389 if (typelib_TypeClass_DOUBLE < return_type->eTypeClass)
393 jvalue val;
394 val.l = java_ret.get();
395 map_to_uno(
396 jni, uno_ret, val, return_type, 0,
397 false /* no assign */, false /* no out param */ );
399 catch (...)
401 // cleanup uno pure out
402 for ( sal_Int32 i = 0; i < nParams; ++i )
404 typelib_MethodParameter const & param = params[ i ];
405 if (! param.bIn)
407 uno_type_destructData(
408 uno_args[ i ], param.pTypeRef, 0 );
411 #ifdef BROKEN_ALLOCA
412 free( java_args );
413 #endif
414 throw;
416 } // else: already set integral uno return value
418 // no exception occured
419 *uno_exc = 0;
421 #ifdef BROKEN_ALLOCA
422 free( java_args );
423 #endif
426 //==== a uno proxy wrapping a java interface ===================================
427 struct UNO_proxy : public uno_Interface
429 mutable oslInterlockedCount m_ref;
430 Bridge const * m_bridge;
432 // mapping information
433 jobject m_javaI;
434 jstring m_jo_oid;
435 OUString m_oid;
436 JNI_interface_type_info const * m_type_info;
438 inline void acquire() const;
439 inline void release() const;
441 // ctor
442 inline UNO_proxy(
443 JNI_context const & jni, Bridge const * bridge,
444 jobject javaI, jstring jo_oid, OUString const & oid,
445 JNI_interface_type_info const * info );
448 //______________________________________________________________________________
449 inline UNO_proxy::UNO_proxy(
450 JNI_context const & jni, Bridge const * bridge,
451 jobject javaI, jstring jo_oid, OUString const & oid,
452 JNI_interface_type_info const * info )
453 : m_ref( 1 ),
454 m_oid( oid ),
455 m_type_info( info )
457 JNI_info const * jni_info = bridge->m_jni_info;
458 JLocalAutoRef jo_string_array(
459 jni, jni->NewObjectArray( 1, jni_info->m_class_String, jo_oid ) );
460 jni.ensure_no_exception();
461 jvalue args[ 3 ];
462 args[ 0 ].l = javaI;
463 args[ 1 ].l = jo_string_array.get();
464 args[ 2 ].l = info->m_type;
465 jobject jo_iface = jni->CallObjectMethodA(
466 jni_info->m_object_java_env,
467 jni_info->m_method_IEnvironment_registerInterface, args );
468 jni.ensure_no_exception();
470 m_javaI = jni->NewGlobalRef( jo_iface );
471 m_jo_oid = (jstring) jni->NewGlobalRef( jo_oid );
472 bridge->acquire();
473 m_bridge = bridge;
475 // uno_Interface
476 uno_Interface::acquire = UNO_proxy_acquire;
477 uno_Interface::release = UNO_proxy_release;
478 uno_Interface::pDispatcher = UNO_proxy_dispatch;
481 //______________________________________________________________________________
482 inline void UNO_proxy::acquire() const
484 if (1 == osl_incrementInterlockedCount( &m_ref ))
486 // rebirth of proxy zombie
487 void * that = const_cast< UNO_proxy * >( this );
488 // register at uno env
489 (*m_bridge->m_uno_env->registerProxyInterface)(
490 m_bridge->m_uno_env, &that,
491 UNO_proxy_free, m_oid.pData,
492 (typelib_InterfaceTypeDescription *)m_type_info->m_td.get() );
493 #if OSL_DEBUG_LEVEL > 1
494 OSL_ASSERT( this == (void const * const)that );
495 #endif
499 //______________________________________________________________________________
500 inline void UNO_proxy::release() const
502 if (0 == osl_decrementInterlockedCount( &m_ref ))
504 // revoke from uno env on last release
505 (*m_bridge->m_uno_env->revokeInterface)(
506 m_bridge->m_uno_env, const_cast< UNO_proxy * >( this ) );
511 //______________________________________________________________________________
512 uno_Interface * Bridge::map_to_uno(
513 JNI_context const & jni,
514 jobject javaI, JNI_interface_type_info const * info ) const
516 JLocalAutoRef jo_oid( jni, compute_oid( jni, javaI ) );
517 OUString oid( jstring_to_oustring( jni, (jstring) jo_oid.get() ) );
519 uno_Interface * pUnoI = 0;
520 (*m_uno_env->getRegisteredInterface)(
521 m_uno_env, (void **)&pUnoI,
522 oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() );
524 if (0 == pUnoI) // no existing interface, register new proxy
526 // refcount initially 1
527 pUnoI = new UNO_proxy(
528 jni, const_cast< Bridge * >( this ),
529 javaI, (jstring) jo_oid.get(), oid, info );
531 (*m_uno_env->registerProxyInterface)(
532 m_uno_env, (void **)&pUnoI,
533 UNO_proxy_free,
534 oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() );
536 return pUnoI;
541 using namespace ::jni_uno;
543 namespace
545 extern "C"
548 //------------------------------------------------------------------------------
549 void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy )
550 SAL_THROW_EXTERN_C()
552 UNO_proxy const * that = reinterpret_cast< UNO_proxy const * >( proxy );
553 Bridge const * bridge = that->m_bridge;
555 if ( env != bridge->m_uno_env ) {
556 OSL_ASSERT(false);
558 #if OSL_DEBUG_LEVEL > 1
559 OString cstr_msg(
560 OUStringToOString(
561 OUSTR("freeing binary uno proxy: ") + that->m_oid,
562 RTL_TEXTENCODING_ASCII_US ) );
563 OSL_TRACE( cstr_msg.getStr() );
564 #endif
568 JNI_guarded_context jni(
569 bridge->m_jni_info,
570 reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
571 bridge->m_java_env->pContext ) );
573 jni->DeleteGlobalRef( that->m_javaI );
574 jni->DeleteGlobalRef( that->m_jo_oid );
576 catch (BridgeRuntimeError & err)
578 #if OSL_DEBUG_LEVEL > 0
579 OString cstr_msg2(
580 OUStringToOString( err.m_message, RTL_TEXTENCODING_ASCII_US ) );
581 OSL_ENSURE( 0, cstr_msg2.getStr() );
582 #else
583 (void) err; // unused
584 #endif
586 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &)
588 OSL_ENSURE(
590 "[jni_uno bridge error] attaching current thread to java failed!" );
593 bridge->release();
594 #if OSL_DEBUG_LEVEL > 1
595 *(int *)that = 0xdeadcafe;
596 #endif
597 delete that;
600 //------------------------------------------------------------------------------
601 void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI )
602 SAL_THROW_EXTERN_C()
604 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI );
605 that->acquire();
608 //------------------------------------------------------------------------------
609 void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI )
610 SAL_THROW_EXTERN_C()
612 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI );
613 that->release();
616 //------------------------------------------------------------------------------
617 void SAL_CALL UNO_proxy_dispatch(
618 uno_Interface * pUnoI, typelib_TypeDescription const * member_td,
619 void * uno_ret, void * uno_args [], uno_Any ** uno_exc )
620 SAL_THROW_EXTERN_C()
622 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI );
623 Bridge const * bridge = that->m_bridge;
625 #if OSL_DEBUG_LEVEL > 1
626 OUStringBuffer trace_buf( 64 );
627 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("uno->java call: ") );
628 trace_buf.append( OUString::unacquired( &member_td->pTypeName ) );
629 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on oid ") );
630 trace_buf.append( that->m_oid );
631 OString cstr_msg(
632 OUStringToOString(
633 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
634 OSL_TRACE( cstr_msg.getStr() );
635 #endif
639 switch (member_td->eTypeClass)
641 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
643 typelib_InterfaceAttributeTypeDescription const * attrib_td =
644 reinterpret_cast<
645 typelib_InterfaceAttributeTypeDescription const * >(
646 member_td );
647 com::sun::star::uno::TypeDescription attrib_holder;
648 while ( attrib_td->pBaseRef != 0 ) {
649 attrib_holder = com::sun::star::uno::TypeDescription(
650 attrib_td->pBaseRef );
651 OSL_ASSERT(
652 attrib_holder.get()->eTypeClass
653 == typelib_TypeClass_INTERFACE_ATTRIBUTE );
654 attrib_td = reinterpret_cast<
655 typelib_InterfaceAttributeTypeDescription * >(
656 attrib_holder.get() );
658 typelib_InterfaceTypeDescription * iface_td = attrib_td->pInterface;
660 if (0 == uno_ret) // is setter method
662 typelib_MethodParameter param;
663 param.pTypeRef = attrib_td->pAttributeTypeRef;
664 param.bIn = sal_True;
665 param.bOut = sal_False;
667 bridge->call_java(
668 that->m_javaI, iface_td,
669 attrib_td->nIndex, 1, // get, then set method
670 bridge->m_jni_info->m_void_type.getTypeLibType(),
671 &param, 1,
672 0, uno_args, uno_exc );
674 else // is getter method
676 bridge->call_java(
677 that->m_javaI, iface_td, attrib_td->nIndex, 0,
678 attrib_td->pAttributeTypeRef,
679 0, 0, // no params
680 uno_ret, 0, uno_exc );
682 break;
684 case typelib_TypeClass_INTERFACE_METHOD:
686 typelib_InterfaceMethodTypeDescription const * method_td =
687 reinterpret_cast<
688 typelib_InterfaceMethodTypeDescription const * >(
689 member_td );
690 com::sun::star::uno::TypeDescription method_holder;
691 while ( method_td->pBaseRef != 0 ) {
692 method_holder = com::sun::star::uno::TypeDescription(
693 method_td->pBaseRef );
694 OSL_ASSERT(
695 method_holder.get()->eTypeClass
696 == typelib_TypeClass_INTERFACE_METHOD );
697 method_td = reinterpret_cast<
698 typelib_InterfaceMethodTypeDescription * >(
699 method_holder.get() );
701 typelib_InterfaceTypeDescription * iface_td = method_td->pInterface;
703 switch ( method_td->aBase.nPosition )
705 case 0: // queryInterface()
707 TypeDescr demanded_td(
708 *reinterpret_cast< typelib_TypeDescriptionReference ** >(
709 uno_args[ 0 ] ) );
710 if (typelib_TypeClass_INTERFACE !=
711 demanded_td.get()->eTypeClass)
713 throw BridgeRuntimeError(
714 OUSTR("queryInterface() call demands "
715 "an INTERFACE type!") );
718 uno_Interface * pInterface = 0;
719 (*bridge->m_uno_env->getRegisteredInterface)(
720 bridge->m_uno_env,
721 (void **) &pInterface, that->m_oid.pData,
722 (typelib_InterfaceTypeDescription *)demanded_td.get() );
724 if (0 == pInterface)
726 JNI_info const * jni_info = bridge->m_jni_info;
727 JNI_guarded_context jni(
728 jni_info,
729 reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
730 bridge->m_java_env->pContext ) );
732 JNI_interface_type_info const * info =
733 static_cast< JNI_interface_type_info const * >(
734 jni_info->get_type_info( jni, demanded_td.get() ) );
736 jvalue args[ 2 ];
737 args[ 0 ].l = info->m_type;
738 args[ 1 ].l = that->m_javaI;
740 JLocalAutoRef jo_ret(
741 jni, jni->CallStaticObjectMethodA(
742 jni_info->m_class_UnoRuntime,
743 jni_info->m_method_UnoRuntime_queryInterface,
744 args ) );
746 if (jni->ExceptionCheck())
748 JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() );
749 jni->ExceptionClear();
750 bridge->handle_java_exc( jni, jo_exc, *uno_exc );
752 else
754 if (jo_ret.is())
756 #if OSL_DEBUG_LEVEL > 0
757 JLocalAutoRef jo_oid(
758 jni, compute_oid( jni, jo_ret.get() ) );
759 OUString oid( jstring_to_oustring(
760 jni, (jstring) jo_oid.get() ) );
761 OSL_ENSURE(
762 oid.equals( that->m_oid ),
763 "### different oids!" );
764 #endif
765 // refcount initially 1
766 uno_Interface * pUnoI2 = new UNO_proxy(
767 jni, bridge, jo_ret.get(),
768 that->m_jo_oid, that->m_oid, info );
770 (*bridge->m_uno_env->registerProxyInterface)(
771 bridge->m_uno_env,
772 (void **) &pUnoI2,
773 UNO_proxy_free, that->m_oid.pData,
774 reinterpret_cast<
775 typelib_InterfaceTypeDescription * >(
776 info->m_td.get() ) );
778 uno_any_construct(
779 (uno_Any *)uno_ret, &pUnoI2,
780 demanded_td.get(), 0 );
781 (*pUnoI2->release)( pUnoI2 );
783 else // object does not support demanded interface
785 uno_any_construct(
786 reinterpret_cast< uno_Any * >( uno_ret ),
787 0, 0, 0 );
789 // no exception occured
790 *uno_exc = 0;
793 else
795 uno_any_construct(
796 reinterpret_cast< uno_Any * >( uno_ret ),
797 &pInterface, demanded_td.get(), 0 );
798 (*pInterface->release)( pInterface );
799 *uno_exc = 0;
801 break;
803 case 1: // acquire this proxy
804 that->acquire();
805 *uno_exc = 0;
806 break;
807 case 2: // release this proxy
808 that->release();
809 *uno_exc = 0;
810 break;
811 default: // arbitrary method call
812 bridge->call_java(
813 that->m_javaI, iface_td, method_td->nIndex, 0,
814 method_td->pReturnTypeRef,
815 method_td->pParams, method_td->nParams,
816 uno_ret, uno_args, uno_exc );
817 break;
819 break;
821 default:
823 throw BridgeRuntimeError(
824 OUSTR("illegal member type description!") );
828 catch (BridgeRuntimeError & err)
830 OUStringBuffer buf( 128 );
831 buf.appendAscii(
832 RTL_CONSTASCII_STRINGPARAM(
833 "[jni_uno bridge error] UNO calling Java method ") );
834 if (typelib_TypeClass_INTERFACE_METHOD == member_td->eTypeClass ||
835 typelib_TypeClass_INTERFACE_ATTRIBUTE == member_td->eTypeClass)
837 buf.append( OUString::unacquired(
838 &reinterpret_cast<
839 typelib_InterfaceMemberTypeDescription const * >(
840 member_td )->pMemberName ) );
842 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") );
843 buf.append( err.m_message );
844 // binary identical struct
845 ::com::sun::star::uno::RuntimeException exc(
846 buf.makeStringAndClear(),
847 ::com::sun::star::uno::Reference<
848 ::com::sun::star::uno::XInterface >() );
849 ::com::sun::star::uno::Type const & exc_type = ::getCppuType( &exc );
850 uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0 );
851 #if OSL_DEBUG_LEVEL > 0
852 OString cstr_msg2(
853 OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) );
854 OSL_ENSURE( 0, cstr_msg2.getStr() );
855 #endif
857 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &)
859 // binary identical struct
860 ::com::sun::star::uno::RuntimeException exc(
861 OUSTR("[jni_uno bridge error] attaching current thread "
862 "to java failed!"),
863 ::com::sun::star::uno::Reference<
864 ::com::sun::star::uno::XInterface >() );
865 ::com::sun::star::uno::Type const & exc_type = ::getCppuType( &exc );
866 uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0 );
867 #if OSL_DEBUG_LEVEL > 0
868 OString cstr_msg2(
869 OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) );
870 OSL_ENSURE( 0, cstr_msg2.getStr() );
871 #endif