1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_bridges.hxx" 26 27 #include <sal/alloca.h> 28 29 #include "com/sun/star/uno/RuntimeException.hpp" 30 31 #include "rtl/ustrbuf.hxx" 32 33 #include "jni_bridge.h" 34 35 36 using namespace ::std; 37 using namespace ::rtl; 38 39 namespace 40 { 41 extern "C" 42 { 43 44 //------------------------------------------------------------------------------ 45 void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy ) 46 SAL_THROW_EXTERN_C(); 47 48 //------------------------------------------------------------------------------ 49 void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI ) 50 SAL_THROW_EXTERN_C(); 51 52 //------------------------------------------------------------------------------ 53 void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI ) 54 SAL_THROW_EXTERN_C(); 55 56 //------------------------------------------------------------------------------ 57 void SAL_CALL UNO_proxy_dispatch( 58 uno_Interface * pUnoI, typelib_TypeDescription const * member_td, 59 void * uno_ret, void * uno_args[], uno_Any ** uno_exc ) 60 SAL_THROW_EXTERN_C(); 61 } 62 } 63 64 namespace jni_uno 65 { 66 67 //______________________________________________________________________________ 68 void Bridge::handle_java_exc( 69 JNI_context const & jni, 70 JLocalAutoRef const & jo_exc, uno_Any * uno_exc ) const 71 { 72 OSL_ASSERT( jo_exc.is() ); 73 if (! jo_exc.is()) 74 { 75 throw BridgeRuntimeError( 76 OUSTR("java exception occured, but no java exception available!?") + 77 jni.get_stack_trace() ); 78 } 79 80 JLocalAutoRef jo_class( jni, jni->GetObjectClass( jo_exc.get() ) ); 81 JLocalAutoRef jo_class_name( 82 jni, jni->CallObjectMethodA( 83 jo_class.get(), m_jni_info->m_method_Class_getName, 0 ) ); 84 jni.ensure_no_exception(); 85 OUString exc_name( 86 jstring_to_oustring( jni, (jstring) jo_class_name.get() ) ); 87 88 ::com::sun::star::uno::TypeDescription td( exc_name.pData ); 89 if (!td.is() || (typelib_TypeClass_EXCEPTION != td.get()->eTypeClass)) 90 { 91 // call toString() 92 JLocalAutoRef jo_descr( 93 jni, jni->CallObjectMethodA( 94 jo_exc.get(), m_jni_info->m_method_Object_toString, 0 ) ); 95 jni.ensure_no_exception(); 96 OUStringBuffer buf( 128 ); 97 buf.appendAscii( 98 RTL_CONSTASCII_STRINGPARAM("non-UNO exception occurred: ") ); 99 buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); 100 buf.append( jni.get_stack_trace( jo_exc.get() ) ); 101 throw BridgeRuntimeError( buf.makeStringAndClear() ); 102 } 103 104 auto_ptr< rtl_mem > uno_data( rtl_mem::allocate( td.get()->nSize ) ); 105 jvalue val; 106 val.l = jo_exc.get(); 107 map_to_uno( 108 jni, uno_data.get(), val, td.get()->pWeakRef, 0, 109 false /* no assign */, false /* no out param */ ); 110 111 #if OSL_DEBUG_LEVEL > 0 112 // patch Message, append stack trace 113 reinterpret_cast< ::com::sun::star::uno::Exception * >( 114 uno_data.get() )->Message += jni.get_stack_trace( jo_exc.get() ); 115 #endif 116 117 typelib_typedescriptionreference_acquire( td.get()->pWeakRef ); 118 uno_exc->pType = td.get()->pWeakRef; 119 uno_exc->pData = uno_data.release(); 120 121 #if OSL_DEBUG_LEVEL > 1 122 OUStringBuffer trace_buf( 128 ); 123 trace_buf.appendAscii( 124 RTL_CONSTASCII_STRINGPARAM("exception occured uno->java: [") ); 125 trace_buf.append( exc_name ); 126 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") ); 127 trace_buf.append( 128 reinterpret_cast< ::com::sun::star::uno::Exception const * >( 129 uno_exc->pData )->Message ); 130 OString cstr_trace( 131 OUStringToOString( 132 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); 133 OSL_TRACE( cstr_trace.getStr() ); 134 #endif 135 } 136 137 //______________________________________________________________________________ 138 void Bridge::call_java( 139 jobject javaI, typelib_InterfaceTypeDescription * iface_td, 140 sal_Int32 local_member_index, sal_Int32 function_pos_offset, 141 typelib_TypeDescriptionReference * return_type, 142 typelib_MethodParameter * params, sal_Int32 nParams, 143 void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const 144 { 145 OSL_ASSERT( function_pos_offset == 0 || function_pos_offset == 1 ); 146 147 JNI_guarded_context jni( 148 m_jni_info, reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( 149 m_java_env->pContext ) ); 150 151 // assure fully initialized iface_td: 152 ::com::sun::star::uno::TypeDescription iface_holder; 153 if (! iface_td->aBase.bComplete) { 154 iface_holder = ::com::sun::star::uno::TypeDescription( 155 reinterpret_cast<typelib_TypeDescription *>(iface_td) ); 156 iface_holder.makeComplete(); 157 if (! iface_holder.get()->bComplete) { 158 OUStringBuffer buf; 159 buf.appendAscii( 160 RTL_CONSTASCII_STRINGPARAM("cannot make type complete: ") ); 161 buf.append( OUString::unacquired(&iface_holder.get()->pTypeName) ); 162 buf.append( jni.get_stack_trace() ); 163 throw BridgeRuntimeError( buf.makeStringAndClear() ); 164 } 165 iface_td = reinterpret_cast<typelib_InterfaceTypeDescription *>( 166 iface_holder.get() ); 167 OSL_ASSERT( iface_td->aBase.eTypeClass == typelib_TypeClass_INTERFACE ); 168 } 169 170 // prepare java args, save param td 171 #ifdef BROKEN_ALLOCA 172 jvalue * java_args = (jvalue *) malloc( sizeof (jvalue) * nParams ); 173 #else 174 jvalue * java_args = (jvalue *) alloca( sizeof (jvalue) * nParams ); 175 #endif 176 177 sal_Int32 nPos; 178 for ( nPos = 0; nPos < nParams; ++nPos ) 179 { 180 try 181 { 182 typelib_MethodParameter const & param = params[ nPos ]; 183 java_args[ nPos ].l = 0; // if out: build up array[ 1 ] 184 map_to_java( 185 jni, &java_args[ nPos ], 186 uno_args[ nPos ], 187 param.pTypeRef, 0, 188 sal_False != param.bIn /* convert uno value */, 189 sal_False != param.bOut /* build up array[ 1 ] */ ); 190 } 191 catch (...) 192 { 193 // cleanup 194 for ( sal_Int32 n = 0; n < nPos; ++n ) 195 { 196 typelib_MethodParameter const & param = params[ n ]; 197 if (param.bOut || 198 typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass) 199 { 200 jni->DeleteLocalRef( java_args[ n ].l ); 201 } 202 } 203 #ifdef BROKEN_ALLOCA 204 free( java_args ); 205 #endif 206 throw; 207 } 208 } 209 210 sal_Int32 base_members = iface_td->nAllMembers - iface_td->nMembers; 211 OSL_ASSERT( base_members < iface_td->nAllMembers ); 212 sal_Int32 base_members_function_pos = 213 iface_td->pMapMemberIndexToFunctionIndex[ base_members ]; 214 sal_Int32 member_pos = base_members + local_member_index; 215 OSL_ENSURE( 216 member_pos < iface_td->nAllMembers, "### member pos out of range!" ); 217 sal_Int32 function_pos = 218 iface_td->pMapMemberIndexToFunctionIndex[ member_pos ] 219 + function_pos_offset; 220 OSL_ENSURE( 221 function_pos >= base_members_function_pos 222 && function_pos < iface_td->nMapFunctionIndexToMemberIndex, 223 "### illegal function index!" ); 224 function_pos -= base_members_function_pos; 225 226 JNI_interface_type_info const * info = 227 static_cast< JNI_interface_type_info const * >( 228 m_jni_info->get_type_info( jni, &iface_td->aBase ) ); 229 jmethodID method_id = info->m_methods[ function_pos ]; 230 231 #if OSL_DEBUG_LEVEL > 1 232 OUStringBuffer trace_buf( 128 ); 233 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("calling ") ); 234 JLocalAutoRef jo_method( 235 jni, jni->ToReflectedMethod( info->m_class, method_id, JNI_FALSE ) ); 236 jni.ensure_no_exception(); 237 JLocalAutoRef jo_descr( 238 jni, jni->CallObjectMethodA( 239 jo_method.get(), m_jni_info->m_method_Object_toString, 0 ) ); 240 jni.ensure_no_exception(); 241 trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); 242 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on ") ); 243 jo_descr.reset( 244 jni->CallObjectMethodA( 245 javaI, 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.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (") ); 249 JLocalAutoRef jo_class( jni, jni->GetObjectClass( javaI ) ); 250 jo_descr.reset( 251 jni->CallObjectMethodA( 252 jo_class.get(), 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 OString cstr_trace( 257 OUStringToOString( 258 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); 259 OSL_TRACE( cstr_trace.getStr() ); 260 #endif 261 262 // complex return value 263 JLocalAutoRef java_ret( jni ); 264 265 switch (return_type->eTypeClass) 266 { 267 case typelib_TypeClass_VOID: 268 jni->CallVoidMethodA( javaI, method_id, java_args ); 269 break; 270 case typelib_TypeClass_CHAR: 271 *(sal_Unicode *)uno_ret = 272 jni->CallCharMethodA( javaI, method_id, java_args ); 273 break; 274 case typelib_TypeClass_BOOLEAN: 275 *(sal_Bool *)uno_ret = 276 jni->CallBooleanMethodA( javaI, method_id, java_args ); 277 break; 278 case typelib_TypeClass_BYTE: 279 *(sal_Int8 *)uno_ret = 280 jni->CallByteMethodA( javaI, method_id, java_args ); 281 break; 282 case typelib_TypeClass_SHORT: 283 case typelib_TypeClass_UNSIGNED_SHORT: 284 *(sal_Int16 *)uno_ret = 285 jni->CallShortMethodA( javaI, method_id, java_args ); 286 break; 287 case typelib_TypeClass_LONG: 288 case typelib_TypeClass_UNSIGNED_LONG: 289 *(sal_Int32 *)uno_ret = 290 jni->CallIntMethodA( javaI, method_id, java_args ); 291 break; 292 case typelib_TypeClass_HYPER: 293 case typelib_TypeClass_UNSIGNED_HYPER: 294 *(sal_Int64 *)uno_ret = 295 jni->CallLongMethodA( javaI, method_id, java_args ); 296 break; 297 case typelib_TypeClass_FLOAT: 298 *(float *)uno_ret = 299 jni->CallFloatMethodA( javaI, method_id, java_args ); 300 break; 301 case typelib_TypeClass_DOUBLE: 302 *(double *)uno_ret = 303 jni->CallDoubleMethodA( javaI, method_id, java_args ); 304 break; 305 default: 306 java_ret.reset( 307 jni->CallObjectMethodA( javaI, method_id, java_args ) ); 308 break; 309 } 310 311 if (jni->ExceptionCheck()) 312 { 313 JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() ); 314 jni->ExceptionClear(); 315 316 // release temp java local refs 317 for ( nPos = 0; nPos < nParams; ++nPos ) 318 { 319 typelib_MethodParameter const & param = params[ nPos ]; 320 if (param.bOut || 321 typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass) 322 { 323 jni->DeleteLocalRef( java_args[ nPos ].l ); 324 } 325 } 326 327 handle_java_exc( jni, jo_exc, *uno_exc ); 328 } 329 else // no exception 330 { 331 for ( nPos = 0; nPos < nParams; ++nPos ) 332 { 333 typelib_MethodParameter const & param = params[ nPos ]; 334 if (param.bOut) 335 { 336 try 337 { 338 map_to_uno( 339 jni, uno_args[ nPos ], 340 java_args[ nPos ], param.pTypeRef, 0, 341 sal_False != param.bIn /* assign if inout */, 342 true /* out param */ ); 343 } 344 catch (...) 345 { 346 // cleanup uno pure out 347 for ( sal_Int32 n = 0; n < nPos; ++n ) 348 { 349 typelib_MethodParameter const & p = params[ n ]; 350 if (! p.bIn) 351 { 352 uno_type_destructData( 353 uno_args[ n ], p.pTypeRef, 0 ); 354 } 355 } 356 // cleanup java temp local refs 357 for ( ; nPos < nParams; ++nPos ) 358 { 359 typelib_MethodParameter const & p = params[ nPos ]; 360 if (p.bOut || 361 typelib_TypeClass_DOUBLE < 362 p.pTypeRef->eTypeClass) 363 { 364 jni->DeleteLocalRef( java_args[ nPos ].l ); 365 } 366 } 367 #ifdef BROKEN_ALLOCA 368 free( java_args ); 369 #endif 370 throw; 371 } 372 jni->DeleteLocalRef( java_args[ nPos ].l ); 373 } 374 else // pure temp in param 375 { 376 if (typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass) 377 jni->DeleteLocalRef( java_args[ nPos ].l ); 378 } 379 } 380 381 // return value 382 if (typelib_TypeClass_DOUBLE < return_type->eTypeClass) 383 { 384 try 385 { 386 jvalue val; 387 val.l = java_ret.get(); 388 map_to_uno( 389 jni, uno_ret, val, return_type, 0, 390 false /* no assign */, false /* no out param */ ); 391 } 392 catch (...) 393 { 394 // cleanup uno pure out 395 for ( sal_Int32 i = 0; i < nParams; ++i ) 396 { 397 typelib_MethodParameter const & param = params[ i ]; 398 if (! param.bIn) 399 { 400 uno_type_destructData( 401 uno_args[ i ], param.pTypeRef, 0 ); 402 } 403 } 404 #ifdef BROKEN_ALLOCA 405 free( java_args ); 406 #endif 407 throw; 408 } 409 } // else: already set integral uno return value 410 411 // no exception occured 412 *uno_exc = 0; 413 } 414 #ifdef BROKEN_ALLOCA 415 free( java_args ); 416 #endif 417 } 418 419 //==== a uno proxy wrapping a java interface =================================== 420 struct UNO_proxy : public uno_Interface 421 { 422 mutable oslInterlockedCount m_ref; 423 Bridge const * m_bridge; 424 425 // mapping information 426 jobject m_javaI; 427 jstring m_jo_oid; 428 OUString m_oid; 429 JNI_interface_type_info const * m_type_info; 430 431 inline void acquire() const; 432 inline void release() const; 433 434 // ctor 435 inline 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 }; 440 441 //______________________________________________________________________________ 442 inline UNO_proxy::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 ) 446 : m_ref( 1 ), 447 m_oid( oid ), 448 m_type_info( info ) 449 { 450 JNI_info const * jni_info = bridge->m_jni_info; 451 JLocalAutoRef jo_string_array( 452 jni, jni->NewObjectArray( 1, jni_info->m_class_String, jo_oid ) ); 453 jni.ensure_no_exception(); 454 jvalue args[ 3 ]; 455 args[ 0 ].l = javaI; 456 args[ 1 ].l = jo_string_array.get(); 457 args[ 2 ].l = info->m_type; 458 jobject jo_iface = jni->CallObjectMethodA( 459 jni_info->m_object_java_env, 460 jni_info->m_method_IEnvironment_registerInterface, args ); 461 jni.ensure_no_exception(); 462 463 m_javaI = jni->NewGlobalRef( jo_iface ); 464 m_jo_oid = (jstring) jni->NewGlobalRef( jo_oid ); 465 bridge->acquire(); 466 m_bridge = bridge; 467 468 // uno_Interface 469 uno_Interface::acquire = UNO_proxy_acquire; 470 uno_Interface::release = UNO_proxy_release; 471 uno_Interface::pDispatcher = UNO_proxy_dispatch; 472 } 473 474 //______________________________________________________________________________ 475 inline void UNO_proxy::acquire() const 476 { 477 if (1 == osl_incrementInterlockedCount( &m_ref )) 478 { 479 // rebirth of proxy zombie 480 void * that = const_cast< UNO_proxy * >( this ); 481 // register at uno env 482 (*m_bridge->m_uno_env->registerProxyInterface)( 483 m_bridge->m_uno_env, &that, 484 UNO_proxy_free, m_oid.pData, 485 (typelib_InterfaceTypeDescription *)m_type_info->m_td.get() ); 486 #if OSL_DEBUG_LEVEL > 1 487 OSL_ASSERT( this == (void const * const)that ); 488 #endif 489 } 490 } 491 492 //______________________________________________________________________________ 493 inline void UNO_proxy::release() const 494 { 495 if (0 == osl_decrementInterlockedCount( &m_ref )) 496 { 497 // revoke from uno env on last release 498 (*m_bridge->m_uno_env->revokeInterface)( 499 m_bridge->m_uno_env, const_cast< UNO_proxy * >( this ) ); 500 } 501 } 502 503 504 //______________________________________________________________________________ 505 uno_Interface * Bridge::map_to_uno( 506 JNI_context const & jni, 507 jobject javaI, JNI_interface_type_info const * info ) const 508 { 509 JLocalAutoRef jo_oid( jni, compute_oid( jni, javaI ) ); 510 OUString oid( jstring_to_oustring( jni, (jstring) jo_oid.get() ) ); 511 512 uno_Interface * pUnoI = 0; 513 (*m_uno_env->getRegisteredInterface)( 514 m_uno_env, (void **)&pUnoI, 515 oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() ); 516 517 if (0 == pUnoI) // no existing interface, register new proxy 518 { 519 // refcount initially 1 520 pUnoI = new UNO_proxy( 521 jni, const_cast< Bridge * >( this ), 522 javaI, (jstring) jo_oid.get(), oid, info ); 523 524 (*m_uno_env->registerProxyInterface)( 525 m_uno_env, (void **)&pUnoI, 526 UNO_proxy_free, 527 oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() ); 528 } 529 return pUnoI; 530 } 531 532 } 533 534 using namespace ::jni_uno; 535 536 namespace 537 { 538 extern "C" 539 { 540 541 //------------------------------------------------------------------------------ 542 void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy ) 543 SAL_THROW_EXTERN_C() 544 { 545 UNO_proxy const * that = reinterpret_cast< UNO_proxy const * >( proxy ); 546 Bridge const * bridge = that->m_bridge; 547 548 if ( env != bridge->m_uno_env ) { 549 OSL_ASSERT(false); 550 } 551 #if OSL_DEBUG_LEVEL > 1 552 OString cstr_msg( 553 OUStringToOString( 554 OUSTR("freeing binary uno proxy: ") + that->m_oid, 555 RTL_TEXTENCODING_ASCII_US ) ); 556 OSL_TRACE( cstr_msg.getStr() ); 557 #endif 558 559 try 560 { 561 JNI_guarded_context jni( 562 bridge->m_jni_info, 563 reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( 564 bridge->m_java_env->pContext ) ); 565 566 jni->DeleteGlobalRef( that->m_javaI ); 567 jni->DeleteGlobalRef( that->m_jo_oid ); 568 } 569 catch (BridgeRuntimeError & err) 570 { 571 #if OSL_DEBUG_LEVEL > 0 572 OString cstr_msg2( 573 OUStringToOString( err.m_message, RTL_TEXTENCODING_ASCII_US ) ); 574 OSL_ENSURE( 0, cstr_msg2.getStr() ); 575 #else 576 (void) err; // unused 577 #endif 578 } 579 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) 580 { 581 OSL_ENSURE( 582 0, 583 "[jni_uno bridge error] attaching current thread to java failed!" ); 584 } 585 586 bridge->release(); 587 #if OSL_DEBUG_LEVEL > 1 588 *(int *)that = 0xdeadcafe; 589 #endif 590 delete that; 591 } 592 593 //------------------------------------------------------------------------------ 594 void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI ) 595 SAL_THROW_EXTERN_C() 596 { 597 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI ); 598 that->acquire(); 599 } 600 601 //------------------------------------------------------------------------------ 602 void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI ) 603 SAL_THROW_EXTERN_C() 604 { 605 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI ); 606 that->release(); 607 } 608 609 //------------------------------------------------------------------------------ 610 void SAL_CALL UNO_proxy_dispatch( 611 uno_Interface * pUnoI, typelib_TypeDescription const * member_td, 612 void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) 613 SAL_THROW_EXTERN_C() 614 { 615 UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI ); 616 Bridge const * bridge = that->m_bridge; 617 618 #if OSL_DEBUG_LEVEL > 1 619 OUStringBuffer trace_buf( 64 ); 620 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("uno->java call: ") ); 621 trace_buf.append( OUString::unacquired( &member_td->pTypeName ) ); 622 trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on oid ") ); 623 trace_buf.append( that->m_oid ); 624 OString cstr_msg( 625 OUStringToOString( 626 trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); 627 OSL_TRACE( cstr_msg.getStr() ); 628 #endif 629 630 try 631 { 632 switch (member_td->eTypeClass) 633 { 634 case typelib_TypeClass_INTERFACE_ATTRIBUTE: 635 { 636 typelib_InterfaceAttributeTypeDescription const * attrib_td = 637 reinterpret_cast< 638 typelib_InterfaceAttributeTypeDescription const * >( 639 member_td ); 640 com::sun::star::uno::TypeDescription attrib_holder; 641 while ( attrib_td->pBaseRef != 0 ) { 642 attrib_holder = com::sun::star::uno::TypeDescription( 643 attrib_td->pBaseRef ); 644 OSL_ASSERT( 645 attrib_holder.get()->eTypeClass 646 == typelib_TypeClass_INTERFACE_ATTRIBUTE ); 647 attrib_td = reinterpret_cast< 648 typelib_InterfaceAttributeTypeDescription * >( 649 attrib_holder.get() ); 650 } 651 typelib_InterfaceTypeDescription * iface_td = attrib_td->pInterface; 652 653 if (0 == uno_ret) // is setter method 654 { 655 typelib_MethodParameter param; 656 param.pTypeRef = attrib_td->pAttributeTypeRef; 657 param.bIn = sal_True; 658 param.bOut = sal_False; 659 660 bridge->call_java( 661 that->m_javaI, iface_td, 662 attrib_td->nIndex, 1, // get, then set method 663 bridge->m_jni_info->m_void_type.getTypeLibType(), 664 ¶m, 1, 665 0, uno_args, uno_exc ); 666 } 667 else // is getter method 668 { 669 bridge->call_java( 670 that->m_javaI, iface_td, attrib_td->nIndex, 0, 671 attrib_td->pAttributeTypeRef, 672 0, 0, // no params 673 uno_ret, 0, uno_exc ); 674 } 675 break; 676 } 677 case typelib_TypeClass_INTERFACE_METHOD: 678 { 679 typelib_InterfaceMethodTypeDescription const * method_td = 680 reinterpret_cast< 681 typelib_InterfaceMethodTypeDescription const * >( 682 member_td ); 683 com::sun::star::uno::TypeDescription method_holder; 684 while ( method_td->pBaseRef != 0 ) { 685 method_holder = com::sun::star::uno::TypeDescription( 686 method_td->pBaseRef ); 687 OSL_ASSERT( 688 method_holder.get()->eTypeClass 689 == typelib_TypeClass_INTERFACE_METHOD ); 690 method_td = reinterpret_cast< 691 typelib_InterfaceMethodTypeDescription * >( 692 method_holder.get() ); 693 } 694 typelib_InterfaceTypeDescription * iface_td = method_td->pInterface; 695 696 switch ( method_td->aBase.nPosition ) 697 { 698 case 0: // queryInterface() 699 { 700 TypeDescr demanded_td( 701 *reinterpret_cast< typelib_TypeDescriptionReference ** >( 702 uno_args[ 0 ] ) ); 703 if (typelib_TypeClass_INTERFACE != 704 demanded_td.get()->eTypeClass) 705 { 706 throw BridgeRuntimeError( 707 OUSTR("queryInterface() call demands " 708 "an INTERFACE type!") ); 709 } 710 711 uno_Interface * pInterface = 0; 712 (*bridge->m_uno_env->getRegisteredInterface)( 713 bridge->m_uno_env, 714 (void **) &pInterface, that->m_oid.pData, 715 (typelib_InterfaceTypeDescription *)demanded_td.get() ); 716 717 if (0 == pInterface) 718 { 719 JNI_info const * jni_info = bridge->m_jni_info; 720 JNI_guarded_context jni( 721 jni_info, 722 reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( 723 bridge->m_java_env->pContext ) ); 724 725 JNI_interface_type_info const * info = 726 static_cast< JNI_interface_type_info const * >( 727 jni_info->get_type_info( jni, demanded_td.get() ) ); 728 729 jvalue args[ 2 ]; 730 args[ 0 ].l = info->m_type; 731 args[ 1 ].l = that->m_javaI; 732 733 JLocalAutoRef jo_ret( 734 jni, jni->CallStaticObjectMethodA( 735 jni_info->m_class_UnoRuntime, 736 jni_info->m_method_UnoRuntime_queryInterface, 737 args ) ); 738 739 if (jni->ExceptionCheck()) 740 { 741 JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() ); 742 jni->ExceptionClear(); 743 bridge->handle_java_exc( jni, jo_exc, *uno_exc ); 744 } 745 else 746 { 747 if (jo_ret.is()) 748 { 749 #if OSL_DEBUG_LEVEL > 0 750 JLocalAutoRef jo_oid( 751 jni, compute_oid( jni, jo_ret.get() ) ); 752 OUString oid( jstring_to_oustring( 753 jni, (jstring) jo_oid.get() ) ); 754 OSL_ENSURE( 755 oid.equals( that->m_oid ), 756 "### different oids!" ); 757 #endif 758 // refcount initially 1 759 uno_Interface * pUnoI2 = new UNO_proxy( 760 jni, bridge, jo_ret.get(), 761 that->m_jo_oid, that->m_oid, info ); 762 763 (*bridge->m_uno_env->registerProxyInterface)( 764 bridge->m_uno_env, 765 (void **) &pUnoI2, 766 UNO_proxy_free, that->m_oid.pData, 767 reinterpret_cast< 768 typelib_InterfaceTypeDescription * >( 769 info->m_td.get() ) ); 770 771 uno_any_construct( 772 (uno_Any *)uno_ret, &pUnoI2, 773 demanded_td.get(), 0 ); 774 (*pUnoI2->release)( pUnoI2 ); 775 } 776 else // object does not support demanded interface 777 { 778 uno_any_construct( 779 reinterpret_cast< uno_Any * >( uno_ret ), 780 0, 0, 0 ); 781 } 782 // no exception occured 783 *uno_exc = 0; 784 } 785 } 786 else 787 { 788 uno_any_construct( 789 reinterpret_cast< uno_Any * >( uno_ret ), 790 &pInterface, demanded_td.get(), 0 ); 791 (*pInterface->release)( pInterface ); 792 *uno_exc = 0; 793 } 794 break; 795 } 796 case 1: // acquire this proxy 797 that->acquire(); 798 *uno_exc = 0; 799 break; 800 case 2: // release this proxy 801 that->release(); 802 *uno_exc = 0; 803 break; 804 default: // arbitrary method call 805 bridge->call_java( 806 that->m_javaI, iface_td, method_td->nIndex, 0, 807 method_td->pReturnTypeRef, 808 method_td->pParams, method_td->nParams, 809 uno_ret, uno_args, uno_exc ); 810 break; 811 } 812 break; 813 } 814 default: 815 { 816 throw BridgeRuntimeError( 817 OUSTR("illegal member type description!") ); 818 } 819 } 820 } 821 catch (BridgeRuntimeError & err) 822 { 823 OUStringBuffer buf( 128 ); 824 buf.appendAscii( 825 RTL_CONSTASCII_STRINGPARAM( 826 "[jni_uno bridge error] UNO calling Java method ") ); 827 if (typelib_TypeClass_INTERFACE_METHOD == member_td->eTypeClass || 828 typelib_TypeClass_INTERFACE_ATTRIBUTE == member_td->eTypeClass) 829 { 830 buf.append( OUString::unacquired( 831 &reinterpret_cast< 832 typelib_InterfaceMemberTypeDescription const * >( 833 member_td )->pMemberName ) ); 834 } 835 buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") ); 836 buf.append( err.m_message ); 837 // binary identical struct 838 ::com::sun::star::uno::RuntimeException exc( 839 buf.makeStringAndClear(), 840 ::com::sun::star::uno::Reference< 841 ::com::sun::star::uno::XInterface >() ); 842 ::com::sun::star::uno::Type const & exc_type = ::getCppuType( &exc ); 843 uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0 ); 844 #if OSL_DEBUG_LEVEL > 0 845 OString cstr_msg2( 846 OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) ); 847 OSL_TRACE( "%s", cstr_msg2.getStr() ); 848 #endif 849 } 850 catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) 851 { 852 // binary identical struct 853 ::com::sun::star::uno::RuntimeException exc( 854 OUSTR("[jni_uno bridge error] attaching current thread " 855 "to java failed!"), 856 ::com::sun::star::uno::Reference< 857 ::com::sun::star::uno::XInterface >() ); 858 ::com::sun::star::uno::Type const & exc_type = ::getCppuType( &exc ); 859 uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0 ); 860 #if OSL_DEBUG_LEVEL > 0 861 OString cstr_msg2( 862 OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) ); 863 OSL_ENSURE( 0, cstr_msg2.getStr() ); 864 #endif 865 } 866 } 867 868 } 869 } 870