/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_bridges.hxx" #include #include "com/sun/star/uno/RuntimeException.hpp" #include "rtl/ustrbuf.hxx" #include "jni_bridge.h" using namespace ::std; using namespace ::rtl; namespace { extern "C" { //------------------------------------------------------------------------------ void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy ) SAL_THROW_EXTERN_C(); //------------------------------------------------------------------------------ void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI ) SAL_THROW_EXTERN_C(); //------------------------------------------------------------------------------ void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI ) SAL_THROW_EXTERN_C(); //------------------------------------------------------------------------------ void SAL_CALL UNO_proxy_dispatch( uno_Interface * pUnoI, typelib_TypeDescription const * member_td, void * uno_ret, void * uno_args[], uno_Any ** uno_exc ) SAL_THROW_EXTERN_C(); } } namespace jni_uno { //______________________________________________________________________________ void Bridge::handle_java_exc( JNI_context const & jni, JLocalAutoRef const & jo_exc, uno_Any * uno_exc ) const { OSL_ASSERT( jo_exc.is() ); if (! jo_exc.is()) { throw BridgeRuntimeError( OUSTR("java exception occured, but no java exception available!?") + jni.get_stack_trace() ); } JLocalAutoRef jo_class( jni, jni->GetObjectClass( jo_exc.get() ) ); JLocalAutoRef jo_class_name( jni, jni->CallObjectMethodA( jo_class.get(), m_jni_info->m_method_Class_getName, 0 ) ); jni.ensure_no_exception(); OUString exc_name( jstring_to_oustring( jni, (jstring) jo_class_name.get() ) ); ::com::sun::star::uno::TypeDescription td( exc_name.pData ); if (!td.is() || (typelib_TypeClass_EXCEPTION != td.get()->eTypeClass)) { // call toString() JLocalAutoRef jo_descr( jni, jni->CallObjectMethodA( jo_exc.get(), m_jni_info->m_method_Object_toString, 0 ) ); jni.ensure_no_exception(); OUStringBuffer buf( 128 ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("non-UNO exception occurred: ") ); buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); buf.append( jni.get_stack_trace( jo_exc.get() ) ); throw BridgeRuntimeError( buf.makeStringAndClear() ); } auto_ptr< rtl_mem > uno_data( rtl_mem::allocate( td.get()->nSize ) ); jvalue val; val.l = jo_exc.get(); map_to_uno( jni, uno_data.get(), val, td.get()->pWeakRef, 0, false /* no assign */, false /* no out param */ ); #if OSL_DEBUG_LEVEL > 0 // patch Message, append stack trace reinterpret_cast< ::com::sun::star::uno::Exception * >( uno_data.get() )->Message += jni.get_stack_trace( jo_exc.get() ); #endif typelib_typedescriptionreference_acquire( td.get()->pWeakRef ); uno_exc->pType = td.get()->pWeakRef; uno_exc->pData = uno_data.release(); #if OSL_DEBUG_LEVEL > 1 OUStringBuffer trace_buf( 128 ); trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("exception occured uno->java: [") ); trace_buf.append( exc_name ); trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") ); trace_buf.append( reinterpret_cast< ::com::sun::star::uno::Exception const * >( uno_exc->pData )->Message ); OString cstr_trace( OUStringToOString( trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); OSL_TRACE( cstr_trace.getStr() ); #endif } //______________________________________________________________________________ void Bridge::call_java( jobject javaI, typelib_InterfaceTypeDescription * iface_td, sal_Int32 local_member_index, sal_Int32 function_pos_offset, typelib_TypeDescriptionReference * return_type, typelib_MethodParameter * params, sal_Int32 nParams, void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) const { OSL_ASSERT( function_pos_offset == 0 || function_pos_offset == 1 ); JNI_guarded_context jni( m_jni_info, reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( m_java_env->pContext ) ); // assure fully initialized iface_td: ::com::sun::star::uno::TypeDescription iface_holder; if (! iface_td->aBase.bComplete) { iface_holder = ::com::sun::star::uno::TypeDescription( reinterpret_cast(iface_td) ); iface_holder.makeComplete(); if (! iface_holder.get()->bComplete) { OUStringBuffer buf; buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("cannot make type complete: ") ); buf.append( OUString::unacquired(&iface_holder.get()->pTypeName) ); buf.append( jni.get_stack_trace() ); throw BridgeRuntimeError( buf.makeStringAndClear() ); } iface_td = reinterpret_cast( iface_holder.get() ); OSL_ASSERT( iface_td->aBase.eTypeClass == typelib_TypeClass_INTERFACE ); } // prepare java args, save param td #ifdef BROKEN_ALLOCA jvalue * java_args = (jvalue *) malloc( sizeof (jvalue) * nParams ); #else jvalue * java_args = (jvalue *) alloca( sizeof (jvalue) * nParams ); #endif sal_Int32 nPos; for ( nPos = 0; nPos < nParams; ++nPos ) { try { typelib_MethodParameter const & param = params[ nPos ]; java_args[ nPos ].l = 0; // if out: build up array[ 1 ] map_to_java( jni, &java_args[ nPos ], uno_args[ nPos ], param.pTypeRef, 0, sal_False != param.bIn /* convert uno value */, sal_False != param.bOut /* build up array[ 1 ] */ ); } catch (...) { // cleanup for ( sal_Int32 n = 0; n < nPos; ++n ) { typelib_MethodParameter const & param = params[ n ]; if (param.bOut || typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass) { jni->DeleteLocalRef( java_args[ n ].l ); } } #ifdef BROKEN_ALLOCA free( java_args ); #endif throw; } } sal_Int32 base_members = iface_td->nAllMembers - iface_td->nMembers; OSL_ASSERT( base_members < iface_td->nAllMembers ); sal_Int32 base_members_function_pos = iface_td->pMapMemberIndexToFunctionIndex[ base_members ]; sal_Int32 member_pos = base_members + local_member_index; OSL_ENSURE( member_pos < iface_td->nAllMembers, "### member pos out of range!" ); sal_Int32 function_pos = iface_td->pMapMemberIndexToFunctionIndex[ member_pos ] + function_pos_offset; OSL_ENSURE( function_pos >= base_members_function_pos && function_pos < iface_td->nMapFunctionIndexToMemberIndex, "### illegal function index!" ); function_pos -= base_members_function_pos; JNI_interface_type_info const * info = static_cast< JNI_interface_type_info const * >( m_jni_info->get_type_info( jni, &iface_td->aBase ) ); jmethodID method_id = info->m_methods[ function_pos ]; #if OSL_DEBUG_LEVEL > 1 OUStringBuffer trace_buf( 128 ); trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("calling ") ); JLocalAutoRef jo_method( jni, jni->ToReflectedMethod( info->m_class, method_id, JNI_FALSE ) ); jni.ensure_no_exception(); JLocalAutoRef jo_descr( jni, jni->CallObjectMethodA( jo_method.get(), m_jni_info->m_method_Object_toString, 0 ) ); jni.ensure_no_exception(); trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on ") ); jo_descr.reset( jni->CallObjectMethodA( javaI, m_jni_info->m_method_Object_toString, 0 ) ); jni.ensure_no_exception(); trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" (") ); JLocalAutoRef jo_class( jni, jni->GetObjectClass( javaI ) ); jo_descr.reset( jni->CallObjectMethodA( jo_class.get(), m_jni_info->m_method_Object_toString, 0 ) ); jni.ensure_no_exception(); trace_buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(")") ); OString cstr_trace( OUStringToOString( trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); OSL_TRACE( cstr_trace.getStr() ); #endif // complex return value JLocalAutoRef java_ret( jni ); switch (return_type->eTypeClass) { case typelib_TypeClass_VOID: jni->CallVoidMethodA( javaI, method_id, java_args ); break; case typelib_TypeClass_CHAR: *(sal_Unicode *)uno_ret = jni->CallCharMethodA( javaI, method_id, java_args ); break; case typelib_TypeClass_BOOLEAN: *(sal_Bool *)uno_ret = jni->CallBooleanMethodA( javaI, method_id, java_args ); break; case typelib_TypeClass_BYTE: *(sal_Int8 *)uno_ret = jni->CallByteMethodA( javaI, method_id, java_args ); break; case typelib_TypeClass_SHORT: case typelib_TypeClass_UNSIGNED_SHORT: *(sal_Int16 *)uno_ret = jni->CallShortMethodA( javaI, method_id, java_args ); break; case typelib_TypeClass_LONG: case typelib_TypeClass_UNSIGNED_LONG: *(sal_Int32 *)uno_ret = jni->CallIntMethodA( javaI, method_id, java_args ); break; case typelib_TypeClass_HYPER: case typelib_TypeClass_UNSIGNED_HYPER: *(sal_Int64 *)uno_ret = jni->CallLongMethodA( javaI, method_id, java_args ); break; case typelib_TypeClass_FLOAT: *(float *)uno_ret = jni->CallFloatMethodA( javaI, method_id, java_args ); break; case typelib_TypeClass_DOUBLE: *(double *)uno_ret = jni->CallDoubleMethodA( javaI, method_id, java_args ); break; default: java_ret.reset( jni->CallObjectMethodA( javaI, method_id, java_args ) ); break; } if (jni->ExceptionCheck()) { JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() ); jni->ExceptionClear(); // release temp java local refs for ( nPos = 0; nPos < nParams; ++nPos ) { typelib_MethodParameter const & param = params[ nPos ]; if (param.bOut || typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass) { jni->DeleteLocalRef( java_args[ nPos ].l ); } } handle_java_exc( jni, jo_exc, *uno_exc ); } else // no exception { for ( nPos = 0; nPos < nParams; ++nPos ) { typelib_MethodParameter const & param = params[ nPos ]; if (param.bOut) { try { map_to_uno( jni, uno_args[ nPos ], java_args[ nPos ], param.pTypeRef, 0, sal_False != param.bIn /* assign if inout */, true /* out param */ ); } catch (...) { // cleanup uno pure out for ( sal_Int32 n = 0; n < nPos; ++n ) { typelib_MethodParameter const & p = params[ n ]; if (! p.bIn) { uno_type_destructData( uno_args[ n ], p.pTypeRef, 0 ); } } // cleanup java temp local refs for ( ; nPos < nParams; ++nPos ) { typelib_MethodParameter const & p = params[ nPos ]; if (p.bOut || typelib_TypeClass_DOUBLE < p.pTypeRef->eTypeClass) { jni->DeleteLocalRef( java_args[ nPos ].l ); } } #ifdef BROKEN_ALLOCA free( java_args ); #endif throw; } jni->DeleteLocalRef( java_args[ nPos ].l ); } else // pure temp in param { if (typelib_TypeClass_DOUBLE < param.pTypeRef->eTypeClass) jni->DeleteLocalRef( java_args[ nPos ].l ); } } // return value if (typelib_TypeClass_DOUBLE < return_type->eTypeClass) { try { jvalue val; val.l = java_ret.get(); map_to_uno( jni, uno_ret, val, return_type, 0, false /* no assign */, false /* no out param */ ); } catch (...) { // cleanup uno pure out for ( sal_Int32 i = 0; i < nParams; ++i ) { typelib_MethodParameter const & param = params[ i ]; if (! param.bIn) { uno_type_destructData( uno_args[ i ], param.pTypeRef, 0 ); } } #ifdef BROKEN_ALLOCA free( java_args ); #endif throw; } } // else: already set integral uno return value // no exception occured *uno_exc = 0; } #ifdef BROKEN_ALLOCA free( java_args ); #endif } //==== a uno proxy wrapping a java interface =================================== struct UNO_proxy : public uno_Interface { mutable oslInterlockedCount m_ref; Bridge const * m_bridge; // mapping information jobject m_javaI; jstring m_jo_oid; OUString m_oid; JNI_interface_type_info const * m_type_info; inline void acquire() const; inline void release() const; // ctor inline UNO_proxy( JNI_context const & jni, Bridge const * bridge, jobject javaI, jstring jo_oid, OUString const & oid, JNI_interface_type_info const * info ); }; //______________________________________________________________________________ inline UNO_proxy::UNO_proxy( JNI_context const & jni, Bridge const * bridge, jobject javaI, jstring jo_oid, OUString const & oid, JNI_interface_type_info const * info ) : m_ref( 1 ), m_oid( oid ), m_type_info( info ) { JNI_info const * jni_info = bridge->m_jni_info; JLocalAutoRef jo_string_array( jni, jni->NewObjectArray( 1, jni_info->m_class_String, jo_oid ) ); jni.ensure_no_exception(); jvalue args[ 3 ]; args[ 0 ].l = javaI; args[ 1 ].l = jo_string_array.get(); args[ 2 ].l = info->m_type; jobject jo_iface = jni->CallObjectMethodA( jni_info->m_object_java_env, jni_info->m_method_IEnvironment_registerInterface, args ); jni.ensure_no_exception(); m_javaI = jni->NewGlobalRef( jo_iface ); m_jo_oid = (jstring) jni->NewGlobalRef( jo_oid ); bridge->acquire(); m_bridge = bridge; // uno_Interface uno_Interface::acquire = UNO_proxy_acquire; uno_Interface::release = UNO_proxy_release; uno_Interface::pDispatcher = UNO_proxy_dispatch; } //______________________________________________________________________________ inline void UNO_proxy::acquire() const { if (1 == osl_incrementInterlockedCount( &m_ref )) { // rebirth of proxy zombie void * that = const_cast< UNO_proxy * >( this ); // register at uno env (*m_bridge->m_uno_env->registerProxyInterface)( m_bridge->m_uno_env, &that, UNO_proxy_free, m_oid.pData, (typelib_InterfaceTypeDescription *)m_type_info->m_td.get() ); #if OSL_DEBUG_LEVEL > 1 OSL_ASSERT( this == (void const * const)that ); #endif } } //______________________________________________________________________________ inline void UNO_proxy::release() const { if (0 == osl_decrementInterlockedCount( &m_ref )) { // revoke from uno env on last release (*m_bridge->m_uno_env->revokeInterface)( m_bridge->m_uno_env, const_cast< UNO_proxy * >( this ) ); } } //______________________________________________________________________________ uno_Interface * Bridge::map_to_uno( JNI_context const & jni, jobject javaI, JNI_interface_type_info const * info ) const { JLocalAutoRef jo_oid( jni, compute_oid( jni, javaI ) ); OUString oid( jstring_to_oustring( jni, (jstring) jo_oid.get() ) ); uno_Interface * pUnoI = 0; (*m_uno_env->getRegisteredInterface)( m_uno_env, (void **)&pUnoI, oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() ); if (0 == pUnoI) // no existing interface, register new proxy { // refcount initially 1 pUnoI = new UNO_proxy( jni, const_cast< Bridge * >( this ), javaI, (jstring) jo_oid.get(), oid, info ); (*m_uno_env->registerProxyInterface)( m_uno_env, (void **)&pUnoI, UNO_proxy_free, oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() ); } return pUnoI; } } using namespace ::jni_uno; namespace { extern "C" { //------------------------------------------------------------------------------ void SAL_CALL UNO_proxy_free( uno_ExtEnvironment * env, void * proxy ) SAL_THROW_EXTERN_C() { UNO_proxy const * that = reinterpret_cast< UNO_proxy const * >( proxy ); Bridge const * bridge = that->m_bridge; if ( env != bridge->m_uno_env ) { OSL_ASSERT(false); } #if OSL_DEBUG_LEVEL > 1 OString cstr_msg( OUStringToOString( OUSTR("freeing binary uno proxy: ") + that->m_oid, RTL_TEXTENCODING_ASCII_US ) ); OSL_TRACE( cstr_msg.getStr() ); #endif try { JNI_guarded_context jni( bridge->m_jni_info, reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( bridge->m_java_env->pContext ) ); jni->DeleteGlobalRef( that->m_javaI ); jni->DeleteGlobalRef( that->m_jo_oid ); } catch (BridgeRuntimeError & err) { #if OSL_DEBUG_LEVEL > 0 OString cstr_msg2( OUStringToOString( err.m_message, RTL_TEXTENCODING_ASCII_US ) ); OSL_ENSURE( 0, cstr_msg2.getStr() ); #else (void) err; // unused #endif } catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) { OSL_ENSURE( 0, "[jni_uno bridge error] attaching current thread to java failed!" ); } bridge->release(); #if OSL_DEBUG_LEVEL > 1 *(int *)that = 0xdeadcafe; #endif delete that; } //------------------------------------------------------------------------------ void SAL_CALL UNO_proxy_acquire( uno_Interface * pUnoI ) SAL_THROW_EXTERN_C() { UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI ); that->acquire(); } //------------------------------------------------------------------------------ void SAL_CALL UNO_proxy_release( uno_Interface * pUnoI ) SAL_THROW_EXTERN_C() { UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI ); that->release(); } //------------------------------------------------------------------------------ void SAL_CALL UNO_proxy_dispatch( uno_Interface * pUnoI, typelib_TypeDescription const * member_td, void * uno_ret, void * uno_args [], uno_Any ** uno_exc ) SAL_THROW_EXTERN_C() { UNO_proxy const * that = static_cast< UNO_proxy const * >( pUnoI ); Bridge const * bridge = that->m_bridge; #if OSL_DEBUG_LEVEL > 1 OUStringBuffer trace_buf( 64 ); trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("uno->java call: ") ); trace_buf.append( OUString::unacquired( &member_td->pTypeName ) ); trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on oid ") ); trace_buf.append( that->m_oid ); OString cstr_msg( OUStringToOString( trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); OSL_TRACE( cstr_msg.getStr() ); #endif try { switch (member_td->eTypeClass) { case typelib_TypeClass_INTERFACE_ATTRIBUTE: { typelib_InterfaceAttributeTypeDescription const * attrib_td = reinterpret_cast< typelib_InterfaceAttributeTypeDescription const * >( member_td ); com::sun::star::uno::TypeDescription attrib_holder; while ( attrib_td->pBaseRef != 0 ) { attrib_holder = com::sun::star::uno::TypeDescription( attrib_td->pBaseRef ); OSL_ASSERT( attrib_holder.get()->eTypeClass == typelib_TypeClass_INTERFACE_ATTRIBUTE ); attrib_td = reinterpret_cast< typelib_InterfaceAttributeTypeDescription * >( attrib_holder.get() ); } typelib_InterfaceTypeDescription * iface_td = attrib_td->pInterface; if (0 == uno_ret) // is setter method { typelib_MethodParameter param; param.pTypeRef = attrib_td->pAttributeTypeRef; param.bIn = sal_True; param.bOut = sal_False; bridge->call_java( that->m_javaI, iface_td, attrib_td->nIndex, 1, // get, then set method bridge->m_jni_info->m_void_type.getTypeLibType(), ¶m, 1, 0, uno_args, uno_exc ); } else // is getter method { bridge->call_java( that->m_javaI, iface_td, attrib_td->nIndex, 0, attrib_td->pAttributeTypeRef, 0, 0, // no params uno_ret, 0, uno_exc ); } break; } case typelib_TypeClass_INTERFACE_METHOD: { typelib_InterfaceMethodTypeDescription const * method_td = reinterpret_cast< typelib_InterfaceMethodTypeDescription const * >( member_td ); com::sun::star::uno::TypeDescription method_holder; while ( method_td->pBaseRef != 0 ) { method_holder = com::sun::star::uno::TypeDescription( method_td->pBaseRef ); OSL_ASSERT( method_holder.get()->eTypeClass == typelib_TypeClass_INTERFACE_METHOD ); method_td = reinterpret_cast< typelib_InterfaceMethodTypeDescription * >( method_holder.get() ); } typelib_InterfaceTypeDescription * iface_td = method_td->pInterface; switch ( method_td->aBase.nPosition ) { case 0: // queryInterface() { TypeDescr demanded_td( *reinterpret_cast< typelib_TypeDescriptionReference ** >( uno_args[ 0 ] ) ); if (typelib_TypeClass_INTERFACE != demanded_td.get()->eTypeClass) { throw BridgeRuntimeError( OUSTR("queryInterface() call demands " "an INTERFACE type!") ); } uno_Interface * pInterface = 0; (*bridge->m_uno_env->getRegisteredInterface)( bridge->m_uno_env, (void **) &pInterface, that->m_oid.pData, (typelib_InterfaceTypeDescription *)demanded_td.get() ); if (0 == pInterface) { JNI_info const * jni_info = bridge->m_jni_info; JNI_guarded_context jni( jni_info, reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( bridge->m_java_env->pContext ) ); JNI_interface_type_info const * info = static_cast< JNI_interface_type_info const * >( jni_info->get_type_info( jni, demanded_td.get() ) ); jvalue args[ 2 ]; args[ 0 ].l = info->m_type; args[ 1 ].l = that->m_javaI; JLocalAutoRef jo_ret( jni, jni->CallStaticObjectMethodA( jni_info->m_class_UnoRuntime, jni_info->m_method_UnoRuntime_queryInterface, args ) ); if (jni->ExceptionCheck()) { JLocalAutoRef jo_exc( jni, jni->ExceptionOccurred() ); jni->ExceptionClear(); bridge->handle_java_exc( jni, jo_exc, *uno_exc ); } else { if (jo_ret.is()) { #if OSL_DEBUG_LEVEL > 0 JLocalAutoRef jo_oid( jni, compute_oid( jni, jo_ret.get() ) ); OUString oid( jstring_to_oustring( jni, (jstring) jo_oid.get() ) ); OSL_ENSURE( oid.equals( that->m_oid ), "### different oids!" ); #endif // refcount initially 1 uno_Interface * pUnoI2 = new UNO_proxy( jni, bridge, jo_ret.get(), that->m_jo_oid, that->m_oid, info ); (*bridge->m_uno_env->registerProxyInterface)( bridge->m_uno_env, (void **) &pUnoI2, UNO_proxy_free, that->m_oid.pData, reinterpret_cast< typelib_InterfaceTypeDescription * >( info->m_td.get() ) ); uno_any_construct( (uno_Any *)uno_ret, &pUnoI2, demanded_td.get(), 0 ); (*pUnoI2->release)( pUnoI2 ); } else // object does not support demanded interface { uno_any_construct( reinterpret_cast< uno_Any * >( uno_ret ), 0, 0, 0 ); } // no exception occured *uno_exc = 0; } } else { uno_any_construct( reinterpret_cast< uno_Any * >( uno_ret ), &pInterface, demanded_td.get(), 0 ); (*pInterface->release)( pInterface ); *uno_exc = 0; } break; } case 1: // acquire this proxy that->acquire(); *uno_exc = 0; break; case 2: // release this proxy that->release(); *uno_exc = 0; break; default: // arbitrary method call bridge->call_java( that->m_javaI, iface_td, method_td->nIndex, 0, method_td->pReturnTypeRef, method_td->pParams, method_td->nParams, uno_ret, uno_args, uno_exc ); break; } break; } default: { throw BridgeRuntimeError( OUSTR("illegal member type description!") ); } } } catch (BridgeRuntimeError & err) { OUStringBuffer buf( 128 ); buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "[jni_uno bridge error] UNO calling Java method ") ); if (typelib_TypeClass_INTERFACE_METHOD == member_td->eTypeClass || typelib_TypeClass_INTERFACE_ATTRIBUTE == member_td->eTypeClass) { buf.append( OUString::unacquired( &reinterpret_cast< typelib_InterfaceMemberTypeDescription const * >( member_td )->pMemberName ) ); } buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") ); buf.append( err.m_message ); // binary identical struct ::com::sun::star::uno::RuntimeException exc( buf.makeStringAndClear(), ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); ::com::sun::star::uno::Type const & exc_type = ::getCppuType( &exc ); uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0 ); #if OSL_DEBUG_LEVEL > 0 OString cstr_msg2( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) ); OSL_TRACE( "%s", cstr_msg2.getStr() ); #endif } catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) { // binary identical struct ::com::sun::star::uno::RuntimeException exc( OUSTR("[jni_uno bridge error] attaching current thread " "to java failed!"), ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ); ::com::sun::star::uno::Type const & exc_type = ::getCppuType( &exc ); uno_type_any_construct( *uno_exc, &exc, exc_type.getTypeLibType(), 0 ); #if OSL_DEBUG_LEVEL > 0 OString cstr_msg2( OUStringToOString( exc.Message, RTL_TEXTENCODING_ASCII_US ) ); OSL_ENSURE( 0, cstr_msg2.getStr() ); #endif } } } }