1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_bridges.hxx" 30 31 #include <sal/alloca.h> 32 33 #include "com/sun/star/uno/RuntimeException.hpp" 34 35 #include "rtl/ustrbuf.hxx" 36 37 #include "jni_bridge.h" 38 39 40 using namespace ::std; 41 using namespace ::rtl; 42 43 namespace 44 { 45 extern "C" 46 { 47 48 //------------------------------------------------------------------------------ 49 void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy ) 50 SAL_THROW_EXTERN_C(); 51 52 //------------------------------------------------------------------------------ 53 void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI ) 54 SAL_THROW_EXTERN_C(); 55 56 //------------------------------------------------------------------------------ 57 void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI ) 58 SAL_THROW_EXTERN_C(); 59 60 //------------------------------------------------------------------------------ 61 void SAL_CALL UNO_proxy_dispatch( 62 uno_Interface * pUnoI, typelib_TypeDescription const * member_td, 63 void * uno_ret, void * uno_args[], uno_Any ** uno_exc ) 64 SAL_THROW_EXTERN_C(); 65 } 66 } 67 68 namespace jni_uno 69 { 70 71 //______________________________________________________________________________ 72 void Bridge::handle_java_exc( 73 JNI_context const & jni, 74 JLocalAutoRef const & jo_exc, uno_Any * uno_exc ) const 75 { 76 OSL_ASSERT( jo_exc.is() ); 77 if (! jo_exc.is()) 78 { 79 throw BridgeRuntimeError( 80 OUSTR("java exception occured, but no java exception available!?") + 81 jni.get_stack_trace() ); 82 } 83 84 JLocalAutoRef jo_class( jni, jni->GetObjectClass( jo_exc.get() ) ); 85 JLocalAutoRef jo_class_name( 86 jni, jni->CallObjectMethodA( 87 jo_class.get(), m_jni_info->m_method_Class_getName, 0 ) ); 88 jni.ensure_no_exception(); 89 OUString exc_name( 90 jstring_to_oustring( jni, (jstring) jo_class_name.get() ) ); 91 92 ::com::sun::star::uno::TypeDescription td( exc_name.pData ); 93 if (!td.is() || (typelib_TypeClass_EXCEPTION != td.get()->eTypeClass)) 94 { 95 // call toString() 96 JLocalAutoRef jo_descr( 97 jni, jni->CallObjectMethodA( 98 jo_exc.get(), m_jni_info->m_method_Object_toString, 0 ) ); 99 jni.ensure_no_exception(); 100 OUStringBuffer buf( 128 ); 101 buf.appendAscii( 102 RTL_CONSTASCII_STRINGPARAM("non-UNO exception occurred: ") ); 103 buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); 104 buf.append( jni.get_stack_trace( jo_exc.get() ) ); 105 throw BridgeRuntimeError( buf.makeStringAndClear() ); 106 } 107 108 auto_ptr< rtl_mem > uno_data( rtl_mem::allocate( td.get()->nSize ) ); 109 jvalue val; 110 val.l = jo_exc.get(); 111 map_to_uno( 112 jni, uno_data.get(), val, td.get()->pWeakRef, 0, 113 false /* no assign */, false /* no out param */ ); 114 115 #if OSL_DEBUG_LEVEL > 0 116 // patch Message, append stack trace 117 reinterpret_cast< ::com::sun::star::uno::Exception * >( 118 uno_data.get() )->Message += jni.get_stack_trace( jo_exc.get() ); 119 #endif 120 121 typelib_typedescriptionreference_acquire( td.get()->pWeakRef ); 122 uno_exc->pType = td.get()->pWeakRef; 123 uno_exc->pData = uno_data.release(); 124 125 #if OSL_DEBUG_LEVEL > 1 126 OUStringBuffer trace_buf( 128 ); 127 trace_buf.appendAscii( 128 RTL_CONSTASCII_STRINGPARAM("exception occured uno->java: [") ); 129 trace_buf.append( exc_name ); 130 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") ); 131 trace_buf.append( 132 reinterpret_cast< ::com::sun::star::uno::Exception const * >( 133 uno_exc->pData )->Message ); 134 OString cstr_trace( 135 OUStringToOString( 136 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); 137 OSL_TRACE( cstr_trace.getStr() ); 138 #endif 139 } 140 141 //______________________________________________________________________________ 142 void Bridge::call_java( 143 jobject javaI, typelib_InterfaceTypeDescription * iface_td, 144 sal_Int32 local_member_index, sal_Int32 function_pos_offset, 145 typelib_TypeDescriptionReference * return_type, 146 typelib_MethodParameter * params, sal_Int32 nParams, 147 void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const 148 { 149 OSL_ASSERT( function_pos_offset == 0 || function_pos_offset == 1 ); 150 151 JNI_guarded_context jni( 152 m_jni_info, reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( 153 m_java_env->pContext ) ); 154 155 // assure fully initialized iface_td: 156 ::com::sun::star::uno::TypeDescription iface_holder; 157 if (! iface_td->aBase.bComplete) { 158 iface_holder = ::com::sun::star::uno::TypeDescription( 159 reinterpret_cast<typelib_TypeDescription *>(iface_td) ); 160 iface_holder.makeComplete(); 161 if (! iface_holder.get()->bComplete) { 162 OUStringBuffer buf; 163 buf.appendAscii( 164 RTL_CONSTASCII_STRINGPARAM("cannot make type complete: ") ); 165 buf.append( OUString::unacquired(&iface_holder.get()->pTypeName) ); 166 buf.append( jni.get_stack_trace() ); 167 throw BridgeRuntimeError( buf.makeStringAndClear() ); 168 } 169 iface_td = reinterpret_cast<typelib_InterfaceTypeDescription *>( 170 iface_holder.get() ); 171 OSL_ASSERT( iface_td->aBase.eTypeClass == typelib_TypeClass_INTERFACE ); 172 } 173 174 // prepare java args, save param td 175 #ifdef BROKEN_ALLOCA 176 jvalue * java_args = (jvalue *) malloc( sizeof (jvalue) * nParams ); 177 #else 178 jvalue * java_args = (jvalue *) alloca( sizeof (jvalue) * nParams ); 179 #endif 180 181 sal_Int32 nPos; 182 for ( nPos = 0; nPos < nParams; ++nPos ) 183 { 184 try 185 { 186 typelib_MethodParameter const & param = params[ nPos ]; 187 java_args[ nPos ].l = 0; // if out: build up array[ 1 ] 188 map_to_java( 189 jni, &java_args[ nPos ], 190 uno_args[ nPos ], 191 param.pTypeRef, 0, 192 sal_False != param.bIn /* convert uno value */, 193 sal_False != param.bOut /* build up array[ 1 ] */ ); 194 } 195 catch (...) 196 { 197 // cleanup 198 for ( sal_Int32 n = 0; n < nPos; ++n ) 199 { 200 typelib_MethodParameter const & param = params[ n ]; 201 if (param.bOut || 202 typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass) 203 { 204 jni->DeleteLocalRef( java_args[ n ].l ); 205 } 206 } 207 #ifdef BROKEN_ALLOCA 208 free( java_args ); 209 #endif 210 throw; 211 } 212 } 213 214 sal_Int32 base_members = iface_td->nAllMembers - iface_td->nMembers; 215 OSL_ASSERT( base_members < iface_td->nAllMembers ); 216 sal_Int32 base_members_function_pos = 217 iface_td->pMapMemberIndexToFunctionIndex[ base_members ]; 218 sal_Int32 member_pos = base_members + local_member_index; 219 OSL_ENSURE( 220 member_pos < iface_td->nAllMembers, "### member pos out of range!" ); 221 sal_Int32 function_pos = 222 iface_td->pMapMemberIndexToFunctionIndex[ member_pos ] 223 + function_pos_offset; 224 OSL_ENSURE( 225 function_pos >= base_members_function_pos 226 && function_pos < iface_td->nMapFunctionIndexToMemberIndex, 227 "### illegal function index!" ); 228 function_pos -= base_members_function_pos; 229 230 JNI_interface_type_info const * info = 231 static_cast< JNI_interface_type_info const * >( 232 m_jni_info->get_type_info( jni, &iface_td->aBase ) ); 233 jmethodID method_id = info->m_methods[ function_pos ]; 234 235 #if OSL_DEBUG_LEVEL > 1 236 OUStringBuffer trace_buf( 128 ); 237 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("calling ") ); 238 JLocalAutoRef jo_method( 239 jni, jni->ToReflectedMethod( info->m_class, method_id, JNI_FALSE ) ); 240 jni.ensure_no_exception(); 241 JLocalAutoRef jo_descr( 242 jni, jni->CallObjectMethodA( 243 jo_method.get(), m_jni_info->m_method_Object_toString, 0 ) ); 244 jni.ensure_no_exception(); 245 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); 246 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on ") ); 247 jo_descr.reset( 248 jni->CallObjectMethodA( 249 javaI, m_jni_info->m_method_Object_toString, 0 ) ); 250 jni.ensure_no_exception(); 251 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); 252 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (") ); 253 JLocalAutoRef jo_class( jni, jni->GetObjectClass( javaI ) ); 254 jo_descr.reset( 255 jni->CallObjectMethodA( 256 jo_class.get(), m_jni_info->m_method_Object_toString, 0 ) ); 257 jni.ensure_no_exception(); 258 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); 259 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(")") ); 260 OString cstr_trace( 261 OUStringToOString( 262 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); 263 OSL_TRACE( cstr_trace.getStr() ); 264 #endif 265 266 // complex return value 267 JLocalAutoRef java_ret( jni ); 268 269 switch (return_type->eTypeClass) 270 { 271 case typelib_TypeClass_VOID: 272 jni->CallVoidMethodA( javaI, method_id, java_args ); 273 break; 274 case typelib_TypeClass_CHAR: 275 *(sal_Unicode *)uno_ret = 276 jni->CallCharMethodA( javaI, method_id, java_args ); 277 break; 278 case typelib_TypeClass_BOOLEAN: 279 *(sal_Bool *)uno_ret = 280 jni->CallBooleanMethodA( javaI, method_id, java_args ); 281 break; 282 case typelib_TypeClass_BYTE: 283 *(sal_Int8 *)uno_ret = 284 jni->CallByteMethodA( javaI, method_id, java_args ); 285 break; 286 case typelib_TypeClass_SHORT: 287 case typelib_TypeClass_UNSIGNED_SHORT: 288 *(sal_Int16 *)uno_ret = 289 jni->CallShortMethodA( javaI, method_id, java_args ); 290 break; 291 case typelib_TypeClass_LONG: 292 case typelib_TypeClass_UNSIGNED_LONG: 293 *(sal_Int32 *)uno_ret = 294 jni->CallIntMethodA( javaI, method_id, java_args ); 295 break; 296 case typelib_TypeClass_HYPER: 297 case typelib_TypeClass_UNSIGNED_HYPER: 298 *(sal_Int64 *)uno_ret = 299 jni->CallLongMethodA( javaI, method_id, java_args ); 300 break; 301 case typelib_TypeClass_FLOAT: 302 *(float *)uno_ret = 303 jni->CallFloatMethodA( javaI, method_id, java_args ); 304 break; 305 case typelib_TypeClass_DOUBLE: 306 *(double *)uno_ret = 307 jni->CallDoubleMethodA( javaI, method_id, java_args ); 308 break; 309 default: 310 java_ret.reset( 311 jni->CallObjectMethodA( javaI, method_id, java_args ) ); 312 break; 313 } 314 315 if (jni->ExceptionCheck()) 316 { 317 JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() ); 318 jni->ExceptionClear(); 319 320 // release temp java local refs 321 for ( nPos = 0; nPos < nParams; ++nPos ) 322 { 323 typelib_MethodParameter const & param = params[ nPos ]; 324 if (param.bOut || 325 typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass) 326 { 327 jni->DeleteLocalRef( java_args[ nPos ].l ); 328 } 329 } 330 331 handle_java_exc( jni, jo_exc, *uno_exc ); 332 } 333 else // no exception 334 { 335 for ( nPos = 0; nPos < nParams; ++nPos ) 336 { 337 typelib_MethodParameter const & param = params[ nPos ]; 338 if (param.bOut) 339 { 340 try 341 { 342 map_to_uno( 343 jni, uno_args[ nPos ], 344 java_args[ nPos ], param.pTypeRef, 0, 345 sal_False != param.bIn /* assign if inout */, 346 true /* out param */ ); 347 } 348 catch (...) 349 { 350 // cleanup uno pure out 351 for ( sal_Int32 n = 0; n < nPos; ++n ) 352 { 353 typelib_MethodParameter const & p = params[ n ]; 354 if (! p.bIn) 355 { 356 uno_type_destructData( 357 uno_args[ n ], p.pTypeRef, 0 ); 358 } 359 } 360 // cleanup java temp local refs 361 for ( ; nPos < nParams; ++nPos ) 362 { 363 typelib_MethodParameter const & p = params[ nPos ]; 364 if (p.bOut || 365 typelib_TypeClass_DOUBLE < 366 p.pTypeRef->eTypeClass) 367 { 368 jni->DeleteLocalRef( java_args[ nPos ].l ); 369 } 370 } 371 #ifdef BROKEN_ALLOCA 372 free( java_args ); 373 #endif 374 throw; 375 } 376 jni->DeleteLocalRef( java_args[ nPos ].l ); 377 } 378 else // pure temp in param 379 { 380 if (typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass) 381 jni->DeleteLocalRef( java_args[ nPos ].l ); 382 } 383 } 384 385 // return value 386 if (typelib_TypeClass_DOUBLE < return_type->eTypeClass) 387 { 388 try 389 { 390 jvalue val; 391 val.l = java_ret.get(); 392 map_to_uno( 393 jni, uno_ret, val, return_type, 0, 394 false /* no assign */, false /* no out param */ ); 395 } 396 catch (...) 397 { 398 // cleanup uno pure out 399 for ( sal_Int32 i = 0; i < nParams; ++i ) 400 { 401 typelib_MethodParameter const & param = params[ i ]; 402 if (! param.bIn) 403 { 404 uno_type_destructData( 405 uno_args[ i ], param.pTypeRef, 0 ); 406 } 407 } 408 #ifdef BROKEN_ALLOCA 409 free( java_args ); 410 #endif 411 throw; 412 } 413 } // else: already set integral uno return value 414 415 // no exception occured 416 *uno_exc = 0; 417 } 418 #ifdef BROKEN_ALLOCA 419 free( java_args ); 420 #endif 421 } 422 423 //==== a uno proxy wrapping a java interface =================================== 424 struct UNO_proxy : public uno_Interface 425 { 426 mutable oslInterlockedCount m_ref; 427 Bridge const * m_bridge; 428 429 // mapping information 430 jobject m_javaI; 431 jstring m_jo_oid; 432 OUString m_oid; 433 JNI_interface_type_info const * m_type_info; 434 435 inline void acquire() const; 436 inline void release() const; 437 438 // ctor 439 inline UNO_proxy( 440 JNI_context const & jni, Bridge const * bridge, 441 jobject javaI, jstring jo_oid, OUString const & oid, 442 JNI_interface_type_info const * info ); 443 }; 444 445 //______________________________________________________________________________ 446 inline UNO_proxy::UNO_proxy( 447 JNI_context const & jni, Bridge const * bridge, 448 jobject javaI, jstring jo_oid, OUString const & oid, 449 JNI_interface_type_info const * info ) 450 : m_ref( 1 ), 451 m_oid( oid ), 452 m_type_info( info ) 453 { 454 JNI_info const * jni_info = bridge->m_jni_info; 455 JLocalAutoRef jo_string_array( 456 jni, jni->NewObjectArray( 1, jni_info->m_class_String, jo_oid ) ); 457 jni.ensure_no_exception(); 458 jvalue args[ 3 ]; 459 args[ 0 ].l = javaI; 460 args[ 1 ].l = jo_string_array.get(); 461 args[ 2 ].l = info->m_type; 462 jobject jo_iface = jni->CallObjectMethodA( 463 jni_info->m_object_java_env, 464 jni_info->m_method_IEnvironment_registerInterface, args ); 465 jni.ensure_no_exception(); 466 467 m_javaI = jni->NewGlobalRef( jo_iface ); 468 m_jo_oid = (jstring) jni->NewGlobalRef( jo_oid ); 469 bridge->acquire(); 470 m_bridge = bridge; 471 472 // uno_Interface 473 uno_Interface::acquire = UNO_proxy_acquire; 474 uno_Interface::release = UNO_proxy_release; 475 uno_Interface::pDispatcher = UNO_proxy_dispatch; 476 } 477 478 //______________________________________________________________________________ 479 inline void UNO_proxy::acquire() const 480 { 481 if (1 == osl_incrementInterlockedCount( &m_ref )) 482 { 483 // rebirth of proxy zombie 484 void * that = const_cast< UNO_proxy * >( this ); 485 // register at uno env 486 (*m_bridge->m_uno_env->registerProxyInterface)( 487 m_bridge->m_uno_env, &that, 488 UNO_proxy_free, m_oid.pData, 489 (typelib_InterfaceTypeDescription *)m_type_info->m_td.get() ); 490 #if OSL_DEBUG_LEVEL > 1 491 OSL_ASSERT( this == (void const * const)that ); 492 #endif 493 } 494 } 495 496 //______________________________________________________________________________ 497 inline void UNO_proxy::release() const 498 { 499 if (0 == osl_decrementInterlockedCount( &m_ref )) 500 { 501 // revoke from uno env on last release 502 (*m_bridge->m_uno_env->revokeInterface)( 503 m_bridge->m_uno_env, const_cast< UNO_proxy * >( this ) ); 504 } 505 } 506 507 508 //______________________________________________________________________________ 509 uno_Interface * Bridge::map_to_uno( 510 JNI_context const & jni, 511 jobject javaI, JNI_interface_type_info const * info ) const 512 { 513 JLocalAutoRef jo_oid( jni, compute_oid( jni, javaI ) ); 514 OUString oid( jstring_to_oustring( jni, (jstring) jo_oid.get() ) ); 515 516 uno_Interface * pUnoI = 0; 517 (*m_uno_env->getRegisteredInterface)( 518 m_uno_env, (void **)&pUnoI, 519 oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() ); 520 521 if (0 == pUnoI) // no existing interface, register new proxy 522 { 523 // refcount initially 1 524 pUnoI = new UNO_proxy( 525 jni, const_cast< Bridge * >( this ), 526 javaI, (jstring) jo_oid.get(), oid, info ); 527 528 (*m_uno_env->registerProxyInterface)( 529 m_uno_env, (void **)&pUnoI, 530 UNO_proxy_free, 531 oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() ); 532 } 533 return pUnoI; 534 } 535 536 } 537 538 using namespace ::jni_uno; 539 540 namespace 541 { 542 extern "C" 543 { 544 545 //------------------------------------------------------------------------------ 546 void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy ) 547 SAL_THROW_EXTERN_C() 548 { 549 UNO_proxy const * that = reinterpret_cast< UNO_proxy const * >( proxy ); 550 Bridge const * bridge = that->m_bridge; 551 552 if ( env != bridge->m_uno_env ) { 553 OSL_ASSERT(false); 554 } 555 #if OSL_DEBUG_LEVEL > 1 556 OString cstr_msg( 557 OUStringToOString( 558 OUSTR("freeing binary uno proxy: ") + that->m_oid, 559 RTL_TEXTENCODING_ASCII_US ) ); 560 OSL_TRACE( cstr_msg.getStr() ); 561 #endif 562 563 try 564 { 565 JNI_guarded_context jni( 566 bridge->m_jni_info, 567 reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( 568 bridge->m_java_env->pContext ) ); 569 570 jni->DeleteGlobalRef( that->m_javaI ); 571 jni->DeleteGlobalRef( that->m_jo_oid ); 572 } 573 catch (BridgeRuntimeError & err) 574 { 575 #if OSL_DEBUG_LEVEL > 0 576 OString cstr_msg2( 577 OUStringToOString( err.m_message, RTL_TEXTENCODING_ASCII_US ) ); 578 OSL_ENSURE( 0, cstr_msg2.getStr() ); 579 #else 580 (void) err; // unused 581 #endif 582 } 583 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) 584 { 585 OSL_ENSURE( 586 0, 587 "[jni_uno bridge error] attaching current thread to java failed!" ); 588 } 589 590 bridge->release(); 591 #if OSL_DEBUG_LEVEL > 1 592 *(int *)that = 0xdeadcafe; 593 #endif 594 delete that; 595 } 596 597 //------------------------------------------------------------------------------ 598 void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI ) 599 SAL_THROW_EXTERN_C() 600 { 601 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI ); 602 that->acquire(); 603 } 604 605 //------------------------------------------------------------------------------ 606 void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI ) 607 SAL_THROW_EXTERN_C() 608 { 609 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI ); 610 that->release(); 611 } 612 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() 618 { 619 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI ); 620 Bridge const * bridge = that->m_bridge; 621 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( cstr_msg.getStr() ); 632 #endif 633 634 try 635 { 636 switch (member_td->eTypeClass) 637 { 638 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 639 { 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() ); 654 } 655 typelib_InterfaceTypeDescription * iface_td = attrib_td->pInterface; 656 657 if (0 == uno_ret) // is setter method 658 { 659 typelib_MethodParameter param; 660 param.pTypeRef = attrib_td->pAttributeTypeRef; 661 param.bIn = sal_True; 662 param.bOut = sal_False; 663 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 ¶m, 1, 669 0, uno_args, uno_exc ); 670 } 671 else // is getter method 672 { 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 ); 678 } 679 break; 680 } 681 case typelib_TypeClass_INTERFACE_METHOD: 682 { 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() ); 697 } 698 typelib_InterfaceTypeDescription * iface_td = method_td->pInterface; 699 700 switch ( method_td->aBase.nPosition ) 701 { 702 case 0: // queryInterface() 703 { 704 TypeDescr demanded_td( 705 *reinterpret_cast< typelib_TypeDescriptionReference ** >( 706 uno_args[ 0 ] ) ); 707 if (typelib_TypeClass_INTERFACE != 708 demanded_td.get()->eTypeClass) 709 { 710 throw BridgeRuntimeError( 711 OUSTR("queryInterface() call demands " 712 "an INTERFACE type!") ); 713 } 714 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() ); 720 721 if (0 == pInterface) 722 { 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 ) ); 728 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() ) ); 732 733 jvalue args[ 2 ]; 734 args[ 0 ].l = info->m_type; 735 args[ 1 ].l = that->m_javaI; 736 737 JLocalAutoRef jo_ret( 738 jni, jni->CallStaticObjectMethodA( 739 jni_info->m_class_UnoRuntime, 740 jni_info->m_method_UnoRuntime_queryInterface, 741 args ) ); 742 743 if (jni->ExceptionCheck()) 744 { 745 JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() ); 746 jni->ExceptionClear(); 747 bridge->handle_java_exc( jni, jo_exc, *uno_exc ); 748 } 749 else 750 { 751 if (jo_ret.is()) 752 { 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 ); 766 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() ) ); 774 775 uno_any_construct( 776 (uno_Any *)uno_ret, &pUnoI2, 777 demanded_td.get(), 0 ); 778 (*pUnoI2->release)( pUnoI2 ); 779 } 780 else // object does not support demanded interface 781 { 782 uno_any_construct( 783 reinterpret_cast< uno_Any * >( uno_ret ), 784 0, 0, 0 ); 785 } 786 // no exception occured 787 *uno_exc = 0; 788 } 789 } 790 else 791 { 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; 797 } 798 break; 799 } 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; 815 } 816 break; 817 } 818 default: 819 { 820 throw BridgeRuntimeError( 821 OUSTR("illegal member type description!") ); 822 } 823 } 824 } 825 catch (BridgeRuntimeError & err) 826 { 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) 833 { 834 buf.append( OUString::unacquired( 835 &reinterpret_cast< 836 typelib_InterfaceMemberTypeDescription const * >( 837 member_td )->pMemberName ) ); 838 } 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 853 } 854 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) 855 { 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_ENSURE( 0, cstr_msg2.getStr() ); 868 #endif 869 } 870 } 871 872 } 873 } 874