bump product version to 4.1.6.2
[LibreOffice.git] / bridges / source / jni_uno / jni_uno2java.cxx
blob9ba852f1f7ac05d63e839a29a5c23998b4e07df2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <sal/alloca.h>
23 #include "com/sun/star/uno/RuntimeException.hpp"
25 #include "rtl/ustrbuf.hxx"
27 #include "jni_bridge.h"
30 using namespace ::std;
31 using namespace ::rtl;
33 namespace
35 extern "C"
38 //------------------------------------------------------------------------------
39 void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy )
40 SAL_THROW_EXTERN_C();
42 //------------------------------------------------------------------------------
43 void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI )
44 SAL_THROW_EXTERN_C();
46 //------------------------------------------------------------------------------
47 void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI )
48 SAL_THROW_EXTERN_C();
50 //------------------------------------------------------------------------------
51 void SAL_CALL UNO_proxy_dispatch(
52 uno_Interface * pUnoI, typelib_TypeDescription const * member_td,
53 void * uno_ret, void * uno_args[], uno_Any ** uno_exc )
54 SAL_THROW_EXTERN_C();
58 namespace jni_uno
61 //______________________________________________________________________________
62 void Bridge::handle_java_exc(
63 JNI_context const & jni,
64 JLocalAutoRef const & jo_exc, uno_Any * uno_exc ) const
66 OSL_ASSERT( jo_exc.is() );
67 if (! jo_exc.is())
69 throw BridgeRuntimeError(
70 "java exception occurred, but no java exception available!?" +
71 jni.get_stack_trace() );
74 JLocalAutoRef jo_class( jni, jni->GetObjectClass( jo_exc.get() ) );
75 JLocalAutoRef jo_class_name(
76 jni, jni->CallObjectMethodA(
77 jo_class.get(), m_jni_info->m_method_Class_getName, 0 ) );
78 jni.ensure_no_exception();
79 OUString exc_name(
80 jstring_to_oustring( jni, (jstring) jo_class_name.get() ) );
82 ::com::sun::star::uno::TypeDescription td( exc_name.pData );
83 if (!td.is() || (typelib_TypeClass_EXCEPTION != td.get()->eTypeClass))
85 // call toString()
86 JLocalAutoRef jo_descr(
87 jni, jni->CallObjectMethodA(
88 jo_exc.get(), m_jni_info->m_method_Object_toString, 0 ) );
89 jni.ensure_no_exception();
90 OUStringBuffer buf( 128 );
91 buf.append( "non-UNO exception occurred: " );
92 buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
93 buf.append( jni.get_stack_trace( jo_exc.get() ) );
94 throw BridgeRuntimeError( buf.makeStringAndClear() );
97 SAL_WNODEPRECATED_DECLARATIONS_PUSH
98 auto_ptr< rtl_mem > uno_data( rtl_mem::allocate( td.get()->nSize ) );
99 SAL_WNODEPRECATED_DECLARATIONS_POP
100 jvalue val;
101 val.l = jo_exc.get();
102 map_to_uno(
103 jni, uno_data.get(), val, td.get()->pWeakRef, 0,
104 false /* no assign */, false /* no out param */ );
106 #if OSL_DEBUG_LEVEL > 0
107 // patch Message, append stack trace
108 reinterpret_cast< ::com::sun::star::uno::Exception * >(
109 uno_data.get() )->Message += jni.get_stack_trace( jo_exc.get() );
110 #endif
112 typelib_typedescriptionreference_acquire( td.get()->pWeakRef );
113 uno_exc->pType = td.get()->pWeakRef;
114 uno_exc->pData = uno_data.release();
116 #if OSL_DEBUG_LEVEL > 1
117 OUStringBuffer trace_buf( 128 );
118 trace_buf.append( "exception occurred uno->java: [" );
119 trace_buf.append( exc_name );
120 trace_buf.append( "] " );
121 trace_buf.append(
122 reinterpret_cast< ::com::sun::star::uno::Exception const * >(
123 uno_exc->pData )->Message );
124 OString cstr_trace(
125 OUStringToOString(
126 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
127 OSL_TRACE( "%s", cstr_trace.getStr() );
128 #endif
131 //______________________________________________________________________________
132 void Bridge::call_java(
133 jobject javaI, typelib_InterfaceTypeDescription * iface_td,
134 sal_Int32 local_member_index, sal_Int32 function_pos_offset,
135 typelib_TypeDescriptionReference * return_type,
136 typelib_MethodParameter * params, sal_Int32 nParams,
137 void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const
139 OSL_ASSERT( function_pos_offset == 0 || function_pos_offset == 1 );
141 JNI_guarded_context jni(
142 m_jni_info, reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
143 m_java_env->pContext ) );
145 // assure fully initialized iface_td:
146 ::com::sun::star::uno::TypeDescription iface_holder;
147 if (! iface_td->aBase.bComplete) {
148 iface_holder = ::com::sun::star::uno::TypeDescription(
149 reinterpret_cast<typelib_TypeDescription *>(iface_td) );
150 iface_holder.makeComplete();
151 if (! iface_holder.get()->bComplete) {
152 OUStringBuffer buf;
153 buf.append( "cannot make type complete: " );
154 buf.append( OUString::unacquired(&iface_holder.get()->pTypeName) );
155 buf.append( jni.get_stack_trace() );
156 throw BridgeRuntimeError( buf.makeStringAndClear() );
158 iface_td = reinterpret_cast<typelib_InterfaceTypeDescription *>(
159 iface_holder.get() );
160 OSL_ASSERT( iface_td->aBase.eTypeClass == typelib_TypeClass_INTERFACE );
163 // prepare java args, save param td
164 #ifdef BROKEN_ALLOCA
165 jvalue * java_args = (jvalue *) malloc( sizeof (jvalue) * nParams );
166 #else
167 jvalue * java_args = (jvalue *) alloca( sizeof (jvalue) * nParams );
168 #endif
170 sal_Int32 nPos;
171 for ( nPos = 0; nPos < nParams; ++nPos )
175 typelib_MethodParameter const & param = params[ nPos ];
176 java_args[ nPos ].l = 0; // if out: build up array[ 1 ]
177 map_to_java(
178 jni, &java_args[ nPos ],
179 uno_args[ nPos ],
180 param.pTypeRef, 0,
181 sal_False != param.bIn /* convert uno value */,
182 sal_False != param.bOut /* build up array[ 1 ] */ );
184 catch (...)
186 // cleanup
187 for ( sal_Int32 n = 0; n < nPos; ++n )
189 typelib_MethodParameter const & param = params[ n ];
190 if (param.bOut ||
191 typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass)
193 jni->DeleteLocalRef( java_args[ n ].l );
196 #ifdef BROKEN_ALLOCA
197 free( java_args );
198 #endif
199 throw;
203 sal_Int32 base_members = iface_td->nAllMembers - iface_td->nMembers;
204 OSL_ASSERT( base_members < iface_td->nAllMembers );
205 sal_Int32 base_members_function_pos =
206 iface_td->pMapMemberIndexToFunctionIndex[ base_members ];
207 sal_Int32 member_pos = base_members + local_member_index;
208 OSL_ENSURE(
209 member_pos < iface_td->nAllMembers, "### member pos out of range!" );
210 sal_Int32 function_pos =
211 iface_td->pMapMemberIndexToFunctionIndex[ member_pos ]
212 + function_pos_offset;
213 OSL_ENSURE(
214 function_pos >= base_members_function_pos
215 && function_pos < iface_td->nMapFunctionIndexToMemberIndex,
216 "### illegal function index!" );
217 function_pos -= base_members_function_pos;
219 JNI_interface_type_info const * info =
220 static_cast< JNI_interface_type_info const * >(
221 m_jni_info->get_type_info( jni, &iface_td->aBase ) );
222 jmethodID method_id = info->m_methods[ function_pos ];
224 #if OSL_DEBUG_LEVEL > 1
225 OUStringBuffer trace_buf( 128 );
226 trace_buf.append( "calling " );
227 JLocalAutoRef jo_method(
228 jni, jni->ToReflectedMethod( info->m_class, method_id, JNI_FALSE ) );
229 jni.ensure_no_exception();
230 JLocalAutoRef jo_descr(
231 jni, jni->CallObjectMethodA(
232 jo_method.get(), m_jni_info->m_method_Object_toString, 0 ) );
233 jni.ensure_no_exception();
234 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
235 trace_buf.append( " on " );
236 jo_descr.reset(
237 jni->CallObjectMethodA(
238 javaI, m_jni_info->m_method_Object_toString, 0 ) );
239 jni.ensure_no_exception();
240 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
241 trace_buf.append( " (" );
242 JLocalAutoRef jo_class( jni, jni->GetObjectClass( javaI ) );
243 jo_descr.reset(
244 jni->CallObjectMethodA(
245 jo_class.get(), m_jni_info->m_method_Object_toString, 0 ) );
246 jni.ensure_no_exception();
247 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) );
248 trace_buf.append( ")" );
249 OString cstr_trace(
250 OUStringToOString(
251 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
252 OSL_TRACE( "%s", cstr_trace.getStr() );
253 #endif
255 // complex return value
256 JLocalAutoRef java_ret( jni );
258 switch (return_type->eTypeClass)
260 case typelib_TypeClass_VOID:
261 jni->CallVoidMethodA( javaI, method_id, java_args );
262 break;
263 case typelib_TypeClass_CHAR:
264 *(sal_Unicode *)uno_ret =
265 jni->CallCharMethodA( javaI, method_id, java_args );
266 break;
267 case typelib_TypeClass_BOOLEAN:
268 *(sal_Bool *)uno_ret =
269 jni->CallBooleanMethodA( javaI, method_id, java_args );
270 break;
271 case typelib_TypeClass_BYTE:
272 *(sal_Int8 *)uno_ret =
273 jni->CallByteMethodA( javaI, method_id, java_args );
274 break;
275 case typelib_TypeClass_SHORT:
276 case typelib_TypeClass_UNSIGNED_SHORT:
277 *(sal_Int16 *)uno_ret =
278 jni->CallShortMethodA( javaI, method_id, java_args );
279 break;
280 case typelib_TypeClass_LONG:
281 case typelib_TypeClass_UNSIGNED_LONG:
282 *(sal_Int32 *)uno_ret =
283 jni->CallIntMethodA( javaI, method_id, java_args );
284 break;
285 case typelib_TypeClass_HYPER:
286 case typelib_TypeClass_UNSIGNED_HYPER:
287 *(sal_Int64 *)uno_ret =
288 jni->CallLongMethodA( javaI, method_id, java_args );
289 break;
290 case typelib_TypeClass_FLOAT:
291 *(float *)uno_ret =
292 jni->CallFloatMethodA( javaI, method_id, java_args );
293 break;
294 case typelib_TypeClass_DOUBLE:
295 *(double *)uno_ret =
296 jni->CallDoubleMethodA( javaI, method_id, java_args );
297 break;
298 default:
299 java_ret.reset(
300 jni->CallObjectMethodA( javaI, method_id, java_args ) );
301 break;
304 if (jni->ExceptionCheck())
306 JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() );
307 jni->ExceptionClear();
309 // release temp java local refs
310 for ( nPos = 0; nPos < nParams; ++nPos )
312 typelib_MethodParameter const & param = params[ nPos ];
313 if (param.bOut ||
314 typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass)
316 jni->DeleteLocalRef( java_args[ nPos ].l );
320 handle_java_exc( jni, jo_exc, *uno_exc );
322 else // no exception
324 for ( nPos = 0; nPos < nParams; ++nPos )
326 typelib_MethodParameter const & param = params[ nPos ];
327 if (param.bOut)
331 map_to_uno(
332 jni, uno_args[ nPos ],
333 java_args[ nPos ], param.pTypeRef, 0,
334 sal_False != param.bIn /* assign if inout */,
335 true /* out param */ );
337 catch (...)
339 // cleanup uno pure out
340 for ( sal_Int32 n = 0; n < nPos; ++n )
342 typelib_MethodParameter const & p = params[ n ];
343 if (! p.bIn)
345 uno_type_destructData(
346 uno_args[ n ], p.pTypeRef, 0 );
349 // cleanup java temp local refs
350 for ( ; nPos < nParams; ++nPos )
352 typelib_MethodParameter const & p = params[ nPos ];
353 if (p.bOut ||
354 typelib_TypeClass_DOUBLE <
355 p.pTypeRef->eTypeClass)
357 jni->DeleteLocalRef( java_args[ nPos ].l );
360 #ifdef BROKEN_ALLOCA
361 free( java_args );
362 #endif
363 throw;
365 jni->DeleteLocalRef( java_args[ nPos ].l );
367 else // pure temp in param
369 if (typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass)
370 jni->DeleteLocalRef( java_args[ nPos ].l );
374 // return value
375 if (typelib_TypeClass_DOUBLE < return_type->eTypeClass)
379 jvalue val;
380 val.l = java_ret.get();
381 map_to_uno(
382 jni, uno_ret, val, return_type, 0,
383 false /* no assign */, false /* no out param */ );
385 catch (...)
387 // cleanup uno pure out
388 for ( sal_Int32 i = 0; i < nParams; ++i )
390 typelib_MethodParameter const & param = params[ i ];
391 if (! param.bIn)
393 uno_type_destructData(
394 uno_args[ i ], param.pTypeRef, 0 );
397 #ifdef BROKEN_ALLOCA
398 free( java_args );
399 #endif
400 throw;
402 } // else: already set integral uno return value
404 // no exception occurred
405 *uno_exc = 0;
407 #ifdef BROKEN_ALLOCA
408 free( java_args );
409 #endif
412 //==== a uno proxy wrapping a java interface ===================================
413 struct UNO_proxy : public uno_Interface
415 mutable oslInterlockedCount m_ref;
416 Bridge const * m_bridge;
418 // mapping information
419 jobject m_javaI;
420 jstring m_jo_oid;
421 OUString m_oid;
422 JNI_interface_type_info const * m_type_info;
424 inline void acquire() const;
425 inline void release() const;
427 // ctor
428 inline UNO_proxy(
429 JNI_context const & jni, Bridge const * bridge,
430 jobject javaI, jstring jo_oid, OUString const & oid,
431 JNI_interface_type_info const * info );
434 //______________________________________________________________________________
435 inline UNO_proxy::UNO_proxy(
436 JNI_context const & jni, Bridge const * bridge,
437 jobject javaI, jstring jo_oid, OUString const & oid,
438 JNI_interface_type_info const * info )
439 : m_ref( 1 ),
440 m_oid( oid ),
441 m_type_info( info )
443 JNI_info const * jni_info = bridge->m_jni_info;
444 JLocalAutoRef jo_string_array(
445 jni, jni->NewObjectArray( 1, jni_info->m_class_String, jo_oid ) );
446 jni.ensure_no_exception();
447 jvalue args[ 3 ];
448 args[ 0 ].l = javaI;
449 args[ 1 ].l = jo_string_array.get();
450 args[ 2 ].l = info->m_type;
451 jobject jo_iface = jni->CallObjectMethodA(
452 jni_info->m_object_java_env,
453 jni_info->m_method_IEnvironment_registerInterface, args );
454 jni.ensure_no_exception();
456 m_javaI = jni->NewGlobalRef( jo_iface );
457 m_jo_oid = (jstring) jni->NewGlobalRef( jo_oid );
458 bridge->acquire();
459 m_bridge = bridge;
461 // uno_Interface
462 uno_Interface::acquire = UNO_proxy_acquire;
463 uno_Interface::release = UNO_proxy_release;
464 uno_Interface::pDispatcher = UNO_proxy_dispatch;
467 //______________________________________________________________________________
468 inline void UNO_proxy::acquire() const
470 if (1 == osl_atomic_increment( &m_ref ))
472 // rebirth of proxy zombie
473 void * that = const_cast< UNO_proxy * >( this );
474 // register at uno env
475 (*m_bridge->m_uno_env->registerProxyInterface)(
476 m_bridge->m_uno_env, &that,
477 UNO_proxy_free, m_oid.pData,
478 (typelib_InterfaceTypeDescription *)m_type_info->m_td.get() );
479 #if OSL_DEBUG_LEVEL > 1
480 OSL_ASSERT( this == (void const * const)that );
481 #endif
485 //______________________________________________________________________________
486 inline void UNO_proxy::release() const
488 if (0 == osl_atomic_decrement( &m_ref ))
490 // revoke from uno env on last release
491 (*m_bridge->m_uno_env->revokeInterface)(
492 m_bridge->m_uno_env, const_cast< UNO_proxy * >( this ) );
497 //______________________________________________________________________________
498 uno_Interface * Bridge::map_to_uno(
499 JNI_context const & jni,
500 jobject javaI, JNI_interface_type_info const * info ) const
502 JLocalAutoRef jo_oid( jni, compute_oid( jni, javaI ) );
503 OUString oid( jstring_to_oustring( jni, (jstring) jo_oid.get() ) );
505 uno_Interface * pUnoI = 0;
506 (*m_uno_env->getRegisteredInterface)(
507 m_uno_env, (void **)&pUnoI,
508 oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() );
510 if (0 == pUnoI) // no existing interface, register new proxy
512 // refcount initially 1
513 pUnoI = new UNO_proxy(
514 jni, const_cast< Bridge * >( this ),
515 javaI, (jstring) jo_oid.get(), oid, info );
517 (*m_uno_env->registerProxyInterface)(
518 m_uno_env, (void **)&pUnoI,
519 UNO_proxy_free,
520 oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() );
522 return pUnoI;
527 using namespace ::jni_uno;
529 namespace
531 extern "C"
534 //------------------------------------------------------------------------------
535 void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy )
536 SAL_THROW_EXTERN_C()
538 UNO_proxy const * that = reinterpret_cast< UNO_proxy const * >( proxy );
539 Bridge const * bridge = that->m_bridge;
541 if ( env != bridge->m_uno_env ) {
542 OSL_ASSERT(false);
544 #if OSL_DEBUG_LEVEL > 1
545 OString cstr_msg(
546 OUStringToOString(
547 "freeing binary uno proxy: " + that->m_oid,
548 RTL_TEXTENCODING_ASCII_US ) );
549 OSL_TRACE( "%s", cstr_msg.getStr() );
550 #endif
554 JNI_guarded_context jni(
555 bridge->m_jni_info,
556 reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
557 bridge->m_java_env->pContext ) );
559 jni->DeleteGlobalRef( that->m_javaI );
560 jni->DeleteGlobalRef( that->m_jo_oid );
562 catch (BridgeRuntimeError & err)
564 #if OSL_DEBUG_LEVEL > 0
565 OString cstr_msg2(
566 OUStringToOString( err.m_message, RTL_TEXTENCODING_ASCII_US ) );
567 OSL_FAIL( cstr_msg2.getStr() );
568 #else
569 (void) err; // unused
570 #endif
572 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &)
574 OSL_FAIL(
575 "[jni_uno bridge error] attaching current thread to java failed!" );
578 bridge->release();
579 #if OSL_DEBUG_LEVEL > 1
580 *(int *)that = 0xdeadcafe;
581 #endif
582 delete that;
585 //------------------------------------------------------------------------------
586 void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI )
587 SAL_THROW_EXTERN_C()
589 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI );
590 that->acquire();
593 //------------------------------------------------------------------------------
594 void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI )
595 SAL_THROW_EXTERN_C()
597 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI );
598 that->release();
601 //------------------------------------------------------------------------------
602 void SAL_CALL UNO_proxy_dispatch(
603 uno_Interface * pUnoI, typelib_TypeDescription const * member_td,
604 void * uno_ret, void * uno_args [], uno_Any ** uno_exc )
605 SAL_THROW_EXTERN_C()
607 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI );
608 Bridge const * bridge = that->m_bridge;
610 #if OSL_DEBUG_LEVEL > 1
611 OUStringBuffer trace_buf( 64 );
612 trace_buf.append( "uno->java call: " );
613 trace_buf.append( OUString::unacquired( &member_td->pTypeName ) );
614 trace_buf.append( " on oid " );
615 trace_buf.append( that->m_oid );
616 OString cstr_msg(
617 OUStringToOString(
618 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) );
619 OSL_TRACE( "%s", cstr_msg.getStr() );
620 #endif
624 switch (member_td->eTypeClass)
626 case typelib_TypeClass_INTERFACE_ATTRIBUTE:
628 typelib_InterfaceAttributeTypeDescription const * attrib_td =
629 reinterpret_cast<
630 typelib_InterfaceAttributeTypeDescription const * >(
631 member_td );
632 com::sun::star::uno::TypeDescription attrib_holder;
633 while ( attrib_td->pBaseRef != 0 ) {
634 attrib_holder = com::sun::star::uno::TypeDescription(
635 attrib_td->pBaseRef );
636 OSL_ASSERT(
637 attrib_holder.get()->eTypeClass
638 == typelib_TypeClass_INTERFACE_ATTRIBUTE );
639 attrib_td = reinterpret_cast<
640 typelib_InterfaceAttributeTypeDescription * >(
641 attrib_holder.get() );
643 typelib_InterfaceTypeDescription * iface_td = attrib_td->pInterface;
645 if (0 == uno_ret) // is setter method
647 typelib_MethodParameter param;
648 param.pTypeRef = attrib_td->pAttributeTypeRef;
649 param.bIn = sal_True;
650 param.bOut = sal_False;
652 bridge->call_java(
653 that->m_javaI, iface_td,
654 attrib_td->nIndex, 1, // get, then set method
655 bridge->m_jni_info->m_void_type.getTypeLibType(),
656 &param, 1,
657 0, uno_args, uno_exc );
659 else // is getter method
661 bridge->call_java(
662 that->m_javaI, iface_td, attrib_td->nIndex, 0,
663 attrib_td->pAttributeTypeRef,
664 0, 0, // no params
665 uno_ret, 0, uno_exc );
667 break;
669 case typelib_TypeClass_INTERFACE_METHOD:
671 typelib_InterfaceMethodTypeDescription const * method_td =
672 reinterpret_cast<
673 typelib_InterfaceMethodTypeDescription const * >(
674 member_td );
675 com::sun::star::uno::TypeDescription method_holder;
676 while ( method_td->pBaseRef != 0 ) {
677 method_holder = com::sun::star::uno::TypeDescription(
678 method_td->pBaseRef );
679 OSL_ASSERT(
680 method_holder.get()->eTypeClass
681 == typelib_TypeClass_INTERFACE_METHOD );
682 method_td = reinterpret_cast<
683 typelib_InterfaceMethodTypeDescription * >(
684 method_holder.get() );
686 typelib_InterfaceTypeDescription * iface_td = method_td->pInterface;
688 switch ( method_td->aBase.nPosition )
690 case 0: // queryInterface()
692 TypeDescr demanded_td(
693 *reinterpret_cast< typelib_TypeDescriptionReference ** >(
694 uno_args[ 0 ] ) );
695 if (typelib_TypeClass_INTERFACE !=
696 demanded_td.get()->eTypeClass)
698 throw BridgeRuntimeError(
699 "queryInterface() call demands an INTERFACE type!" );
702 uno_Interface * pInterface = 0;
703 (*bridge->m_uno_env->getRegisteredInterface)(
704 bridge->m_uno_env,
705 (void **) &pInterface, that->m_oid.pData,
706 (typelib_InterfaceTypeDescription *)demanded_td.get() );
708 if (0 == pInterface)
710 JNI_info const * jni_info = bridge->m_jni_info;
711 JNI_guarded_context jni(
712 jni_info,
713 reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >(
714 bridge->m_java_env->pContext ) );
716 JNI_interface_type_info const * info =
717 static_cast< JNI_interface_type_info const * >(
718 jni_info->get_type_info( jni, demanded_td.get() ) );
720 jvalue args[ 2 ];
721 args[ 0 ].l = info->m_type;
722 args[ 1 ].l = that->m_javaI;
724 JLocalAutoRef jo_ret(
725 jni, jni->CallStaticObjectMethodA(
726 jni_info->m_class_UnoRuntime,
727 jni_info->m_method_UnoRuntime_queryInterface,
728 args ) );
730 if (jni->ExceptionCheck())
732 JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() );
733 jni->ExceptionClear();
734 bridge->handle_java_exc( jni, jo_exc, *uno_exc );
736 else
738 if (jo_ret.is())
740 #if OSL_DEBUG_LEVEL > 0
741 JLocalAutoRef jo_oid(
742 jni, compute_oid( jni, jo_ret.get() ) );
743 OUString oid( jstring_to_oustring(
744 jni, (jstring) jo_oid.get() ) );
745 OSL_ENSURE(
746 oid.equals( that->m_oid ),
747 "### different oids!" );
748 #endif
749 // refcount initially 1
750 uno_Interface * pUnoI2 = new UNO_proxy(
751 jni, bridge, jo_ret.get(),
752 that->m_jo_oid, that->m_oid, info );
754 (*bridge->m_uno_env->registerProxyInterface)(
755 bridge->m_uno_env,
756 (void **) &pUnoI2,
757 UNO_proxy_free, that->m_oid.pData,
758 reinterpret_cast<
759 typelib_InterfaceTypeDescription * >(
760 info->m_td.get() ) );
762 uno_any_construct(
763 (uno_Any *)uno_ret, &pUnoI2,
764 demanded_td.get(), 0 );
765 (*pUnoI2->release)( pUnoI2 );
767 else // object does not support demanded interface
769 uno_any_construct(
770 reinterpret_cast< uno_Any * >( uno_ret ),
771 0, 0, 0 );
773 // no exception occurred
774 *uno_exc = 0;
777 else
779 uno_any_construct(
780 reinterpret_cast< uno_Any * >( uno_ret ),
781 &pInterface, demanded_td.get(), 0 );
782 (*pInterface->release)( pInterface );
783 *uno_exc = 0;
785 break;
787 case 1: // acquire this proxy
788 that->acquire();
789 *uno_exc = 0;
790 break;
791 case 2: // release this proxy
792 that->release();
793 *uno_exc = 0;
794 break;
795 default: // arbitrary method call
796 bridge->call_java(
797 that->m_javaI, iface_td, method_td->nIndex, 0,
798 method_td->pReturnTypeRef,
799 method_td->pParams, method_td->nParams,
800 uno_ret, uno_args, uno_exc );
801 break;
803 break;
805 default:
807 throw BridgeRuntimeError(
808 "illegal member type description!" );
812 catch (BridgeRuntimeError & err)
814 OUStringBuffer buf( 128 );
815 buf.append( "[jni_uno bridge error] UNO calling Java method " );
816 if (typelib_TypeClass_INTERFACE_METHOD == member_td->eTypeClass ||
817 typelib_TypeClass_INTERFACE_ATTRIBUTE == member_td->eTypeClass)
819 buf.append( OUString::unacquired(
820 &reinterpret_cast<
821 typelib_InterfaceMemberTypeDescription const * >(
822 member_td )->pMemberName ) );
824 buf.append( ": " );
825 buf.append( err.m_message );
826 // binary identical struct
827 ::com::sun::star::uno::RuntimeException exc(
828 buf.makeStringAndClear(),
829 ::com::sun::star::uno::Reference<
830 ::com::sun::star::uno::XInterface >() );
831 ::com::sun::star::uno::Type const & exc_type = ::getCppuType( &exc );
832 uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0 );
833 #if OSL_DEBUG_LEVEL > 0
834 OString cstr_msg2(
835 OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) );
836 OSL_TRACE( "%s", cstr_msg2.getStr() );
837 #endif
839 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &)
841 // binary identical struct
842 ::com::sun::star::uno::RuntimeException exc(
843 "[jni_uno bridge error] attaching current thread to java failed!",
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_FAIL( cstr_msg2.getStr() );
852 #endif
859 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */