| /************************************************************** |
| * |
| * 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 <sal/alloca.h> |
| |
| #include "jni_bridge.h" |
| //#include "jni_finalizer.h" |
| |
| #include <rtl/ustrbuf.hxx> |
| |
| #include <algorithm> |
| |
| |
| using namespace ::rtl; |
| |
| namespace jni_uno |
| { |
| |
| //______________________________________________________________________________ |
| jobject Bridge::map_to_java( |
| JNI_context const & jni, |
| uno_Interface * pUnoI, JNI_interface_type_info const * info ) const |
| { |
| // get oid |
| rtl_uString * pOid = 0; |
| (*m_uno_env->getObjectIdentifier)( m_uno_env, &pOid, pUnoI ); |
| OSL_ASSERT( 0 != pOid ); |
| OUString oid( pOid, SAL_NO_ACQUIRE ); |
| |
| // opt getRegisteredInterface() |
| JLocalAutoRef jo_oid( jni, ustring_to_jstring( jni, oid.pData ) ); |
| jvalue args[ 2 ]; |
| args[ 0 ].l = jo_oid.get(); |
| args[ 1 ].l = info->m_type; |
| jobject jo_iface = jni->CallObjectMethodA( |
| m_jni_info->m_object_java_env, |
| m_jni_info->m_method_IEnvironment_getRegisteredInterface, args ); |
| jni.ensure_no_exception(); |
| |
| if (0 == jo_iface) // no registered iface |
| { |
| // register uno interface |
| (*m_uno_env->registerInterface)( |
| m_uno_env, reinterpret_cast< void ** >( &pUnoI ), |
| oid.pData, (typelib_InterfaceTypeDescription *)info->m_td.get() ); |
| |
| // create java and register java proxy |
| jvalue args2[ 7 ]; |
| acquire(); |
| args2[ 0 ].j = reinterpret_cast< sal_Int64 >( this ); |
| (*pUnoI->acquire)( pUnoI ); |
| args2[ 1 ].l = m_jni_info->m_object_java_env; |
| args2[ 2 ].j = reinterpret_cast< sal_Int64 >( pUnoI ); |
| typelib_typedescription_acquire( info->m_td.get() ); |
| args2[ 3 ].j = reinterpret_cast< sal_Int64 >( info->m_td.get() ); |
| args2[ 4 ].l = info->m_type; |
| args2[ 5 ].l = jo_oid.get(); |
| args2[ 6 ].l = info->m_proxy_ctor; |
| jo_iface = jni->CallStaticObjectMethodA( |
| m_jni_info->m_class_JNI_proxy, |
| m_jni_info->m_method_JNI_proxy_create, args2 ); |
| jni.ensure_no_exception(); |
| } |
| |
| OSL_ASSERT( 0 != jo_iface ); |
| return jo_iface; |
| } |
| |
| |
| //______________________________________________________________________________ |
| void Bridge::handle_uno_exc( JNI_context const & jni, uno_Any * uno_exc ) const |
| { |
| if (typelib_TypeClass_EXCEPTION == uno_exc->pType->eTypeClass) |
| { |
| #if OSL_DEBUG_LEVEL > 0 |
| // append java stack trace to Message member |
| reinterpret_cast< ::com::sun::star::uno::Exception * >( |
| uno_exc->pData )->Message += jni.get_stack_trace(); |
| #endif |
| |
| #if OSL_DEBUG_LEVEL > 1 |
| { |
| OUStringBuffer buf( 128 ); |
| buf.appendAscii( |
| RTL_CONSTASCII_STRINGPARAM("exception occured java->uno: [") ); |
| buf.append( OUString::unacquired( &uno_exc->pType->pTypeName ) ); |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("] ") ); |
| buf.append( |
| reinterpret_cast< ::com::sun::star::uno::Exception const * >( |
| uno_exc->pData )->Message ); |
| OString cstr_msg( |
| OUStringToOString( |
| buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); |
| OSL_TRACE( cstr_msg.getStr() ); |
| } |
| #endif |
| // signal exception |
| jvalue java_exc; |
| try |
| { |
| map_to_java( |
| jni, &java_exc, uno_exc->pData, uno_exc->pType, 0, |
| true /* in */, false /* no out */ ); |
| } |
| catch (...) |
| { |
| uno_any_destruct( uno_exc, 0 ); |
| throw; |
| } |
| uno_any_destruct( uno_exc, 0 ); |
| |
| JLocalAutoRef jo_exc( jni, java_exc.l ); |
| jint res = jni->Throw( (jthrowable) jo_exc.get() ); |
| if (0 != res) |
| { |
| // 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( |
| "throwing java exception failed: ") ); |
| buf.append( jstring_to_oustring( jni, (jstring) jo_descr.get() ) ); |
| buf.append( jni.get_stack_trace() ); |
| throw BridgeRuntimeError( buf.makeStringAndClear() ); |
| } |
| } |
| else |
| { |
| OUString message( |
| OUSTR("thrown exception is no uno exception: ") + |
| OUString::unacquired( &uno_exc->pType->pTypeName ) + |
| jni.get_stack_trace() ); |
| uno_any_destruct( uno_exc, 0 ); |
| throw BridgeRuntimeError( message ); |
| } |
| } |
| |
| union largest |
| { |
| sal_Int64 n; |
| double d; |
| void * p; |
| uno_Any a; |
| }; |
| |
| //______________________________________________________________________________ |
| jobject Bridge::call_uno( |
| JNI_context const & jni, |
| uno_Interface * pUnoI, typelib_TypeDescription * member_td, |
| typelib_TypeDescriptionReference * return_type, |
| sal_Int32 nParams, typelib_MethodParameter const * pParams, |
| jobjectArray jo_args /* may be 0 */ ) const |
| { |
| // return mem |
| sal_Int32 return_size; |
| switch (return_type->eTypeClass) { |
| case typelib_TypeClass_VOID: |
| return_size = 0; |
| break; |
| |
| case typelib_TypeClass_STRUCT: |
| case typelib_TypeClass_EXCEPTION: |
| return_size = std::max( |
| TypeDescr(return_type).get()->nSize, |
| static_cast< sal_Int32 >(sizeof (largest))); |
| break; |
| |
| default: |
| return_size = sizeof (largest); |
| break; |
| } |
| |
| #ifdef BROKEN_ALLOCA |
| char * mem = (char *) malloc( |
| #else |
| char * mem = (char *) alloca( |
| #endif |
| (nParams * sizeof (void *)) + |
| return_size + (nParams * sizeof (largest)) ); |
| void ** uno_args = (void **) mem; |
| void * uno_ret = return_size == 0 ? 0 : (mem + (nParams * sizeof (void *))); |
| largest * uno_args_mem = (largest *) |
| (mem + (nParams * sizeof (void *)) + return_size); |
| |
| OSL_ASSERT( (0 == nParams) || (nParams == jni->GetArrayLength( jo_args )) ); |
| for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) |
| { |
| typelib_MethodParameter const & param = pParams[ nPos ]; |
| typelib_TypeDescriptionReference * type = param.pTypeRef; |
| |
| uno_args[ nPos ] = &uno_args_mem[ nPos ]; |
| if (typelib_TypeClass_STRUCT == type->eTypeClass || |
| typelib_TypeClass_EXCEPTION == type->eTypeClass) |
| { |
| TypeDescr td( type ); |
| if (sal::static_int_cast< sal_uInt32 >(td.get()->nSize) |
| > sizeof (largest)) |
| #ifdef BROKEN_ALLOCA |
| uno_args[ nPos ] = malloc( td.get()->nSize ); |
| #else |
| uno_args[ nPos ] = alloca( td.get()->nSize ); |
| #endif |
| } |
| |
| if (param.bIn) |
| { |
| try |
| { |
| JLocalAutoRef jo_arg( |
| jni, jni->GetObjectArrayElement( jo_args, nPos ) ); |
| jni.ensure_no_exception(); |
| jvalue java_arg; |
| java_arg.l = jo_arg.get(); |
| map_to_uno( |
| jni, uno_args[ nPos ], java_arg, type, 0, |
| false /* no assign */, sal_False != param.bOut, |
| true /* special wrapped integral types */ ); |
| } |
| catch (...) |
| { |
| // cleanup uno in args |
| for ( sal_Int32 n = 0; n < nPos; ++n ) |
| { |
| typelib_MethodParameter const & p = pParams[ n ]; |
| if (p.bIn) |
| { |
| uno_type_destructData( |
| uno_args[ n ], p.pTypeRef, 0 ); |
| } |
| #ifdef BROKEN_ALLOCA |
| if (uno_args[ nPos ] && uno_args[ nPos ] != &uno_args_mem[ nPos ]) |
| free( uno_args[ nPos ] ); |
| #endif |
| } |
| #ifdef BROKEN_ALLOCA |
| free( mem ); |
| #endif |
| throw; |
| } |
| } |
| } |
| |
| uno_Any uno_exc_holder; |
| uno_Any * uno_exc = &uno_exc_holder; |
| // call binary uno |
| (*pUnoI->pDispatcher)( pUnoI, member_td, uno_ret, uno_args, &uno_exc ); |
| |
| if (0 == uno_exc) |
| { |
| // convert out args; destruct uno args |
| for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) |
| { |
| typelib_MethodParameter const & param = pParams[ nPos ]; |
| typelib_TypeDescriptionReference * type = param.pTypeRef; |
| if (param.bOut) |
| { |
| try |
| { |
| // get out holder array[ 1 ] |
| JLocalAutoRef jo_out_holder( |
| jni, jni->GetObjectArrayElement( jo_args, nPos ) ); |
| jni.ensure_no_exception(); |
| jvalue java_arg; |
| java_arg.l = jo_out_holder.get(); |
| map_to_java( |
| jni, &java_arg, uno_args[ nPos ], type, 0, |
| true /* in */, true /* out holder */ ); |
| } |
| catch (...) |
| { |
| // cleanup further uno args |
| for ( sal_Int32 n = nPos; n < nParams; ++n ) |
| { |
| uno_type_destructData( |
| uno_args[ n ], pParams[ n ].pTypeRef, 0 ); |
| #ifdef BROKEN_ALLOCA |
| if (uno_args[ nPos ] && uno_args[ nPos ] != &uno_args_mem[ nPos ]) |
| free( uno_args[ nPos ] ); |
| #endif |
| } |
| // cleanup uno return value |
| uno_type_destructData( uno_ret, return_type, 0 ); |
| #ifdef BROKEN_ALLOCA |
| free( mem ); |
| #endif |
| throw; |
| } |
| } |
| if (typelib_TypeClass_DOUBLE < type->eTypeClass && |
| typelib_TypeClass_ENUM != type->eTypeClass) // opt |
| { |
| uno_type_destructData( uno_args[ nPos ], type, 0 ); |
| #ifdef BROKEN_ALLOCA |
| if (uno_args[ nPos ] && uno_args[ nPos ] != &uno_args_mem[ nPos ]) |
| free( uno_args[ nPos ] ); |
| #endif |
| } |
| } |
| |
| if (typelib_TypeClass_VOID != return_type->eTypeClass) |
| { |
| // convert uno return value |
| jvalue java_ret; |
| try |
| { |
| map_to_java( |
| jni, &java_ret, uno_ret, return_type, 0, |
| true /* in */, false /* no out */, |
| true /* special_wrapped_integral_types */ ); |
| } |
| catch (...) |
| { |
| uno_type_destructData( uno_ret, return_type, 0 ); |
| #ifdef BROKEN_ALLOCA |
| free( mem ); |
| #endif |
| throw; |
| } |
| if (typelib_TypeClass_DOUBLE < return_type->eTypeClass && |
| typelib_TypeClass_ENUM != return_type->eTypeClass) // opt |
| { |
| uno_type_destructData( uno_ret, return_type, 0 ); |
| } |
| #ifdef BROKEN_ALLOCA |
| free( mem ); |
| #endif |
| return java_ret.l; |
| } |
| #ifdef BROKEN_ALLOCA |
| free( mem ); |
| #endif |
| return 0; // void return |
| } |
| else // exception occured |
| { |
| // destruct uno in args |
| for ( sal_Int32 nPos = 0; nPos < nParams; ++nPos ) |
| { |
| typelib_MethodParameter const & param = pParams[ nPos ]; |
| if (param.bIn) |
| uno_type_destructData( uno_args[ nPos ], param.pTypeRef, 0 ); |
| #ifdef BROKEN_ALLOCA |
| if (uno_args[ nPos ] && uno_args[ nPos ] != &uno_args_mem[ nPos ]) |
| free( uno_args[ nPos ] ); |
| #endif |
| } |
| |
| handle_uno_exc( jni, uno_exc ); |
| #ifdef BROKEN_ALLOCA |
| free( mem ); |
| #endif |
| return 0; |
| } |
| } |
| |
| } |
| |
| using namespace ::jni_uno; |
| |
| extern "C" |
| { |
| |
| //------------------------------------------------------------------------------ |
| JNIEXPORT jobject |
| JNICALL Java_com_sun_star_bridges_jni_1uno_JNI_1proxy_dispatch_1call( |
| JNIEnv * jni_env, jobject jo_proxy, jlong bridge_handle, jstring, |
| jstring jo_method, jobjectArray jo_args /* may be 0 */ ) |
| SAL_THROW_EXTERN_C() |
| { |
| Bridge const * bridge = reinterpret_cast< Bridge const * >( bridge_handle ); |
| JNI_info const * jni_info = bridge->m_jni_info; |
| JNI_context jni( |
| jni_info, jni_env, |
| static_cast< jobject >( |
| reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( |
| bridge->m_java_env->pContext )->getClassLoader() ) ); |
| |
| OUString method_name; |
| |
| try |
| { |
| method_name = jstring_to_oustring( jni, jo_method ); |
| #if OSL_DEBUG_LEVEL > 1 |
| { |
| OUStringBuffer trace_buf( 64 ); |
| trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("java->uno call: ") ); |
| trace_buf.append( method_name ); |
| trace_buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(" on oid ") ); |
| JLocalAutoRef jo_oid( |
| jni, jni->GetObjectField( |
| jo_proxy, jni_info->m_field_JNI_proxy_m_oid ) ); |
| trace_buf.append( jstring_to_oustring( jni, (jstring) jo_oid.get() ) ); |
| OString cstr_msg( |
| OUStringToOString( |
| trace_buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US ) ); |
| OSL_TRACE( cstr_msg.getStr() ); |
| } |
| #endif |
| |
| // special IQueryInterface.queryInterface() |
| if (method_name.equalsAsciiL( |
| RTL_CONSTASCII_STRINGPARAM("queryInterface") )) |
| { |
| // oid |
| JLocalAutoRef jo_oid( |
| jni, jni->GetObjectField( |
| jo_proxy, jni_info->m_field_JNI_proxy_m_oid ) ); |
| // type |
| JLocalAutoRef jo_type( |
| jni, jni->GetObjectArrayElement( jo_args, 0 ) ); |
| jni.ensure_no_exception(); |
| |
| JLocalAutoRef jo_type_name( |
| jni, jni->GetObjectField( |
| jo_type.get(), jni_info->m_field_Type__typeName ) ); |
| if (! jo_type_name.is()) |
| { |
| throw BridgeRuntimeError( |
| OUSTR("incomplete type object: no type name!") + |
| jni.get_stack_trace() ); |
| } |
| OUString type_name( |
| jstring_to_oustring( jni, (jstring) jo_type_name.get() ) ); |
| JNI_type_info const * info = |
| jni_info->get_type_info( jni, type_name ); |
| if (typelib_TypeClass_INTERFACE != info->m_td.get()->eTypeClass) |
| { |
| throw BridgeRuntimeError( |
| OUSTR("queryInterface() call demands an INTERFACE type!") ); |
| } |
| JNI_interface_type_info const * iface_info = |
| static_cast< JNI_interface_type_info const * >( info ); |
| |
| // getRegisteredInterface() already tested in JNI_proxy: |
| // perform queryInterface call on binary uno interface |
| uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >( |
| jni->GetLongField( |
| jo_proxy, jni_info->m_field_JNI_proxy_m_receiver_handle ) ); |
| |
| uno_Any uno_ret; |
| void * uno_args[] = { &iface_info->m_td.get()->pWeakRef }; |
| uno_Any uno_exc_holder; |
| uno_Any * uno_exc = &uno_exc_holder; |
| // call binary uno |
| (*pUnoI->pDispatcher)( |
| pUnoI, jni_info->m_XInterface_queryInterface_td.get(), |
| &uno_ret, uno_args, &uno_exc ); |
| if (0 == uno_exc) |
| { |
| jobject jo_ret = 0; |
| if (typelib_TypeClass_INTERFACE == uno_ret.pType->eTypeClass) |
| { |
| uno_Interface * pUnoRet = |
| (uno_Interface *) uno_ret.pReserved; |
| if (0 != pUnoRet) |
| { |
| try |
| { |
| jo_ret = |
| bridge->map_to_java( jni, pUnoRet, iface_info ); |
| } |
| catch (...) |
| { |
| uno_any_destruct( &uno_ret, 0 ); |
| throw; |
| } |
| } |
| } |
| uno_any_destruct( &uno_ret, 0 ); |
| return jo_ret; |
| } |
| else |
| { |
| bridge->handle_uno_exc( jni, uno_exc ); |
| return 0; |
| } |
| } |
| |
| typelib_InterfaceTypeDescription * td = |
| reinterpret_cast< typelib_InterfaceTypeDescription * >( |
| jni->GetLongField( |
| jo_proxy, jni_info->m_field_JNI_proxy_m_td_handle ) ); |
| uno_Interface * pUnoI = |
| reinterpret_cast< uno_Interface * >( |
| jni->GetLongField( |
| jo_proxy, jni_info->m_field_JNI_proxy_m_receiver_handle ) ); |
| |
| typelib_TypeDescriptionReference ** ppAllMembers = td->ppAllMembers; |
| for ( sal_Int32 nPos = td->nAllMembers; nPos--; ) |
| { |
| // try to avoid getting typedescription as long as possible, |
| // because of a Mutex.acquire() in |
| // typelib_typedescriptionreference_getDescription() |
| typelib_TypeDescriptionReference * member_type = |
| ppAllMembers[ nPos ]; |
| |
| // check method_name against fully qualified type_name |
| // of member_type; type_name is of the form |
| // <name> "::" <method_name> *(":@" <idx> "," <idx> ":" <name>) |
| OUString const & type_name = |
| OUString::unacquired( &member_type->pTypeName ); |
| sal_Int32 offset = type_name.indexOf( ':' ) + 2; |
| OSL_ASSERT( |
| offset >= 2 && offset < type_name.getLength() |
| && type_name[offset - 1] == ':' ); |
| sal_Int32 remainder = type_name.getLength() - offset; |
| if (typelib_TypeClass_INTERFACE_METHOD == member_type->eTypeClass) |
| { |
| if ((method_name.getLength() == remainder |
| || (method_name.getLength() < remainder |
| && type_name[offset + method_name.getLength()] == ':')) |
| && type_name.match(method_name, offset)) |
| { |
| TypeDescr member_td( member_type ); |
| typelib_InterfaceMethodTypeDescription * method_td = |
| reinterpret_cast< |
| typelib_InterfaceMethodTypeDescription * >( |
| member_td.get() ); |
| return bridge->call_uno( |
| jni, pUnoI, member_td.get(), |
| method_td->pReturnTypeRef, |
| method_td->nParams, method_td->pParams, |
| jo_args ); |
| } |
| } |
| else // attribute |
| { |
| OSL_ASSERT( |
| typelib_TypeClass_INTERFACE_ATTRIBUTE == |
| member_type->eTypeClass ); |
| |
| if (method_name.getLength() >= 3 |
| && (method_name.getLength() - 3 == remainder |
| || (method_name.getLength() - 3 < remainder |
| && type_name[ |
| offset + (method_name.getLength() - 3)] == ':')) |
| && method_name[1] == 'e' && method_name[2] == 't' |
| && rtl_ustr_compare_WithLength( |
| type_name.getStr() + offset, |
| method_name.getLength() - 3, |
| method_name.getStr() + 3, |
| method_name.getLength() - 3) == 0) |
| { |
| if ('g' == method_name[ 0 ]) |
| { |
| TypeDescr member_td( member_type ); |
| typelib_InterfaceAttributeTypeDescription * attr_td = |
| reinterpret_cast< |
| typelib_InterfaceAttributeTypeDescription * >( |
| member_td.get() ); |
| return bridge->call_uno( |
| jni, pUnoI, member_td.get(), |
| attr_td->pAttributeTypeRef, |
| 0, 0, |
| jo_args ); |
| } |
| else if ('s' == method_name[ 0 ]) |
| { |
| TypeDescr member_td( member_type ); |
| typelib_InterfaceAttributeTypeDescription * attr_td = |
| reinterpret_cast< |
| typelib_InterfaceAttributeTypeDescription * >( |
| member_td.get() ); |
| if (! attr_td->bReadOnly) |
| { |
| typelib_MethodParameter param; |
| param.pTypeRef = attr_td->pAttributeTypeRef; |
| param.bIn = sal_True; |
| param.bOut = sal_False; |
| return bridge->call_uno( |
| jni, pUnoI, member_td.get(), |
| jni_info->m_void_type.getTypeLibType(), |
| 1, ¶m, |
| jo_args ); |
| } |
| } |
| } |
| } |
| } |
| // the thing that should not be... no method info found! |
| OUStringBuffer buf( 64 ); |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM( |
| "calling undeclared function on interface ") ); |
| buf.append( OUString::unacquired( |
| &((typelib_TypeDescription *)td)->pTypeName ) ); |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") ); |
| buf.append( method_name ); |
| buf.append( jni.get_stack_trace() ); |
| throw BridgeRuntimeError( buf.makeStringAndClear() ); |
| } |
| catch (BridgeRuntimeError & err) |
| { |
| OUStringBuffer buf( 128 ); |
| buf.appendAscii( |
| RTL_CONSTASCII_STRINGPARAM("[jni_uno bridge error] " |
| "Java calling UNO method ") ); |
| buf.append( method_name ); |
| buf.appendAscii( RTL_CONSTASCII_STRINGPARAM(": ") ); |
| buf.append( err.m_message ); |
| // notify RuntimeException |
| OString cstr_msg( |
| OUStringToOString( |
| buf.makeStringAndClear(), RTL_TEXTENCODING_JAVA_UTF8 ) ); |
| OSL_ENSURE( 0, cstr_msg.getStr() ); |
| if (jni->ThrowNew(jni_info->m_class_RuntimeException, cstr_msg.getStr()) |
| != 0) |
| { |
| OSL_ASSERT( false ); |
| } |
| return 0; |
| } |
| catch (::jvmaccess::VirtualMachine::AttachGuard::CreationException &) |
| { |
| OString cstr_msg( |
| OString( RTL_CONSTASCII_STRINGPARAM( |
| "[jni_uno bridge error] " |
| "attaching current thread to java failed!") ) + |
| OUStringToOString( |
| jni.get_stack_trace(), RTL_TEXTENCODING_JAVA_UTF8 ) ); |
| OSL_ENSURE( 0, cstr_msg.getStr() ); |
| if (jni->ThrowNew(jni_info->m_class_RuntimeException, cstr_msg.getStr()) |
| != 0) |
| { |
| OSL_ASSERT( false ); |
| } |
| return 0; |
| } |
| } |
| |
| //------------------------------------------------------------------------------ |
| JNIEXPORT void |
| JNICALL Java_com_sun_star_bridges_jni_1uno_JNI_1proxy_finalize__J( |
| JNIEnv * jni_env, jobject jo_proxy, jlong bridge_handle ) |
| SAL_THROW_EXTERN_C() |
| { |
| Bridge const * bridge = reinterpret_cast< Bridge const * >( bridge_handle ); |
| JNI_info const * jni_info = bridge->m_jni_info; |
| JNI_context jni( |
| jni_info, jni_env, |
| static_cast< jobject >( |
| reinterpret_cast< ::jvmaccess::UnoVirtualMachine * >( |
| bridge->m_java_env->pContext )->getClassLoader() ) ); |
| |
| uno_Interface * pUnoI = reinterpret_cast< uno_Interface * >( |
| jni->GetLongField( |
| jo_proxy, jni_info->m_field_JNI_proxy_m_receiver_handle ) ); |
| typelib_TypeDescription * td = |
| reinterpret_cast< typelib_TypeDescription * >( |
| jni->GetLongField( |
| jo_proxy, jni_info->m_field_JNI_proxy_m_td_handle ) ); |
| |
| #if OSL_DEBUG_LEVEL > 1 |
| { |
| JLocalAutoRef jo_oid( |
| jni, jni->GetObjectField( |
| jo_proxy, jni_info->m_field_JNI_proxy_m_oid ) ); |
| OUString oid( jstring_to_oustring( jni, (jstring) jo_oid.get() ) ); |
| OString cstr_msg( |
| OUStringToOString( |
| OUSTR("freeing java uno proxy: ") + oid, |
| RTL_TEXTENCODING_ASCII_US ) ); |
| OSL_TRACE( cstr_msg.getStr() ); |
| } |
| #endif |
| // revoke from uno env; has already been revoked from java env |
| (*bridge->m_uno_env->revokeInterface)( bridge->m_uno_env, pUnoI ); |
| // release receiver |
| (*pUnoI->release)( pUnoI ); |
| // release typedescription handle |
| typelib_typedescription_release( td ); |
| // release bridge handle |
| bridge->release(); |
| } |
| |
| } |