blob: 409b12602360aa88adc14ce16710be25732f9ecf [file] [log] [blame]
/**************************************************************
*
* 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 "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<typelib_TypeDescription *>(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<typelib_InterfaceTypeDescription *>(
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(),
&param, 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
}
}
}
}