Bump for 3.6-28
[LibreOffice.git] / bridges / source / jni_uno / jni_uno2java.cxx
blobb38aad90391f56a9d3586ab0254ee7fe8669ec83
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <sal/alloca.h>
32 #include "com/sun/star/uno/RuntimeException.hpp"
34 #include "rtl/ustrbuf.hxx"
36 #include "jni_bridge.h"
39 using namespace ::std;
40 using namespace ::rtl;
42 namespace
44 extern "C"
47 //------------------------------------------------------------------------------
48 void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy )
49 SAL_THROW_EXTERN_C();
51 //------------------------------------------------------------------------------
52 void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI )
53 SAL_THROW_EXTERN_C();
55 //------------------------------------------------------------------------------
56 void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI )
57 SAL_THROW_EXTERN_C();
59 //------------------------------------------------------------------------------
60 void SAL_CALL UNO_proxy_dispatch(
61 uno_Interface * pUnoI, typelib_TypeDescription const * member_td,
62 void * uno_ret, void * uno_args[], uno_Any ** uno_exc )
63 SAL_THROW_EXTERN_C();
67 namespace jni_uno
70 //______________________________________________________________________________
71 void Bridge::handle_java_exc(
72 JNI_context const & jni,
73 JLocalAutoRef const & jo_exc, uno_Any * uno_exc ) const
75 OSL_ASSERT( jo_exc.is() );
76 if (! jo_exc.is())
78 throw BridgeRuntimeError(
79 OUSTR("java exception occurred, but no java exception available!?") +
80 jni.get_stack_trace() );
83 JLocalAutoRef jo_class( jni, jni->GetObjectClass( jo_exc.get() ) );
84 JLocalAutoRef jo_class_name(
85 jni, jni->CallObjectMethodA(
86 jo_class.get(), m_jni_info->m_method_Class_getName, 0 ) );
87 jni.ensure_no_exception();
88 OUString exc_name(
89 jstring_to_oustring( jni, (jstring) jo_class_name.get() ) );
91 ::com::sun::star::uno::TypeDescription td( exc_name.pData );
92 if (!td.is() || (typelib_TypeClass_EXCEPTION != td.get()->eTypeClass))
94 // call toString()
95 JLocalAutoRef jo_descr(
96 jni, jni->CallObjectMethodA(
97 jo_exc.get(), m_jni_info->m_method_Object_toString, 0 ) );
98 jni.ensure_no_exception();
99 OUStringBuffer buf( 128 );
100 buf.appendAscii(
101 RTL_CONSTASCII_STRINGPARAM("non-UNO exception occurred: ") );
102 buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
103 buf.append( jni.get_stack_trace( jo_exc.get() ) );
104 throw BridgeRuntimeError( buf.makeStringAndClear() );
107 SAL_WNODEPRECATED_DECLARATIONS_PUSH
108 auto_ptr< rtl_mem > uno_data( rtl_mem::allocate( td.get()->nSize ) );
109 SAL_WNODEPRECATED_DECLARATIONS_POP
110 jvalue val;
111 val.l = jo_exc.get();
112 map_to_uno(
113 jni, uno_data.get(), val, td.get()->pWeakRef, 0,
114 false /* no assign */, false /* no out param */ );
116 #if OSL_DEBUG_LEVEL > 0
117 // patch Message, append stack trace
118 reinterpret_cast< ::com::sun::star::uno::Exception * >(
119 uno_data.get() )->Message += jni.get_stack_trace( jo_exc.get() );
120 #endif
122 typelib_typedescriptionreference_acquire( td.get()->pWeakRef );
123 uno_exc->pType = td.get()->pWeakRef;
124 uno_exc->pData = uno_data.release();
126 #if OSL_DEBUG_LEVEL > 1
127 OUStringBuffer trace_buf( 128 );
128 trace_buf.appendAscii(
129 RTL_CONSTASCII_STRINGPARAM("exception occurred uno->java: [") );
130 trace_buf.append( exc_name );
131 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") );
132 trace_buf.append(
133 reinterpret_cast< ::com::sun::star::uno::Exception const * >(
134 uno_exc->pData )->Message );
135 OString cstr_trace(
136 OUStringToOString(
137 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
138 OSL_TRACE( "%s", cstr_trace.getStr() );
139 #endif
142 //______________________________________________________________________________
143 void Bridge::call_java(
144 jobject javaI, typelib_InterfaceTypeDescription * iface_td,
145 sal_Int32 local_member_index, sal_Int32 function_pos_offset,
146 typelib_TypeDescriptionReference * return_type,
147 typelib_MethodParameter * params, sal_Int32 nParams,
148 void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const
150 OSL_ASSERT( function_pos_offset == 0 || function_pos_offset == 1 );
152 JNI_guarded_context jni(
153 m_jni_info, reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
154 m_java_env->pContext ) );
156 // assure fully initialized iface_td:
157 ::com::sun::star::uno::TypeDescription iface_holder;
158 if (! iface_td->aBase.bComplete) {
159 iface_holder = ::com::sun::star::uno::TypeDescription(
160 reinterpret_cast<typelib_TypeDescription *>(iface_td) );
161 iface_holder.makeComplete();
162 if (! iface_holder.get()->bComplete) {
163 OUStringBuffer buf;
164 buf.appendAscii(
165 RTL_CONSTASCII_STRINGPARAM("cannot make type complete: ") );
166 buf.append( OUString::unacquired(&iface_holder.get()->pTypeName) );
167 buf.append( jni.get_stack_trace() );
168 throw BridgeRuntimeError( buf.makeStringAndClear() );
170 iface_td = reinterpret_cast<typelib_InterfaceTypeDescription *>(
171 iface_holder.get() );
172 OSL_ASSERT( iface_td->aBase.eTypeClass == typelib_TypeClass_INTERFACE );
175 // prepare java args, save param td
176 #ifdef BROKEN_ALLOCA
177 jvalue * java_args = (jvalue *) malloc( sizeof (jvalue) * nParams );
178 #else
179 jvalue * java_args = (jvalue *) alloca( sizeof (jvalue) * nParams );
180 #endif
182 sal_Int32 nPos;
183 for ( nPos = 0; nPos < nParams; ++nPos )
187 typelib_MethodParameter const & param = params[ nPos ];
188 java_args[ nPos ].l = 0; // if out: build up array[ 1 ]
189 map_to_java(
190 jni, &java_args[ nPos ],
191 uno_args[ nPos ],
192 param.pTypeRef, 0,
193 sal_False != param.bIn /* convert uno value */,
194 sal_False != param.bOut /* build up array[ 1 ] */ );
196 catch (...)
198 // cleanup
199 for ( sal_Int32 n = 0; n < nPos; ++n )
201 typelib_MethodParameter const & param = params[ n ];
202 if (param.bOut ||
203 typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass)
205 jni->DeleteLocalRef( java_args[ n ].l );
208 #ifdef BROKEN_ALLOCA
209 free( java_args );
210 #endif
211 throw;
215 sal_Int32 base_members = iface_td->nAllMembers - iface_td->nMembers;
216 OSL_ASSERT( base_members < iface_td->nAllMembers );
217 sal_Int32 base_members_function_pos =
218 iface_td->pMapMemberIndexToFunctionIndex[ base_members ];
219 sal_Int32 member_pos = base_members + local_member_index;
220 OSL_ENSURE(
221 member_pos < iface_td->nAllMembers, "### member pos out of range!" );
222 sal_Int32 function_pos =
223 iface_td->pMapMemberIndexToFunctionIndex[ member_pos ]
224 + function_pos_offset;
225 OSL_ENSURE(
226 function_pos >= base_members_function_pos
227 && function_pos < iface_td->nMapFunctionIndexToMemberIndex,
228 "### illegal function index!" );
229 function_pos -= base_members_function_pos;
231 JNI_interface_type_info const * info =
232 static_cast< JNI_interface_type_info const * >(
233 m_jni_info->get_type_info( jni, &iface_td->aBase ) );
234 jmethodID method_id = info->m_methods[ function_pos ];
236 #if OSL_DEBUG_LEVEL > 1
237 OUStringBuffer trace_buf( 128 );
238 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("calling ") );
239 JLocalAutoRef jo_method(
240 jni, jni->ToReflectedMethod( info->m_class, method_id, JNI_FALSE ) );
241 jni.ensure_no_exception();
242 JLocalAutoRef jo_descr(
243 jni, jni->CallObjectMethodA(
244 jo_method.get(), m_jni_info->m_method_Object_toString, 0 ) );
245 jni.ensure_no_exception();
246 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
247 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on ") );
248 jo_descr.reset(
249 jni->CallObjectMethodA(
250 javaI, m_jni_info->m_method_Object_toString, 0 ) );
251 jni.ensure_no_exception();
252 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
253 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (") );
254 JLocalAutoRef jo_class( jni, jni->GetObjectClass( javaI ) );
255 jo_descr.reset(
256 jni->CallObjectMethodA(
257 jo_class.get(), m_jni_info->m_method_Object_toString, 0 ) );
258 jni.ensure_no_exception();
259 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
260 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(")") );
261 OString cstr_trace(
262 OUStringToOString(
263 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
264 OSL_TRACE( "%s", cstr_trace.getStr() );
265 #endif
267 // complex return value
268 JLocalAutoRef java_ret( jni );
270 switch (return_type->eTypeClass)
272 case typelib_TypeClass_VOID:
273 jni->CallVoidMethodA( javaI, method_id, java_args );
274 break;
275 case typelib_TypeClass_CHAR:
276 *(sal_Unicode *)uno_ret =
277 jni->CallCharMethodA( javaI, method_id, java_args );
278 break;
279 case typelib_TypeClass_BOOLEAN:
280 *(sal_Bool *)uno_ret =
281 jni->CallBooleanMethodA( javaI, method_id, java_args );
282 break;
283 case typelib_TypeClass_BYTE:
284 *(sal_Int8 *)uno_ret =
285 jni->CallByteMethodA( javaI, method_id, java_args );
286 break;
287 case typelib_TypeClass_SHORT:
288 case typelib_TypeClass_UNSIGNED_SHORT:
289 *(sal_Int16 *)uno_ret =
290 jni->CallShortMethodA( javaI, method_id, java_args );
291 break;
292 case typelib_TypeClass_LONG:
293 case typelib_TypeClass_UNSIGNED_LONG:
294 *(sal_Int32 *)uno_ret =
295 jni->CallIntMethodA( javaI, method_id, java_args );
296 break;
297 case typelib_TypeClass_HYPER:
298 case typelib_TypeClass_UNSIGNED_HYPER:
299 *(sal_Int64 *)uno_ret =
300 jni->CallLongMethodA( javaI, method_id, java_args );
301 break;
302 case typelib_TypeClass_FLOAT:
303 *(float *)uno_ret =
304 jni->CallFloatMethodA( javaI, method_id, java_args );
305 break;
306 case typelib_TypeClass_DOUBLE:
307 *(double *)uno_ret =
308 jni->CallDoubleMethodA( javaI, method_id, java_args );
309 break;
310 default:
311 java_ret.reset(
312 jni->CallObjectMethodA( javaI, method_id, java_args ) );
313 break;
316 if (jni->ExceptionCheck())
318 JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() );
319 jni->ExceptionClear();
321 // release temp java local refs
322 for ( nPos = 0; nPos < nParams; ++nPos )
324 typelib_MethodParameter const & param = params[ nPos ];
325 if (param.bOut ||
326 typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass)
328 jni->DeleteLocalRef( java_args[ nPos ].l );
332 handle_java_exc( jni, jo_exc, *uno_exc );
334 else // no exception
336 for ( nPos = 0; nPos < nParams; ++nPos )
338 typelib_MethodParameter const & param = params[ nPos ];
339 if (param.bOut)
343 map_to_uno(
344 jni, uno_args[ nPos ],
345 java_args[ nPos ], param.pTypeRef, 0,
346 sal_False != param.bIn /* assign if inout */,
347 true /* out param */ );
349 catch (...)
351 // cleanup uno pure out
352 for ( sal_Int32 n = 0; n < nPos; ++n )
354 typelib_MethodParameter const & p = params[ n ];
355 if (! p.bIn)
357 uno_type_destructData(
358 uno_args[ n ], p.pTypeRef, 0 );
361 // cleanup java temp local refs
362 for ( ; nPos < nParams; ++nPos )
364 typelib_MethodParameter const & p = params[ nPos ];
365 if (p.bOut ||
366 typelib_TypeClass_DOUBLE <
367 p.pTypeRef->eTypeClass)
369 jni->DeleteLocalRef( java_args[ nPos ].l );
372 #ifdef BROKEN_ALLOCA
373 free( java_args );
374 #endif
375 throw;
377 jni->DeleteLocalRef( java_args[ nPos ].l );
379 else // pure temp in param
381 if (typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass)
382 jni->DeleteLocalRef( java_args[ nPos ].l );
386 // return value
387 if (typelib_TypeClass_DOUBLE < return_type->eTypeClass)
391 jvalue val;
392 val.l = java_ret.get();
393 map_to_uno(
394 jni, uno_ret, val, return_type, 0,
395 false /* no assign */, false /* no out param */ );
397 catch (...)
399 // cleanup uno pure out
400 for ( sal_Int32 i = 0; i < nParams; ++i )
402 typelib_MethodParameter const & param = params[ i ];
403 if (! param.bIn)
405 uno_type_destructData(
406 uno_args[ i ], param.pTypeRef, 0 );
409 #ifdef BROKEN_ALLOCA
410 free( java_args );
411 #endif
412 throw;
414 } // else: already set integral uno return value
416 // no exception occurred
417 *uno_exc = 0;
419 #ifdef BROKEN_ALLOCA
420 free( java_args );
421 #endif
424 //==== a uno proxy wrapping a java interface ===================================
425 struct UNO_proxy : public uno_Interface
427 mutable oslInterlockedCount m_ref;
428 Bridge const * m_bridge;
430 // mapping information
431 jobject m_javaI;
432 jstring m_jo_oid;
433 OUString m_oid;
434 JNI_interface_type_info const * m_type_info;
436 inline void acquire() const;
437 inline void release() const;
439 // ctor
440 inline UNO_proxy(
441 JNI_context const & jni, Bridge const * bridge,
442 jobject javaI, jstring jo_oid, OUString const & oid,
443 JNI_interface_type_info const * info );
446 //______________________________________________________________________________
447 inline UNO_proxy::UNO_proxy(
448 JNI_context const & jni, Bridge const * bridge,
449 jobject javaI, jstring jo_oid, OUString const & oid,
450 JNI_interface_type_info const * info )
451 : m_ref( 1 ),
452 m_oid( oid ),
453 m_type_info( info )
455 JNI_info const * jni_info = bridge->m_jni_info;
456 JLocalAutoRef jo_string_array(
457 jni, jni->NewObjectArray( 1, jni_info->m_class_String, jo_oid ) );
458 jni.ensure_no_exception();
459 jvalue args[ 3 ];
460 args[ 0 ].l = javaI;
461 args[ 1 ].l = jo_string_array.get();
462 args[ 2 ].l = info->m_type;
463 jobject jo_iface = jni->CallObjectMethodA(
464 jni_info->m_object_java_env,
465 jni_info->m_method_IEnvironment_registerInterface, args );
466 jni.ensure_no_exception();
468 m_javaI = jni->NewGlobalRef( jo_iface );
469 m_jo_oid = (jstring) jni->NewGlobalRef( jo_oid );
470 bridge->acquire();
471 m_bridge = bridge;
473 // uno_Interface
474 uno_Interface::acquire = UNO_proxy_acquire;
475 uno_Interface::release = UNO_proxy_release;
476 uno_Interface::pDispatcher = UNO_proxy_dispatch;
479 //______________________________________________________________________________
480 inline void UNO_proxy::acquire() const
482 if (1 == osl_incrementInterlockedCount( &m_ref ))
484 // rebirth of proxy zombie
485 void * that = const_cast< UNO_proxy * >( this );
486 // register at uno env
487 (*m_bridge->m_uno_env->registerProxyInterface)(
488 m_bridge->m_uno_env, &that,
489 UNO_proxy_free, m_oid.pData,
490 (typelib_InterfaceTypeDescription *)m_type_info->m_td.get() );
491 #if OSL_DEBUG_LEVEL > 1
492 OSL_ASSERT( this == (void const * const)that );
493 #endif
497 //______________________________________________________________________________
498 inline void UNO_proxy::release() const
500 if (0 == osl_decrementInterlockedCount( &m_ref ))
502 // revoke from uno env on last release
503 (*m_bridge->m_uno_env->revokeInterface)(
504 m_bridge->m_uno_env, const_cast< UNO_proxy * >( this ) );
509 //______________________________________________________________________________
510 uno_Interface * Bridge::map_to_uno(
511 JNI_context const & jni,
512 jobject javaI, JNI_interface_type_info const * info ) const
514 JLocalAutoRef jo_oid( jni, compute_oid( jni, javaI ) );
515 OUString oid( jstring_to_oustring( jni, (jstring) jo_oid.get() ) );
517 uno_Interface * pUnoI = 0;
518 (*m_uno_env->getRegisteredInterface)(
519 m_uno_env, (void **)&pUnoI,
520 oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() );
522 if (0 == pUnoI) // no existing interface, register new proxy
524 // refcount initially 1
525 pUnoI = new UNO_proxy(
526 jni, const_cast< Bridge * >( this ),
527 javaI, (jstring) jo_oid.get(), oid, info );
529 (*m_uno_env->registerProxyInterface)(
530 m_uno_env, (void **)&pUnoI,
531 UNO_proxy_free,
532 oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() );
534 return pUnoI;
539 using namespace ::jni_uno;
541 namespace
543 extern "C"
546 //------------------------------------------------------------------------------
547 void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy )
548 SAL_THROW_EXTERN_C()
550 UNO_proxy const * that = reinterpret_cast< UNO_proxy const * >( proxy );
551 Bridge const * bridge = that->m_bridge;
553 if ( env != bridge->m_uno_env ) {
554 OSL_ASSERT(false);
556 #if OSL_DEBUG_LEVEL > 1
557 OString cstr_msg(
558 OUStringToOString(
559 OUSTR("freeing binary uno proxy: ") + that->m_oid,
560 RTL_TEXTENCODING_ASCII_US ) );
561 OSL_TRACE( "%s", cstr_msg.getStr() );
562 #endif
566 JNI_guarded_context jni(
567 bridge->m_jni_info,
568 reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
569 bridge->m_java_env->pContext ) );
571 jni->DeleteGlobalRef( that->m_javaI );
572 jni->DeleteGlobalRef( that->m_jo_oid );
574 catch (BridgeRuntimeError & err)
576 #if OSL_DEBUG_LEVEL > 0
577 OString cstr_msg2(
578 OUStringToOString( err.m_message, RTL_TEXTENCODING_ASCII_US ) );
579 OSL_FAIL( cstr_msg2.getStr() );
580 #else
581 (void) err; // unused
582 #endif
584 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &)
586 OSL_FAIL(
587 "[jni_uno bridge error] attaching current thread to java failed!" );
590 bridge->release();
591 #if OSL_DEBUG_LEVEL > 1
592 *(int *)that = 0xdeadcafe;
593 #endif
594 delete that;
597 //------------------------------------------------------------------------------
598 void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI )
599 SAL_THROW_EXTERN_C()
601 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI );
602 that->acquire();
605 //------------------------------------------------------------------------------
606 void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI )
607 SAL_THROW_EXTERN_C()
609 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI );
610 that->release();
613 //------------------------------------------------------------------------------
614 void SAL_CALL UNO_proxy_dispatch(
615 uno_Interface * pUnoI, typelib_TypeDescription const * member_td,
616 void * uno_ret, void * uno_args [], uno_Any ** uno_exc )
617 SAL_THROW_EXTERN_C()
619 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI );
620 Bridge const * bridge = that->m_bridge;
622 #if OSL_DEBUG_LEVEL > 1
623 OUStringBuffer trace_buf( 64 );
624 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("uno->java call: ") );
625 trace_buf.append( OUString::unacquired( &member_td->pTypeName ) );
626 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on oid ") );
627 trace_buf.append( that->m_oid );
628 OString cstr_msg(
629 OUStringToOString(
630 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
631 OSL_TRACE( "%s", cstr_msg.getStr() );
632 #endif
636 switch (member_td->eTypeClass)
638 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
640 typelib_InterfaceAttributeTypeDescription const * attrib_td =
641 reinterpret_cast<
642 typelib_InterfaceAttributeTypeDescription const * >(
643 member_td );
644 com::sun::star::uno::TypeDescription attrib_holder;
645 while ( attrib_td->pBaseRef != 0 ) {
646 attrib_holder = com::sun::star::uno::TypeDescription(
647 attrib_td->pBaseRef );
648 OSL_ASSERT(
649 attrib_holder.get()->eTypeClass
650 == typelib_TypeClass_INTERFACE_ATTRIBUTE );
651 attrib_td = reinterpret_cast<
652 typelib_InterfaceAttributeTypeDescription * >(
653 attrib_holder.get() );
655 typelib_InterfaceTypeDescription * iface_td = attrib_td->pInterface;
657 if (0 == uno_ret) // is setter method
659 typelib_MethodParameter param;
660 param.pTypeRef = attrib_td->pAttributeTypeRef;
661 param.bIn = sal_True;
662 param.bOut = sal_False;
664 bridge->call_java(
665 that->m_javaI, iface_td,
666 attrib_td->nIndex, 1, // get, then set method
667 bridge->m_jni_info->m_void_type.getTypeLibType(),
668 &param, 1,
669 0, uno_args, uno_exc );
671 else // is getter method
673 bridge->call_java(
674 that->m_javaI, iface_td, attrib_td->nIndex, 0,
675 attrib_td->pAttributeTypeRef,
676 0, 0, // no params
677 uno_ret, 0, uno_exc );
679 break;
681 case typelib_TypeClass_INTERFACE_METHOD:
683 typelib_InterfaceMethodTypeDescription const * method_td =
684 reinterpret_cast<
685 typelib_InterfaceMethodTypeDescription const * >(
686 member_td );
687 com::sun::star::uno::TypeDescription method_holder;
688 while ( method_td->pBaseRef != 0 ) {
689 method_holder = com::sun::star::uno::TypeDescription(
690 method_td->pBaseRef );
691 OSL_ASSERT(
692 method_holder.get()->eTypeClass
693 == typelib_TypeClass_INTERFACE_METHOD );
694 method_td = reinterpret_cast<
695 typelib_InterfaceMethodTypeDescription * >(
696 method_holder.get() );
698 typelib_InterfaceTypeDescription * iface_td = method_td->pInterface;
700 switch ( method_td->aBase.nPosition )
702 case 0: // queryInterface()
704 TypeDescr demanded_td(
705 *reinterpret_cast< typelib_TypeDescriptionReference ** >(
706 uno_args[ 0 ] ) );
707 if (typelib_TypeClass_INTERFACE !=
708 demanded_td.get()->eTypeClass)
710 throw BridgeRuntimeError(
711 OUSTR("queryInterface() call demands "
712 "an INTERFACE type!") );
715 uno_Interface * pInterface = 0;
716 (*bridge->m_uno_env->getRegisteredInterface)(
717 bridge->m_uno_env,
718 (void **) &pInterface, that->m_oid.pData,
719 (typelib_InterfaceTypeDescription *)demanded_td.get() );
721 if (0 == pInterface)
723 JNI_info const * jni_info = bridge->m_jni_info;
724 JNI_guarded_context jni(
725 jni_info,
726 reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
727 bridge->m_java_env->pContext ) );
729 JNI_interface_type_info const * info =
730 static_cast< JNI_interface_type_info const * >(
731 jni_info->get_type_info( jni, demanded_td.get() ) );
733 jvalue args[ 2 ];
734 args[ 0 ].l = info->m_type;
735 args[ 1 ].l = that->m_javaI;
737 JLocalAutoRef jo_ret(
738 jni, jni->CallStaticObjectMethodA(
739 jni_info->m_class_UnoRuntime,
740 jni_info->m_method_UnoRuntime_queryInterface,
741 args ) );
743 if (jni->ExceptionCheck())
745 JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() );
746 jni->ExceptionClear();
747 bridge->handle_java_exc( jni, jo_exc, *uno_exc );
749 else
751 if (jo_ret.is())
753 #if OSL_DEBUG_LEVEL > 0
754 JLocalAutoRef jo_oid(
755 jni, compute_oid( jni, jo_ret.get() ) );
756 OUString oid( jstring_to_oustring(
757 jni, (jstring) jo_oid.get() ) );
758 OSL_ENSURE(
759 oid.equals( that->m_oid ),
760 "### different oids!" );
761 #endif
762 // refcount initially 1
763 uno_Interface * pUnoI2 = new UNO_proxy(
764 jni, bridge, jo_ret.get(),
765 that->m_jo_oid, that->m_oid, info );
767 (*bridge->m_uno_env->registerProxyInterface)(
768 bridge->m_uno_env,
769 (void **) &pUnoI2,
770 UNO_proxy_free, that->m_oid.pData,
771 reinterpret_cast<
772 typelib_InterfaceTypeDescription * >(
773 info->m_td.get() ) );
775 uno_any_construct(
776 (uno_Any *)uno_ret, &pUnoI2,
777 demanded_td.get(), 0 );
778 (*pUnoI2->release)( pUnoI2 );
780 else // object does not support demanded interface
782 uno_any_construct(
783 reinterpret_cast< uno_Any * >( uno_ret ),
784 0, 0, 0 );
786 // no exception occurred
787 *uno_exc = 0;
790 else
792 uno_any_construct(
793 reinterpret_cast< uno_Any * >( uno_ret ),
794 &pInterface, demanded_td.get(), 0 );
795 (*pInterface->release)( pInterface );
796 *uno_exc = 0;
798 break;
800 case 1: // acquire this proxy
801 that->acquire();
802 *uno_exc = 0;
803 break;
804 case 2: // release this proxy
805 that->release();
806 *uno_exc = 0;
807 break;
808 default: // arbitrary method call
809 bridge->call_java(
810 that->m_javaI, iface_td, method_td->nIndex, 0,
811 method_td->pReturnTypeRef,
812 method_td->pParams, method_td->nParams,
813 uno_ret, uno_args, uno_exc );
814 break;
816 break;
818 default:
820 throw BridgeRuntimeError(
821 OUSTR("illegal member type description!") );
825 catch (BridgeRuntimeError & err)
827 OUStringBuffer buf( 128 );
828 buf.appendAscii(
829 RTL_CONSTASCII_STRINGPARAM(
830 "[jni_uno bridge error] UNO calling Java method ") );
831 if (typelib_TypeClass_INTERFACE_METHOD == member_td->eTypeClass ||
832 typelib_TypeClass_INTERFACE_ATTRIBUTE == member_td->eTypeClass)
834 buf.append( OUString::unacquired(
835 &reinterpret_cast<
836 typelib_InterfaceMemberTypeDescription const * >(
837 member_td )->pMemberName ) );
839 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") );
840 buf.append( err.m_message );
841 // binary identical struct
842 ::com::sun::star::uno::RuntimeException exc(
843 buf.makeStringAndClear(),
844 ::com::sun::star::uno::Reference<
845 ::com::sun::star::uno::XInterface >() );
846 ::com::sun::star::uno::Type const & exc_type = ::getCppuType( &exc );
847 uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0 );
848 #if OSL_DEBUG_LEVEL > 0
849 OString cstr_msg2(
850 OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) );
851 OSL_TRACE( "%s", cstr_msg2.getStr() );
852 #endif
854 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &)
856 // binary identical struct
857 ::com::sun::star::uno::RuntimeException exc(
858 OUSTR("[jni_uno bridge error] attaching current thread "
859 "to java failed!"),
860 ::com::sun::star::uno::Reference<
861 ::com::sun::star::uno::XInterface >() );
862 ::com::sun::star::uno::Type const & exc_type = ::getCppuType( &exc );
863 uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0 );
864 #if OSL_DEBUG_LEVEL > 0
865 OString cstr_msg2(
866 OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) );
867 OSL_FAIL( cstr_msg2.getStr() );
868 #endif
875 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */